mirror of
https://github.com/microsoft/playwright.git
synced 2024-09-11 20:37:54 +03:00
fix(utility): create utility world when web security is disabled (#31458)
Reverts previous attempt at #31096 Fixes: https://github.com/microsoft/playwright/issues/31431 Fixes: https://github.com/microsoft/playwright/issues/31442
This commit is contained in:
parent
87785d6092
commit
c9e673c6dc
@ -24,6 +24,7 @@ import type { Download } from './download';
|
|||||||
import type * as frames from './frames';
|
import type * as frames from './frames';
|
||||||
import { helper } from './helper';
|
import { helper } from './helper';
|
||||||
import * as network from './network';
|
import * as network from './network';
|
||||||
|
import { InitScript } from './page';
|
||||||
import type { PageDelegate } from './page';
|
import type { PageDelegate } from './page';
|
||||||
import { Page, PageBinding } from './page';
|
import { Page, PageBinding } from './page';
|
||||||
import type { Progress, ProgressController } from './progress';
|
import type { Progress, ProgressController } from './progress';
|
||||||
@ -84,7 +85,7 @@ export abstract class BrowserContext extends SdkObject {
|
|||||||
private _customCloseHandler?: () => Promise<any>;
|
private _customCloseHandler?: () => Promise<any>;
|
||||||
readonly _tempDirs: string[] = [];
|
readonly _tempDirs: string[] = [];
|
||||||
private _settingStorageState = false;
|
private _settingStorageState = false;
|
||||||
readonly initScripts: string[] = [];
|
readonly initScripts: InitScript[] = [];
|
||||||
private _routesInFlight = new Set<network.Route>();
|
private _routesInFlight = new Set<network.Route>();
|
||||||
private _debugger!: Debugger;
|
private _debugger!: Debugger;
|
||||||
_closeReason: string | undefined;
|
_closeReason: string | undefined;
|
||||||
@ -266,7 +267,7 @@ export abstract class BrowserContext extends SdkObject {
|
|||||||
protected abstract doGrantPermissions(origin: string, permissions: string[]): Promise<void>;
|
protected abstract doGrantPermissions(origin: string, permissions: string[]): Promise<void>;
|
||||||
protected abstract doClearPermissions(): Promise<void>;
|
protected abstract doClearPermissions(): Promise<void>;
|
||||||
protected abstract doSetHTTPCredentials(httpCredentials?: types.Credentials): Promise<void>;
|
protected abstract doSetHTTPCredentials(httpCredentials?: types.Credentials): Promise<void>;
|
||||||
protected abstract doAddInitScript(expression: string): Promise<void>;
|
protected abstract doAddInitScript(initScript: InitScript): Promise<void>;
|
||||||
protected abstract doRemoveInitScripts(): Promise<void>;
|
protected abstract doRemoveInitScripts(): Promise<void>;
|
||||||
protected abstract doExposeBinding(binding: PageBinding): Promise<void>;
|
protected abstract doExposeBinding(binding: PageBinding): Promise<void>;
|
||||||
protected abstract doRemoveExposedBindings(): Promise<void>;
|
protected abstract doRemoveExposedBindings(): Promise<void>;
|
||||||
@ -403,9 +404,10 @@ export abstract class BrowserContext extends SdkObject {
|
|||||||
this._options.httpCredentials = { username, password: password || '' };
|
this._options.httpCredentials = { username, password: password || '' };
|
||||||
}
|
}
|
||||||
|
|
||||||
async addInitScript(script: string) {
|
async addInitScript(source: string) {
|
||||||
this.initScripts.push(script);
|
const initScript = new InitScript(source);
|
||||||
await this.doAddInitScript(script);
|
this.initScripts.push(initScript);
|
||||||
|
await this.doAddInitScript(initScript);
|
||||||
}
|
}
|
||||||
|
|
||||||
async _removeInitScripts(): Promise<void> {
|
async _removeInitScripts(): Promise<void> {
|
||||||
|
@ -21,7 +21,7 @@ import { Browser } from '../browser';
|
|||||||
import { assertBrowserContextIsNotOwned, BrowserContext, verifyGeolocation } from '../browserContext';
|
import { assertBrowserContextIsNotOwned, BrowserContext, verifyGeolocation } from '../browserContext';
|
||||||
import { assert, createGuid } from '../../utils';
|
import { assert, createGuid } from '../../utils';
|
||||||
import * as network from '../network';
|
import * as network from '../network';
|
||||||
import type { PageBinding, PageDelegate, Worker } from '../page';
|
import type { InitScript, PageBinding, PageDelegate, Worker } from '../page';
|
||||||
import { Page } from '../page';
|
import { Page } from '../page';
|
||||||
import { Frame } from '../frames';
|
import { Frame } from '../frames';
|
||||||
import type { Dialog } from '../dialog';
|
import type { Dialog } from '../dialog';
|
||||||
@ -486,9 +486,9 @@ export class CRBrowserContext extends BrowserContext {
|
|||||||
await (sw as CRServiceWorker).updateHttpCredentials();
|
await (sw as CRServiceWorker).updateHttpCredentials();
|
||||||
}
|
}
|
||||||
|
|
||||||
async doAddInitScript(source: string) {
|
async doAddInitScript(initScript: InitScript) {
|
||||||
for (const page of this.pages())
|
for (const page of this.pages())
|
||||||
await (page._delegate as CRPage).addInitScript(source);
|
await (page._delegate as CRPage).addInitScript(initScript);
|
||||||
}
|
}
|
||||||
|
|
||||||
async doRemoveInitScripts() {
|
async doRemoveInitScripts() {
|
||||||
|
@ -26,7 +26,7 @@ import * as dom from '../dom';
|
|||||||
import * as frames from '../frames';
|
import * as frames from '../frames';
|
||||||
import { helper } from '../helper';
|
import { helper } from '../helper';
|
||||||
import * as network from '../network';
|
import * as network from '../network';
|
||||||
import type { PageBinding, PageDelegate } from '../page';
|
import type { InitScript, PageBinding, PageDelegate } from '../page';
|
||||||
import { Page, Worker } from '../page';
|
import { Page, Worker } from '../page';
|
||||||
import type { Progress } from '../progress';
|
import type { Progress } from '../progress';
|
||||||
import type * as types from '../types';
|
import type * as types from '../types';
|
||||||
@ -256,8 +256,8 @@ export class CRPage implements PageDelegate {
|
|||||||
return this._go(+1);
|
return this._go(+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
async addInitScript(source: string, world: types.World = 'main'): Promise<void> {
|
async addInitScript(initScript: InitScript, world: types.World = 'main'): Promise<void> {
|
||||||
await this._forAllFrameSessions(frame => frame._evaluateOnNewDocument(source, world));
|
await this._forAllFrameSessions(frame => frame._evaluateOnNewDocument(initScript, world));
|
||||||
}
|
}
|
||||||
|
|
||||||
async removeInitScripts() {
|
async removeInitScripts() {
|
||||||
@ -511,6 +511,20 @@ class FrameSession {
|
|||||||
this._addRendererListeners();
|
this._addRendererListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const localFrames = this._isMainFrame() ? this._page.frames() : [this._page._frameManager.frame(this._targetId)!];
|
||||||
|
for (const frame of localFrames) {
|
||||||
|
// Note: frames might be removed before we send these.
|
||||||
|
this._client._sendMayFail('Page.createIsolatedWorld', {
|
||||||
|
frameId: frame._id,
|
||||||
|
grantUniveralAccess: true,
|
||||||
|
worldName: UTILITY_WORLD_NAME,
|
||||||
|
});
|
||||||
|
for (const binding of this._crPage._browserContext._pageBindings.values())
|
||||||
|
frame.evaluateExpression(binding.source).catch(e => {});
|
||||||
|
for (const initScript of this._crPage._browserContext.initScripts)
|
||||||
|
frame.evaluateExpression(initScript.source).catch(e => {});
|
||||||
|
}
|
||||||
|
|
||||||
const isInitialEmptyPage = this._isMainFrame() && this._page.mainFrame().url() === ':';
|
const isInitialEmptyPage = this._isMainFrame() && this._page.mainFrame().url() === ':';
|
||||||
if (isInitialEmptyPage) {
|
if (isInitialEmptyPage) {
|
||||||
// Ignore lifecycle events, worlds and bindings for the initial empty page. It is never the final page
|
// Ignore lifecycle events, worlds and bindings for the initial empty page. It is never the final page
|
||||||
@ -520,20 +534,6 @@ class FrameSession {
|
|||||||
this._eventListeners.push(eventsHelper.addEventListener(this._client, 'Page.lifecycleEvent', event => this._onLifecycleEvent(event)));
|
this._eventListeners.push(eventsHelper.addEventListener(this._client, 'Page.lifecycleEvent', event => this._onLifecycleEvent(event)));
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
const localFrames = this._isMainFrame() ? this._page.frames() : [this._page._frameManager.frame(this._targetId)!];
|
|
||||||
for (const frame of localFrames) {
|
|
||||||
// Note: frames might be removed before we send these.
|
|
||||||
this._client._sendMayFail('Page.createIsolatedWorld', {
|
|
||||||
frameId: frame._id,
|
|
||||||
grantUniveralAccess: true,
|
|
||||||
worldName: UTILITY_WORLD_NAME,
|
|
||||||
});
|
|
||||||
for (const binding of this._crPage._browserContext._pageBindings.values())
|
|
||||||
frame.evaluateExpression(binding.source).catch(e => {});
|
|
||||||
for (const source of this._crPage._browserContext.initScripts)
|
|
||||||
frame.evaluateExpression(source).catch(e => {});
|
|
||||||
}
|
|
||||||
|
|
||||||
this._firstNonInitialNavigationCommittedFulfill();
|
this._firstNonInitialNavigationCommittedFulfill();
|
||||||
this._eventListeners.push(eventsHelper.addEventListener(this._client, 'Page.lifecycleEvent', event => this._onLifecycleEvent(event)));
|
this._eventListeners.push(eventsHelper.addEventListener(this._client, 'Page.lifecycleEvent', event => this._onLifecycleEvent(event)));
|
||||||
}
|
}
|
||||||
@ -575,10 +575,10 @@ class FrameSession {
|
|||||||
promises.push(this._updateFileChooserInterception(true));
|
promises.push(this._updateFileChooserInterception(true));
|
||||||
for (const binding of this._crPage._page.allBindings())
|
for (const binding of this._crPage._page.allBindings())
|
||||||
promises.push(this._initBinding(binding));
|
promises.push(this._initBinding(binding));
|
||||||
for (const source of this._crPage._browserContext.initScripts)
|
for (const initScript of this._crPage._browserContext.initScripts)
|
||||||
promises.push(this._evaluateOnNewDocument(source, 'main'));
|
promises.push(this._evaluateOnNewDocument(initScript, 'main'));
|
||||||
for (const source of this._crPage._page.initScripts)
|
for (const initScript of this._crPage._page.initScripts)
|
||||||
promises.push(this._evaluateOnNewDocument(source, 'main'));
|
promises.push(this._evaluateOnNewDocument(initScript, 'main'));
|
||||||
if (screencastOptions)
|
if (screencastOptions)
|
||||||
promises.push(this._startVideoRecording(screencastOptions));
|
promises.push(this._startVideoRecording(screencastOptions));
|
||||||
}
|
}
|
||||||
@ -1099,9 +1099,9 @@ class FrameSession {
|
|||||||
await this._client.send('Page.setInterceptFileChooserDialog', { enabled }).catch(() => {}); // target can be closed.
|
await this._client.send('Page.setInterceptFileChooserDialog', { enabled }).catch(() => {}); // target can be closed.
|
||||||
}
|
}
|
||||||
|
|
||||||
async _evaluateOnNewDocument(source: string, world: types.World): Promise<void> {
|
async _evaluateOnNewDocument(initScript: InitScript, world: types.World): Promise<void> {
|
||||||
const worldName = world === 'utility' ? UTILITY_WORLD_NAME : undefined;
|
const worldName = world === 'utility' ? UTILITY_WORLD_NAME : undefined;
|
||||||
const { identifier } = await this._client.send('Page.addScriptToEvaluateOnNewDocument', { source, worldName });
|
const { identifier } = await this._client.send('Page.addScriptToEvaluateOnNewDocument', { source: initScript.source, worldName });
|
||||||
this._evaluateOnNewDocumentIdentifiers.push(identifier);
|
this._evaluateOnNewDocumentIdentifiers.push(identifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ import type { BrowserOptions } from '../browser';
|
|||||||
import { Browser } from '../browser';
|
import { Browser } from '../browser';
|
||||||
import { assertBrowserContextIsNotOwned, BrowserContext, verifyGeolocation } from '../browserContext';
|
import { assertBrowserContextIsNotOwned, BrowserContext, verifyGeolocation } from '../browserContext';
|
||||||
import * as network from '../network';
|
import * as network from '../network';
|
||||||
import type { Page, PageBinding, PageDelegate } from '../page';
|
import type { InitScript, Page, PageBinding, PageDelegate } from '../page';
|
||||||
import type { ConnectionTransport } from '../transport';
|
import type { ConnectionTransport } from '../transport';
|
||||||
import type * as types from '../types';
|
import type * as types from '../types';
|
||||||
import type * as channels from '@protocol/channels';
|
import type * as channels from '@protocol/channels';
|
||||||
@ -352,8 +352,8 @@ export class FFBrowserContext extends BrowserContext {
|
|||||||
await this._browser.session.send('Browser.setHTTPCredentials', { browserContextId: this._browserContextId, credentials });
|
await this._browser.session.send('Browser.setHTTPCredentials', { browserContextId: this._browserContextId, credentials });
|
||||||
}
|
}
|
||||||
|
|
||||||
async doAddInitScript(source: string) {
|
async doAddInitScript(initScript: InitScript) {
|
||||||
await this._browser.session.send('Browser.setInitScripts', { browserContextId: this._browserContextId, scripts: this.initScripts.map(script => ({ script })) });
|
await this._browser.session.send('Browser.setInitScripts', { browserContextId: this._browserContextId, scripts: this.initScripts.map(script => ({ script: script.source })) });
|
||||||
}
|
}
|
||||||
|
|
||||||
async doRemoveInitScripts() {
|
async doRemoveInitScripts() {
|
||||||
|
@ -21,6 +21,7 @@ import type * as frames from '../frames';
|
|||||||
import type { RegisteredListener } from '../../utils/eventsHelper';
|
import type { RegisteredListener } from '../../utils/eventsHelper';
|
||||||
import { eventsHelper } from '../../utils/eventsHelper';
|
import { eventsHelper } from '../../utils/eventsHelper';
|
||||||
import type { PageBinding, PageDelegate } from '../page';
|
import type { PageBinding, PageDelegate } from '../page';
|
||||||
|
import { InitScript } from '../page';
|
||||||
import { Page, Worker } from '../page';
|
import { Page, Worker } from '../page';
|
||||||
import type * as types from '../types';
|
import type * as types from '../types';
|
||||||
import { getAccessibilityTree } from './ffAccessibility';
|
import { getAccessibilityTree } from './ffAccessibility';
|
||||||
@ -56,7 +57,7 @@ export class FFPage implements PageDelegate {
|
|||||||
private _eventListeners: RegisteredListener[];
|
private _eventListeners: RegisteredListener[];
|
||||||
private _workers = new Map<string, { frameId: string, session: FFSession }>();
|
private _workers = new Map<string, { frameId: string, session: FFSession }>();
|
||||||
private _screencastId: string | undefined;
|
private _screencastId: string | undefined;
|
||||||
private _initScripts: { script: string, worldName?: string }[] = [];
|
private _initScripts: { initScript: InitScript, worldName?: string }[] = [];
|
||||||
|
|
||||||
constructor(session: FFSession, browserContext: FFBrowserContext, opener: FFPage | null) {
|
constructor(session: FFSession, browserContext: FFBrowserContext, opener: FFPage | null) {
|
||||||
this._session = session;
|
this._session = session;
|
||||||
@ -113,7 +114,7 @@ export class FFPage implements PageDelegate {
|
|||||||
});
|
});
|
||||||
// Ideally, we somehow ensure that utility world is created before Page.ready arrives, but currently it is racy.
|
// Ideally, we somehow ensure that utility world is created before Page.ready arrives, but currently it is racy.
|
||||||
// Therefore, we can end up with an initialized page without utility world, although very unlikely.
|
// Therefore, we can end up with an initialized page without utility world, although very unlikely.
|
||||||
this.addInitScript('', UTILITY_WORLD_NAME).catch(e => this._markAsError(e));
|
this.addInitScript(new InitScript(''), UTILITY_WORLD_NAME).catch(e => this._markAsError(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
potentiallyUninitializedPage(): Page {
|
potentiallyUninitializedPage(): Page {
|
||||||
@ -406,9 +407,9 @@ export class FFPage implements PageDelegate {
|
|||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
async addInitScript(script: string, worldName?: string): Promise<void> {
|
async addInitScript(initScript: InitScript, worldName?: string): Promise<void> {
|
||||||
this._initScripts.push({ script, worldName });
|
this._initScripts.push({ initScript, worldName });
|
||||||
await this._session.send('Page.setInitScripts', { scripts: this._initScripts });
|
await this._session.send('Page.setInitScripts', { scripts: this._initScripts.map(s => ({ script: s.initScript.source, worldName: s.worldName })) });
|
||||||
}
|
}
|
||||||
|
|
||||||
async removeInitScripts() {
|
async removeInitScripts() {
|
||||||
|
@ -31,7 +31,7 @@ import * as accessibility from './accessibility';
|
|||||||
import { FileChooser } from './fileChooser';
|
import { FileChooser } from './fileChooser';
|
||||||
import type { Progress } from './progress';
|
import type { Progress } from './progress';
|
||||||
import { ProgressController } from './progress';
|
import { ProgressController } from './progress';
|
||||||
import { LongStandingScope, assert, isError } from '../utils';
|
import { LongStandingScope, assert, createGuid, isError } from '../utils';
|
||||||
import { ManualPromise } from '../utils/manualPromise';
|
import { ManualPromise } from '../utils/manualPromise';
|
||||||
import { debugLogger } from '../utils/debugLogger';
|
import { debugLogger } from '../utils/debugLogger';
|
||||||
import type { ImageComparatorOptions } from '../utils/comparators';
|
import type { ImageComparatorOptions } from '../utils/comparators';
|
||||||
@ -56,7 +56,7 @@ export interface PageDelegate {
|
|||||||
goForward(): Promise<boolean>;
|
goForward(): Promise<boolean>;
|
||||||
exposeBinding(binding: PageBinding): Promise<void>;
|
exposeBinding(binding: PageBinding): Promise<void>;
|
||||||
removeExposedBindings(): Promise<void>;
|
removeExposedBindings(): Promise<void>;
|
||||||
addInitScript(source: string): Promise<void>;
|
addInitScript(initScript: InitScript): Promise<void>;
|
||||||
removeInitScripts(): Promise<void>;
|
removeInitScripts(): Promise<void>;
|
||||||
closePage(runBeforeUnload: boolean): Promise<void>;
|
closePage(runBeforeUnload: boolean): Promise<void>;
|
||||||
potentiallyUninitializedPage(): Page;
|
potentiallyUninitializedPage(): Page;
|
||||||
@ -154,7 +154,7 @@ export class Page extends SdkObject {
|
|||||||
private _emulatedMedia: Partial<EmulatedMedia> = {};
|
private _emulatedMedia: Partial<EmulatedMedia> = {};
|
||||||
private _interceptFileChooser = false;
|
private _interceptFileChooser = false;
|
||||||
private readonly _pageBindings = new Map<string, PageBinding>();
|
private readonly _pageBindings = new Map<string, PageBinding>();
|
||||||
readonly initScripts: string[] = [];
|
readonly initScripts: InitScript[] = [];
|
||||||
readonly _screenshotter: Screenshotter;
|
readonly _screenshotter: Screenshotter;
|
||||||
readonly _frameManager: frames.FrameManager;
|
readonly _frameManager: frames.FrameManager;
|
||||||
readonly accessibility: accessibility.Accessibility;
|
readonly accessibility: accessibility.Accessibility;
|
||||||
@ -527,8 +527,9 @@ export class Page extends SdkObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async addInitScript(source: string) {
|
async addInitScript(source: string) {
|
||||||
this.initScripts.push(source);
|
const initScript = new InitScript(source);
|
||||||
await this._delegate.addInitScript(source);
|
this.initScripts.push(initScript);
|
||||||
|
await this._delegate.addInitScript(initScript);
|
||||||
}
|
}
|
||||||
|
|
||||||
async _removeInitScripts() {
|
async _removeInitScripts() {
|
||||||
@ -905,6 +906,22 @@ function addPageBinding(bindingName: string, needsHandle: boolean, utilityScript
|
|||||||
(globalThis as any)[bindingName].__installed = true;
|
(globalThis as any)[bindingName].__installed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class InitScript {
|
||||||
|
readonly source: string;
|
||||||
|
|
||||||
|
constructor(source: string) {
|
||||||
|
const guid = createGuid();
|
||||||
|
this.source = `(() => {
|
||||||
|
globalThis.__pwInitScripts = globalThis.__pwInitScripts || {};
|
||||||
|
const hasInitScript = globalThis.__pwInitScripts[${JSON.stringify(guid)}];
|
||||||
|
if (hasInitScript)
|
||||||
|
return;
|
||||||
|
globalThis.__pwInitScripts[${JSON.stringify(guid)}] = true;
|
||||||
|
${source}
|
||||||
|
})();`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class FrameThrottler {
|
class FrameThrottler {
|
||||||
private _acks: (() => void)[] = [];
|
private _acks: (() => void)[] = [];
|
||||||
private _defaultInterval: number;
|
private _defaultInterval: number;
|
||||||
|
@ -22,7 +22,7 @@ import type { RegisteredListener } from '../../utils/eventsHelper';
|
|||||||
import { assert } from '../../utils';
|
import { assert } from '../../utils';
|
||||||
import { eventsHelper } from '../../utils/eventsHelper';
|
import { eventsHelper } from '../../utils/eventsHelper';
|
||||||
import * as network from '../network';
|
import * as network from '../network';
|
||||||
import type { Page, PageBinding, PageDelegate } from '../page';
|
import type { InitScript, Page, PageBinding, PageDelegate } from '../page';
|
||||||
import type { ConnectionTransport } from '../transport';
|
import type { ConnectionTransport } from '../transport';
|
||||||
import type * as types from '../types';
|
import type * as types from '../types';
|
||||||
import type * as channels from '@protocol/channels';
|
import type * as channels from '@protocol/channels';
|
||||||
@ -315,7 +315,7 @@ export class WKBrowserContext extends BrowserContext {
|
|||||||
await (page._delegate as WKPage).updateHttpCredentials();
|
await (page._delegate as WKPage).updateHttpCredentials();
|
||||||
}
|
}
|
||||||
|
|
||||||
async doAddInitScript(source: string) {
|
async doAddInitScript(initScript: InitScript) {
|
||||||
for (const page of this.pages())
|
for (const page of this.pages())
|
||||||
await (page._delegate as WKPage)._updateBootstrapScript();
|
await (page._delegate as WKPage)._updateBootstrapScript();
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@ import { eventsHelper } from '../../utils/eventsHelper';
|
|||||||
import { helper } from '../helper';
|
import { helper } from '../helper';
|
||||||
import type { JSHandle } from '../javascript';
|
import type { JSHandle } from '../javascript';
|
||||||
import * as network from '../network';
|
import * as network from '../network';
|
||||||
import type { PageBinding, PageDelegate } from '../page';
|
import type { InitScript, PageBinding, PageDelegate } from '../page';
|
||||||
import { Page } from '../page';
|
import { Page } from '../page';
|
||||||
import type { Progress } from '../progress';
|
import type { Progress } from '../progress';
|
||||||
import type * as types from '../types';
|
import type * as types from '../types';
|
||||||
@ -777,7 +777,7 @@ export class WKPage implements PageDelegate {
|
|||||||
await this._updateBootstrapScript();
|
await this._updateBootstrapScript();
|
||||||
}
|
}
|
||||||
|
|
||||||
async addInitScript(script: string): Promise<void> {
|
async addInitScript(initScript: InitScript): Promise<void> {
|
||||||
await this._updateBootstrapScript();
|
await this._updateBootstrapScript();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -797,8 +797,8 @@ export class WKPage implements PageDelegate {
|
|||||||
|
|
||||||
for (const binding of this._page.allBindings())
|
for (const binding of this._page.allBindings())
|
||||||
scripts.push(binding.source);
|
scripts.push(binding.source);
|
||||||
scripts.push(...this._browserContext.initScripts);
|
scripts.push(...this._browserContext.initScripts.map(s => s.source));
|
||||||
scripts.push(...this._page.initScripts);
|
scripts.push(...this._page.initScripts.map(s => s.source));
|
||||||
return scripts.join(';\n');
|
return scripts.join(';\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
68
tests/library/chromium/disable-web-security.spec.ts
Normal file
68
tests/library/chromium/disable-web-security.spec.ts
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2018 Google Inc. All rights reserved.
|
||||||
|
* Modifications copyright (c) Microsoft Corporation.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { contextTest as it, expect } from '../../config/browserTest';
|
||||||
|
|
||||||
|
it.use({
|
||||||
|
launchOptions: async ({ launchOptions }, use) => {
|
||||||
|
await use({ ...launchOptions, args: ['--disable-web-security'] });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('test utility world in popup w/ --disable-web-security', async ({ page, server }) => {
|
||||||
|
server.setRoute('/main.html', (req, res) => {
|
||||||
|
res.writeHead(200, {
|
||||||
|
'Content-Type': 'text/html'
|
||||||
|
});
|
||||||
|
res.end(`<a href="${server.PREFIX}/target.html" target="_blank">Click me</a>`);
|
||||||
|
});
|
||||||
|
server.setRoute('/target.html', (req, res) => {
|
||||||
|
res.writeHead(200, {
|
||||||
|
'Content-Type': 'text/html'
|
||||||
|
});
|
||||||
|
res.end(`<html></html>`);
|
||||||
|
});
|
||||||
|
|
||||||
|
await page.goto(server.PREFIX + '/main.html');
|
||||||
|
const page1Promise = page.context().waitForEvent('page');
|
||||||
|
await page.getByRole('link', { name: 'Click me' }).click();
|
||||||
|
const page1 = await page1Promise;
|
||||||
|
await expect(page1).toHaveURL(/target/);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('test init script w/ --disable-web-security', async ({ page, server }) => {
|
||||||
|
server.setRoute('/main.html', (req, res) => {
|
||||||
|
res.writeHead(200, {
|
||||||
|
'Content-Type': 'text/html'
|
||||||
|
});
|
||||||
|
res.end(`<a href="${server.PREFIX}/target.html" target="_blank">Click me</a>`);
|
||||||
|
});
|
||||||
|
server.setRoute('/target.html', (req, res) => {
|
||||||
|
res.writeHead(200, {
|
||||||
|
'Content-Type': 'text/html'
|
||||||
|
});
|
||||||
|
res.end(`<html></html>`);
|
||||||
|
});
|
||||||
|
|
||||||
|
await page.context().addInitScript('window.injected = 123');
|
||||||
|
await page.goto(server.PREFIX + '/main.html');
|
||||||
|
const page1Promise = page.context().waitForEvent('page');
|
||||||
|
await page.getByRole('link', { name: 'Click me' }).click();
|
||||||
|
const page1 = await page1Promise;
|
||||||
|
const value = await page1.evaluate('window.injected');
|
||||||
|
expect(value).toBe(123);
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user