Browse Source

fix(extensions): bypass cors in requests made from background pages (#24915)

Eryk Rakowski 4 years ago
parent
commit
ea118c3984

+ 9 - 4
shell/browser/electron_browser_client.cc

@@ -47,10 +47,6 @@
 #include "content/public/common/web_preferences.h"
 #include "electron/buildflags/buildflags.h"
 #include "electron/grit/electron_resources.h"
-#include "extensions/browser/extension_navigation_ui_data.h"
-#include "extensions/browser/extension_protocols.h"
-#include "extensions/common/constants.h"
-#include "extensions/common/switches.h"
 #include "net/base/escape.h"
 #include "net/ssl/ssl_cert_request_info.h"
 #include "ppapi/buildflags/buildflags.h"
@@ -142,9 +138,12 @@
 #include "content/public/browser/file_url_loader.h"
 #include "content/public/browser/web_ui_url_loader_factory.h"
 #include "extensions/browser/api/mime_handler_private/mime_handler_private.h"
+#include "extensions/browser/browser_context_keyed_api_factory.h"
 #include "extensions/browser/extension_host.h"
 #include "extensions/browser/extension_message_filter.h"
 #include "extensions/browser/extension_navigation_throttle.h"
+#include "extensions/browser/extension_navigation_ui_data.h"
+#include "extensions/browser/extension_protocols.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/browser/extensions_browser_client.h"
 #include "extensions/browser/guest_view/extensions_guest_view_message_filter.h"
@@ -152,8 +151,11 @@
 #include "extensions/browser/info_map.h"
 #include "extensions/browser/process_manager.h"
 #include "extensions/browser/process_map.h"
+#include "extensions/browser/url_loader_factory_manager.h"
 #include "extensions/common/api/mime_handler.mojom.h"
+#include "extensions/common/constants.h"
 #include "extensions/common/extension.h"
+#include "extensions/common/switches.h"
 #include "shell/browser/extensions/electron_extension_message_filter.h"
 #include "shell/browser/extensions/electron_extension_system.h"
 #include "shell/browser/extensions/electron_extension_web_contents_observer.h"
@@ -1523,6 +1525,9 @@ void ElectronBrowserClient::OverrideURLLoaderFactoryParams(
       factory_params->is_corb_enabled = false;
     }
   }
+
+  extensions::URLLoaderFactoryManager::OverrideURLLoaderFactoryParams(
+      browser_context, origin, is_for_isolated_world, factory_params);
 }
 
 #if defined(OS_WIN)

+ 28 - 10
spec-main/extensions-spec.ts

@@ -15,7 +15,12 @@ ifdescribe(process.electronBinding('features').isExtensionsEnabled())('chrome ex
   let server: http.Server;
   let url: string;
   before(async () => {
-    server = http.createServer((req, res) => res.end());
+    server = http.createServer((req, res) => {
+      if (req.url === '/cors') {
+        res.setHeader('Access-Control-Allow-Origin', 'http://example.com');
+      }
+      res.end();
+    });
     await new Promise(resolve => server.listen(0, '127.0.0.1', () => {
       url = `http://127.0.0.1:${(server.address() as AddressInfo).port}`;
       resolve();
@@ -31,6 +36,19 @@ ifdescribe(process.electronBinding('features').isExtensionsEnabled())('chrome ex
     });
   });
 
+  function fetch (contents: WebContents, url: string) {
+    return contents.executeJavaScript(`fetch(${JSON.stringify(url)})`);
+  }
+
+  it('bypasses CORS in requests made from extensions', async () => {
+    const customSession = session.fromPartition(`persist:${require('uuid').v4()}`);
+    const w = new BrowserWindow({ show: false, webPreferences: { session: customSession, sandbox: true } });
+    const extension = await customSession.loadExtension(path.join(fixtures, 'extensions', 'ui-page'));
+    w.loadURL(`${extension.url}bare-page.html`);
+    await emittedOnce(w.webContents, 'dom-ready');
+    await expect(fetch(w.webContents, `${url}/cors`)).to.not.be.rejectedWith(TypeError);
+  });
+
   it('loads an extension', async () => {
     // NB. we have to use a persist: session (i.e. non-OTR) because the
     // extension registry is redirected to the main session. so installing an
@@ -241,7 +259,7 @@ ifdescribe(process.electronBinding('features').isExtensionsEnabled())('chrome ex
       const { id } = await customSession.loadExtension(path.join(fixtures, 'extensions', 'lazy-background-page'));
       const w = new BrowserWindow({ show: false, webPreferences: { session: customSession } });
       await w.loadURL(`chrome-extension://${id}/page-get-background.html`);
-      const receivedMessage = await w.webContents.executeJavaScript(`window.completionPromise`);
+      const receivedMessage = await w.webContents.executeJavaScript('window.completionPromise');
       expect(receivedMessage).to.deep.equal({ some: 'message' });
     });
 
@@ -250,7 +268,7 @@ ifdescribe(process.electronBinding('features').isExtensionsEnabled())('chrome ex
       const { id } = await customSession.loadExtension(path.join(fixtures, 'extensions', 'lazy-background-page'));
       const w = new BrowserWindow({ show: false, webPreferences: { session: customSession } });
       await w.loadURL(`chrome-extension://${id}/page-get-background.html`);
-      const receivedMessage = await w.webContents.executeJavaScript(`window.completionPromise`);
+      const receivedMessage = await w.webContents.executeJavaScript('window.completionPromise');
       expect(receivedMessage).to.deep.equal({ some: 'message' });
     });
 
@@ -259,7 +277,7 @@ ifdescribe(process.electronBinding('features').isExtensionsEnabled())('chrome ex
       const { id } = await customSession.loadExtension(path.join(fixtures, 'extensions', 'lazy-background-page'));
       const w = new BrowserWindow({ show: false, webPreferences: { session: customSession } });
       await w.loadURL(`chrome-extension://${id}/page-runtime-get-background.html`);
-      const receivedMessage = await w.webContents.executeJavaScript(`window.completionPromise`);
+      const receivedMessage = await w.webContents.executeJavaScript('window.completionPromise');
       expect(receivedMessage).to.deep.equal({ some: 'message' });
     });
   });
@@ -269,7 +287,7 @@ ifdescribe(process.electronBinding('features').isExtensionsEnabled())('chrome ex
     await customSession.loadExtension(path.join(fixtures, 'extensions', 'persistent-background-page'));
     const w = new BrowserWindow({ show: false, webPreferences: { session: customSession } });
     const promise = emittedOnce(app, 'web-contents-created');
-    await w.loadURL(`about:blank`);
+    await w.loadURL('about:blank');
     const [, bgPageContents] = await promise;
     expect(bgPageContents.session).to.not.equal(undefined);
   });
@@ -418,9 +436,9 @@ ifdescribe(process.electronBinding('features').isExtensionsEnabled())('chrome ex
           const contentScript = path.resolve(fixtures, 'extensions/content-script');
 
           // Computed style values
-          const COLOR_RED = `rgb(255, 0, 0)`;
-          const COLOR_BLUE = `rgb(0, 0, 255)`;
-          const COLOR_TRANSPARENT = `rgba(0, 0, 0, 0)`;
+          const COLOR_RED = 'rgb(255, 0, 0)';
+          const COLOR_BLUE = 'rgb(0, 0, 255)';
+          const COLOR_TRANSPARENT = 'rgba(0, 0, 0, 0)';
 
           before(() => {
             BrowserWindow.addExtension(contentScript);
@@ -496,7 +514,7 @@ ifdescribe(process.electronBinding('features').isExtensionsEnabled())('chrome ex
       const { id } = await session.defaultSession.loadExtension(path.join(fixtures, 'extensions', 'ui-page'));
       const w = new BrowserWindow({ show: false });
       await w.loadURL(`chrome-extension://${id}/bare-page.html`);
-      const textContent = await w.webContents.executeJavaScript(`document.body.textContent`);
+      const textContent = await w.webContents.executeJavaScript('document.body.textContent');
       expect(textContent).to.equal('ui page loaded ok\n');
     });
 
@@ -504,7 +522,7 @@ ifdescribe(process.electronBinding('features').isExtensionsEnabled())('chrome ex
       const { id } = await session.defaultSession.loadExtension(path.join(fixtures, 'extensions', 'ui-page'));
       const w = new BrowserWindow({ show: false });
       await w.loadURL(`chrome-extension://${id}/page-script-load.html`);
-      const textContent = await w.webContents.executeJavaScript(`document.body.textContent`);
+      const textContent = await w.webContents.executeJavaScript('document.body.textContent');
       expect(textContent).to.equal('script loaded ok\n');
     });
   });

+ 2 - 1
spec-main/fixtures/extensions/ui-page/manifest.json

@@ -1,5 +1,6 @@
 {
   "name": "ui-page",
   "version": "1.0",
-  "manifest_version": 2
+  "manifest_version": 2,
+  "permissions": ["<all_urls>"]
 }