fix(webkit): move UI process agents to page proxy (#416)
This commit is contained in:
parent
eab5108719
commit
80ffd92552
|
|
@ -10,7 +10,7 @@
|
||||||
"playwright": {
|
"playwright": {
|
||||||
"chromium_revision": "724623",
|
"chromium_revision": "724623",
|
||||||
"firefox_revision": "1009",
|
"firefox_revision": "1009",
|
||||||
"webkit_revision": "1068"
|
"webkit_revision": "1070"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"unit": "node test/test.js",
|
"unit": "node test/test.js",
|
||||||
|
|
|
||||||
|
|
@ -96,7 +96,7 @@ export class WKBrowser extends browser.Browser {
|
||||||
}
|
}
|
||||||
if (!context)
|
if (!context)
|
||||||
context = this._defaultContext;
|
context = this._defaultContext;
|
||||||
const pageProxy = new WKPageProxy(this, session, context);
|
const pageProxy = new WKPageProxy(session, context);
|
||||||
this._pageProxies.set(pageProxyInfo.pageProxyId, pageProxy);
|
this._pageProxies.set(pageProxyInfo.pageProxyId, pageProxy);
|
||||||
|
|
||||||
if (pageProxyInfo.openerId) {
|
if (pageProxyInfo.openerId) {
|
||||||
|
|
|
||||||
|
|
@ -139,8 +139,9 @@ export const WKTargetSessionEvents = {
|
||||||
export class WKPageProxySession extends platform.EventEmitter {
|
export class WKPageProxySession extends platform.EventEmitter {
|
||||||
_connection: WKConnection;
|
_connection: WKConnection;
|
||||||
private readonly _sessions = new Map<string, WKTargetSession>();
|
private readonly _sessions = new Map<string, WKTargetSession>();
|
||||||
private readonly _callbacks = new Map<number, {resolve:(o: any) => void, reject: (e: Error) => void, error: Error, method: string}>();
|
|
||||||
private readonly _pageProxyId: string;
|
private readonly _pageProxyId: string;
|
||||||
|
private readonly _closePromise: Promise<void>;
|
||||||
|
private _closePromiseCallback: () => void;
|
||||||
on: <T extends keyof Protocol.Events | symbol>(event: T, listener: (payload: T extends symbol ? any : Protocol.Events[T extends keyof Protocol.Events ? T : never]) => void) => this;
|
on: <T extends keyof Protocol.Events | symbol>(event: T, listener: (payload: T extends symbol ? any : Protocol.Events[T extends keyof Protocol.Events ? T : never]) => void) => this;
|
||||||
addListener: <T extends keyof Protocol.Events | symbol>(event: T, listener: (payload: T extends symbol ? any : Protocol.Events[T extends keyof Protocol.Events ? T : never]) => void) => this;
|
addListener: <T extends keyof Protocol.Events | symbol>(event: T, listener: (payload: T extends symbol ? any : Protocol.Events[T extends keyof Protocol.Events ? T : never]) => void) => this;
|
||||||
off: <T extends keyof Protocol.Events | symbol>(event: T, listener: (payload: T extends symbol ? any : Protocol.Events[T extends keyof Protocol.Events ? T : never]) => void) => this;
|
off: <T extends keyof Protocol.Events | symbol>(event: T, listener: (payload: T extends symbol ? any : Protocol.Events[T extends keyof Protocol.Events ? T : never]) => void) => this;
|
||||||
|
|
@ -151,6 +152,7 @@ export class WKPageProxySession extends platform.EventEmitter {
|
||||||
super();
|
super();
|
||||||
this._connection = connection;
|
this._connection = connection;
|
||||||
this._pageProxyId = pageProxyId;
|
this._pageProxyId = pageProxyId;
|
||||||
|
this._closePromise = new Promise(r => this._closePromiseCallback = r);
|
||||||
}
|
}
|
||||||
|
|
||||||
send<T extends keyof Protocol.CommandParameters>(
|
send<T extends keyof Protocol.CommandParameters>(
|
||||||
|
|
@ -159,11 +161,10 @@ export class WKPageProxySession extends platform.EventEmitter {
|
||||||
): Promise<Protocol.CommandReturnValues[T]> {
|
): Promise<Protocol.CommandReturnValues[T]> {
|
||||||
if (!this._connection)
|
if (!this._connection)
|
||||||
return Promise.reject(new Error(`Protocol error (${method}): Session closed. Most likely the pageProxy has been closed.`));
|
return Promise.reject(new Error(`Protocol error (${method}): Session closed. Most likely the pageProxy has been closed.`));
|
||||||
return this._connection.send(method, params, this._pageProxyId).catch(e => {
|
return Promise.race([
|
||||||
// There is a possible race of the connection closure. We may have received
|
this._closePromise.then(() => { throw new Error('Page proxy closed'); }),
|
||||||
// targetDestroyed notification before response for the command, in that
|
this._connection.send(method, params, this._pageProxyId)
|
||||||
// case it's safe to swallow the exception.
|
]);
|
||||||
}) as Promise<Protocol.CommandReturnValues[T]>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_dispatchEvent(object: {method: string, params: any, pageProxyId?: string}, wrappedMessage: string) {
|
_dispatchEvent(object: {method: string, params: any, pageProxyId?: string}, wrappedMessage: string) {
|
||||||
|
|
@ -205,11 +206,16 @@ export class WKPageProxySession extends platform.EventEmitter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isClosed() {
|
||||||
|
return !this._connection;
|
||||||
|
}
|
||||||
|
|
||||||
dispose() {
|
dispose() {
|
||||||
for (const session of this._sessions.values())
|
for (const session of this._sessions.values())
|
||||||
session._onClosed();
|
session._onClosed();
|
||||||
this._sessions.clear();
|
this._sessions.clear();
|
||||||
|
|
||||||
|
this._closePromiseCallback();
|
||||||
this._connection = null;
|
this._connection = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@
|
||||||
import * as input from '../input';
|
import * as input from '../input';
|
||||||
import { helper } from '../helper';
|
import { helper } from '../helper';
|
||||||
import { macEditingCommands } from '../usKeyboardLayout';
|
import { macEditingCommands } from '../usKeyboardLayout';
|
||||||
import { WKTargetSession } from './wkConnection';
|
import { WKPageProxySession, WKTargetSession } from './wkConnection';
|
||||||
|
|
||||||
function toModifiersMask(modifiers: Set<input.Modifier>): number {
|
function toModifiersMask(modifiers: Set<input.Modifier>): number {
|
||||||
// From Source/WebKit/Shared/WebEvent.h
|
// From Source/WebKit/Shared/WebEvent.h
|
||||||
|
|
@ -35,8 +35,13 @@ function toModifiersMask(modifiers: Set<input.Modifier>): number {
|
||||||
}
|
}
|
||||||
|
|
||||||
export class RawKeyboardImpl implements input.RawKeyboard {
|
export class RawKeyboardImpl implements input.RawKeyboard {
|
||||||
|
private readonly _pageProxySession: WKPageProxySession;
|
||||||
private _session: WKTargetSession;
|
private _session: WKTargetSession;
|
||||||
|
|
||||||
|
constructor(session: WKPageProxySession) {
|
||||||
|
this._pageProxySession = session;
|
||||||
|
}
|
||||||
|
|
||||||
setSession(session: WKTargetSession) {
|
setSession(session: WKTargetSession) {
|
||||||
this._session = session;
|
this._session = session;
|
||||||
}
|
}
|
||||||
|
|
@ -52,7 +57,7 @@ export class RawKeyboardImpl implements input.RawKeyboard {
|
||||||
let commands = macEditingCommands[shortcut];
|
let commands = macEditingCommands[shortcut];
|
||||||
if (helper.isString(commands))
|
if (helper.isString(commands))
|
||||||
commands = [commands];
|
commands = [commands];
|
||||||
await this._session.send('Input.dispatchKeyEvent', {
|
await this._pageProxySession.send('Input.dispatchKeyEvent', {
|
||||||
type: 'keyDown',
|
type: 'keyDown',
|
||||||
modifiers: toModifiersMask(modifiers),
|
modifiers: toModifiersMask(modifiers),
|
||||||
windowsVirtualKeyCode: keyCode,
|
windowsVirtualKeyCode: keyCode,
|
||||||
|
|
@ -67,7 +72,7 @@ export class RawKeyboardImpl implements input.RawKeyboard {
|
||||||
}
|
}
|
||||||
|
|
||||||
async keyup(modifiers: Set<input.Modifier>, code: string, keyCode: number, keyCodeWithoutLocation: number, key: string, location: number): Promise<void> {
|
async keyup(modifiers: Set<input.Modifier>, code: string, keyCode: number, keyCodeWithoutLocation: number, key: string, location: number): Promise<void> {
|
||||||
await this._session.send('Input.dispatchKeyEvent', {
|
await this._pageProxySession.send('Input.dispatchKeyEvent', {
|
||||||
type: 'keyUp',
|
type: 'keyUp',
|
||||||
modifiers: toModifiersMask(modifiers),
|
modifiers: toModifiersMask(modifiers),
|
||||||
key,
|
key,
|
||||||
|
|
@ -83,14 +88,14 @@ export class RawKeyboardImpl implements input.RawKeyboard {
|
||||||
}
|
}
|
||||||
|
|
||||||
export class RawMouseImpl implements input.RawMouse {
|
export class RawMouseImpl implements input.RawMouse {
|
||||||
private _client: WKTargetSession;
|
private readonly _pageProxySession: WKPageProxySession;
|
||||||
|
|
||||||
setSession(client: WKTargetSession) {
|
constructor(session: WKPageProxySession) {
|
||||||
this._client = client;
|
this._pageProxySession = session;
|
||||||
}
|
}
|
||||||
|
|
||||||
async move(x: number, y: number, button: input.Button | 'none', buttons: Set<input.Button>, modifiers: Set<input.Modifier>): Promise<void> {
|
async move(x: number, y: number, button: input.Button | 'none', buttons: Set<input.Button>, modifiers: Set<input.Modifier>): Promise<void> {
|
||||||
await this._client.send('Input.dispatchMouseEvent', {
|
await this._pageProxySession.send('Input.dispatchMouseEvent', {
|
||||||
type: 'move',
|
type: 'move',
|
||||||
button,
|
button,
|
||||||
x,
|
x,
|
||||||
|
|
@ -100,7 +105,7 @@ export class RawMouseImpl implements input.RawMouse {
|
||||||
}
|
}
|
||||||
|
|
||||||
async down(x: number, y: number, button: input.Button, buttons: Set<input.Button>, modifiers: Set<input.Modifier>, clickCount: number): Promise<void> {
|
async down(x: number, y: number, button: input.Button, buttons: Set<input.Button>, modifiers: Set<input.Modifier>, clickCount: number): Promise<void> {
|
||||||
await this._client.send('Input.dispatchMouseEvent', {
|
await this._pageProxySession.send('Input.dispatchMouseEvent', {
|
||||||
type: 'down',
|
type: 'down',
|
||||||
button,
|
button,
|
||||||
x,
|
x,
|
||||||
|
|
@ -111,7 +116,7 @@ export class RawMouseImpl implements input.RawMouse {
|
||||||
}
|
}
|
||||||
|
|
||||||
async up(x: number, y: number, button: input.Button, buttons: Set<input.Button>, modifiers: Set<input.Modifier>, clickCount: number): Promise<void> {
|
async up(x: number, y: number, button: input.Button, buttons: Set<input.Button>, modifiers: Set<input.Modifier>, clickCount: number): Promise<void> {
|
||||||
await this._client.send('Input.dispatchMouseEvent', {
|
await this._pageProxySession.send('Input.dispatchMouseEvent', {
|
||||||
type: 'up',
|
type: 'up',
|
||||||
button,
|
button,
|
||||||
x,
|
x,
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { WKTargetSession } from './wkConnection';
|
import { WKTargetSession, WKPageProxySession } from './wkConnection';
|
||||||
import { Page } from '../page';
|
import { Page } from '../page';
|
||||||
import { helper, RegisteredListener, assert } from '../helper';
|
import { helper, RegisteredListener, assert } from '../helper';
|
||||||
import { Protocol } from './protocol';
|
import { Protocol } from './protocol';
|
||||||
|
|
@ -25,14 +25,20 @@ import * as types from '../types';
|
||||||
import * as platform from '../platform';
|
import * as platform from '../platform';
|
||||||
|
|
||||||
export class WKNetworkManager {
|
export class WKNetworkManager {
|
||||||
|
private readonly _page: Page;
|
||||||
|
private readonly _pageProxySession: WKPageProxySession;
|
||||||
private _session: WKTargetSession;
|
private _session: WKTargetSession;
|
||||||
_page: Page;
|
private readonly _requestIdToRequest = new Map<string, InterceptableRequest>();
|
||||||
private _requestIdToRequest = new Map<string, InterceptableRequest>();
|
|
||||||
private _userCacheDisabled = false;
|
private _userCacheDisabled = false;
|
||||||
private _sessionListeners: RegisteredListener[] = [];
|
private _sessionListeners: RegisteredListener[] = [];
|
||||||
|
|
||||||
constructor(page: Page) {
|
constructor(page: Page, pageProxySession: WKPageProxySession) {
|
||||||
this._page = page;
|
this._page = page;
|
||||||
|
this._pageProxySession = pageProxySession;
|
||||||
|
}
|
||||||
|
|
||||||
|
async initializePageProxySession(credentials: types.Credentials | null) {
|
||||||
|
await this.authenticate(credentials);
|
||||||
}
|
}
|
||||||
|
|
||||||
setSession(session: WKTargetSession) {
|
setSession(session: WKTargetSession) {
|
||||||
|
|
@ -47,17 +53,13 @@ export class WKNetworkManager {
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
async initializeSession(session: WKTargetSession, interceptNetwork: boolean | null, offlineMode: boolean | null, credentials: types.Credentials | null) {
|
async initializeSession(session: WKTargetSession, interceptNetwork: boolean | null, offlineMode: boolean | null) {
|
||||||
const promises = [];
|
const promises = [];
|
||||||
promises.push(session.send('Network.enable'));
|
promises.push(session.send('Network.enable'));
|
||||||
if (interceptNetwork)
|
if (interceptNetwork)
|
||||||
promises.push(session.send('Network.setInterceptionEnabled', { enabled: true }));
|
promises.push(session.send('Network.setInterceptionEnabled', { enabled: true }));
|
||||||
if (offlineMode)
|
if (offlineMode)
|
||||||
promises.push(session.send('Network.setEmulateOfflineState', { offline: true }));
|
promises.push(session.send('Network.setEmulateOfflineState', { offline: true }));
|
||||||
if (credentials)
|
|
||||||
promises.push(session.send('Emulation.setAuthCredentials', { ...credentials }));
|
|
||||||
else
|
|
||||||
promises.push(session.send('Emulation.setAuthCredentials', { username: '', password: '' }));
|
|
||||||
await Promise.all(promises);
|
await Promise.all(promises);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -160,7 +162,7 @@ export class WKNetworkManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
async authenticate(credentials: types.Credentials | null) {
|
async authenticate(credentials: types.Credentials | null) {
|
||||||
await this._session.send('Emulation.setAuthCredentials', { ...(credentials || {}) });
|
await this._pageProxySession.send('Emulation.setAuthCredentials', { ...(credentials || { username: '', password: '' }) });
|
||||||
}
|
}
|
||||||
|
|
||||||
async setOfflineMode(value: boolean): Promise<void> {
|
async setOfflineMode(value: boolean): Promise<void> {
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ import * as frames from '../frames';
|
||||||
import { debugError, helper, RegisteredListener } from '../helper';
|
import { debugError, helper, RegisteredListener } from '../helper';
|
||||||
import * as dom from '../dom';
|
import * as dom from '../dom';
|
||||||
import * as network from '../network';
|
import * as network from '../network';
|
||||||
import { WKTargetSession, WKTargetSessionEvents } from './wkConnection';
|
import { WKTargetSession, WKTargetSessionEvents, WKPageProxySession } from './wkConnection';
|
||||||
import { Events } from '../events';
|
import { Events } from '../events';
|
||||||
import { WKExecutionContext, EVALUATION_SCRIPT_URL } from './wkExecutionContext';
|
import { WKExecutionContext, EVALUATION_SCRIPT_URL } from './wkExecutionContext';
|
||||||
import { WKNetworkManager } from './wkNetworkManager';
|
import { WKNetworkManager } from './wkNetworkManager';
|
||||||
|
|
@ -43,31 +43,43 @@ export class WKPage implements PageDelegate {
|
||||||
readonly rawKeyboard: RawKeyboardImpl;
|
readonly rawKeyboard: RawKeyboardImpl;
|
||||||
_session: WKTargetSession;
|
_session: WKTargetSession;
|
||||||
readonly _page: Page;
|
readonly _page: Page;
|
||||||
private _browser: WKBrowser;
|
private readonly _pageProxySession: WKPageProxySession;
|
||||||
private _networkManager: WKNetworkManager;
|
private readonly _networkManager: WKNetworkManager;
|
||||||
private _workers: WKWorkers;
|
private readonly _workers: WKWorkers;
|
||||||
private _contextIdToContext: Map<number, dom.FrameExecutionContext>;
|
private readonly _contextIdToContext: Map<number, dom.FrameExecutionContext>;
|
||||||
private _isolatedWorlds: Set<string>;
|
private _isolatedWorlds: Set<string>;
|
||||||
private _sessionListeners: RegisteredListener[] = [];
|
private _sessionListeners: RegisteredListener[] = [];
|
||||||
private _bootstrapScripts: string[] = [];
|
private readonly _bootstrapScripts: string[] = [];
|
||||||
|
|
||||||
constructor(browser: WKBrowser, browserContext: BrowserContext) {
|
constructor(browserContext: BrowserContext, pageProxySession: WKPageProxySession) {
|
||||||
this._browser = browser;
|
this._pageProxySession = pageProxySession;
|
||||||
this.rawKeyboard = new RawKeyboardImpl();
|
this.rawKeyboard = new RawKeyboardImpl(pageProxySession);
|
||||||
this.rawMouse = new RawMouseImpl();
|
this.rawMouse = new RawMouseImpl(pageProxySession);
|
||||||
this._contextIdToContext = new Map();
|
this._contextIdToContext = new Map();
|
||||||
this._isolatedWorlds = new Set();
|
this._isolatedWorlds = new Set();
|
||||||
this._page = new Page(this, browserContext);
|
this._page = new Page(this, browserContext);
|
||||||
this._networkManager = new WKNetworkManager(this._page);
|
this._networkManager = new WKNetworkManager(this._page, pageProxySession);
|
||||||
this._workers = new WKWorkers(this._page);
|
this._workers = new WKWorkers(this._page);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async _initializePageProxySession() {
|
||||||
|
const promises : Promise<any>[] = [
|
||||||
|
this._pageProxySession.send('Dialog.enable'),
|
||||||
|
this._networkManager.initializePageProxySession(this._page._state.credentials)
|
||||||
|
];
|
||||||
|
const contextOptions = this._page.browserContext()._options;
|
||||||
|
if (contextOptions.javaScriptEnabled === false)
|
||||||
|
promises.push(this._pageProxySession.send('Emulation.setJavaScriptEnabled', { enabled: false }));
|
||||||
|
if (this._page._state.viewport)
|
||||||
|
promises.push(this.setViewport(this._page._state.viewport));
|
||||||
|
await Promise.all(promises);
|
||||||
|
}
|
||||||
|
|
||||||
setSession(session: WKTargetSession) {
|
setSession(session: WKTargetSession) {
|
||||||
helper.removeEventListeners(this._sessionListeners);
|
helper.removeEventListeners(this._sessionListeners);
|
||||||
this.disconnectFromTarget();
|
this.disconnectFromTarget();
|
||||||
this._session = session;
|
this._session = session;
|
||||||
this.rawKeyboard.setSession(session);
|
this.rawKeyboard.setSession(session);
|
||||||
this.rawMouse.setSession(session);
|
|
||||||
this._addSessionListeners();
|
this._addSessionListeners();
|
||||||
this._networkManager.setSession(session);
|
this._networkManager.setSession(session);
|
||||||
this._workers.setSession(session);
|
this._workers.setSession(session);
|
||||||
|
|
@ -90,30 +102,28 @@ export class WKPage implements PageDelegate {
|
||||||
session.send('Runtime.enable').then(() => this._ensureIsolatedWorld(UTILITY_WORLD_NAME)),
|
session.send('Runtime.enable').then(() => this._ensureIsolatedWorld(UTILITY_WORLD_NAME)),
|
||||||
session.send('Console.enable'),
|
session.send('Console.enable'),
|
||||||
session.send('Page.setInterceptFileChooserDialog', { enabled: true }),
|
session.send('Page.setInterceptFileChooserDialog', { enabled: true }),
|
||||||
this._networkManager.initializeSession(session, this._page._state.interceptNetwork, this._page._state.offlineMode, this._page._state.credentials),
|
this._networkManager.initializeSession(session, this._page._state.interceptNetwork, this._page._state.offlineMode),
|
||||||
this._workers.initializeSession(session)
|
this._workers.initializeSession(session),
|
||||||
];
|
];
|
||||||
if (!session.isProvisional()) {
|
|
||||||
// FIXME: move dialog agent to web process.
|
|
||||||
// Dialog agent resides in the UI process and should not be re-enabled on navigation.
|
|
||||||
promises.push(session.send('Dialog.enable'));
|
|
||||||
}
|
|
||||||
const contextOptions = this._page.browserContext()._options;
|
const contextOptions = this._page.browserContext()._options;
|
||||||
if (contextOptions.userAgent)
|
if (contextOptions.userAgent)
|
||||||
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(this._setEmulateMedia(session, this._page._state.mediaType, this._page._state.colorScheme));
|
promises.push(this._setEmulateMedia(session, this._page._state.mediaType, this._page._state.colorScheme));
|
||||||
if (contextOptions.javaScriptEnabled === false)
|
|
||||||
promises.push(session.send('Emulation.setJavaScriptEnabled', { enabled: false }));
|
|
||||||
if (session.isProvisional())
|
if (session.isProvisional())
|
||||||
promises.push(this._setBootstrapScripts(session));
|
promises.push(this._setBootstrapScripts(session));
|
||||||
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.extraHTTPHeaders !== null)
|
if (this._page._state.extraHTTPHeaders !== null)
|
||||||
promises.push(this._setExtraHTTPHeaders(session, this._page._state.extraHTTPHeaders));
|
promises.push(this._setExtraHTTPHeaders(session, this._page._state.extraHTTPHeaders));
|
||||||
if (this._page._state.viewport)
|
await Promise.all(promises).catch(e => {
|
||||||
promises.push(WKPage._setViewport(session, this._page._state.viewport));
|
if (session.isClosed())
|
||||||
await Promise.all(promises);
|
return;
|
||||||
|
// Swallow initialization errors due to newer target swap in,
|
||||||
|
// since we will reinitialize again.
|
||||||
|
if (this._session === session)
|
||||||
|
throw e;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
didClose(crashed: boolean) {
|
didClose(crashed: boolean) {
|
||||||
|
|
@ -137,7 +147,7 @@ export class WKPage implements PageDelegate {
|
||||||
helper.addEventListener(this._session, 'Page.domContentEventFired', event => this._onLifecycleEvent(event.frameId, 'domcontentloaded')),
|
helper.addEventListener(this._session, 'Page.domContentEventFired', event => this._onLifecycleEvent(event.frameId, 'domcontentloaded')),
|
||||||
helper.addEventListener(this._session, 'Runtime.executionContextCreated', event => this._onExecutionContextCreated(event.context)),
|
helper.addEventListener(this._session, 'Runtime.executionContextCreated', event => this._onExecutionContextCreated(event.context)),
|
||||||
helper.addEventListener(this._session, 'Console.messageAdded', event => this._onConsoleMessage(event)),
|
helper.addEventListener(this._session, 'Console.messageAdded', event => this._onConsoleMessage(event)),
|
||||||
helper.addEventListener(this._session, 'Dialog.javascriptDialogOpening', event => this._onDialog(event)),
|
helper.addEventListener(this._pageProxySession, 'Dialog.javascriptDialogOpening', event => this._onDialog(event)),
|
||||||
helper.addEventListener(this._session, 'Page.fileChooserOpened', event => this._onFileChooserOpened(event)),
|
helper.addEventListener(this._session, 'Page.fileChooserOpened', event => this._onFileChooserOpened(event)),
|
||||||
helper.addEventListener(this._session, WKTargetSessionEvents.Disconnected, event => this._page._didDisconnect()),
|
helper.addEventListener(this._session, WKTargetSessionEvents.Disconnected, event => this._page._didDisconnect()),
|
||||||
];
|
];
|
||||||
|
|
@ -259,7 +269,7 @@ export class WKPage implements PageDelegate {
|
||||||
event.type as dialog.DialogType,
|
event.type as dialog.DialogType,
|
||||||
event.message,
|
event.message,
|
||||||
async (accept: boolean, promptText?: string) => {
|
async (accept: boolean, promptText?: string) => {
|
||||||
await this._session.send('Dialog.handleJavaScriptDialog', { accept, promptText });
|
await this._pageProxySession.send('Dialog.handleJavaScriptDialog', { accept, promptText });
|
||||||
},
|
},
|
||||||
event.defaultPrompt));
|
event.defaultPrompt));
|
||||||
}
|
}
|
||||||
|
|
@ -307,15 +317,11 @@ export class WKPage implements PageDelegate {
|
||||||
}
|
}
|
||||||
|
|
||||||
async setViewport(viewport: types.Viewport): Promise<void> {
|
async setViewport(viewport: types.Viewport): Promise<void> {
|
||||||
return WKPage._setViewport(this._session, viewport);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static async _setViewport(session: WKTargetSession, viewport: types.Viewport): Promise<void> {
|
|
||||||
if (viewport.isMobile || viewport.isLandscape || viewport.hasTouch)
|
if (viewport.isMobile || viewport.isLandscape || viewport.hasTouch)
|
||||||
throw new Error('Not implemented');
|
throw new Error('Not implemented');
|
||||||
const width = viewport.width;
|
const width = viewport.width;
|
||||||
const height = viewport.height;
|
const height = viewport.height;
|
||||||
await session.send('Emulation.setDeviceMetricsOverride', { width, height, fixedLayout: false, deviceScaleFactor: viewport.deviceScaleFactor || 1 });
|
await this._pageProxySession.send('Emulation.setDeviceMetricsOverride', { width, height, fixedLayout: false, deviceScaleFactor: viewport.deviceScaleFactor || 1 });
|
||||||
}
|
}
|
||||||
|
|
||||||
setCacheEnabled(enabled: boolean): Promise<void> {
|
setCacheEnabled(enabled: boolean): Promise<void> {
|
||||||
|
|
@ -402,7 +408,7 @@ export class WKPage implements PageDelegate {
|
||||||
}
|
}
|
||||||
|
|
||||||
async resetViewport(oldSize: types.Size): Promise<void> {
|
async resetViewport(oldSize: types.Size): Promise<void> {
|
||||||
await this._session.send('Emulation.setDeviceMetricsOverride', { ...oldSize, fixedLayout: false, deviceScaleFactor: 0 });
|
await this._pageProxySession.send('Emulation.setDeviceMetricsOverride', { ...oldSize, fixedLayout: false, deviceScaleFactor: 0 });
|
||||||
}
|
}
|
||||||
|
|
||||||
async getContentFrame(handle: dom.ElementHandle): Promise<frames.Frame | null> {
|
async getContentFrame(handle: dom.ElementHandle): Promise<frames.Frame | null> {
|
||||||
|
|
|
||||||
|
|
@ -7,12 +7,10 @@ import { Page } from '../page';
|
||||||
import { Protocol } from './protocol';
|
import { Protocol } from './protocol';
|
||||||
import { WKPageProxySession, WKPageProxySessionEvents, WKTargetSession } from './wkConnection';
|
import { WKPageProxySession, WKPageProxySessionEvents, WKTargetSession } from './wkConnection';
|
||||||
import { WKPage } from './wkPage';
|
import { WKPage } from './wkPage';
|
||||||
import { WKBrowser } from './wkBrowser';
|
|
||||||
import { RegisteredListener, helper, assert, debugError } from '../helper';
|
import { RegisteredListener, helper, assert, debugError } from '../helper';
|
||||||
import { Events } from '../events';
|
import { Events } from '../events';
|
||||||
|
|
||||||
export class WKPageProxy {
|
export class WKPageProxy {
|
||||||
private readonly _browser: WKBrowser;
|
|
||||||
private readonly _pageProxySession: WKPageProxySession;
|
private readonly _pageProxySession: WKPageProxySession;
|
||||||
readonly _browserContext: BrowserContext;
|
readonly _browserContext: BrowserContext;
|
||||||
private _pagePromise: Promise<Page> | null = null;
|
private _pagePromise: Promise<Page> | null = null;
|
||||||
|
|
@ -22,8 +20,7 @@ export class WKPageProxy {
|
||||||
private readonly _targetSessions = new Map<string, WKTargetSession>();
|
private readonly _targetSessions = new Map<string, WKTargetSession>();
|
||||||
private readonly _eventListeners: RegisteredListener[];
|
private readonly _eventListeners: RegisteredListener[];
|
||||||
|
|
||||||
constructor(browser: WKBrowser, session: WKPageProxySession, browserContext: BrowserContext) {
|
constructor(session: WKPageProxySession, browserContext: BrowserContext) {
|
||||||
this._browser = browser;
|
|
||||||
this._pageProxySession = session;
|
this._pageProxySession = session;
|
||||||
this._browserContext = browserContext;
|
this._browserContext = browserContext;
|
||||||
this._firstTargetPromise = new Promise(r => this._firstTargetCallback = r);
|
this._firstTargetPromise = new Promise(r => this._firstTargetCallback = r);
|
||||||
|
|
@ -35,6 +32,8 @@ export class WKPageProxy {
|
||||||
|
|
||||||
// Intercept provisional targets during cross-process navigation.
|
// Intercept provisional targets during cross-process navigation.
|
||||||
this._pageProxySession.send('Target.setPauseOnStart', { pauseOnStart: true }).catch(e => {
|
this._pageProxySession.send('Target.setPauseOnStart', { pauseOnStart: true }).catch(e => {
|
||||||
|
if (this._pageProxySession.isClosed())
|
||||||
|
return;
|
||||||
debugError(e);
|
debugError(e);
|
||||||
throw e;
|
throw e;
|
||||||
});
|
});
|
||||||
|
|
@ -68,23 +67,15 @@ export class WKPageProxy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert(session, 'One non-provisional target session must exist');
|
assert(session, 'One non-provisional target session must exist');
|
||||||
this._wkPage = new WKPage(this._browser, this._browserContext);
|
this._wkPage = new WKPage(this._browserContext, this._pageProxySession);
|
||||||
this._wkPage.setSession(session);
|
this._wkPage.setSession(session);
|
||||||
await this._initializeSession(session);
|
await Promise.all([
|
||||||
|
this._wkPage._initializePageProxySession(),
|
||||||
|
this._wkPage._initializeSession(session)
|
||||||
|
]);
|
||||||
return this._wkPage._page;
|
return this._wkPage._page;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _initializeSession(session: WKTargetSession) : Promise<void> {
|
|
||||||
return this._wkPage._initializeSession(session).catch(e => {
|
|
||||||
if (session.isClosed())
|
|
||||||
return;
|
|
||||||
// Swallow initialization errors due to newer target swap in,
|
|
||||||
// since we will reinitialize again.
|
|
||||||
if (this._wkPage._session === session)
|
|
||||||
throw e;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private _onTargetCreated(session: WKTargetSession, targetInfo: Protocol.Target.TargetInfo) {
|
private _onTargetCreated(session: WKTargetSession, targetInfo: Protocol.Target.TargetInfo) {
|
||||||
assert(targetInfo.type === 'page', 'Only page targets are expected in WebKit, received: ' + targetInfo.type);
|
assert(targetInfo.type === 'page', 'Only page targets are expected in WebKit, received: ' + targetInfo.type);
|
||||||
this._targetSessions.set(targetInfo.targetId, session);
|
this._targetSessions.set(targetInfo.targetId, session);
|
||||||
|
|
@ -93,7 +84,7 @@ export class WKPageProxy {
|
||||||
this._firstTargetCallback = null;
|
this._firstTargetCallback = null;
|
||||||
}
|
}
|
||||||
if (targetInfo.isProvisional && this._wkPage)
|
if (targetInfo.isProvisional && this._wkPage)
|
||||||
this._initializeSession(session);
|
this._wkPage._initializeSession(session);
|
||||||
if (targetInfo.isPaused)
|
if (targetInfo.isPaused)
|
||||||
this._pageProxySession.send('Target.resume', { targetId: targetInfo.targetId }).catch(debugError);
|
this._pageProxySession.send('Target.resume', { targetId: targetInfo.targetId }).catch(debugError);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue