feat: Add Content Protection for Windows and macOS#4485
Conversation
- Prevents window contents from being captured by screen recording/sharing software - Windows: Uses WDA_EXCLUDEFROMCAPTURE on Windows 10 2004+, falls back to WDA_MONITOR - macOS: Uses NSWindowSharingType to set window as read-only for screen sharing - Added ContentProtectionEnabled option to WebviewWindowOptions - Added SetContentProtection() method for runtime control - Added comprehensive documentation and example usage
|
Caution Review failedThe pull request is closed. WalkthroughThis change introduces a cross-platform "Content Protection" feature for application windows, primarily targeting Windows and macOS. New methods and fields are added to window interfaces and implementations to enable or disable content protection, preventing screen capture and recording. Documentation and usage examples are updated, and platform-specific logic is implemented for Windows and macOS, with Linux stubbing the feature. Changes
Sequence Diagram(s)sequenceDiagram
participant App
participant Window (cross-platform)
participant PlatformAPI (Win/Mac)
App->>Window: SetContentProtection(true/false)
alt impl not initialized
Window->>Window: Set option ContentProtectionEnabled
else impl initialized
Window->>PlatformAPI: setContentProtection(true/false)
alt Windows
PlatformAPI->>PlatformAPI: SetWindowDisplayAffinity(hwnd, flag)
else macOS
PlatformAPI->>PlatformAPI: Set NSWindow sharingType
else Linux
PlatformAPI->>PlatformAPI: (no-op)
end
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related issues
Possibly related PRs
Suggested labels
Poem
Note 🔌 MCP (Model Context Protocol) integration is now available in Early Access!Pro users can now connect to remote MCP servers under the Integrations page to get reviews and chat conversations that understand additional development context. 📜 Recent review detailsConfiguration used: .coderabbit.yaml 📒 Files selected for processing (1)
✨ Finishing Touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
Documentation and Community
|
Deploying wails with
|
| Latest commit: |
b9f3c83
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://c6c8f6f9.wails.pages.dev |
| Branch Preview URL: | https://v3-alpha-feature-content-pro.wails.pages.dev |
There was a problem hiding this comment.
Actionable comments posted: 7
🧹 Nitpick comments (6)
v3/pkg/application/webview_window_options.go (1)
138-141: Clarify platform scope and default in the new option’s doc commentMatch the style used for IgnoreMouseEvents (Windows + Mac only) and note Linux no-op/default.
- // ContentProtectionEnabled specifies whether content protection is enabled, preventing screen capture and recording. + // ContentProtectionEnabled specifies whether content protection is enabled, preventing screen capture/recording. + // Windows + Mac only (no-op on Linux). Default: false. ContentProtectionEnabled boolv3/UNRELEASED_CHANGELOG.md (1)
20-21: Wording/consistency: “Windows and macOS”; optionally note Linux no-opUse “macOS” (consistent across docs) and mention the Linux no-op to set expectations.
-- Add Content Protection on Windows/Mac by [@leaanthony](https://github.com/leaanthony) based on the original work of [@Taiterbase](https://github.com/Taiterbase) in this [PR](https://github.com/wailsapp/wails/pull/4241) +- Add Content Protection on Windows and macOS (Linux no-op) by [@leaanthony](https://github.com/leaanthony), based on the original work of [@Taiterbase](https://github.com/Taiterbase) in this [PR](https://github.com/wailsapp/wails/pull/4241)v3/pkg/application/webview_window_linux.go (1)
427-432: Annotate Linux content protection as an explicit no-op for claritySet content protection is intentionally unsupported on Linux. Matching the nearby snapAssist comment improves readability and avoids confusion.
-func (w *linuxWebviewWindow) setContentProtection(enabled bool) {} +func (w *linuxWebviewWindow) setContentProtection(enabled bool) {} // No-op on Linuxv3/examples/window/main.go (1)
124-135: Good example; minor clarity/consistency tweaks suggestedNice addition demonstrating enabling content protection at creation. Two optional improvements:
- Clarify the label so users know it’s supported on Windows/macOS:
- myMenu.Add("New WebviewWindow (Content Protection Enabled)"). + myMenu.Add("New WebviewWindow (Content Protection, Windows/macOS)").
- Optional: For consistency with other OS-guarded examples below, explicitly guard for Windows/macOS instead of “not Linux.” This avoids surprising behavior on any other unsupported GOOS:
// replace: if runtime.GOOS != "linux" { if runtime.GOOS == "windows" || runtime.GOOS == "darwin" {
- Optional: The PR mentions runtime toggling; consider adding a toggle example for the current window:
// Example addition near other Controls/State items if runtime.GOOS == "windows" || runtime.GOOS == "darwin" { stateMenu.Add("Toggle Content Protection").OnClick(func(ctx *application.Context) { currentWindow(func(w *application.WebviewWindow) { // If you expose a getter, prefer it. Otherwise, track a local state or flip a stored flag. // Example assumes you track a boolean somewhere: // contentProtected = !contentProtected // w.SetContentProtection(contentProtected) w.SetContentProtection(true) // or false to disable }) }) }v3/pkg/w32/wda.go (1)
5-9: Constants look correct; consider adding short doc commentsWDA_NONE=0x0, WDA_MONITOR=0x1, WDA_EXCLUDEFROMCAPTURE=0x11 are correct. Adding brief comments on semantics aids maintainability (e.g., EXCLUDEFROMCAPTURE: Windows 10 2004+, blocks OS capture APIs; MONITOR: restricts display to a monitor, partial capture protection).
docs/src/content/docs/learn/windows.mdx (1)
199-201: Cross-reference the new APIConsider linking this method item to the Content Protection section below for discoverability, e.g., “See Content Protection for platform specifics.”
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (12)
docs/src/content/docs/changelog.mdx(1 hunks)docs/src/content/docs/learn/windows.mdx(1 hunks)v3/UNRELEASED_CHANGELOG.md(1 hunks)v3/examples/window/main.go(1 hunks)v3/pkg/application/webview_window.go(2 hunks)v3/pkg/application/webview_window_darwin.go(2 hunks)v3/pkg/application/webview_window_linux.go(1 hunks)v3/pkg/application/webview_window_options.go(1 hunks)v3/pkg/application/webview_window_windows.go(2 hunks)v3/pkg/application/window.go(1 hunks)v3/pkg/w32/user32.go(1 hunks)v3/pkg/w32/wda.go(1 hunks)
🧰 Additional context used
🧠 Learnings (10)
📚 Learning: 2024-09-20T23:34:29.841Z
Learnt from: nixpare
PR: wailsapp/wails#3763
File: v3/examples/keybindings/main.go:16-17
Timestamp: 2024-09-20T23:34:29.841Z
Learning: In the codebase, `application.Options.KeyBindings` uses the `application.Window` type, whereas `application.WebviewWindowOptions.KeyBindings` uses `*application.WebviewWindow`. This is intentional and acceptable.
Applied to files:
v3/pkg/application/webview_window_options.gov3/pkg/application/webview_window.gov3/pkg/application/webview_window_linux.gov3/pkg/application/webview_window_darwin.godocs/src/content/docs/learn/windows.mdxv3/examples/window/main.gov3/pkg/application/webview_window_windows.go
📚 Learning: 2025-04-29T23:54:07.488Z
Learnt from: popaprozac
PR: wailsapp/wails#4256
File: v2/internal/frontend/desktop/linux/notifications.go:27-28
Timestamp: 2025-04-29T23:54:07.488Z
Learning: In Wails v2, unlike v3-alpha which has a `ServiceShutdown` method for services, there is no standardized teardown pattern for frontend implementations. When implementing features that require cleanup (like goroutines or resources), add explicit cleanup methods (e.g., `CleanupNotifications()`) that handle resource release, context cancellation, and connection closure.
Applied to files:
docs/src/content/docs/changelog.mdx
📚 Learning: 2025-08-08T13:15:20.287Z
Learnt from: APshenkin
PR: wailsapp/wails#4484
File: v2/internal/frontend/utils/urlValidator.go:25-31
Timestamp: 2025-08-08T13:15:20.287Z
Learning: In Wails v2 (PR wailsapp/wails#4484), for BrowserOpenURL URL validation (v2/internal/frontend/utils/urlValidator.go), maintainers (APshenkin) prefer not to restrict schemes to an http/https allowlist because supported schemes may vary. The allowlist suggestion is declined; continue with the existing denylist approach and generic validation.
Applied to files:
docs/src/content/docs/changelog.mdx
📚 Learning: 2024-10-08T22:11:37.054Z
Learnt from: nixpare
PR: wailsapp/wails#3763
File: v3/pkg/application/application_options.go:93-93
Timestamp: 2024-10-08T22:11:37.054Z
Learning: The `KeyBindings` property of `application.Option` uses the `application.Window` type, while `application.WebviewWindowOptions` still accepts `*application.WebviewWindow`, and this is intentional.
Applied to files:
v3/pkg/application/webview_window.godocs/src/content/docs/learn/windows.mdx
📚 Learning: 2025-08-08T09:13:16.884Z
Learnt from: APshenkin
PR: wailsapp/wails#4480
File: v2/internal/frontend/desktop/darwin/message.h:17-19
Timestamp: 2025-08-08T09:13:16.884Z
Learning: In Wails v2 bindings origin verification, processBindingMessage intentionally has different signatures across platforms: Darwin includes an isMainFrame bool (WKWebKit provides it), Linux uses two params (message, source) as WebKitGTK doesn’t expose main-frame info there, and Windows handles origin checks in Go via WebView2 sender/args without a C bridge. This divergence is acceptable/expected per maintainer (APshenkin).
Applied to files:
v3/pkg/application/webview_window.gov3/pkg/w32/user32.gov3/pkg/application/webview_window_darwin.gov3/examples/window/main.go
📚 Learning: 2024-09-21T13:34:24.145Z
Learnt from: nixpare
PR: wailsapp/wails#3763
File: v3/pkg/application/webview_window_bindings_darwin.h:0-0
Timestamp: 2024-09-21T13:34:24.145Z
Learning: In this codebase, typedefs for window references (like replacing `void *` with `WindowRef`) are not preferred; using `void *` is acceptable.
Applied to files:
v3/pkg/w32/user32.go
📚 Learning: 2024-09-21T09:56:48.126Z
Learnt from: nixpare
PR: wailsapp/wails#3763
File: v3/pkg/application/webview_panel_darwin.go:88-89
Timestamp: 2024-09-21T09:56:48.126Z
Learning: Safety checks for `p.nsPanel` are performed in the `SetFloating` method of `WebviewPanel`, following the `WebviewWindow` and `macosWebviewWindow` implementations and code style.
Applied to files:
v3/pkg/application/webview_window_darwin.go
📚 Learning: 2024-10-08T22:11:37.054Z
Learnt from: leaanthony
PR: wailsapp/wails#3763
File: v3/examples/window/main.go:472-475
Timestamp: 2024-10-08T22:11:37.054Z
Learning: In `v3/examples/window/main.go`, `time.Sleep` is used within a goroutine and does not block the UI thread.
Applied to files:
v3/pkg/w32/wda.godocs/src/content/docs/learn/windows.mdxv3/examples/window/main.go
📚 Learning: 2025-01-24T22:41:18.566Z
Learnt from: leaanthony
PR: wailsapp/wails#4031
File: v3/pkg/application/menu.go:199-202
Timestamp: 2025-01-24T22:41:18.566Z
Learning: In the Wails menu system (v3/pkg/application/menu.go), shared state between menus is intentionally designed and desirable. Methods like `Append()` and `Prepend()` should maintain shared references to menu items rather than creating deep copies.
Applied to files:
v3/examples/window/main.go
📚 Learning: 2024-09-30T06:14:32.602Z
Learnt from: leaanthony
PR: wailsapp/wails#3763
File: v3/internal/commands/appimage_testfiles/main.go:295-299
Timestamp: 2024-09-30T06:14:32.602Z
Learning: In `v3/internal/commands/appimage_testfiles/main.go`, `time.Sleep` is used within a goroutine and does not block the UI thread.
Applied to files:
v3/examples/window/main.go
🧬 Code Graph Analysis (3)
v3/pkg/application/webview_window.go (1)
v3/pkg/application/window.go (1)
Window(14-92)
v3/pkg/w32/wda.go (1)
v3/pkg/w32/consts.go (1)
IsWindowsVersionAtLeast(33-37)
v3/pkg/application/webview_window_windows.go (1)
v3/pkg/w32/wda.go (3)
WDA_EXCLUDEFROMCAPTURE(8-8)WDA_NONE(6-6)SetWindowDisplayAffinity(11-21)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Run Go Tests v3 (ubuntu-latest, 1.24)
- GitHub Check: Run Go Tests v3 (windows-latest, 1.24)
🔇 Additional comments (4)
v3/pkg/application/window.go (1)
91-92: Confirm external Window implementations updatedI’ve verified that the only internal
Windowimplementation (WebviewWindow inv3/pkg/application/webview_window.go:524) already implementsSetContentProtection, so no internal changes are missing. However, addingSetContentProtection(bool) Windowto the exportedWindowinterface is a breaking change.• Internal implementations checked:
– WebviewWindow (v3/pkg/application/webview_window.go:524)Next steps:
• Please review any external mocks or customWindowimplementations (in downstream projects or tests) and update them to includeSetContentProtection.docs/src/content/docs/changelog.mdx (1)
184-184: Fix duplicate PR link and clarify attribution for Gin supportThis line links the same PR twice and reads ambiguously (“original work … in this PR”). If there’s a separate original PR by @AnalogJ, please link that; otherwise, simplify the sentence to avoid duplication.
Proposed minimal edit:
- Gin support by [Lea Anthony](https://github.com/leaanthony) in [PR](https://github.com/wailsapp/wails/pull/3537) based on the original work of [@AnalogJ](https://github.com/AnalogJ) in this [PR](https://github.com/wailsapp/wails/pull/3537) + Gin support by [Lea Anthony](https://github.com/leaanthony) in [PR #3537](https://github.com/wailsapp/wails/pull/3537), based on original work by [@AnalogJ](https://github.com/AnalogJ).If a different PR by @AnalogJ should be credited, replace the trailing text with the correct link instead of removing it.
Likely an incorrect or invalid review comment.
v3/pkg/application/webview_window.go (1)
115-116: Interface extension looks consistent.Adding setContentProtection(enabled bool) to webviewWindowImpl aligns with the new Window API and platform implementations.
v3/pkg/application/webview_window_windows.go (1)
383-385: Verify UI-Thread Dispatch for SetContentProtection
I wasn’t able to find any UI/main-thread marshalling when
WebviewWindow.SetContentProtectioncalls into
windowsWebviewWindow.setContentProtection. Win32 APIs like
SetWindowDisplayAffinitymust be invoked on the window’s UI thread.Please confirm that toggling content protection runs on the OS-thread locked for your message loop. If it doesn’t, wrap the call in your application’s UI dispatch mechanism (e.g. via
app.dispatchor similar).• Wrapper in v3/pkg/application/webview_window.go (lines 524–528)
• Windows impl in v3/pkg/application/webview_window_windows.go (lines 2449–2454)
| func (w *macosWebviewWindow) setContentProtection(enabled bool) { | ||
| C.setContentProtection(w.nsWindow, C.bool(enabled)) | ||
| } |
There was a problem hiding this comment.
💡 Verification agent
🧩 Analysis chain
Main-thread requirement: this call must be invoked via InvokeSync.
macOS UI mutations must happen on the main thread. Given the current WebviewWindow.SetContentProtection implementation does not use InvokeSync, this will run off the main thread and can cause undefined behavior.
Recommendation: wrap the call site (in WebviewWindow.SetContentProtection) with InvokeSync. See suggested diff in webview_window.go comment.
🏁 Script executed:
#!/bin/bash
# Search for SetContentProtection in the repository
rg --color=never -n "SetContentProtection" .
# Also search for lower-case setContentProtection invocations
rg --color=never -n "setContentProtection" .Length of output: 1422
#!/bin/bash
# Display WebviewWindow.SetContentProtection implementation
sed -n '520,560p' v3/pkg/application/webview_window.go
# Display top-level Window.SetContentProtection implementation
sed -n '80,120p' v3/pkg/application/window.go
# Search for any InvokeSync calls in the repo
rg --color=never -n "InvokeSync" .🏁 Script executed:
#!/bin/bash
# Inspect the Objective-C implementation of setContentProtection in Darwin binding
sed -n '800,860p' v3/pkg/application/webview_window_darwin.goLength of output: 1633
🏁 Script executed:
#!/bin/bash
# Extract WebviewWindow.SetContentProtection implementation
sed -n '510,560p' v3/pkg/application/webview_window.go
# Search for threading helpers in webview_window.go
rg --color=never -n "InvokeSync" v3/pkg/application/webview_window.go || true
rg --color=never -n "MainThread" v3/pkg/application/webview_window.go || true
rg --color=never -n "runtime\." v3/pkg/application/webview_window.go | head -n20Length of output: 4211
Invoke setContentProtection on the main thread via InvokeSync
The current WebviewWindow.SetContentProtection calls w.impl.setContentProtection(b) directly. UI mutations on macOS must happen on the main thread, so this needs to be wrapped in InvokeSync, consistent with all other window operations.
• File: v3/pkg/application/webview_window.go, around line 524
• Change:
func (w *WebviewWindow) SetContentProtection(b bool) Window {
if w.impl == nil {
w.options.ContentProtectionEnabled = b
} else {
- w.impl.setContentProtection(b)
+ InvokeSync(func() {
+ w.impl.setContentProtection(b)
+ })
}
return w
}Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In v3/pkg/application/webview_window.go around line 524, the call to
w.impl.setContentProtection(b) must be wrapped inside an InvokeSync call to
ensure it runs on the main thread, as UI updates on macOS require main thread
execution. Modify the method to invoke setContentProtection using InvokeSync to
maintain thread safety and consistency with other window operations.
There was a problem hiding this comment.
Actionable comments posted: 7
🔭 Outside diff range comments (1)
v3/pkg/application/webview_window_linux.go (1)
427-432: Add Linux wiring for content protection and debug loggingThe Linux stub for
setContentProtectionis never invoked on window creation. To align with Windows and macOS, you should:
- In
v3/pkg/application/webview_window_linux.go, inside thefunc (w *linuxWebviewWindow) show()implementation (around where you register capabilities), add:// Process ContentProtection (Linux does not support it) w.setContentProtection(w.parent.options.ContentProtectionEnabled)- Update the stub at the bottom of that file to emit a debug log when
enabledis true:func (w *linuxWebviewWindow) setContentProtection(enabled bool) { - // no-op on Linux + if enabled { + globalApplication.debug("ContentProtectionEnabled requested on Linux: no-op (not supported)") + } }This ensures diagnostics are visible whenever an app requests content protection on Linux.
🧹 Nitpick comments (7)
docs/src/content/docs/changelog.mdx (1)
184-184: Duplicate/ambiguous PR reference; tighten wordingThe line links to the same PR twice (“in PR … based on … in this PR”), which reads oddly. Suggest simplifying and making the platform naming consistent.
-- Gin support by [Lea Anthony](https://github.com/leaanthony) in [PR](https://github.com/wailsapp/wails/pull/3537) based on the original work of [@AnalogJ](https://github.com/AnalogJ) in this [PR](https://github.com/wailsapp/wails/pull/3537) +- Gin support by [Lea Anthony](https://github.com/leaanthony), based on the original work of [@AnalogJ](https://github.com/AnalogJ) in [PR #3537](https://github.com/wailsapp/wails/pull/3537)v3/UNRELEASED_CHANGELOG.md (1)
20-20: Changelog phrasing and platform naming consistencyPrefer “Windows and macOS” over “Windows/Mac”, and avoid “this PR” ambiguity in changelogs; use an explicit PR number.
-- Add Content Protection on Windows/Mac by [@leaanthony](https://github.com/leaanthony) based on the original work of [@Taiterbase](https://github.com/Taiterbase) in this [PR](https://github.com/wailsapp/wails/pull/4241) +- Add Content Protection on Windows and macOS by [@leaanthony](https://github.com/leaanthony), based on the original work of [@Taiterbase](https://github.com/Taiterbase) in [PR #4241](https://github.com/wailsapp/wails/pull/4241)v3/examples/window/main.go (1)
124-135: Demo improvement: showcase runtime toggling as wellNice addition for initial enable. To fully demonstrate the feature per PR (toggle at runtime), consider adding two menu items under “State” or “Controls” that call
SetContentProtection(true/false)on the current window. Example:stateMenu.Add("Enable Content Protection").OnClick(func(ctx *application.Context) { currentWindow(func(w *application.WebviewWindow) { w.SetContentProtection(true) }) }) stateMenu.Add("Disable Content Protection").OnClick(func(ctx *application.Context) { currentWindow(func(w *application.WebviewWindow) { w.SetContentProtection(false) }) })v3/pkg/w32/wda.go (1)
5-9: Nit: Add doc comments and link to MSDNAdd brief comments for the WDA_* flags and reference SetWindowDisplayAffinity docs. Improves readability and future maintenance.
const ( - WDA_NONE = 0x00000000 - WDA_MONITOR = 0x00000001 - WDA_EXCLUDEFROMCAPTURE = 0x00000011 // windows 10 2004+ + // WDA_NONE disables display affinity restrictions. + WDA_NONE = 0x00000000 + // WDA_MONITOR restricts content to a local monitor (older fallback; will appear black in remote sessions). + WDA_MONITOR = 0x00000001 + // WDA_EXCLUDEFROMCAPTURE excludes the window from screen capture (Windows 10, version 2004+). + // See: https://learn.microsoft.com/windows/win32/api/winuser/nf-winuser-setwindowdisplayaffinity + WDA_EXCLUDEFROMCAPTURE = 0x00000011 )docs/src/content/docs/learn/windows.mdx (3)
199-201: Clarify cross-platform behavior in method list (optional)Consider appending “(Windows/macOS; no-op on Linux)” to the bullet so readers scanning this list don’t miss the later platform support section.
208-238: Add caveats about thumbnails and remote sessions (Windows)Two practical caveats worth calling out here:
- With content protection enabled, Windows may show black thumbnails in Taskbar previews, Task View, and Snap Assist.
- On Windows versions where the fallback (WDA_MONITOR) is used, the window will appear black in remote sessions (RDP/VM streaming/screen-share).
You can fold these into the “Platform Support” bullets or move them to Important Notes.
239-254: Expand Important Notes with Windows-specific behaviorTo set expectations, add these items:
- On Windows, taskbar thumbnails, Task View and Snap Assist previews may be black while protection is enabled.
- On pre-2004 Windows (fallback to WDA_MONITOR), the window will be black in remote sessions (RDP/VMs) and many screen-sharing tools. This is expected.
Apply this diff inside the Important Notes list:
1. Content protection does not prevent physical photography of the screen 2. On Windows, the fallback for older versions provides partial protection 3. Some screen capture tools may still be able to capture protected content using low-level APIs 4. This feature should be part of a comprehensive security strategy, not the only protection +5. Windows taskbar thumbnails, Task View and Snap Assist previews may appear black while protection is enabled +6. On older Windows where fallback (WDA_MONITOR) is used, the window will appear black in remote sessions (RDP/VMs) and some screen-sharing environmentsHappy to update the docs section with the exact wording you prefer.
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (12)
docs/src/content/docs/changelog.mdx(1 hunks)docs/src/content/docs/learn/windows.mdx(1 hunks)v3/UNRELEASED_CHANGELOG.md(1 hunks)v3/examples/window/main.go(1 hunks)v3/pkg/application/webview_window.go(2 hunks)v3/pkg/application/webview_window_darwin.go(2 hunks)v3/pkg/application/webview_window_linux.go(1 hunks)v3/pkg/application/webview_window_options.go(1 hunks)v3/pkg/application/webview_window_windows.go(2 hunks)v3/pkg/application/window.go(1 hunks)v3/pkg/w32/user32.go(1 hunks)v3/pkg/w32/wda.go(1 hunks)
🧰 Additional context used
🧠 Learnings (10)
📚 Learning: 2024-09-20T23:34:29.841Z
Learnt from: nixpare
PR: wailsapp/wails#3763
File: v3/examples/keybindings/main.go:16-17
Timestamp: 2024-09-20T23:34:29.841Z
Learning: In the codebase, `application.Options.KeyBindings` uses the `application.Window` type, whereas `application.WebviewWindowOptions.KeyBindings` uses `*application.WebviewWindow`. This is intentional and acceptable.
Applied to files:
v3/pkg/application/webview_window_linux.gov3/pkg/application/webview_window_options.gov3/examples/window/main.gov3/pkg/application/webview_window.godocs/src/content/docs/learn/windows.mdxv3/pkg/application/webview_window_darwin.gov3/pkg/application/webview_window_windows.go
📚 Learning: 2024-10-08T22:11:37.054Z
Learnt from: nixpare
PR: wailsapp/wails#3763
File: v3/pkg/application/application_options.go:93-93
Timestamp: 2024-10-08T22:11:37.054Z
Learning: The `KeyBindings` property of `application.Option` uses the `application.Window` type, while `application.WebviewWindowOptions` still accepts `*application.WebviewWindow`, and this is intentional.
Applied to files:
v3/pkg/application/webview_window_options.gov3/pkg/application/webview_window.godocs/src/content/docs/learn/windows.mdx
📚 Learning: 2024-09-21T13:34:24.145Z
Learnt from: nixpare
PR: wailsapp/wails#3763
File: v3/pkg/application/webview_window_bindings_darwin.h:0-0
Timestamp: 2024-09-21T13:34:24.145Z
Learning: In this codebase, typedefs for window references (like replacing `void *` with `WindowRef`) are not preferred; using `void *` is acceptable.
Applied to files:
v3/pkg/w32/user32.go
📚 Learning: 2025-08-08T09:13:16.884Z
Learnt from: APshenkin
PR: wailsapp/wails#4480
File: v2/internal/frontend/desktop/darwin/message.h:17-19
Timestamp: 2025-08-08T09:13:16.884Z
Learning: In Wails v2 bindings origin verification, processBindingMessage intentionally has different signatures across platforms: Darwin includes an isMainFrame bool (WKWebKit provides it), Linux uses two params (message, source) as WebKitGTK doesn’t expose main-frame info there, and Windows handles origin checks in Go via WebView2 sender/args without a C bridge. This divergence is acceptable/expected per maintainer (APshenkin).
Applied to files:
v3/pkg/w32/user32.gov3/examples/window/main.gov3/pkg/application/webview_window_darwin.go
📚 Learning: 2025-04-29T23:54:07.488Z
Learnt from: popaprozac
PR: wailsapp/wails#4256
File: v2/internal/frontend/desktop/linux/notifications.go:27-28
Timestamp: 2025-04-29T23:54:07.488Z
Learning: In Wails v2, unlike v3-alpha which has a `ServiceShutdown` method for services, there is no standardized teardown pattern for frontend implementations. When implementing features that require cleanup (like goroutines or resources), add explicit cleanup methods (e.g., `CleanupNotifications()`) that handle resource release, context cancellation, and connection closure.
Applied to files:
docs/src/content/docs/changelog.mdx
📚 Learning: 2025-08-08T13:15:20.287Z
Learnt from: APshenkin
PR: wailsapp/wails#4484
File: v2/internal/frontend/utils/urlValidator.go:25-31
Timestamp: 2025-08-08T13:15:20.287Z
Learning: In Wails v2 (PR wailsapp/wails#4484), for BrowserOpenURL URL validation (v2/internal/frontend/utils/urlValidator.go), maintainers (APshenkin) prefer not to restrict schemes to an http/https allowlist because supported schemes may vary. The allowlist suggestion is declined; continue with the existing denylist approach and generic validation.
Applied to files:
docs/src/content/docs/changelog.mdx
📚 Learning: 2024-10-08T22:11:37.054Z
Learnt from: leaanthony
PR: wailsapp/wails#3763
File: v3/examples/window/main.go:472-475
Timestamp: 2024-10-08T22:11:37.054Z
Learning: In `v3/examples/window/main.go`, `time.Sleep` is used within a goroutine and does not block the UI thread.
Applied to files:
v3/examples/window/main.gov3/pkg/w32/wda.godocs/src/content/docs/learn/windows.mdx
📚 Learning: 2025-01-24T22:41:18.566Z
Learnt from: leaanthony
PR: wailsapp/wails#4031
File: v3/pkg/application/menu.go:199-202
Timestamp: 2025-01-24T22:41:18.566Z
Learning: In the Wails menu system (v3/pkg/application/menu.go), shared state between menus is intentionally designed and desirable. Methods like `Append()` and `Prepend()` should maintain shared references to menu items rather than creating deep copies.
Applied to files:
v3/examples/window/main.go
📚 Learning: 2024-09-30T06:14:32.602Z
Learnt from: leaanthony
PR: wailsapp/wails#3763
File: v3/internal/commands/appimage_testfiles/main.go:295-299
Timestamp: 2024-09-30T06:14:32.602Z
Learning: In `v3/internal/commands/appimage_testfiles/main.go`, `time.Sleep` is used within a goroutine and does not block the UI thread.
Applied to files:
v3/examples/window/main.go
📚 Learning: 2024-09-21T09:56:48.126Z
Learnt from: nixpare
PR: wailsapp/wails#3763
File: v3/pkg/application/webview_panel_darwin.go:88-89
Timestamp: 2024-09-21T09:56:48.126Z
Learning: Safety checks for `p.nsPanel` are performed in the `SetFloating` method of `WebviewPanel`, following the `WebviewWindow` and `macosWebviewWindow` implementations and code style.
Applied to files:
v3/pkg/application/webview_window_darwin.go
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Run Go Tests v3 (ubuntu-latest, 1.24)
- GitHub Check: Run Go Tests v3 (windows-latest, 1.24)
🔇 Additional comments (3)
v3/pkg/application/window.go (1)
91-91: SetContentProtection added to Window – internal and platform implementations verifiedVerified:
- Internal implementation:
WebviewWindowimplementsSetContentProtection(v3/pkg/application/webview_window.go:524). No otherWindowimplementers were found.- macOS (Darwin):
- The C bridge for content protection uses
dispatch_async(dispatch_get_main_queue(), …)in v3/pkg/application/webview_window_darwin.go (lines 397–405).- Windows:
SetWindowDisplayAffinityin v3/pkg/w32/wda.go falls back toWDA_MONITORfor Windows < 10 2004 (build 19041).- It’s invoked in v3/pkg/application/webview_window_windows.go (lines 2450–2454).
- Documentation:
- Updated in docs/src/content/docs/learn/windows.mdx (mentions and examples of
SetContentProtection(true/false)).Next step:
- If your JS/TS runtime or TypeScript definitions expose the
WindowAPI, please confirm thatSetContentProtectionis surfaced there as well.v3/pkg/application/webview_window_darwin.go (1)
821-833: Content Protection via NSWindowSharingType Is Ineffective on Modern macOSApple now documents that NSWindowSharingNone is a legacy constant and no longer prevents a window from being shared or captured, and NSWindowSharingReadOnly never did. As a result, swapping these values has no effect on today’s screen-recording or sharing APIs.
• Remove or deprecate
setContentProtection()’s use ofsetSharingType:entirely, or clearly document that it does not guarantee privacy.
• If you choose to keep it, at minimum wrap the call in a main-thread dispatch and add a comment describing the limitation:dispatch_async(dispatch_get_main_queue(), ^{ // NOTE: Neither NSWindowSharingNone nor NSWindowSharingReadOnly // prevents screen capture on modern macOS. This API is effectively a no-op. [window setSharingType: enabled ? NSWindowSharingReadOnly : NSWindowSharingNone]; });• For true capture prevention, consider platform-supported alternatives (e.g. ScreenCaptureKit, CoreGraphics window-image options, or CA filters) and document the trade-offs clearly.
Likely an incorrect or invalid review comment.
v3/pkg/application/webview_window_windows.go (1)
383-385: Good integration point for applying content protectionApplied immediately after CreateWindowEx and before Chromium init, which is ideal. No ordering concerns spotted.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
v3/tasks/cleanup/cleanup.go (1)
28-30: Nit: clarify descriptions.Tighten the wording for consistency and clarity.
- {Type: "exact", Pattern: "myapp.ARCHLINUX", TargetFiles: true, Description: "Linux ARCHLINUX package"}, - {Type: "exact", Pattern: "myapp.DEB", TargetFiles: true, Description: "Linux DEB package"}, - {Type: "exact", Pattern: "myapp.RPM", TargetFiles: true, Description: "Linux RPM package"}, + {Type: "exact", Pattern: "myapp.ARCHLINUX", TargetFiles: true, Description: "Arch Linux package artifact"}, + {Type: "exact", Pattern: "myapp.DEB", TargetFiles: true, Description: "DEB package artifact"}, + {Type: "exact", Pattern: "myapp.RPM", TargetFiles: true, Description: "RPM package artifact"},
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
v3/pkg/application/webview_window_windows.go(2 hunks)v3/tasks/cleanup/cleanup.go(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- v3/pkg/application/webview_window_windows.go
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
- GitHub Check: Run Go Tests v3 (macos-latest, 1.24)
- GitHub Check: Run Go Tests v3 (windows-latest, 1.24)
- GitHub Check: Run Go Tests v3 (ubuntu-latest, 1.24)
- GitHub Check: semgrep/ci
- GitHub Check: Analyze (javascript-typescript)
- GitHub Check: Analyze (go)
- GitHub Check: semgrep-cloud-platform/scan
- GitHub Check: Cloudflare Pages
🔇 Additional comments (6)
v3/tasks/cleanup/cleanup.go (6)
22-22: No-op formatting change.
25-25: No-op formatting change.
31-31: No-op formatting change.
34-34: No-op formatting change.
97-97: No-op change (closing brace).
28-30: Ensure cleanup patterns match actual package filenames
The current exact-match rules in v3/tasks/cleanup/cleanup.go assume uppercase extensions and no version/arch metadata. Most builders emit lowercase “.deb”/“.rpm” files (often with version and arch in the name), so these patterns may never match:• File: v3/tasks/cleanup/cleanup.go (lines 28–30)
• Current rules:{Type: "exact", Pattern: "myapp.ARCHLINUX", TargetFiles: true, Description: "Linux ARCHLINUX package"}, {Type: "exact", Pattern: "myapp.DEB", TargetFiles: true, Description: "Linux DEB package"}, {Type: "exact", Pattern: "myapp.RPM", TargetFiles: true, Description: "Linux RPM package"},Please verify the filenames your packaging tests actually generate. If they use lowercase extensions and include version/arch, switch to suffix matches, for example:
-{Type: "exact", Pattern: "myapp.DEB", TargetFiles: true, Description: "Linux DEB package"}, -{Type: "exact", Pattern: "myapp.RPM", TargetFiles: true, Description: "Linux RPM package"}, +{Type: "suffix", Pattern: ".deb", TargetFiles: true, Description: "Linux DEB package"}, +{Type: "suffix", Pattern: ".rpm", TargetFiles: true, Description: "Linux RPM package"},And adjust the ARCHLINUX rule similarly (e.g., “.pkg.tar.zst”). If your tests really do produce uppercase artifacts named “myapp.DEB”/“myapp.RPM”, you can leave the exact match in place.
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
|
* feat: Add Content Protection for Windows and macOS - Prevents window contents from being captured by screen recording/sharing software - Windows: Uses WDA_EXCLUDEFROMCAPTURE on Windows 10 2004+, falls back to WDA_MONITOR - macOS: Uses NSWindowSharingType to set window as read-only for screen sharing - Added ContentProtectionEnabled option to WebviewWindowOptions - Added SetContentProtection() method for runtime control - Added comprehensive documentation and example usage * fix changelog.mdx * Misc fixes * Misc fixes * Update v3/pkg/w32/user32.go Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Remove debug line --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>


Summary
Adds content protection capability to prevent window contents from being captured by screen recording/sharing software.
Usage
Platform Support
WDA_EXCLUDEFROMCAPTURE(Windows 10 2004+), falls back toWDA_MONITORNSWindowSharingTypefor screen sharing protectionBased on original v2 work by @Taiterbase in #4241
Summary by CodeRabbit