fix: make sure service worker scheme is registered with allowServiceWorkers (#28326)
* Fix custom scheme not registered as service worker scheme * ServiceWorker loaders do not have WebContents associated * Add test for service worker * Revert "Fix custom scheme not registered as service worker scheme" This reverts commit a249235b220a0edcfcb906e0b3b3c0486ece73a6. * Add scheme to ServiceWorkerSchemes
This commit is contained in:
parent
7c36463085
commit
1e9e2f8cf6
4 changed files with 54 additions and 9 deletions
|
@ -10,6 +10,7 @@
|
||||||
|
|
||||||
#include "base/command_line.h"
|
#include "base/command_line.h"
|
||||||
#include "base/stl_util.h"
|
#include "base/stl_util.h"
|
||||||
|
#include "content/common/url_schemes.h"
|
||||||
#include "content/public/browser/child_process_security_policy.h"
|
#include "content/public/browser/child_process_security_policy.h"
|
||||||
#include "gin/object_template_builder.h"
|
#include "gin/object_template_builder.h"
|
||||||
#include "shell/browser/browser.h"
|
#include "shell/browser/browser.h"
|
||||||
|
@ -124,6 +125,13 @@ void RegisterSchemesAsPrivileged(gin_helper::ErrorThrower thrower,
|
||||||
}
|
}
|
||||||
if (custom_scheme.options.allowServiceWorkers) {
|
if (custom_scheme.options.allowServiceWorkers) {
|
||||||
service_worker_schemes.push_back(custom_scheme.scheme);
|
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);
|
||||||
}
|
}
|
||||||
if (custom_scheme.options.stream) {
|
if (custom_scheme.options.stream) {
|
||||||
g_streaming_schemes.push_back(custom_scheme.scheme);
|
g_streaming_schemes.push_back(custom_scheme.scheme);
|
||||||
|
|
|
@ -1352,22 +1352,26 @@ void ElectronBrowserClient::RegisterNonNetworkSubresourceURLLoaderFactories(
|
||||||
int render_process_id,
|
int render_process_id,
|
||||||
int render_frame_id,
|
int render_frame_id,
|
||||||
NonNetworkURLLoaderFactoryMap* factories) {
|
NonNetworkURLLoaderFactoryMap* factories) {
|
||||||
content::RenderFrameHost* frame_host =
|
auto* render_process_host =
|
||||||
content::RenderFrameHost::FromID(render_process_id, render_frame_id);
|
content::RenderProcessHost::FromID(render_process_id);
|
||||||
content::WebContents* web_contents =
|
DCHECK(render_process_host);
|
||||||
content::WebContents::FromRenderFrameHost(frame_host);
|
if (!render_process_host || !render_process_host->GetBrowserContext())
|
||||||
|
return;
|
||||||
|
|
||||||
|
ProtocolRegistry::FromBrowserContext(render_process_host->GetBrowserContext())
|
||||||
|
->RegisterURLLoaderFactories(URLLoaderFactoryType::kDocumentSubResource,
|
||||||
|
factories);
|
||||||
|
|
||||||
if (web_contents) {
|
|
||||||
ProtocolRegistry::FromBrowserContext(web_contents->GetBrowserContext())
|
|
||||||
->RegisterURLLoaderFactories(URLLoaderFactoryType::kDocumentSubResource,
|
|
||||||
factories);
|
|
||||||
}
|
|
||||||
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||||
auto factory = extensions::CreateExtensionURLLoaderFactory(render_process_id,
|
auto factory = extensions::CreateExtensionURLLoaderFactory(render_process_id,
|
||||||
render_frame_id);
|
render_frame_id);
|
||||||
if (factory)
|
if (factory)
|
||||||
factories->emplace(extensions::kExtensionScheme, std::move(factory));
|
factories->emplace(extensions::kExtensionScheme, std::move(factory));
|
||||||
|
|
||||||
|
content::RenderFrameHost* frame_host =
|
||||||
|
content::RenderFrameHost::FromID(render_process_id, render_frame_id);
|
||||||
|
content::WebContents* web_contents =
|
||||||
|
content::WebContents::FromRenderFrameHost(frame_host);
|
||||||
if (!web_contents)
|
if (!web_contents)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { expect } from 'chai';
|
import { expect } from 'chai';
|
||||||
|
import { v4 } from 'uuid';
|
||||||
import { protocol, webContents, WebContents, session, BrowserWindow, ipcMain } from 'electron/main';
|
import { protocol, webContents, WebContents, session, BrowserWindow, ipcMain } from 'electron/main';
|
||||||
import { AddressInfo } from 'net';
|
import { AddressInfo } from 'net';
|
||||||
import * as ChildProcess from 'child_process';
|
import * as ChildProcess from 'child_process';
|
||||||
|
@ -724,6 +725,36 @@ describe('protocol module', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('protocol.registerSchemesAsPrivileged allowServiceWorkers', () => {
|
||||||
|
const { serviceWorkerScheme } = global as any;
|
||||||
|
protocol.registerStringProtocol(serviceWorkerScheme, (request, cb) => {
|
||||||
|
if (request.url.endsWith('.js')) {
|
||||||
|
cb({
|
||||||
|
mimeType: 'text/javascript',
|
||||||
|
charset: 'utf-8',
|
||||||
|
data: 'console.log("Loaded")'
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
cb({
|
||||||
|
mimeType: 'text/html',
|
||||||
|
charset: 'utf-8',
|
||||||
|
data: '<!DOCTYPE html>'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
after(() => protocol.unregisterProtocol(serviceWorkerScheme));
|
||||||
|
|
||||||
|
it('should fail when registering invalid service worker', async () => {
|
||||||
|
await contents.loadURL(`${serviceWorkerScheme}://${v4()}.com`);
|
||||||
|
await expect(contents.executeJavaScript(`navigator.serviceWorker.register('${v4()}.notjs', {scope: './'})`)).to.be.rejected();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to register service worker for custom scheme', async () => {
|
||||||
|
await contents.loadURL(`${serviceWorkerScheme}://${v4()}.com`);
|
||||||
|
await contents.executeJavaScript(`navigator.serviceWorker.register('${v4()}.js', {scope: './'})`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe.skip('protocol.registerSchemesAsPrivileged standard', () => {
|
describe.skip('protocol.registerSchemesAsPrivileged standard', () => {
|
||||||
const standardScheme = (global as any).standardScheme;
|
const standardScheme = (global as any).standardScheme;
|
||||||
const origin = `${standardScheme}://fake-host`;
|
const origin = `${standardScheme}://fake-host`;
|
||||||
|
|
|
@ -34,9 +34,11 @@ app.commandLine.appendSwitch('use-fake-device-for-media-stream');
|
||||||
|
|
||||||
global.standardScheme = 'app';
|
global.standardScheme = 'app';
|
||||||
global.zoomScheme = 'zoom';
|
global.zoomScheme = 'zoom';
|
||||||
|
global.serviceWorkerScheme = 'sw';
|
||||||
protocol.registerSchemesAsPrivileged([
|
protocol.registerSchemesAsPrivileged([
|
||||||
{ scheme: global.standardScheme, privileges: { standard: true, secure: true, stream: false } },
|
{ scheme: global.standardScheme, privileges: { standard: true, secure: true, stream: false } },
|
||||||
{ scheme: global.zoomScheme, privileges: { standard: true, secure: true } },
|
{ scheme: global.zoomScheme, privileges: { standard: true, secure: true } },
|
||||||
|
{ scheme: global.serviceWorkerScheme, privileges: { allowServiceWorkers: true, standard: true, secure: true } },
|
||||||
{ scheme: 'cors-blob', privileges: { corsEnabled: true, supportFetchAPI: true } },
|
{ scheme: 'cors-blob', privileges: { corsEnabled: true, supportFetchAPI: true } },
|
||||||
{ scheme: 'cors', privileges: { corsEnabled: true, supportFetchAPI: true } },
|
{ scheme: 'cors', privileges: { corsEnabled: true, supportFetchAPI: true } },
|
||||||
{ scheme: 'no-cors', privileges: { supportFetchAPI: true } },
|
{ scheme: 'no-cors', privileges: { supportFetchAPI: true } },
|
||||||
|
|
Loading…
Reference in a new issue