fix: ensure standard schemes are registered in nw service process (#22867)
* fix: ensure standard schemes are registered in nw service process Refs https://github.com/electron/electron/pull/20546 * chore: add test * chore: apply suggestions from code review Co-Authored-By: Jeremy Apthorp <jeremya@chromium.org> Co-authored-by: Jeremy Apthorp <jeremya@chromium.org>
This commit is contained in:
parent
d74ad631e7
commit
bac1c7f532
4 changed files with 66 additions and 8 deletions
|
@ -15,6 +15,7 @@
|
||||||
#include "base/strings/string_util.h"
|
#include "base/strings/string_util.h"
|
||||||
#include "base/strings/utf_string_conversions.h"
|
#include "base/strings/utf_string_conversions.h"
|
||||||
#include "content/public/common/content_constants.h"
|
#include "content/public/common/content_constants.h"
|
||||||
|
#include "content/public/common/content_switches.h"
|
||||||
#include "electron/buildflags/buildflags.h"
|
#include "electron/buildflags/buildflags.h"
|
||||||
#include "extensions/common/constants.h"
|
#include "extensions/common/constants.h"
|
||||||
#include "ppapi/buildflags/buildflags.h"
|
#include "ppapi/buildflags/buildflags.h"
|
||||||
|
@ -231,14 +232,27 @@ base::RefCountedMemory* ElectronContentClient::GetDataResourceBytes(
|
||||||
}
|
}
|
||||||
|
|
||||||
void ElectronContentClient::AddAdditionalSchemes(Schemes* schemes) {
|
void ElectronContentClient::AddAdditionalSchemes(Schemes* schemes) {
|
||||||
AppendDelimitedSwitchToVector(switches::kServiceWorkerSchemes,
|
auto* command_line = base::CommandLine::ForCurrentProcess();
|
||||||
&schemes->service_worker_schemes);
|
std::string process_type =
|
||||||
AppendDelimitedSwitchToVector(switches::kSecureSchemes,
|
command_line->GetSwitchValueASCII(::switches::kProcessType);
|
||||||
&schemes->secure_schemes);
|
// Browser Process registration happens in
|
||||||
AppendDelimitedSwitchToVector(switches::kBypassCSPSchemes,
|
// `api::Protocol::RegisterSchemesAsPrivileged`
|
||||||
&schemes->csp_bypassing_schemes);
|
//
|
||||||
AppendDelimitedSwitchToVector(switches::kCORSSchemes,
|
// Renderer Process registration happens in `RendererClientBase`
|
||||||
&schemes->cors_enabled_schemes);
|
//
|
||||||
|
// We use this for registration to network utility process
|
||||||
|
if (process_type == ::switches::kUtilityProcess) {
|
||||||
|
AppendDelimitedSwitchToVector(switches::kServiceWorkerSchemes,
|
||||||
|
&schemes->service_worker_schemes);
|
||||||
|
AppendDelimitedSwitchToVector(switches::kStandardSchemes,
|
||||||
|
&schemes->standard_schemes);
|
||||||
|
AppendDelimitedSwitchToVector(switches::kSecureSchemes,
|
||||||
|
&schemes->secure_schemes);
|
||||||
|
AppendDelimitedSwitchToVector(switches::kBypassCSPSchemes,
|
||||||
|
&schemes->csp_bypassing_schemes);
|
||||||
|
AppendDelimitedSwitchToVector(switches::kCORSSchemes,
|
||||||
|
&schemes->cors_enabled_schemes);
|
||||||
|
}
|
||||||
|
|
||||||
schemes->service_worker_schemes.emplace_back(url::kFileScheme);
|
schemes->service_worker_schemes.emplace_back(url::kFileScheme);
|
||||||
schemes->standard_schemes.emplace_back(extensions::kExtensionScheme);
|
schemes->standard_schemes.emplace_back(extensions::kExtensionScheme);
|
||||||
|
|
|
@ -102,6 +102,11 @@ RendererClientBase::RendererClientBase() {
|
||||||
ParseSchemesCLISwitch(command_line, switches::kStandardSchemes);
|
ParseSchemesCLISwitch(command_line, switches::kStandardSchemes);
|
||||||
for (const std::string& scheme : standard_schemes_list)
|
for (const std::string& scheme : standard_schemes_list)
|
||||||
url::AddStandardScheme(scheme.c_str(), url::SCHEME_WITH_HOST);
|
url::AddStandardScheme(scheme.c_str(), url::SCHEME_WITH_HOST);
|
||||||
|
// Parse --cors-schemes=scheme1,scheme2
|
||||||
|
std::vector<std::string> cors_schemes_list =
|
||||||
|
ParseSchemesCLISwitch(command_line, switches::kCORSSchemes);
|
||||||
|
for (const std::string& scheme : cors_schemes_list)
|
||||||
|
url::AddCorsEnabledScheme(scheme.c_str());
|
||||||
isolated_world_ = base::CommandLine::ForCurrentProcess()->HasSwitch(
|
isolated_world_ = base::CommandLine::ForCurrentProcess()->HasSwitch(
|
||||||
switches::kContextIsolation);
|
switches::kContextIsolation);
|
||||||
// We rely on the unique process host id which is notified to the
|
// We rely on the unique process host id which is notified to the
|
||||||
|
|
|
@ -2,6 +2,7 @@ import { expect } from 'chai';
|
||||||
import { protocol, webContents, WebContents, session, BrowserWindow, ipcMain } from 'electron';
|
import { protocol, webContents, WebContents, session, BrowserWindow, ipcMain } from 'electron';
|
||||||
import { promisify } from 'util';
|
import { promisify } from 'util';
|
||||||
import { AddressInfo } from 'net';
|
import { AddressInfo } from 'net';
|
||||||
|
import * as ChildProcess from 'child_process';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import * as http from 'http';
|
import * as http from 'http';
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
|
@ -637,6 +638,26 @@ describe('protocol module', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('protocol.registerSchemeAsPrivileged', () => {
|
||||||
|
it('does not crash on exit', async () => {
|
||||||
|
const appPath = path.join(__dirname, 'fixtures', 'api', 'custom-protocol-shutdown.js');
|
||||||
|
const appProcess = ChildProcess.spawn(process.execPath, ['--enable-logging', appPath]);
|
||||||
|
let stdout = '';
|
||||||
|
let stderr = '';
|
||||||
|
appProcess.stdout.on('data', data => { stdout += data; });
|
||||||
|
appProcess.stderr.on('data', data => { stderr += data; });
|
||||||
|
const [code] = await emittedOnce(appProcess, 'exit');
|
||||||
|
if (code !== 0) {
|
||||||
|
console.log('Exit code : ', code);
|
||||||
|
console.log('stdout : ', stdout);
|
||||||
|
console.log('stderr : ', stderr);
|
||||||
|
}
|
||||||
|
expect(code).to.equal(0);
|
||||||
|
expect(stdout).to.not.contain('VALIDATION_ERROR_DESERIALIZATION_FAILED');
|
||||||
|
expect(stderr).to.not.contain('VALIDATION_ERROR_DESERIALIZATION_FAILED');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
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`;
|
||||||
|
|
18
spec-main/fixtures/api/custom-protocol-shutdown.js
Normal file
18
spec-main/fixtures/api/custom-protocol-shutdown.js
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
const { app, webContents, protocol, session } = require('electron');
|
||||||
|
|
||||||
|
protocol.registerSchemesAsPrivileged([
|
||||||
|
{ scheme: 'test', privileges: { standard: true, secure: true } }
|
||||||
|
]);
|
||||||
|
|
||||||
|
app.whenReady().then(function () {
|
||||||
|
const ses = session.fromPartition('persist:test-standard-shutdown');
|
||||||
|
const web = webContents.create({ session: ses });
|
||||||
|
|
||||||
|
ses.protocol.registerStringProtocol('test', (request, callback) => {
|
||||||
|
callback('Hello World!');
|
||||||
|
});
|
||||||
|
|
||||||
|
web.webContents.loadURL('test://abc/hello.txt');
|
||||||
|
|
||||||
|
web.webContents.on('did-finish-load', () => app.quit());
|
||||||
|
});
|
Loading…
Reference in a new issue