Browse Source

fix: load window-setup in sandboxed renderer (#21696)

Milan Burda 5 years ago
parent
commit
cbf499b18a

+ 1 - 0
filenames.auto.gni

@@ -166,6 +166,7 @@ auto_filenames = {
     "lib/renderer/web-view/web-view-element.ts",
     "lib/renderer/web-view/web-view-impl.ts",
     "lib/renderer/web-view/web-view-init.ts",
+    "lib/renderer/window-setup.ts",
     "lib/sandboxed_renderer/api/exports/electron.js",
     "lib/sandboxed_renderer/api/module-list.js",
     "lib/sandboxed_renderer/init.js",

+ 4 - 2
lib/browser/guest-window-manager.js

@@ -75,8 +75,10 @@ const mergeBrowserWindowOptions = function (embedder, options) {
     }
   }
 
-  // Sets correct openerId here to give correct options to 'new-window' event handler
-  options.webPreferences.openerId = embedder.id
+  if (!webPreferences.nativeWindowOpen) {
+    // Sets correct openerId here to give correct options to 'new-window' event handler
+    options.webPreferences.openerId = embedder.id
+  }
 
   return options
 }

+ 3 - 0
lib/browser/rpc-server.js

@@ -529,12 +529,15 @@ ipcMainUtils.handle('ELECTRON_GET_CONTENT_SCRIPTS', () => getContentScripts())
 
 ipcMainUtils.handle('ELECTRON_BROWSER_SANDBOX_LOAD', async function (event) {
   const preloadPaths = event.sender._getPreloadPaths()
+  const webPreferences = event.sender.getLastWebPreferences() || {}
 
   return {
     contentScripts: getContentScripts(),
     preloadScripts: await Promise.all(preloadPaths.map(path => getPreloadScript(path))),
     isRemoteModuleEnabled: isRemoteModuleEnabled(event.sender),
     isWebViewTagEnabled: guestViewManager.isWebViewTagEnabled(event.sender),
+    guestInstanceId: webPreferences.guestInstanceId,
+    openerId: webPreferences.openerId,
     process: {
       arch: process.arch,
       platform: process.platform,

+ 39 - 35
lib/renderer/window-setup.ts

@@ -177,7 +177,7 @@ class BrowserWindowProxy {
 export const windowSetup = (
   guestInstanceId: number, openerId: number, isHiddenPage: boolean, usesNativeWindowOpen: boolean
 ) => {
-  if (guestInstanceId == null) {
+  if (!process.sandboxed && guestInstanceId == null) {
     // Override default window.close.
     window.close = function () {
       ipcRendererInternal.sendSync('ELECTRON_BROWSER_WINDOW_CLOSE')
@@ -197,10 +197,10 @@ export const windowSetup = (
         return null
       }
     }
+  }
 
-    if (openerId != null) {
-      window.opener = getOrCreateProxy(openerId)
-    }
+  if (openerId != null) {
+    window.opener = getOrCreateProxy(openerId)
   }
 
   // But we do not support prompt().
@@ -208,42 +208,46 @@ export const windowSetup = (
     throw new Error('prompt() is and will not be supported.')
   }
 
-  ipcRendererInternal.on('ELECTRON_GUEST_WINDOW_POSTMESSAGE', function (
-    _event, sourceId: number, message: any, sourceOrigin: string
-  ) {
-    // Manually dispatch event instead of using postMessage because we also need to
-    // set event.source.
-    //
-    // Why any? We can't construct a MessageEvent and we can't
-    // use `as MessageEvent` because you're not supposed to override
-    // data, origin, and source
-    const event: any = document.createEvent('Event')
-    event.initEvent('message', false, false)
-
-    event.data = message
-    event.origin = sourceOrigin
-    event.source = getOrCreateProxy(sourceId)
-
-    window.dispatchEvent(event as MessageEvent)
-  })
-
-  window.history.back = function () {
-    ipcRendererInternal.send('ELECTRON_NAVIGATION_CONTROLLER_GO_BACK')
+  if (!usesNativeWindowOpen || openerId != null) {
+    ipcRendererInternal.on('ELECTRON_GUEST_WINDOW_POSTMESSAGE', function (
+      _event, sourceId: number, message: any, sourceOrigin: string
+    ) {
+      // Manually dispatch event instead of using postMessage because we also need to
+      // set event.source.
+      //
+      // Why any? We can't construct a MessageEvent and we can't
+      // use `as MessageEvent` because you're not supposed to override
+      // data, origin, and source
+      const event: any = document.createEvent('Event')
+      event.initEvent('message', false, false)
+
+      event.data = message
+      event.origin = sourceOrigin
+      event.source = getOrCreateProxy(sourceId)
+
+      window.dispatchEvent(event as MessageEvent)
+    })
   }
 
-  window.history.forward = function () {
-    ipcRendererInternal.send('ELECTRON_NAVIGATION_CONTROLLER_GO_FORWARD')
-  }
+  if (!process.sandboxed) {
+    window.history.back = function () {
+      ipcRendererInternal.send('ELECTRON_NAVIGATION_CONTROLLER_GO_BACK')
+    }
 
-  window.history.go = function (offset: number) {
-    ipcRendererInternal.send('ELECTRON_NAVIGATION_CONTROLLER_GO_TO_OFFSET', +offset)
-  }
+    window.history.forward = function () {
+      ipcRendererInternal.send('ELECTRON_NAVIGATION_CONTROLLER_GO_FORWARD')
+    }
 
-  Object.defineProperty(window.history, 'length', {
-    get: function () {
-      return ipcRendererInternal.sendSync('ELECTRON_NAVIGATION_CONTROLLER_LENGTH')
+    window.history.go = function (offset: number) {
+      ipcRendererInternal.send('ELECTRON_NAVIGATION_CONTROLLER_GO_TO_OFFSET', +offset)
     }
-  })
+
+    Object.defineProperty(window.history, 'length', {
+      get: function () {
+        return ipcRendererInternal.sendSync('ELECTRON_NAVIGATION_CONTROLLER_LENGTH')
+      }
+    })
+  }
 
   if (guestInstanceId != null) {
     // Webview `document.visibilityState` tracks window visibility (and ignores

+ 21 - 3
lib/sandboxed_renderer/init.js

@@ -30,7 +30,13 @@ const { ipcRendererInternal } = require('@electron/internal/renderer/ipc-rendere
 const ipcRendererUtils = require('@electron/internal/renderer/ipc-renderer-internal-utils')
 
 const {
-  contentScripts, preloadScripts, isRemoteModuleEnabled, isWebViewTagEnabled, process: processProps
+  contentScripts,
+  preloadScripts,
+  isRemoteModuleEnabled,
+  isWebViewTagEnabled,
+  guestInstanceId,
+  openerId,
+  process: processProps
 } = ipcRendererUtils.invokeSync('ELECTRON_BROWSER_SANDBOX_LOAD')
 
 process.isRemoteModuleEnabled = isRemoteModuleEnabled
@@ -109,6 +115,11 @@ function preloadRequire (module) {
 const { hasSwitch } = process.electronBinding('command_line')
 
 const contextIsolation = hasSwitch('context-isolation')
+const isHiddenPage = hasSwitch('hidden-page')
+const usesNativeWindowOpen = true
+
+// The arguments to be passed to isolated world.
+const isolatedWorldArgs = { ipcRendererInternal, guestInstanceId, isHiddenPage, openerId, usesNativeWindowOpen }
 
 switch (window.location.protocol) {
   case 'devtools:': {
@@ -125,19 +136,26 @@ switch (window.location.protocol) {
     break
   }
   default: {
+    // Override default web functions.
+    const { windowSetup } = require('@electron/internal/renderer/window-setup')
+    windowSetup(guestInstanceId, openerId, isHiddenPage, usesNativeWindowOpen)
+
     // Inject content scripts.
     require('@electron/internal/renderer/content-scripts-injector')(contentScripts)
   }
 }
 
-const guestInstanceId = binding.guestInstanceId && parseInt(binding.guestInstanceId)
-
 // Load webview tag implementation.
 if (process.isMainFrame) {
   const { webViewInit } = require('@electron/internal/renderer/web-view/web-view-init')
   webViewInit(contextIsolation, isWebViewTagEnabled, guestInstanceId)
 }
 
+// Pass the arguments to isolatedWorld.
+if (contextIsolation) {
+  v8Util.setHiddenValue(global, 'isolated-world-args', isolatedWorldArgs)
+}
+
 const errorUtils = require('@electron/internal/common/error-utils')
 
 // Wrap the script into a function executed in global scope. It won't have

+ 0 - 6
shell/renderer/atom_sandboxed_renderer_client.cc

@@ -144,12 +144,6 @@ void AtomSandboxedRendererClient::InitializeBindings(
   process.SetReadOnly("sandboxed", true);
   process.SetReadOnly("type", "renderer");
   process.SetReadOnly("isMainFrame", is_main_frame);
-
-  // Pass in CLI flags needed to setup the renderer
-  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
-  if (command_line->HasSwitch(switches::kGuestInstanceID))
-    b.Set(options::kGuestInstanceID,
-          command_line->GetSwitchValueASCII(switches::kGuestInstanceID));
 }
 
 void AtomSandboxedRendererClient::RenderFrameCreated(