refactor: move extension APIs to session.extensions (#45597)

refactor: move extensions to session.extensions
This commit is contained in:
Sam Maddock 2025-02-21 18:36:51 -05:00 committed by GitHub
parent a63f6143ea
commit e3f61b465d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 508 additions and 205 deletions

View file

@ -50,8 +50,8 @@ describe('chrome extensions', () => {
});
afterEach(closeAllWindows);
afterEach(() => {
for (const e of session.defaultSession.getAllExtensions()) {
session.defaultSession.removeExtension(e.id);
for (const e of session.defaultSession.extensions.getAllExtensions()) {
session.defaultSession.extensions.removeExtension(e.id);
}
});
@ -61,7 +61,7 @@ describe('chrome extensions', () => {
await w.loadURL('about:blank');
const promise = once(app, 'web-contents-created') as Promise<[any, WebContents]>;
await customSession.loadExtension(path.join(fixtures, 'extensions', 'persistent-background-page'));
await customSession.extensions.loadExtension(path.join(fixtures, 'extensions', 'persistent-background-page'));
const args: any = await promise;
const wc: Electron.WebContents = args[1];
await expect(wc.executeJavaScript(`
@ -96,7 +96,7 @@ describe('chrome extensions', () => {
await w.loadURL(url);
const extPath = path.join(fixtures, 'extensions', 'host-permissions', 'malformed');
customSession.loadExtension(extPath);
customSession.extensions.loadExtension(extPath);
const warning = await new Promise(resolve => { process.on('warning', resolve); });
@ -107,7 +107,7 @@ describe('chrome extensions', () => {
it('can grant special privileges to urls with host permissions', async () => {
const extPath = path.join(fixtures, 'extensions', 'host-permissions', 'privileged-tab-info');
await customSession.loadExtension(extPath);
await customSession.extensions.loadExtension(extPath);
await w.loadURL(url);
@ -149,7 +149,7 @@ describe('chrome extensions', () => {
await w.loadURL('about:blank');
const extPath = path.join(fixtures, 'extensions', 'minimum-chrome-version');
const load = customSession.loadExtension(extPath);
const load = customSession.extensions.loadExtension(extPath);
await expect(load).to.eventually.be.rejectedWith(
`Loading extension at ${extPath} failed with: This extension requires Chromium version 999 or greater.`
);
@ -162,7 +162,7 @@ describe('chrome extensions', () => {
it('bypasses CORS in requests made from extensions', async () => {
const customSession = session.fromPartition(`persist:${require('uuid').v4()}`);
const w = new BrowserWindow({ show: false, webPreferences: { session: customSession, sandbox: true } });
const extension = await customSession.loadExtension(path.join(fixtures, 'extensions', 'ui-page'));
const extension = await customSession.extensions.loadExtension(path.join(fixtures, 'extensions', 'ui-page'));
await w.loadURL(`${extension.url}bare-page.html`);
await expect(fetch(w.webContents, `${url}/cors`)).to.not.be.rejectedWith(TypeError);
});
@ -173,7 +173,7 @@ describe('chrome extensions', () => {
// extension in an in-memory session results in it being installed in the
// default session.
const customSession = session.fromPartition(`persist:${uuid.v4()}`);
await customSession.loadExtension(path.join(fixtures, 'extensions', 'red-bg'));
await customSession.extensions.loadExtension(path.join(fixtures, 'extensions', 'red-bg'));
const w = new BrowserWindow({ show: false, webPreferences: { session: customSession } });
await w.loadURL(url);
const bg = await w.webContents.executeJavaScript('document.documentElement.style.backgroundColor');
@ -182,13 +182,13 @@ describe('chrome extensions', () => {
it('does not crash when loading an extension with missing manifest', async () => {
const customSession = session.fromPartition(`persist:${uuid.v4()}`);
const promise = customSession.loadExtension(path.join(fixtures, 'extensions', 'missing-manifest'));
const promise = customSession.extensions.loadExtension(path.join(fixtures, 'extensions', 'missing-manifest'));
await expect(promise).to.eventually.be.rejectedWith(/Manifest file is missing or unreadable/);
});
it('does not crash when failing to load an extension', async () => {
const customSession = session.fromPartition(`persist:${uuid.v4()}`);
const promise = customSession.loadExtension(path.join(fixtures, 'extensions', 'load-error'));
const promise = customSession.extensions.loadExtension(path.join(fixtures, 'extensions', 'load-error'));
await expect(promise).to.eventually.be.rejected();
});
@ -196,7 +196,7 @@ describe('chrome extensions', () => {
const extensionPath = path.join(fixtures, 'extensions', 'red-bg');
const manifest = JSON.parse(await fs.readFile(path.join(extensionPath, 'manifest.json'), 'utf-8'));
const customSession = session.fromPartition(`persist:${uuid.v4()}`);
const extension = await customSession.loadExtension(extensionPath);
const extension = await customSession.extensions.loadExtension(extensionPath);
expect(extension.id).to.be.a('string');
expect(extension.name).to.be.a('string');
expect(extension.path).to.be.a('string');
@ -207,14 +207,14 @@ describe('chrome extensions', () => {
it('removes an extension', async () => {
const customSession = session.fromPartition(`persist:${uuid.v4()}`);
const { id } = await customSession.loadExtension(path.join(fixtures, 'extensions', 'red-bg'));
const { id } = await customSession.extensions.loadExtension(path.join(fixtures, 'extensions', 'red-bg'));
{
const w = new BrowserWindow({ show: false, webPreferences: { session: customSession } });
await w.loadURL(url);
const bg = await w.webContents.executeJavaScript('document.documentElement.style.backgroundColor');
expect(bg).to.equal('red');
}
customSession.removeExtension(id);
customSession.extensions.removeExtension(id);
{
const w = new BrowserWindow({ show: false, webPreferences: { session: customSession } });
await w.loadURL(url);
@ -226,40 +226,40 @@ describe('chrome extensions', () => {
it('emits extension lifecycle events', async () => {
const customSession = session.fromPartition(`persist:${require('uuid').v4()}`);
const loadedPromise = once(customSession, 'extension-loaded');
const readyPromise = emittedUntil(customSession, 'extension-ready', (event: Event, extension: Extension) => {
const loadedPromise = once(customSession.extensions, 'extension-loaded');
const readyPromise = emittedUntil(customSession.extensions, 'extension-ready', (event: Event, extension: Extension) => {
return extension.name !== 'Chromium PDF Viewer';
});
const extension = await customSession.loadExtension(path.join(fixtures, 'extensions', 'red-bg'));
const extension = await customSession.extensions.loadExtension(path.join(fixtures, 'extensions', 'red-bg'));
const [, loadedExtension] = await loadedPromise;
const [, readyExtension] = await readyPromise;
expect(loadedExtension).to.deep.equal(extension);
expect(readyExtension).to.deep.equal(extension);
const unloadedPromise = once(customSession, 'extension-unloaded');
await customSession.removeExtension(extension.id);
const unloadedPromise = once(customSession.extensions, 'extension-unloaded');
await customSession.extensions.removeExtension(extension.id);
const [, unloadedExtension] = await unloadedPromise;
expect(unloadedExtension).to.deep.equal(extension);
});
it('lists loaded extensions in getAllExtensions', async () => {
const customSession = session.fromPartition(`persist:${uuid.v4()}`);
const e = await customSession.loadExtension(path.join(fixtures, 'extensions', 'red-bg'));
expect(customSession.getAllExtensions()).to.deep.equal([e]);
customSession.removeExtension(e.id);
expect(customSession.getAllExtensions()).to.deep.equal([]);
const e = await customSession.extensions.loadExtension(path.join(fixtures, 'extensions', 'red-bg'));
expect(customSession.extensions.getAllExtensions()).to.deep.equal([e]);
customSession.extensions.removeExtension(e.id);
expect(customSession.extensions.getAllExtensions()).to.deep.equal([]);
});
it('gets an extension by id', async () => {
const customSession = session.fromPartition(`persist:${uuid.v4()}`);
const e = await customSession.loadExtension(path.join(fixtures, 'extensions', 'red-bg'));
expect(customSession.getExtension(e.id)).to.deep.equal(e);
const e = await customSession.extensions.loadExtension(path.join(fixtures, 'extensions', 'red-bg'));
expect(customSession.extensions.getExtension(e.id)).to.deep.equal(e);
});
it('confines an extension to the session it was loaded in', async () => {
const customSession = session.fromPartition(`persist:${uuid.v4()}`);
await customSession.loadExtension(path.join(fixtures, 'extensions', 'red-bg'));
await customSession.extensions.loadExtension(path.join(fixtures, 'extensions', 'red-bg'));
const w = new BrowserWindow({ show: false }); // not in the session
await w.loadURL(url);
const bg = await w.webContents.executeJavaScript('document.documentElement.style.backgroundColor');
@ -268,7 +268,7 @@ describe('chrome extensions', () => {
it('loading an extension in a temporary session throws an error', async () => {
const customSession = session.fromPartition(uuid.v4());
await expect(customSession.loadExtension(path.join(fixtures, 'extensions', 'red-bg'))).to.eventually.be.rejectedWith('Extensions cannot be loaded in a temporary session');
await expect(customSession.extensions.loadExtension(path.join(fixtures, 'extensions', 'red-bg'))).to.eventually.be.rejectedWith('Extensions cannot be loaded in a temporary session');
});
describe('chrome.i18n', () => {
@ -282,7 +282,7 @@ describe('chrome extensions', () => {
};
beforeEach(async () => {
const customSession = session.fromPartition(`persist:${uuid.v4()}`);
extension = await customSession.loadExtension(path.join(fixtures, 'extensions', 'chrome-i18n', 'v2'));
extension = await customSession.extensions.loadExtension(path.join(fixtures, 'extensions', 'chrome-i18n', 'v2'));
w = new BrowserWindow({ show: false, webPreferences: { session: customSession, nodeIntegration: true, contextIsolation: false } });
await w.loadURL(url);
});
@ -311,7 +311,7 @@ describe('chrome extensions', () => {
};
beforeEach(async () => {
const customSession = session.fromPartition(`persist:${uuid.v4()}`);
await customSession.loadExtension(path.join(fixtures, 'extensions', 'chrome-runtime'));
await customSession.extensions.loadExtension(path.join(fixtures, 'extensions', 'chrome-runtime'));
w = new BrowserWindow({ show: false, webPreferences: { session: customSession, nodeIntegration: true, contextIsolation: false } });
await w.loadURL(url);
});
@ -343,7 +343,7 @@ describe('chrome extensions', () => {
describe('chrome.storage', () => {
it('stores and retrieves a key', async () => {
const customSession = session.fromPartition(`persist:${uuid.v4()}`);
await customSession.loadExtension(path.join(fixtures, 'extensions', 'chrome-storage'));
await customSession.extensions.loadExtension(path.join(fixtures, 'extensions', 'chrome-storage'));
const w = new BrowserWindow({ show: false, webPreferences: { session: customSession, nodeIntegration: true, contextIsolation: false } });
try {
const p = once(ipcMain, 'storage-success');
@ -386,7 +386,7 @@ describe('chrome extensions', () => {
it('can cancel http requests', async () => {
await w.loadURL(url);
await customSession.loadExtension(path.join(fixtures, 'extensions', 'chrome-webRequest'));
await customSession.extensions.loadExtension(path.join(fixtures, 'extensions', 'chrome-webRequest'));
await expect(waitUntil(haveRejectedFetch)).to.eventually.be.fulfilled();
});
@ -405,7 +405,7 @@ describe('chrome extensions', () => {
});
await w.loadURL(url);
await customSession.loadExtension(path.join(fixtures, 'extensions', 'chrome-webRequest'));
await customSession.extensions.loadExtension(path.join(fixtures, 'extensions', 'chrome-webRequest'));
fetch(w.webContents, url);
})();
});
@ -418,7 +418,7 @@ describe('chrome extensions', () => {
resolve();
});
await w.loadFile(path.join(fixtures, 'api', 'webrequest.html'), { query: { port: `${port}` } });
await customSession.loadExtension(path.join(fixtures, 'extensions', 'chrome-webRequest-wss'));
await customSession.extensions.loadExtension(path.join(fixtures, 'extensions', 'chrome-webRequest-wss'));
})();
});
});
@ -426,7 +426,7 @@ describe('chrome extensions', () => {
describe('WebSocket', () => {
it('can be proxied', async () => {
await w.loadFile(path.join(fixtures, 'api', 'webrequest.html'), { query: { port: `${port}` } });
await customSession.loadExtension(path.join(fixtures, 'extensions', 'chrome-webRequest-wss'));
await customSession.extensions.loadExtension(path.join(fixtures, 'extensions', 'chrome-webRequest-wss'));
customSession.webRequest.onSendHeaders((details) => {
if (details.url.startsWith('ws://')) {
expect(details.requestHeaders.foo).be.equal('bar');
@ -440,7 +440,7 @@ describe('chrome extensions', () => {
let customSession: Session;
before(async () => {
customSession = session.fromPartition(`persist:${uuid.v4()}`);
await customSession.loadExtension(path.join(fixtures, 'extensions', 'chrome-api'));
await customSession.extensions.loadExtension(path.join(fixtures, 'extensions', 'chrome-api'));
});
afterEach(closeAllWindows);
@ -512,7 +512,7 @@ describe('chrome extensions', () => {
afterEach(closeAllWindows);
it('loads a lazy background page when sending a message', async () => {
const customSession = session.fromPartition(`persist:${uuid.v4()}`);
await customSession.loadExtension(path.join(fixtures, 'extensions', 'lazy-background-page'));
await customSession.extensions.loadExtension(path.join(fixtures, 'extensions', 'lazy-background-page'));
const w = new BrowserWindow({ show: false, webPreferences: { session: customSession, nodeIntegration: true, contextIsolation: false } });
try {
w.loadURL(url);
@ -528,7 +528,7 @@ describe('chrome extensions', () => {
it('can use extension.getBackgroundPage from a ui page', async () => {
const customSession = session.fromPartition(`persist:${uuid.v4()}`);
const { id } = await customSession.loadExtension(path.join(fixtures, 'extensions', 'lazy-background-page'));
const { id } = await customSession.extensions.loadExtension(path.join(fixtures, 'extensions', 'lazy-background-page'));
const w = new BrowserWindow({ show: false, webPreferences: { session: customSession } });
await w.loadURL(`chrome-extension://${id}/page-get-background.html`);
const receivedMessage = await w.webContents.executeJavaScript('window.completionPromise');
@ -537,7 +537,7 @@ describe('chrome extensions', () => {
it('can use extension.getBackgroundPage from a ui page', async () => {
const customSession = session.fromPartition(`persist:${uuid.v4()}`);
const { id } = await customSession.loadExtension(path.join(fixtures, 'extensions', 'lazy-background-page'));
const { id } = await customSession.extensions.loadExtension(path.join(fixtures, 'extensions', 'lazy-background-page'));
const w = new BrowserWindow({ show: false, webPreferences: { session: customSession } });
await w.loadURL(`chrome-extension://${id}/page-get-background.html`);
const receivedMessage = await w.webContents.executeJavaScript('window.completionPromise');
@ -546,7 +546,7 @@ describe('chrome extensions', () => {
it('can use runtime.getBackgroundPage from a ui page', async () => {
const customSession = session.fromPartition(`persist:${uuid.v4()}`);
const { id } = await customSession.loadExtension(path.join(fixtures, 'extensions', 'lazy-background-page'));
const { id } = await customSession.extensions.loadExtension(path.join(fixtures, 'extensions', 'lazy-background-page'));
const w = new BrowserWindow({ show: false, webPreferences: { session: customSession } });
await w.loadURL(`chrome-extension://${id}/page-runtime-get-background.html`);
const receivedMessage = await w.webContents.executeJavaScript('window.completionPromise');
@ -556,7 +556,7 @@ describe('chrome extensions', () => {
it('has session in background page', async () => {
const customSession = session.fromPartition(`persist:${require('uuid').v4()}`);
const promise = once(app, 'web-contents-created') as Promise<[any, WebContents]>;
const { id } = await customSession.loadExtension(path.join(fixtures, 'extensions', 'persistent-background-page'));
const { id } = await customSession.extensions.loadExtension(path.join(fixtures, 'extensions', 'persistent-background-page'));
const [, bgPageContents] = await promise;
expect(bgPageContents.getType()).to.equal('backgroundPage');
await once(bgPageContents, 'did-finish-load');
@ -567,7 +567,7 @@ describe('chrome extensions', () => {
it('can open devtools of background page', async () => {
const customSession = session.fromPartition(`persist:${require('uuid').v4()}`);
const promise = once(app, 'web-contents-created') as Promise<[any, WebContents]>;
await customSession.loadExtension(path.join(fixtures, 'extensions', 'persistent-background-page'));
await customSession.extensions.loadExtension(path.join(fixtures, 'extensions', 'persistent-background-page'));
const [, bgPageContents] = await promise;
expect(bgPageContents.getType()).to.equal('backgroundPage');
bgPageContents.openDevTools();
@ -609,7 +609,7 @@ describe('chrome extensions', () => {
// TODO(jkleinsc) fix this flaky test on WOA
ifit(process.platform !== 'win32' || process.arch !== 'arm64')('loads a devtools extension', async () => {
const customSession = session.fromPartition(`persist:${uuid.v4()}`);
customSession.loadExtension(path.join(fixtures, 'extensions', 'devtools-extension'));
customSession.extensions.loadExtension(path.join(fixtures, 'extensions', 'devtools-extension'));
const winningMessage = once(ipcMain, 'winning');
const w = new BrowserWindow({ show: true, webPreferences: { session: customSession, nodeIntegration: true, contextIsolation: false } });
await w.loadURL(url);
@ -623,10 +623,10 @@ describe('chrome extensions', () => {
const fixtures = path.resolve(__dirname, 'fixtures');
const extensionPath = path.resolve(fixtures, 'extensions');
const addExtension = (name: string) => session.defaultSession.loadExtension(path.resolve(extensionPath, name));
const addExtension = (name: string) => session.defaultSession.extensions.loadExtension(path.resolve(extensionPath, name));
const removeAllExtensions = () => {
Object.keys(session.defaultSession.getAllExtensions()).forEach(extName => {
session.defaultSession.removeExtension(extName);
Object.keys(session.defaultSession.extensions.getAllExtensions()).forEach(extName => {
session.defaultSession.extensions.removeExtension(extName);
});
};
@ -716,11 +716,11 @@ describe('chrome extensions', () => {
({ port } = await listen(server));
session.defaultSession.loadExtension(contentScript);
session.defaultSession.extensions.loadExtension(contentScript);
});
after(() => {
session.defaultSession.removeExtension('content-script-test');
session.defaultSession.extensions.removeExtension('content-script-test');
server.close();
});
@ -779,14 +779,14 @@ describe('chrome extensions', () => {
describe('extension ui pages', () => {
afterEach(async () => {
for (const e of session.defaultSession.getAllExtensions()) {
session.defaultSession.removeExtension(e.id);
for (const e of session.defaultSession.extensions.getAllExtensions()) {
session.defaultSession.extensions.removeExtension(e.id);
}
await closeAllWindows();
});
it('loads a ui page of an extension', async () => {
const { id } = await session.defaultSession.loadExtension(path.join(fixtures, 'extensions', 'ui-page'));
const { id } = await session.defaultSession.extensions.loadExtension(path.join(fixtures, 'extensions', 'ui-page'));
const w = new BrowserWindow({ show: false });
await w.loadURL(`chrome-extension://${id}/bare-page.html`);
const textContent = await w.webContents.executeJavaScript('document.body.textContent');
@ -794,7 +794,7 @@ describe('chrome extensions', () => {
});
it('can load resources', async () => {
const { id } = await session.defaultSession.loadExtension(path.join(fixtures, 'extensions', 'ui-page'));
const { id } = await session.defaultSession.extensions.loadExtension(path.join(fixtures, 'extensions', 'ui-page'));
const w = new BrowserWindow({ show: false });
await w.loadURL(`chrome-extension://${id}/page-script-load.html`);
const textContent = await w.webContents.executeJavaScript('document.body.textContent');
@ -809,7 +809,7 @@ describe('chrome extensions', () => {
const registrationPromise = new Promise<string>(resolve => {
customSession.serviceWorkers.once('registration-completed', (event, { scope }) => resolve(scope));
});
const extension = await customSession.loadExtension(path.join(fixtures, 'extensions', 'mv3-service-worker'));
const extension = await customSession.extensions.loadExtension(path.join(fixtures, 'extensions', 'mv3-service-worker'));
const scope = await registrationPromise;
expect(scope).equals(extension.url);
});
@ -817,7 +817,7 @@ describe('chrome extensions', () => {
it('can run chrome extension APIs', async () => {
const customSession = session.fromPartition(`persist:${uuid.v4()}`);
const w = new BrowserWindow({ show: false, webPreferences: { session: customSession, nodeIntegration: true } });
await customSession.loadExtension(path.join(fixtures, 'extensions', 'mv3-service-worker'));
await customSession.extensions.loadExtension(path.join(fixtures, 'extensions', 'mv3-service-worker'));
await w.loadURL(url);
@ -835,7 +835,7 @@ describe('chrome extensions', () => {
before(async () => {
customSession = session.fromPartition(`persist:${uuid.v4()}`);
await customSession.loadExtension(path.join(fixtures, 'extensions', 'chrome-i18n', 'v3'));
await customSession.extensions.loadExtension(path.join(fixtures, 'extensions', 'chrome-i18n', 'v3'));
});
beforeEach(() => {
@ -927,7 +927,7 @@ describe('chrome extensions', () => {
before(async () => {
customSession = session.fromPartition(`persist:${uuid.v4()}`);
await customSession.loadExtension(path.join(fixtures, 'extensions', 'chrome-action-fail'));
await customSession.extensions.loadExtension(path.join(fixtures, 'extensions', 'chrome-action-fail'));
});
beforeEach(() => {
@ -984,7 +984,7 @@ describe('chrome extensions', () => {
before(async () => {
customSession = session.fromPartition(`persist:${uuid.v4()}`);
await customSession.loadExtension(path.join(fixtures, 'extensions', 'chrome-tabs', 'api-async'));
await customSession.extensions.loadExtension(path.join(fixtures, 'extensions', 'chrome-tabs', 'api-async'));
});
beforeEach(() => {
@ -1082,7 +1082,7 @@ describe('chrome extensions', () => {
it('does not return privileged properties without tabs permission', async () => {
const noPrivilegeSes = session.fromPartition(`persist:${uuid.v4()}`);
await noPrivilegeSes.loadExtension(path.join(fixtures, 'extensions', 'chrome-tabs', 'no-privileges'));
await noPrivilegeSes.extensions.loadExtension(path.join(fixtures, 'extensions', 'chrome-tabs', 'no-privileges'));
w = new BrowserWindow({ show: false, webPreferences: { session: noPrivilegeSes } });
await w.loadURL(url);
@ -1263,7 +1263,7 @@ describe('chrome extensions', () => {
before(async () => {
customSession = session.fromPartition(`persist:${uuid.v4()}`);
await customSession.loadExtension(path.join(fixtures, 'extensions', 'chrome-scripting'));
await customSession.extensions.loadExtension(path.join(fixtures, 'extensions', 'chrome-scripting'));
});
beforeEach(() => {