diff --git a/shell/browser/api/electron_api_base_window.cc b/shell/browser/api/electron_api_base_window.cc index 01800aab557e..19ad119aba0e 100644 --- a/shell/browser/api/electron_api_base_window.cc +++ b/shell/browser/api/electron_api_base_window.cc @@ -724,6 +724,10 @@ void BaseWindow::SetContentProtection(bool enable) { return window_->SetContentProtection(enable); } +bool BaseWindow::IsContentProtected() const { + return window_->IsContentProtected(); +} + void BaseWindow::SetFocusable(bool focusable) { return window_->SetFocusable(focusable); } @@ -1261,6 +1265,7 @@ void BaseWindow::BuildPrototype(v8::Isolate* isolate, .SetMethod("isDocumentEdited", &BaseWindow::IsDocumentEdited) .SetMethod("setIgnoreMouseEvents", &BaseWindow::SetIgnoreMouseEvents) .SetMethod("setContentProtection", &BaseWindow::SetContentProtection) + .SetMethod("_isContentProtected", &BaseWindow::IsContentProtected) .SetMethod("setFocusable", &BaseWindow::SetFocusable) .SetMethod("isFocusable", &BaseWindow::IsFocusable) .SetMethod("setMenu", &BaseWindow::SetMenu) diff --git a/shell/browser/api/electron_api_base_window.h b/shell/browser/api/electron_api_base_window.h index 081a9fdd2cfb..72e69ad4b89a 100644 --- a/shell/browser/api/electron_api_base_window.h +++ b/shell/browser/api/electron_api_base_window.h @@ -177,6 +177,7 @@ class BaseWindow : public gin_helper::TrackableObject, bool IsDocumentEdited() const; void SetIgnoreMouseEvents(bool ignore, gin_helper::Arguments* args); void SetContentProtection(bool enable); + bool IsContentProtected() const; void SetFocusable(bool focusable); bool IsFocusable() const; void SetMenu(v8::Isolate* isolate, v8::Local menu); diff --git a/shell/browser/native_window.h b/shell/browser/native_window.h index 6108e0b50e30..f02aa559b444 100644 --- a/shell/browser/native_window.h +++ b/shell/browser/native_window.h @@ -186,6 +186,7 @@ class NativeWindow : public base::SupportsUserData, virtual bool IsDocumentEdited() const; virtual void SetIgnoreMouseEvents(bool ignore, bool forward) = 0; virtual void SetContentProtection(bool enable) = 0; + virtual bool IsContentProtected() const = 0; virtual void SetFocusable(bool focusable) {} virtual bool IsFocusable() const; virtual void SetMenu(ElectronMenuModel* menu) {} diff --git a/shell/browser/native_window_mac.h b/shell/browser/native_window_mac.h index c49cdc963593..590ac6d8bb7c 100644 --- a/shell/browser/native_window_mac.h +++ b/shell/browser/native_window_mac.h @@ -110,6 +110,7 @@ class NativeWindowMac : public NativeWindow, bool IsHiddenInMissionControl() const override; void SetHiddenInMissionControl(bool hidden) override; void SetContentProtection(bool enable) override; + bool IsContentProtected() const override; void SetFocusable(bool focusable) override; bool IsFocusable() const override; void SetParentWindow(NativeWindow* parent) override; diff --git a/shell/browser/native_window_mac.mm b/shell/browser/native_window_mac.mm index 521a692f0ae4..37ff7da6d625 100644 --- a/shell/browser/native_window_mac.mm +++ b/shell/browser/native_window_mac.mm @@ -1170,6 +1170,10 @@ void NativeWindowMac::SetContentProtection(bool enable) { setSharingType:enable ? NSWindowSharingNone : NSWindowSharingReadOnly]; } +bool NativeWindowMac::IsContentProtected() const { + return [window_ sharingType] == NSWindowSharingNone; +} + void NativeWindowMac::SetFocusable(bool focusable) { // No known way to unfocus the window if it had the focus. Here we do not // want to call Focus(false) because it moves the window to the back, i.e. diff --git a/shell/browser/native_window_views.cc b/shell/browser/native_window_views.cc index d7765c930802..16300fa2b6f8 100644 --- a/shell/browser/native_window_views.cc +++ b/shell/browser/native_window_views.cc @@ -1317,17 +1317,15 @@ void NativeWindowViews::SetIgnoreMouseEvents(bool ignore, bool forward) { void NativeWindowViews::SetContentProtection(bool enable) { #if BUILDFLAG(IS_WIN) - HWND hwnd = GetAcceleratedWidget(); - DWORD affinity = enable ? WDA_EXCLUDEFROMCAPTURE : WDA_NONE; - ::SetWindowDisplayAffinity(hwnd, affinity); - if (!layered_) { - // Workaround to prevent black window on screen capture after hiding and - // showing the BrowserWindow. - LONG ex_style = ::GetWindowLong(hwnd, GWL_EXSTYLE); - ex_style |= WS_EX_LAYERED; - ::SetWindowLong(hwnd, GWL_EXSTYLE, ex_style); - layered_ = true; - } + widget()->native_widget_private()->SetAllowScreenshots(!enable); +#endif +} + +bool NativeWindowViews::IsContentProtected() const { +#if BUILDFLAG(IS_WIN) + return !widget()->native_widget_private()->AreScreenshotsAllowed(); +#else // Not implemented on Linux + return false; #endif } diff --git a/shell/browser/native_window_views.h b/shell/browser/native_window_views.h index 6387eb434ec7..30f36d005cf9 100644 --- a/shell/browser/native_window_views.h +++ b/shell/browser/native_window_views.h @@ -116,6 +116,7 @@ class NativeWindowViews : public NativeWindow, double GetOpacity() const override; void SetIgnoreMouseEvents(bool ignore, bool forward) override; void SetContentProtection(bool enable) override; + bool IsContentProtected() const override; void SetFocusable(bool focusable) override; bool IsFocusable() const override; void SetMenu(ElectronMenuModel* menu_model) override; diff --git a/spec/api-browser-window-spec.ts b/spec/api-browser-window-spec.ts index 5258abd4b785..66a2188b502a 100755 --- a/spec/api-browser-window-spec.ts +++ b/spec/api-browser-window-spec.ts @@ -296,6 +296,44 @@ describe('BrowserWindow module', () => { }); }); + ifdescribe(process.platform !== 'linux')('BrowserWindow.getContentProtection', () => { + afterEach(closeAllWindows); + it('can set content protection', async () => { + const w = new BrowserWindow({ show: false }); + // @ts-expect-error This is a private API + expect(w._isContentProtected()).to.equal(false); + + const shown = once(w, 'show'); + + w.show(); + await shown; + + w.setContentProtection(true); + // @ts-expect-error This is a private API + expect(w._isContentProtected()).to.equal(true); + }); + + it('does not remove content protection after the window is hidden and shown', async () => { + const w = new BrowserWindow({ show: false }); + + const hidden = once(w, 'hide'); + const shown = once(w, 'show'); + + w.show(); + await shown; + + w.setContentProtection(true); + + w.hide(); + await hidden; + w.show(); + await shown; + + // @ts-expect-error This is a private API + expect(w._isContentProtected()).to.equal(true); + }); + }); + describe('BrowserWindow.loadURL(url)', () => { let w: BrowserWindow; const scheme = 'other';