Browse Source

fix: set nativeWindowOpen when sandboxed (#18273)

Milan Burda 5 years ago
parent
commit
ac002b3c3c

+ 0 - 5
atom/browser/atom_browser_client.cc

@@ -609,11 +609,6 @@ bool AtomBrowserClient::CanCreateWindow(
 
   int opener_render_process_id = opener->GetProcess()->GetID();
 
-  if (IsRendererSandboxed(opener_render_process_id)) {
-    *no_javascript_access = false;
-    return true;
-  }
-
   if (RendererUsesNativeWindowOpen(opener_render_process_id)) {
     if (RendererDisablesPopups(opener_render_process_id)) {
       // <webview> without allowpopups attribute should return

+ 14 - 0
atom/browser/web_contents_preferences.cc

@@ -147,6 +147,8 @@ WebContentsPreferences::WebContentsPreferences(
 #endif
   SetDefaultBoolIfUndefined(options::kOffscreen, false);
 
+  SetDefaults();
+
   // If this is a <webview> tag, and the embedder is offscreen-rendered, then
   // this WebContents is also offscreen-rendered.
   int guest_instance_id = 0;
@@ -172,6 +174,12 @@ WebContentsPreferences::~WebContentsPreferences() {
                    instances_.end());
 }
 
+void WebContentsPreferences::SetDefaults() {
+  if (IsEnabled(options::kSandbox)) {
+    SetBool(options::kNativeWindowOpen, true);
+  }
+}
+
 bool WebContentsPreferences::SetDefaultBoolIfUndefined(
     const base::StringPiece& key,
     bool val) {
@@ -185,6 +193,10 @@ bool WebContentsPreferences::SetDefaultBoolIfUndefined(
   }
 }
 
+void WebContentsPreferences::SetBool(const base::StringPiece& key, bool value) {
+  preference_.SetKey(key, base::Value(value));
+}
+
 bool WebContentsPreferences::IsEnabled(const base::StringPiece& name,
                                        bool default_value) const {
   auto* current_value =
@@ -197,6 +209,8 @@ bool WebContentsPreferences::IsEnabled(const base::StringPiece& name,
 void WebContentsPreferences::Merge(const base::DictionaryValue& extend) {
   if (preference_.is_dict())
     static_cast<base::DictionaryValue*>(&preference_)->MergeDictionary(&extend);
+
+  SetDefaults();
 }
 
 void WebContentsPreferences::Clear() {

+ 6 - 0
atom/browser/web_contents_preferences.h

@@ -36,6 +36,9 @@ class WebContentsPreferences
                          const mate::Dictionary& web_preferences);
   ~WebContentsPreferences() override;
 
+  // Set WebPreferences defaults onto the JS object.
+  void SetDefaults();
+
   // A simple way to know whether a Boolean property is enabled.
   bool IsEnabled(const base::StringPiece& name,
                  bool default_value = false) const;
@@ -75,6 +78,9 @@ class WebContentsPreferences
   // Set preference value to given bool if user did not provide value
   bool SetDefaultBoolIfUndefined(const base::StringPiece& key, bool val);
 
+  // Set preference value to given bool
+  void SetBool(const base::StringPiece& key, bool value);
+
   static std::vector<WebContentsPreferences*> instances_;
 
   content::WebContents* web_contents_;

+ 1 - 6
lib/browser/guest-view-manager.js

@@ -112,7 +112,6 @@ const createGuest = function (embedder, params) {
       }
       this.loadURL(params.src, opts)
     }
-    guest.allowPopups = params.allowpopups
     embedder.emit('did-attach-webview', event, guest)
   })
 
@@ -207,6 +206,7 @@ const attachGuest = function (event, embedderFrameId, elementInstanceId, guestIn
     enableRemoteModule: params.enableremotemodule,
     plugins: params.plugins,
     zoomFactor: embedder.getZoomFactor(),
+    disablePopups: !params.allowpopups,
     webSecurity: !params.disablewebsecurity,
     enableBlinkFeatures: params.blinkfeatures,
     disableBlinkFeatures: params.disableblinkfeatures
@@ -228,11 +228,6 @@ const attachGuest = function (event, embedderFrameId, elementInstanceId, guestIn
     webPreferences.preloadURL = params.preload
   }
 
-  // Return null from native window.open if allowpopups is unset
-  if (webPreferences.nativeWindowOpen === true && !params.allowpopups) {
-    webPreferences.disablePopups = true
-  }
-
   // Security options that guest will always inherit from embedder
   const inheritedWebPreferences = new Map([
     ['contextIsolation', true],

+ 1 - 1
lib/browser/guest-window-manager.js

@@ -244,7 +244,7 @@ ipcMainInternal.on('ELECTRON_GUEST_WINDOW_MANAGER_INTERNAL_WINDOW_OPEN', functio
   options = mergeBrowserWindowOptions(event.sender, options)
   event.sender.emit('new-window', event, url, frameName, disposition, options, additionalFeatures, referrer)
   const { newGuest } = event
-  if ((event.sender.getType() === 'webview' && !event.sender.allowPopups) || event.defaultPrevented) {
+  if ((event.sender.getType() === 'webview' && event.sender.getLastWebPreferences().disablePopups) || event.defaultPrevented) {
     if (newGuest != null) {
       if (options.webContents === newGuest.webContents) {
         // the webContents is not changed, so set defaultPrevented to false to

+ 22 - 12
spec/webview-spec.js

@@ -545,20 +545,30 @@ describe('<webview> tag', function () {
   })
 
   describe('allowpopups attribute', () => {
-    it('can not open new window when not set', async () => {
-      const message = await startLoadingWebViewAndWaitForMessage(webview, {
-        src: `file://${fixtures}/pages/window-open-hide.html`
-      })
-      expect(message).to.equal('null')
-    })
+    const generateSpecs = (description, webpreferences = '') => {
+      describe(description, () => {
+        it('can not open new window when not set', async () => {
+          const message = await startLoadingWebViewAndWaitForMessage(webview, {
+            webpreferences,
+            src: `file://${fixtures}/pages/window-open-hide.html`
+          })
+          expect(message).to.equal('null')
+        })
 
-    it('can open new window when set', async () => {
-      const message = await startLoadingWebViewAndWaitForMessage(webview, {
-        allowpopups: 'on',
-        src: `file://${fixtures}/pages/window-open-hide.html`
+        it('can open new window when set', async () => {
+          const message = await startLoadingWebViewAndWaitForMessage(webview, {
+            webpreferences,
+            allowpopups: 'on',
+            src: `file://${fixtures}/pages/window-open-hide.html`
+          })
+          expect(message).to.equal('window')
+        })
       })
-      expect(message).to.equal('window')
-    })
+    }
+
+    generateSpecs('without sandbox')
+    generateSpecs('with sandbox', 'sandbox=yes')
+    generateSpecs('with nativeWindowOpen', 'nativeWindowOpen=yes')
   })
 
   describe('webpreferences attribute', () => {