chore: remove app.allowRendererProcessReuse (#26874)

This commit is contained in:
Samuel Attard 2021-04-21 13:59:11 -07:00 коммит произвёл GitHub
Родитель 4ca518468d
Коммит 79077f6df9
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
16 изменённых файлов: 43 добавлений и 392 удалений

Просмотреть файл

@ -1426,19 +1426,6 @@ This is the user agent that will be used when no user agent is set at the
app has the same user agent. Set to a custom value as early as possible
in your app's initialization to ensure that your overridden value is used.
### `app.allowRendererProcessReuse`
A `Boolean` which when `true` disables the overrides that Electron has in place
to ensure renderer processes are restarted on every navigation. The current
default value for this property is `true`.
The intention is for these overrides to become disabled by default and then at
some point in the future this property will be removed. This property impacts
which native modules you can use in the renderer process. For more information
on the direction Electron is going with renderer process restarts and usage of
native modules in the renderer process please check out this
[Tracking Issue](https://github.com/electron/electron/issues/18397).
### `app.runningUnderRosettaTranslation` _macOS_ _Readonly_
A `Boolean` which when `true` indicates that the app is currently running

Просмотреть файл

@ -284,13 +284,6 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
same `partition`. If there is no `persist:` prefix, the page will use an
in-memory session. By assigning the same `partition`, multiple pages can share
the same session. Default is the default session.
* `affinity` String (optional) - When specified, web pages with the same
`affinity` will run in the same renderer process. Note that due to reusing
the renderer process, certain `webPreferences` options will also be shared
between the web pages even when you specified different values for them,
including but not limited to `preload`, `sandbox` and `nodeIntegration`.
So it is suggested to use exact same `webPreferences` for web pages with
the same `affinity`. _Deprecated_
* `zoomFactor` Number (optional) - The default zoom factor of the page, `3.0` represents
`300%`. Default is `1.0`.
* `javascript` Boolean (optional) - Enables JavaScript support. Default is `true`.

Просмотреть файл

@ -14,6 +14,21 @@ This document uses the following convention to categorize breaking changes:
## Planned Breaking API Changes (14.0)
### Removed: `app.allowRendererProcessReuse`
The `app.allowRendererProcessReuse` property will be removed as part of our plan to
more closely align with Chromium's process model for security, performance and maintainability.
For more detailed information see [#18397](https://github.com/electron/electron/issues/18397).
### Removed: Browser Window Affinity
The `affinity` option when constructing a new `BrowserWindow` will be removed
as part of our plan to more closely align with Chromium's process model for security,
performance and maintainability.
For more detailed information see [#18397](https://github.com/electron/electron/issues/18397).
### API Changed: `window.open()`
The optional parameter `frameName` will no longer set the title of the window. This now follows the specification described by the [native documentation](https://developer.mozilla.org/en-US/docs/Web/API/Window/open#parameters) under the corresponding parameter `windowName`.
@ -371,14 +386,6 @@ Setting `{ compress: false }` in `crashReporter.start` is deprecated. Nearly
all crash ingestion servers support gzip compression. This option will be
removed in a future version of Electron.
### Removed: Browser Window Affinity
The `affinity` option when constructing a new `BrowserWindow` will be removed
as part of our plan to more closely align with Chromium's process model for security,
performance and maintainability.
For more detailed information see [#18397](https://github.com/electron/electron/issues/18397).
### Default Changed: `enableRemoteModule` defaults to `false`
In Electron 9, using the remote module without explicitly enabling it via the

Просмотреть файл

@ -1,7 +1,7 @@
import * as fs from 'fs';
import * as path from 'path';
import { deprecate, Menu } from 'electron/main';
import { Menu } from 'electron/main';
const bindings = process._linkedBinding('electron_browser_app');
const commandLine = process._linkedBinding('electron_common_command_line');
@ -129,7 +129,3 @@ for (const name of events) {
webContents.emit(name, event, ...args);
});
}
// Deprecate allowRendererProcessReuse but only if they set it to false, no need to log if
// they are setting it to true
deprecate.removeProperty({ __proto__: app } as any, 'allowRendererProcessReuse', [false]);

Просмотреть файл

@ -1457,13 +1457,6 @@ std::string App::GetUserAgentFallback() {
return ElectronBrowserClient::Get()->GetUserAgent();
}
void App::SetBrowserClientCanUseCustomSiteInstance(bool should_disable) {
ElectronBrowserClient::Get()->SetCanUseCustomSiteInstance(should_disable);
}
bool App::CanBrowserClientUseCustomSiteInstance() {
return ElectronBrowserClient::Get()->CanUseCustomSiteInstance();
}
#if defined(OS_MAC)
bool App::MoveToApplicationsFolder(gin_helper::ErrorThrower thrower,
gin::Arguments* args) {
@ -1665,10 +1658,7 @@ gin::ObjectTemplateBuilder App::GetObjectTemplateBuilder(v8::Isolate* isolate) {
#endif
.SetProperty("userAgentFallback", &App::GetUserAgentFallback,
&App::SetUserAgentFallback)
.SetMethod("enableSandbox", &App::EnableSandbox)
.SetProperty("allowRendererProcessReuse",
&App::CanBrowserClientUseCustomSiteInstance,
&App::SetBrowserClientCanUseCustomSiteInstance);
.SetMethod("enableSandbox", &App::EnableSandbox);
}
const char* App::GetTypeName() {

Просмотреть файл

@ -213,8 +213,6 @@ class App : public ElectronBrowserClient::Delegate,
void EnableSandbox(gin_helper::ErrorThrower thrower);
void SetUserAgentFallback(const std::string& user_agent);
std::string GetUserAgentFallback();
void SetBrowserClientCanUseCustomSiteInstance(bool should_disable);
bool CanBrowserClientUseCustomSiteInstance();
#if defined(OS_MAC)
void SetActivationPolicy(gin_helper::ErrorThrower thrower,

Просмотреть файл

@ -2008,23 +2008,14 @@ void WebContents::Stop() {
}
void WebContents::GoBack() {
if (!ElectronBrowserClient::Get()->CanUseCustomSiteInstance()) {
electron::ElectronBrowserClient::SuppressRendererProcessRestartForOnce();
}
web_contents()->GetController().GoBack();
}
void WebContents::GoForward() {
if (!ElectronBrowserClient::Get()->CanUseCustomSiteInstance()) {
electron::ElectronBrowserClient::SuppressRendererProcessRestartForOnce();
}
web_contents()->GetController().GoForward();
}
void WebContents::GoToOffset(int offset) {
if (!ElectronBrowserClient::Get()->CanUseCustomSiteInstance()) {
electron::ElectronBrowserClient::SuppressRendererProcessRestartForOnce();
}
web_contents()->GetController().GoToOffset(offset);
}

Просмотреть файл

@ -353,10 +353,6 @@ int GetCrashSignalFD(const base::CommandLine& command_line) {
} // namespace
// static
void ElectronBrowserClient::SuppressRendererProcessRestartForOnce() {
g_suppress_renderer_process_restart = true;
}
ElectronBrowserClient* ElectronBrowserClient::Get() {
return g_browser_client;
}
@ -488,46 +484,13 @@ bool ElectronBrowserClient::RendererDisablesPopups(int process_id) const {
return it != process_preferences_.end() && it->second.disable_popups;
}
std::string ElectronBrowserClient::GetAffinityPreference(
content::RenderFrameHost* rfh) const {
auto* web_contents = content::WebContents::FromRenderFrameHost(rfh);
auto* web_preferences = WebContentsPreferences::From(web_contents);
std::string affinity;
if (web_preferences &&
web_preferences->GetPreference("affinity", &affinity) &&
!affinity.empty()) {
affinity = base::ToLowerASCII(affinity);
}
return affinity;
}
content::SiteInstance* ElectronBrowserClient::GetSiteInstanceFromAffinity(
content::BrowserContext* browser_context,
const GURL& url,
content::RenderFrameHost* rfh) const {
std::string affinity = GetAffinityPreference(rfh);
if (!affinity.empty()) {
auto iter = site_per_affinities_.find(affinity);
GURL dest_site = GetSiteForURL(browser_context, url).site_url();
if (iter != site_per_affinities_.end() &&
IsSameWebSite(browser_context, iter->second, dest_site)) {
return iter->second;
}
}
return nullptr;
}
void ElectronBrowserClient::ConsiderSiteInstanceForAffinity(
content::RenderFrameHost* rfh,
content::SiteInstance* site_instance) {
std::string affinity = GetAffinityPreference(rfh);
if (!affinity.empty()) {
site_per_affinities_[affinity] = site_instance;
}
}
bool ElectronBrowserClient::IsRendererSubFrame(int process_id) const {
return base::Contains(renderer_is_subframe_, process_id);
}
@ -612,8 +575,7 @@ void ElectronBrowserClient::OverrideWebkitPrefs(
SessionPreferences::GetValidPreloads(web_contents->GetBrowserContext());
if (!preloads.empty())
prefs->preloads = preloads;
if (CanUseCustomSiteInstance())
prefs->disable_electron_site_instance_overrides = true;
prefs->disable_electron_site_instance_overrides = true;
SetFontDefaults(prefs);
@ -624,14 +586,6 @@ void ElectronBrowserClient::OverrideWebkitPrefs(
}
}
void ElectronBrowserClient::SetCanUseCustomSiteInstance(bool should_disable) {
disable_process_restart_tricks_ = should_disable;
}
bool ElectronBrowserClient::CanUseCustomSiteInstance() {
return disable_process_restart_tricks_;
}
content::ContentBrowserClient::SiteInstanceForNavigationType
ElectronBrowserClient::ShouldOverrideSiteInstanceForNavigation(
content::RenderFrameHost* current_rfh,
@ -686,9 +640,6 @@ ElectronBrowserClient::ShouldOverrideSiteInstanceForNavigation(
void ElectronBrowserClient::RegisterPendingSiteInstance(
content::RenderFrameHost* rfh,
content::SiteInstance* pending_site_instance) {
// Do we have an affinity site to manage?
ConsiderSiteInstanceForAffinity(rfh, pending_site_instance);
// Remember the original web contents for the pending renderer process.
auto* web_contents = content::WebContents::FromRenderFrameHost(rfh);
auto* pending_process = pending_site_instance->GetProcess();
@ -1015,16 +966,6 @@ bool ElectronBrowserClient::ArePersistentMediaDeviceIDsAllowed(
void ElectronBrowserClient::SiteInstanceDeleting(
content::SiteInstance* site_instance) {
// We are storing weak_ptr, is it fundamental to maintain the map up-to-date
// when an instance is destroyed.
for (auto iter = site_per_affinities_.begin();
iter != site_per_affinities_.end(); ++iter) {
if (iter->second == site_instance) {
site_per_affinities_.erase(iter);
break;
}
}
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
// Don't do anything if we're shutting down.
if (content::BrowserMainRunner::ExitedMainMessageLoop())
@ -1794,6 +1735,10 @@ ElectronBrowserClient::GetPluginMimeTypesWithExternalHandlers(
return mime_types;
}
bool ElectronBrowserClient::CanUseCustomSiteInstance() {
return true;
}
content::SerialDelegate* ElectronBrowserClient::GetSerialDelegate() {
if (!serial_delegate_)
serial_delegate_ = std::make_unique<ElectronSerialDelegate>();

Просмотреть файл

@ -51,9 +51,6 @@ class ElectronBrowserClient : public content::ContentBrowserClient,
// Returns the WebContents for pending render processes.
content::WebContents* GetWebContentsFromProcessID(int process_id);
// Don't force renderer process to restart for once.
static void SuppressRendererProcessRestartForOnce();
NotificationPresenter* GetNotificationPresenter();
void WebNotificationAllowed(int render_process_id,
@ -87,9 +84,8 @@ class ElectronBrowserClient : public content::ContentBrowserClient,
std::string GetUserAgent() override;
void SetUserAgent(const std::string& user_agent);
void SetCanUseCustomSiteInstance(bool should_disable);
bool CanUseCustomSiteInstance() override;
content::SerialDelegate* GetSerialDelegate() override;
bool CanUseCustomSiteInstance() override;
content::BluetoothDelegate* GetBluetoothDelegate() override;
@ -310,13 +306,10 @@ class ElectronBrowserClient : public content::ContentBrowserClient,
bool IsRendererSandboxed(int process_id) const;
bool RendererUsesNativeWindowOpen(int process_id) const;
bool RendererDisablesPopups(int process_id) const;
std::string GetAffinityPreference(content::RenderFrameHost* rfh) const;
content::SiteInstance* GetSiteInstanceFromAffinity(
content::BrowserContext* browser_context,
const GURL& url,
content::RenderFrameHost* rfh) const;
void ConsiderSiteInstanceForAffinity(content::RenderFrameHost* rfh,
content::SiteInstance* site_instance);
bool IsRendererSubFrame(int process_id) const;
@ -325,9 +318,6 @@ class ElectronBrowserClient : public content::ContentBrowserClient,
std::set<int> renderer_is_subframe_;
// list of site per affinity. weak_ptr to prevent instance locking
std::map<std::string, content::SiteInstance*> site_per_affinities_;
std::unique_ptr<PlatformNotificationService> notification_service_;
std::unique_ptr<NotificationPresenter> notification_presenter_;
@ -337,8 +327,6 @@ class ElectronBrowserClient : public content::ContentBrowserClient,
std::string user_agent_override_ = "";
bool disable_process_restart_tricks_ = true;
// Simple shared ID generator, used by ProxyingURLLoaderFactory and
// ProxyingWebSocket classes.
uint64_t next_id_ = 0;

Просмотреть файл

@ -1661,26 +1661,6 @@ describe('default behavior', () => {
});
});
describe('app.allowRendererProcessReuse', () => {
it('should default to true', () => {
expect(app.allowRendererProcessReuse).to.equal(true);
});
it('should cause renderer processes to get new PIDs when false', async () => {
const output = await runTestApp('site-instance-overrides', 'false');
expect(output[0]).to.be.a('number').that.is.greaterThan(0);
expect(output[1]).to.be.a('number').that.is.greaterThan(0);
expect(output[0]).to.not.equal(output[1]);
});
it('should cause renderer processes to keep the same PID when true', async () => {
const output = await runTestApp('site-instance-overrides', 'true');
expect(output[0]).to.be.a('number').that.is.greaterThan(0);
expect(output[1]).to.be.a('number').that.is.greaterThan(0);
expect(output[0]).to.equal(output[1]);
});
});
describe('login event', () => {
afterEach(closeAllWindows);
let server: http.Server;

Просмотреть файл

@ -1,178 +0,0 @@
import { expect } from 'chai';
import * as path from 'path';
import { ipcMain, BrowserWindow, WebPreferences, app } from 'electron/main';
import { closeWindow } from './window-helpers';
import { emittedOnce } from './events-helpers';
describe('BrowserWindow with affinity module', () => {
const fixtures = path.resolve(__dirname, '..', 'spec', 'fixtures');
const myAffinityName = 'myAffinity';
const myAffinityNameUpper = 'MYAFFINITY';
const anotherAffinityName = 'anotherAffinity';
before(() => {
app.allowRendererProcessReuse = false;
});
after(() => {
app.allowRendererProcessReuse = true;
});
async function createWindowWithWebPrefs (webPrefs: WebPreferences) {
const w = new BrowserWindow({
show: false,
width: 400,
height: 400,
webPreferences: webPrefs || {}
});
await w.loadFile(path.join(fixtures, 'api', 'blank.html'));
return w;
}
function testAffinityProcessIds (name: string, webPreferences: WebPreferences = {}) {
describe(name, () => {
let mAffinityWindow: BrowserWindow;
before(async () => {
mAffinityWindow = await createWindowWithWebPrefs({ affinity: myAffinityName, ...webPreferences });
});
after(async () => {
await closeWindow(mAffinityWindow, { assertNotWindows: false });
mAffinityWindow = null as unknown as BrowserWindow;
});
it('should have a different process id than a default window', async () => {
const w = await createWindowWithWebPrefs({ ...webPreferences });
const affinityID = mAffinityWindow.webContents.getOSProcessId();
const wcID = w.webContents.getOSProcessId();
expect(affinityID).to.not.equal(wcID, 'Should have different OS process IDs');
await closeWindow(w, { assertNotWindows: false });
});
it(`should have a different process id than a window with a different affinity '${anotherAffinityName}'`, async () => {
const w = await createWindowWithWebPrefs({ affinity: anotherAffinityName, ...webPreferences });
const affinityID = mAffinityWindow.webContents.getOSProcessId();
const wcID = w.webContents.getOSProcessId();
expect(affinityID).to.not.equal(wcID, 'Should have different OS process IDs');
await closeWindow(w, { assertNotWindows: false });
});
it(`should have the same OS process id than a window with the same affinity '${myAffinityName}'`, async () => {
const w = await createWindowWithWebPrefs({ affinity: myAffinityName, ...webPreferences });
const affinityID = mAffinityWindow.webContents.getOSProcessId();
const wcID = w.webContents.getOSProcessId();
expect(affinityID).to.equal(wcID, 'Should have the same OS process ID');
await closeWindow(w, { assertNotWindows: false });
});
it(`should have the same OS process id than a window with an equivalent affinity '${myAffinityNameUpper}' (case insensitive)`, async () => {
const w = await createWindowWithWebPrefs({ affinity: myAffinityNameUpper, ...webPreferences });
const affinityID = mAffinityWindow.webContents.getOSProcessId();
const wcID = w.webContents.getOSProcessId();
expect(affinityID).to.equal(wcID, 'Should have the same OS process ID');
await closeWindow(w, { assertNotWindows: false });
});
});
}
testAffinityProcessIds(`BrowserWindow with an affinity '${myAffinityName}'`);
testAffinityProcessIds(`BrowserWindow with an affinity '${myAffinityName}' and sandbox enabled`, { sandbox: true });
testAffinityProcessIds(`BrowserWindow with an affinity '${myAffinityName}' and nativeWindowOpen enabled`, { nativeWindowOpen: true });
describe('BrowserWindow with an affinity : nodeIntegration=false', () => {
const preload = path.join(fixtures, 'module', 'send-later.js');
const affinityWithNodeTrue = 'affinityWithNodeTrue';
const affinityWithNodeFalse = 'affinityWithNodeFalse';
async function testNodeIntegration (present: boolean) {
const [, typeofProcess, typeofBuffer] = await emittedOnce(ipcMain, 'answer');
if (present) {
expect(typeofProcess).to.not.equal('undefined');
expect(typeofBuffer).to.not.equal('undefined');
} else {
expect(typeofProcess).to.equal('undefined');
expect(typeofBuffer).to.equal('undefined');
}
}
it('disables node integration when specified to false', async () => {
const [, w] = await Promise.all([
testNodeIntegration(false),
createWindowWithWebPrefs({
affinity: affinityWithNodeTrue,
preload,
nodeIntegration: false,
contextIsolation: false
})
]);
await closeWindow(w, { assertNotWindows: false });
});
it('allows nodeIntegration to enable in second window with the same affinity', async () => {
const [, w1] = await Promise.all([
testNodeIntegration(false),
createWindowWithWebPrefs({
affinity: affinityWithNodeTrue,
preload,
nodeIntegration: false,
contextIsolation: false
})
]);
const [, w2] = await Promise.all([
testNodeIntegration(true),
createWindowWithWebPrefs({
affinity: affinityWithNodeTrue,
preload,
nodeIntegration: true,
contextIsolation: false
})
]);
await Promise.all([
closeWindow(w1, { assertNotWindows: false }),
closeWindow(w2, { assertNotWindows: false })
]);
});
it('enables node integration when specified to true', async () => {
const [, w] = await Promise.all([
testNodeIntegration(true),
createWindowWithWebPrefs({
affinity: affinityWithNodeFalse,
preload,
nodeIntegration: true,
contextIsolation: false
})
]);
await closeWindow(w, { assertNotWindows: false });
});
it('allows nodeIntegration to disable in second window with the same affinity', async () => {
const [, w1] = await Promise.all([
testNodeIntegration(true),
createWindowWithWebPrefs({
affinity: affinityWithNodeFalse,
preload,
nodeIntegration: true,
contextIsolation: false
})
]);
const [, w2] = await Promise.all([
testNodeIntegration(false),
createWindowWithWebPrefs({
affinity: affinityWithNodeFalse,
preload,
nodeIntegration: false,
contextIsolation: false
})
]);
await Promise.all([
closeWindow(w1, { assertNotWindows: false }),
closeWindow(w2, { assertNotWindows: false })
]);
});
});
});

Просмотреть файл

@ -4411,29 +4411,27 @@ describe('BrowserWindow module', () => {
});
});
describe('reloading with allowRendererProcessReuse enabled', () => {
it('does not cause Node.js module API hangs after reload', (done) => {
const w = new BrowserWindow({
show: false,
webPreferences: {
nodeIntegration: true,
contextIsolation: false
}
});
let count = 0;
ipcMain.on('async-node-api-done', () => {
if (count === 3) {
ipcMain.removeAllListeners('async-node-api-done');
done();
} else {
count++;
w.reload();
}
});
w.loadFile(path.join(fixtures, 'pages', 'send-after-node.html'));
it('reloading does not cause Node.js module API hangs after reload', (done) => {
const w = new BrowserWindow({
show: false,
webPreferences: {
nodeIntegration: true,
contextIsolation: false
}
});
let count = 0;
ipcMain.on('async-node-api-done', () => {
if (count === 3) {
ipcMain.removeAllListeners('async-node-api-done');
done();
} else {
count++;
w.reload();
}
});
w.loadFile(path.join(fixtures, 'pages', 'send-after-node.html'));
});
describe('window.webContents.focus()', () => {

Просмотреть файл

@ -1 +0,0 @@
<html></html>

Просмотреть файл

@ -1,36 +0,0 @@
const { app, BrowserWindow, ipcMain } = require('electron');
const path = require('path');
process.noDeprecation = true;
process.on('uncaughtException', (e) => {
console.error(e);
process.exit(1);
});
app.allowRendererProcessReuse = JSON.parse(process.argv[2]);
const pids = [];
let win;
ipcMain.on('pid', (event, pid) => {
pids.push(pid);
if (pids.length === 2) {
console.log(JSON.stringify(pids));
if (win) win.close();
app.quit();
} else {
if (win) win.reload();
}
});
app.whenReady().then(() => {
win = new BrowserWindow({
show: false,
webPreferences: {
preload: path.resolve(__dirname, 'preload.js'),
contextIsolation: true
}
});
win.loadFile('index.html');
});

Просмотреть файл

@ -1,4 +0,0 @@
{
"name": "electron-test-site-instance-overrides",
"main": "main.js"
}

Просмотреть файл

@ -1,3 +0,0 @@
const { ipcRenderer } = require('electron');
ipcRenderer.send('pid', process.pid);