feat(webkit): bindings in util world (#6592)

This commit is contained in:
Yury Semikhatsky 2021-05-17 18:32:29 +00:00 committed by GitHub
parent be8d836443
commit c4b7818379
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 28 additions and 18 deletions

View File

@ -304,7 +304,7 @@ export class WKBrowserContext extends BrowserContext {
async _doAddInitScript(source: string) { async _doAddInitScript(source: string) {
this._evaluateOnNewDocumentSources.push(source); this._evaluateOnNewDocumentSources.push(source);
for (const page of this.pages()) for (const page of this.pages())
await (page._delegate as WKPage)._updateBootstrapScript(); await (page._delegate as WKPage)._updateBootstrapScript('main');
} }
async _doExposeBinding(binding: PageBinding) { async _doExposeBinding(binding: PageBinding) {

View File

@ -182,9 +182,12 @@ export class WKPage implements PageDelegate {
promises.push(session.send('Page.overrideUserAgent', { value: contextOptions.userAgent })); promises.push(session.send('Page.overrideUserAgent', { value: contextOptions.userAgent }));
if (this._page._state.mediaType || this._page._state.colorScheme) if (this._page._state.mediaType || this._page._state.colorScheme)
promises.push(WKPage._setEmulateMedia(session, this._page._state.mediaType, this._page._state.colorScheme)); promises.push(WKPage._setEmulateMedia(session, this._page._state.mediaType, this._page._state.colorScheme));
const bootstrapScript = this._calculateBootstrapScript(); for (const world of ['main', 'utility'] as const) {
promises.push(session.send('Page.setBootstrapScript', { source: bootstrapScript })); const bootstrapScript = this._calculateBootstrapScript(world);
this._page.frames().map(frame => frame.evaluateExpression(bootstrapScript, false, undefined, 'main').catch(e => {})); if (bootstrapScript.length)
promises.push(session.send('Page.setBootstrapScript', { source: bootstrapScript, worldName: webkitWorldName(world) }));
this._page.frames().map(frame => frame.evaluateExpression(bootstrapScript, false, undefined, world).catch(e => {}));
}
if (contextOptions.bypassCSP) if (contextOptions.bypassCSP)
promises.push(session.send('Page.setBypassCSP', { enabled: true })); promises.push(session.send('Page.setBypassCSP', { enabled: true }));
if (this._page._state.emulatedSize) { if (this._page._state.emulatedSize) {
@ -689,38 +692,38 @@ export class WKPage implements PageDelegate {
} }
async exposeBinding(binding: PageBinding): Promise<void> { async exposeBinding(binding: PageBinding): Promise<void> {
if (binding.world !== 'main') await this._updateBootstrapScript(binding.world);
throw new Error('Only main context bindings are supported in WebKit.');
await this._updateBootstrapScript();
await this._evaluateBindingScript(binding); await this._evaluateBindingScript(binding);
} }
private async _evaluateBindingScript(binding: PageBinding): Promise<void> { private async _evaluateBindingScript(binding: PageBinding): Promise<void> {
if (binding.world !== 'main')
throw new Error('Only main context bindings are supported in WebKit.');
const script = this._bindingToScript(binding); const script = this._bindingToScript(binding);
await Promise.all(this._page.frames().map(frame => frame.evaluateExpression(script, false, {}).catch(e => {}))); await Promise.all(this._page.frames().map(frame => frame.evaluateExpression(script, false, {}, binding.world).catch(e => {})));
} }
async evaluateOnNewDocument(script: string): Promise<void> { async evaluateOnNewDocument(script: string): Promise<void> {
await this._updateBootstrapScript(); await this._updateBootstrapScript('main');
} }
private _bindingToScript(binding: PageBinding): string { private _bindingToScript(binding: PageBinding): string {
return `self.${binding.name} = (param) => console.debug('${BINDING_CALL_MESSAGE}', {}, param); ${binding.source}`; return `self.${binding.name} = (param) => console.debug('${BINDING_CALL_MESSAGE}', {}, param); ${binding.source}`;
} }
private _calculateBootstrapScript(): string { private _calculateBootstrapScript(world: types.World): string {
const scripts: string[] = []; const scripts: string[] = [];
for (const binding of this._page.allBindings()) for (const binding of this._page.allBindings()) {
if (binding.world === world)
scripts.push(this._bindingToScript(binding)); scripts.push(this._bindingToScript(binding));
}
if (world === 'main') {
scripts.push(...this._browserContext._evaluateOnNewDocumentSources); scripts.push(...this._browserContext._evaluateOnNewDocumentSources);
scripts.push(...this._page._evaluateOnNewDocumentSources); scripts.push(...this._page._evaluateOnNewDocumentSources);
}
return scripts.join(';'); return scripts.join(';');
} }
async _updateBootstrapScript(): Promise<void> { async _updateBootstrapScript(world: types.World): Promise<void> {
await this._updateState('Page.setBootstrapScript', { source: this._calculateBootstrapScript() }); await this._updateState('Page.setBootstrapScript', { source: this._calculateBootstrapScript(world), worldName: webkitWorldName(world) });
} }
async closePage(runBeforeUnload: boolean): Promise<void> { async closePage(runBeforeUnload: boolean): Promise<void> {
@ -1032,3 +1035,10 @@ export class WKPage implements PageDelegate {
await this._pageProxySession.send('Emulation.resetPermissions', {}); await this._pageProxySession.send('Emulation.resetPermissions', {});
} }
} }
function webkitWorldName(world: types.World) {
switch (world) {
case 'main': return undefined;
case 'utility': return UTILITY_WORLD_NAME;
}
}