![electron-roller[bot]](/assets/img/avatar_default.png)
* chore: bump chromium in DEPS to 139.0.7258.6 * chore: bump chromium in DEPS to 139.0.7258.5 * chore: bump chromium in DEPS to 140.0.7270.1 * chore: bump chromium in DEPS to 140.0.7271.1 * chore: bump chromium in DEPS to 140.0.7273.0 * chore: bump chromium in DEPS to 140.0.7273.1 * chore: bump chromium in DEPS to 140.0.7275.1 * chore: bump chromium in DEPS to 140.0.7275.4 * chore: bump chromium in DEPS to 140.0.7277.1 * chore: bump chromium in DEPS to 140.0.7279.1 * chore: bump chromium in DEPS to 140.0.7281.1 * chore: bump chromium in DEPS to 140.0.7283.1 * chore: bump chromium in DEPS to 140.0.7285.1 * chore: bump chromium in DEPS to 140.0.7287.1 * chore: bump chromium in DEPS to 140.0.7289.0 * chore: bump chromium in DEPS to 140.0.7289.1 * chore: bump chromium in DEPS to 140.0.7291.1 * chore: bump chromium in DEPS to 140.0.7293.1 * chore: bump chromium in DEPS to 140.0.7295.1 * chore: bump chromium in DEPS to 140.0.7296.0 * chore: bump chromium to 140.0.7281.0 (main) (#47616) cherry picked from603cafad7e
* chore: bump chromium in DEPS to 140.0.7269.2 * chore: bump chromium in DEPS to 140.0.7270.0 * chore: bump chromium in DEPS to 140.0.7271.0 * chore: bump chromium in DEPS to 140.0.7273.0 * 6516731: [ExclusiveAccessForAndroid] remove unneeded includes & deps | https://chromium-review.googlesource.com/c/chromium/src/+/6516731 * 6694809: dbus: Ensure systemd scope is started before using any portal services | https://chromium-review.googlesource.com/c/chromium/src/+/6694809 * chore: patch chromium * chore: export patches * chore: bump chromium in DEPS to 140.0.7275.0 * 6677511: [pepper] More pepper removal | https://chromium-review.googlesource.com/c/chromium/src/+/6677511 * 6513641: [gin] Rename gin::Wrappable to gin::DeprecatedWrappable | https://chromium-review.googlesource.com/c/chromium/src/+/6513641 * chore: export chromium patches * 6513641: [gin] Rename gin::Wrappable to gin::DeprecatedWrappable | https://chromium-review.googlesource.com/c/chromium/src/+/6513641 * chore: bump chromium in DEPS to 140.0.7277.0 * chore: bump chromium in DEPS to 140.0.7279.0 * chore: bump chromium in DEPS to 140.0.7281.0 * 6677314: Plumb enabled client hints in the network requestion to network layer https://chromium-review.googlesource.com/c/chromium/src/+/6677314 * 6351556: [source-phase-imports] Support Wasm Source Phase Imports https://chromium-review.googlesource.com/c/chromium/src/+/6351556 * 6700077: [renderer] Avoid calls to deprecated GetIsolate methods https://chromium-review.googlesource.com/c/chromium/src/+/6700077 * 6692873: Reland "Reland "FSA: Only normalize the hardcoded rules once during initialization"" https://chromium-review.googlesource.com/c/chromium/src/+/6692873 * 6686234: [gin] Cleanup NamedPropertyInterceptor for Wrappable https://chromium-review.googlesource.com/c/chromium/src/+/6686234 * chore: export patches * 6667723: Remove content_enable_legacy_ipc GN arg. https://chromium-review.googlesource.com/c/chromium/src/+/6667723 * 6646566: ui: Move NativeWindowTracker to its own directory https://chromium-review.googlesource.com/c/chromium/src/+/6646566 * fix: add missing includes * 6580522: [WAR, DNR] Fix unsafe redirect error to web accessible resource https://chromium-review.googlesource.com/c/chromium/src/+/6580522 * 6680477: Implement `completeCode` endpoint and expose to DevTools https://chromium-review.googlesource.com/c/chromium/src/+/6680477 * 6677511: [pepper] More pepper removal https://chromium-review.googlesource.com/c/chromium/src/+/6677511 * 6696689: Rename views::WidgetFocusManager -> NativeViewFocusManager https://chromium-review.googlesource.com/c/chromium/src/+/6696689 * 6702812: Move wtf/text/string_impl*.* to "blink" namespace https://chromium-review.googlesource.com/c/chromium/src/+/6702812 * chore: fix dialog patch * 6702431: [animation-trigger] Parse timeline-trigger-name https://chromium-review.googlesource.com/c/chromium/src/+/6702431 * chore: fixup patch indices * feat: replace webFrame.routingId with webFrame.frameToken * feat: WebFrameMain.prototype.frameToken * test: refactor to use replacement APIs * chore: fixup pip patch * test: adjust webFrame tests for frameToken changes * 6703757: Reland "Enable -fsanitize=array-bounds in non-UBSan builds" https://chromium-review.googlesource.com/c/chromium/src/+/6703757 * test: switch to frameTokens * test: routingId is fine to test in the main process * docs: add routingId to breaking changes * docs: update plugin-crashed event * chore: fixup linux dialog patch --------- Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com> Co-authored-by: alice <alice@makenotion.com> Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com> Co-authored-by: Samuel Maddock <smaddock@slack-corp.com> (cherry picked from commit603cafad7e
) --------- Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com> Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org> Co-authored-by: alice <alice@makenotion.com> Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com> Co-authored-by: Samuel Maddock <smaddock@slack-corp.com>
322 lines
12 KiB
TypeScript
322 lines
12 KiB
TypeScript
import { app, BrowserWindow, ipcMain } from 'electron/main';
|
|
|
|
import { expect } from 'chai';
|
|
|
|
import { once } from 'node:events';
|
|
import * as http from 'node:http';
|
|
import * as path from 'node:path';
|
|
|
|
import { emittedNTimes } from './lib/events-helpers';
|
|
import { ifdescribe, listen } from './lib/spec-helpers';
|
|
import { closeWindow } from './lib/window-helpers';
|
|
|
|
describe('renderer nodeIntegrationInSubFrames', () => {
|
|
const generateTests = (description: string, webPreferences: any) => {
|
|
describe(description, () => {
|
|
const fixtureSuffix = webPreferences.webviewTag ? '-webview' : '';
|
|
let w: BrowserWindow;
|
|
|
|
beforeEach(async () => {
|
|
await closeWindow(w);
|
|
w = new BrowserWindow({
|
|
show: false,
|
|
width: 400,
|
|
height: 400,
|
|
webPreferences
|
|
});
|
|
});
|
|
|
|
afterEach(async () => {
|
|
await closeWindow(w);
|
|
w = null as unknown as BrowserWindow;
|
|
});
|
|
|
|
it('should load preload scripts in top level iframes', async () => {
|
|
const detailsPromise = emittedNTimes(ipcMain, 'preload-ran', 2);
|
|
w.loadFile(path.resolve(__dirname, `fixtures/sub-frames/frame-container${fixtureSuffix}.html`));
|
|
const [event1, event2] = await detailsPromise;
|
|
expect(event1[0].senderFrame.frameToken).to.not.equal(event2[0].senderFrame.frameToken);
|
|
expect(event1[0].senderFrame.frameToken).to.equal(event1[2]);
|
|
expect(event2[0].senderFrame.frameToken).to.equal(event2[2]);
|
|
});
|
|
|
|
it('should load preload scripts in nested iframes', async () => {
|
|
const detailsPromise = emittedNTimes(ipcMain, 'preload-ran', 3);
|
|
w.loadFile(path.resolve(__dirname, `fixtures/sub-frames/frame-with-frame-container${fixtureSuffix}.html`));
|
|
const [event1, event2, event3] = await detailsPromise;
|
|
expect(event1[0].senderFrame.frameToken).to.not.equal(event2[0].senderFrame.frameToken);
|
|
expect(event1[0].senderFrame.frameToken).to.not.equal(event3[0].senderFrame.frameToken);
|
|
expect(event2[0].senderFrame.frameToken).to.not.equal(event3[0].senderFrame.frameToken);
|
|
expect(event1[0].senderFrame.frameToken).to.equal(event1[2]);
|
|
expect(event2[0].senderFrame.frameToken).to.equal(event2[2]);
|
|
expect(event3[0].senderFrame.frameToken).to.equal(event3[2]);
|
|
});
|
|
|
|
it('should correctly reply to the main frame with using event.reply', async () => {
|
|
const detailsPromise = emittedNTimes(ipcMain, 'preload-ran', 2);
|
|
w.loadFile(path.resolve(__dirname, `fixtures/sub-frames/frame-container${fixtureSuffix}.html`));
|
|
const [event1] = await detailsPromise;
|
|
const pongPromise = once(ipcMain, 'preload-pong');
|
|
event1[0].reply('preload-ping');
|
|
const [, frameToken] = await pongPromise;
|
|
expect(frameToken).to.equal(event1[0].senderFrame.frameToken);
|
|
});
|
|
|
|
it('should correctly reply to the main frame with using event.senderFrame.send', async () => {
|
|
const detailsPromise = emittedNTimes(ipcMain, 'preload-ran', 2);
|
|
w.loadFile(path.resolve(__dirname, `fixtures/sub-frames/frame-container${fixtureSuffix}.html`));
|
|
const [event1] = await detailsPromise;
|
|
const pongPromise = once(ipcMain, 'preload-pong');
|
|
event1[0].senderFrame.send('preload-ping');
|
|
const [, frameToken] = await pongPromise;
|
|
expect(frameToken).to.equal(event1[0].senderFrame.frameToken);
|
|
});
|
|
|
|
it('should correctly reply to the sub-frames with using event.reply', async () => {
|
|
const detailsPromise = emittedNTimes(ipcMain, 'preload-ran', 2);
|
|
w.loadFile(path.resolve(__dirname, `fixtures/sub-frames/frame-container${fixtureSuffix}.html`));
|
|
const [, event2] = await detailsPromise;
|
|
const pongPromise = once(ipcMain, 'preload-pong');
|
|
event2[0].reply('preload-ping');
|
|
const [, frameToken] = await pongPromise;
|
|
expect(frameToken).to.equal(event2[0].senderFrame.frameToken);
|
|
});
|
|
|
|
it('should correctly reply to the sub-frames with using event.senderFrame.send', async () => {
|
|
const detailsPromise = emittedNTimes(ipcMain, 'preload-ran', 2);
|
|
w.loadFile(path.resolve(__dirname, `fixtures/sub-frames/frame-container${fixtureSuffix}.html`));
|
|
const [, event2] = await detailsPromise;
|
|
const pongPromise = once(ipcMain, 'preload-pong');
|
|
event2[0].senderFrame.send('preload-ping');
|
|
const [, frameToken] = await pongPromise;
|
|
expect(frameToken).to.equal(event2[0].senderFrame.frameToken);
|
|
});
|
|
|
|
it('should correctly reply to the nested sub-frames with using event.reply', async () => {
|
|
const detailsPromise = emittedNTimes(ipcMain, 'preload-ran', 3);
|
|
w.loadFile(path.resolve(__dirname, `fixtures/sub-frames/frame-with-frame-container${fixtureSuffix}.html`));
|
|
const [, , event3] = await detailsPromise;
|
|
const pongPromise = once(ipcMain, 'preload-pong');
|
|
event3[0].reply('preload-ping');
|
|
const [, frameToken] = await pongPromise;
|
|
expect(frameToken).to.equal(event3[0].senderFrame.frameToken);
|
|
});
|
|
|
|
it('should correctly reply to the nested sub-frames with using event.senderFrame.send', async () => {
|
|
const detailsPromise = emittedNTimes(ipcMain, 'preload-ran', 3);
|
|
w.loadFile(path.resolve(__dirname, `fixtures/sub-frames/frame-with-frame-container${fixtureSuffix}.html`));
|
|
const [, , event3] = await detailsPromise;
|
|
const pongPromise = once(ipcMain, 'preload-pong');
|
|
event3[0].senderFrame.send('preload-ping');
|
|
const [, frameToken] = await pongPromise;
|
|
expect(frameToken).to.equal(event3[0].senderFrame.frameToken);
|
|
});
|
|
|
|
it('should not expose globals in main world', async () => {
|
|
const detailsPromise = emittedNTimes(ipcMain, 'preload-ran', 2);
|
|
w.loadFile(path.resolve(__dirname, `fixtures/sub-frames/frame-container${fixtureSuffix}.html`));
|
|
const details = await detailsPromise;
|
|
const senders = details.map(event => event[0].sender);
|
|
const isolatedGlobals = await Promise.all(senders.map(sender => sender.executeJavaScript('window.isolatedGlobal')));
|
|
for (const result of isolatedGlobals) {
|
|
if (webPreferences.contextIsolation === undefined || webPreferences.contextIsolation) {
|
|
expect(result).to.be.undefined();
|
|
} else {
|
|
expect(result).to.equal(true);
|
|
}
|
|
}
|
|
});
|
|
});
|
|
};
|
|
|
|
const generateConfigs = (webPreferences: any, ...permutations: {name: string, webPreferences: any}[]) => {
|
|
const configs = [{ webPreferences, names: [] as string[] }];
|
|
for (const permutation of permutations) {
|
|
const length = configs.length;
|
|
for (let j = 0; j < length; j++) {
|
|
const newConfig = Object.assign({}, configs[j]);
|
|
newConfig.webPreferences = Object.assign({},
|
|
newConfig.webPreferences, permutation.webPreferences);
|
|
newConfig.names = newConfig.names.slice(0);
|
|
newConfig.names.push(permutation.name);
|
|
configs.push(newConfig);
|
|
}
|
|
}
|
|
|
|
return configs.map((config: any) => {
|
|
if (config.names.length > 0) {
|
|
config.title = `with ${config.names.join(', ')} on`;
|
|
} else {
|
|
config.title = 'without anything special turned on';
|
|
}
|
|
delete config.names;
|
|
|
|
return config as {title: string, webPreferences: any};
|
|
});
|
|
};
|
|
|
|
const configs = generateConfigs(
|
|
{
|
|
preload: path.resolve(__dirname, 'fixtures/sub-frames/preload.js'),
|
|
nodeIntegrationInSubFrames: true
|
|
},
|
|
{
|
|
name: 'sandbox',
|
|
webPreferences: { sandbox: true }
|
|
},
|
|
{
|
|
name: 'context isolation disabled',
|
|
webPreferences: { contextIsolation: false }
|
|
},
|
|
{
|
|
name: 'webview',
|
|
webPreferences: { webviewTag: true, preload: false }
|
|
}
|
|
);
|
|
|
|
for (const config of configs) {
|
|
generateTests(config.title, config.webPreferences);
|
|
}
|
|
|
|
describe('internal <iframe> inside of <webview>', () => {
|
|
let w: BrowserWindow;
|
|
|
|
beforeEach(async () => {
|
|
await closeWindow(w);
|
|
w = new BrowserWindow({
|
|
show: false,
|
|
width: 400,
|
|
height: 400,
|
|
webPreferences: {
|
|
preload: path.resolve(__dirname, 'fixtures/sub-frames/webview-iframe-preload.js'),
|
|
nodeIntegrationInSubFrames: true,
|
|
webviewTag: true,
|
|
contextIsolation: false
|
|
}
|
|
});
|
|
});
|
|
|
|
afterEach(async () => {
|
|
await closeWindow(w);
|
|
w = null as unknown as BrowserWindow;
|
|
});
|
|
|
|
it('should not load preload scripts', async () => {
|
|
const promisePass = once(ipcMain, 'webview-loaded');
|
|
const promiseFail = once(ipcMain, 'preload-in-frame').then(() => {
|
|
throw new Error('preload loaded in internal frame');
|
|
});
|
|
await w.loadURL('about:blank');
|
|
return Promise.race([promisePass, promiseFail]);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('subframe with non-standard schemes', () => {
|
|
it('should not crash when changing subframe src to about:blank and back', async () => {
|
|
const w = new BrowserWindow({ show: false, width: 400, height: 400 });
|
|
|
|
const fwfPath = path.resolve(__dirname, 'fixtures/sub-frames/frame-with-frame.html');
|
|
await w.loadFile(fwfPath);
|
|
|
|
const originalSrc = await w.webContents.executeJavaScript(`
|
|
const iframe = document.querySelector('iframe');
|
|
iframe.src;
|
|
`);
|
|
|
|
const updatedSrc = await w.webContents.executeJavaScript(`
|
|
new Promise((resolve, reject) => {
|
|
const iframe = document.querySelector('iframe');
|
|
iframe.src = 'about:blank';
|
|
resolve(iframe.src);
|
|
})
|
|
`);
|
|
|
|
expect(updatedSrc).to.equal('about:blank');
|
|
|
|
const restoredSrc = await w.webContents.executeJavaScript(`
|
|
new Promise((resolve, reject) => {
|
|
const iframe = document.querySelector('iframe');
|
|
iframe.src = '${originalSrc}';
|
|
resolve(iframe.src);
|
|
})
|
|
`);
|
|
|
|
expect(restoredSrc).to.equal(originalSrc);
|
|
});
|
|
});
|
|
|
|
// app.getAppMetrics() does not return sandbox information on Linux.
|
|
ifdescribe(process.platform !== 'linux')('cross-site frame sandboxing', () => {
|
|
let server: http.Server;
|
|
let crossSiteUrl: string;
|
|
let serverUrl: string;
|
|
|
|
before(async function () {
|
|
server = http.createServer((req, res) => {
|
|
res.end(`<iframe name="frame" src="${crossSiteUrl}" />`);
|
|
});
|
|
serverUrl = (await listen(server)).url;
|
|
crossSiteUrl = serverUrl.replace('127.0.0.1', 'localhost');
|
|
});
|
|
|
|
after(() => {
|
|
server.close();
|
|
server = null as unknown as http.Server;
|
|
});
|
|
|
|
let w: BrowserWindow;
|
|
|
|
afterEach(async () => {
|
|
await closeWindow(w);
|
|
w = null as unknown as BrowserWindow;
|
|
});
|
|
|
|
const generateSpecs = (description: string, webPreferences: any) => {
|
|
describe(description, () => {
|
|
it('iframe process is sandboxed if possible', async () => {
|
|
w = new BrowserWindow({
|
|
show: false,
|
|
webPreferences
|
|
});
|
|
|
|
await w.loadURL(serverUrl);
|
|
|
|
const pidMain = w.webContents.getOSProcessId();
|
|
const pidFrame = w.webContents.mainFrame.frames.find(f => f.name === 'frame')!.osProcessId;
|
|
|
|
const metrics = app.getAppMetrics();
|
|
const isProcessSandboxed = function (pid: number) {
|
|
const entry = metrics.find(metric => metric.pid === pid);
|
|
return entry && entry.sandboxed;
|
|
};
|
|
|
|
const sandboxMain = !!(webPreferences.sandbox || process.mas);
|
|
const sandboxFrame = sandboxMain || !webPreferences.nodeIntegrationInSubFrames;
|
|
|
|
expect(isProcessSandboxed(pidMain)).to.equal(sandboxMain);
|
|
expect(isProcessSandboxed(pidFrame)).to.equal(sandboxFrame);
|
|
});
|
|
});
|
|
};
|
|
|
|
generateSpecs('nodeIntegrationInSubFrames = false, sandbox = false', {
|
|
nodeIntegrationInSubFrames: false,
|
|
sandbox: false
|
|
});
|
|
|
|
generateSpecs('nodeIntegrationInSubFrames = false, sandbox = true', {
|
|
nodeIntegrationInSubFrames: false,
|
|
sandbox: true
|
|
});
|
|
|
|
generateSpecs('nodeIntegrationInSubFrames = true, sandbox = false', {
|
|
nodeIntegrationInSubFrames: true,
|
|
sandbox: false
|
|
});
|
|
|
|
generateSpecs('nodeIntegrationInSubFrames = true, sandbox = true', {
|
|
nodeIntegrationInSubFrames: true,
|
|
sandbox: true
|
|
});
|
|
});
|