Browse Source

fix: add service worker schemes from command line in renderer (#29440)

Co-authored-by: David Sanders <[email protected]>
trop[bot] 3 years ago
parent
commit
0d69ba8ca2

+ 11 - 7
shell/browser/api/electron_api_protocol.cc

@@ -89,6 +89,16 @@ std::vector<std::string> GetStandardSchemes() {
   return g_standard_schemes;
 }
 
+void AddServiceWorkerScheme(const std::string& scheme) {
+  // There is no API to add service worker scheme, but there is an API to
+  // return const reference to the schemes vector.
+  // If in future the API is changed to return a copy instead of reference,
+  // the compilation will fail, and we should add a patch at that time.
+  auto& mutable_schemes =
+      const_cast<std::vector<std::string>&>(content::GetServiceWorkerSchemes());
+  mutable_schemes.push_back(scheme);
+}
+
 void RegisterSchemesAsPrivileged(gin_helper::ErrorThrower thrower,
                                  v8::Local<v8::Value> val) {
   std::vector<CustomScheme> custom_schemes;
@@ -125,13 +135,7 @@ void RegisterSchemesAsPrivileged(gin_helper::ErrorThrower thrower,
     }
     if (custom_scheme.options.allowServiceWorkers) {
       service_worker_schemes.push_back(custom_scheme.scheme);
-      // There is no API to add service worker scheme, but there is an API to
-      // return const reference to the schemes vector.
-      // If in future the API is changed to return a copy instead of reference,
-      // the compilation will fail, and we should add a patch at that time.
-      auto& mutable_schemes = const_cast<std::vector<std::string>&>(
-          content::GetServiceWorkerSchemes());
-      mutable_schemes.push_back(custom_scheme.scheme);
+      AddServiceWorkerScheme(custom_scheme.scheme);
     }
     if (custom_scheme.options.stream) {
       g_streaming_schemes.push_back(custom_scheme.scheme);

+ 2 - 0
shell/browser/api/electron_api_protocol.h

@@ -22,6 +22,8 @@ namespace api {
 
 std::vector<std::string> GetStandardSchemes();
 
+void AddServiceWorkerScheme(const std::string& scheme);
+
 void RegisterSchemesAsPrivileged(gin_helper::ErrorThrower thrower,
                                  v8::Local<v8::Value> val);
 

+ 6 - 0
shell/renderer/renderer_client_base.cc

@@ -22,6 +22,7 @@
 #include "electron/buildflags/buildflags.h"
 #include "media/blink/multibuffer_data_source.h"
 #include "printing/buildflags/buildflags.h"
+#include "shell/browser/api/electron_api_protocol.h"
 #include "shell/common/api/electron_api_native_image.h"
 #include "shell/common/color_util.h"
 #include "shell/common/gin_helper/dictionary.h"
@@ -111,6 +112,11 @@ RendererClientBase* g_renderer_client_base = nullptr;
 
 RendererClientBase::RendererClientBase() {
   auto* command_line = base::CommandLine::ForCurrentProcess();
+  // Parse --service-worker-schemes=scheme1,scheme2
+  std::vector<std::string> service_worker_schemes_list =
+      ParseSchemesCLISwitch(command_line, switches::kServiceWorkerSchemes);
+  for (const std::string& scheme : service_worker_schemes_list)
+    electron::api::AddServiceWorkerScheme(scheme);
   // Parse --standard-schemes=scheme1,scheme2
   std::vector<std::string> standard_schemes_list =
       ParseSchemesCLISwitch(command_line, switches::kStandardSchemes);

+ 37 - 0
spec-main/chromium-spec.ts

@@ -586,6 +586,43 @@ describe('chromium features', () => {
       w.loadFile(path.join(fixturesPath, 'pages', 'service-worker', 'index.html'));
     });
 
+    it('should register for custom scheme', (done) => {
+      const customSession = session.fromPartition('custom-scheme');
+      const { serviceWorkerScheme } = global as any;
+      customSession.protocol.registerFileProtocol(serviceWorkerScheme, (request, callback) => {
+        let file = url.parse(request.url).pathname!;
+        if (file[0] === '/' && process.platform === 'win32') file = file.slice(1);
+
+        callback({ path: path.normalize(file) } as any);
+      });
+
+      const w = new BrowserWindow({
+        show: false,
+        webPreferences: {
+          nodeIntegration: true,
+          session: customSession,
+          contextIsolation: false
+        }
+      });
+      w.webContents.on('ipc-message', (event, channel, message) => {
+        if (channel === 'reload') {
+          w.webContents.reload();
+        } else if (channel === 'error') {
+          done(`unexpected error : ${message}`);
+        } else if (channel === 'response') {
+          expect(message).to.equal('Hello from serviceWorker!');
+          customSession.clearStorageData({
+            storages: ['serviceworkers']
+          }).then(() => {
+            customSession.protocol.uninterceptProtocol(serviceWorkerScheme);
+            done();
+          });
+        }
+      });
+      w.webContents.on('crashed', () => done(new Error('WebContents crashed.')));
+      w.loadFile(path.join(fixturesPath, 'pages', 'service-worker', 'custom-scheme-index.html'));
+    });
+
     it('should not crash when nodeIntegration is enabled', (done) => {
       const w = new BrowserWindow({
         show: false,

+ 21 - 0
spec/fixtures/pages/service-worker/custom-scheme-index.html

@@ -0,0 +1,21 @@
+<script>
+  const ipcRenderer = require('electron').ipcRenderer;
+  navigator.serviceWorker.register('service-worker.js', {scope: './'}).then(() => {
+    if (navigator.serviceWorker.controller) {
+      var xhr = new XMLHttpRequest();
+      xhr.open('GET', 'sw://dummy/echo');
+      xhr.setRequestHeader('X-Mock-Response', 'yes');
+      xhr.addEventListener('error', error => {
+        ipcRenderer.send('error', `${error.message}\n${error.stack}`);
+      })
+      xhr.addEventListener('load', () => {
+        ipcRenderer.send('response', xhr.responseText);
+      });
+      xhr.send();
+    } else {
+      ipcRenderer.send('reload');
+    }
+  }).catch(error => {
+    ipcRenderer.send('error', `${error.message}\n${error.stack}`);
+  })
+</script>