"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.WorkerDispatcher = exports.PageDispatcher = exports.BindingCallDispatcher = void 0; var _page = require("../page"); var _dispatcher = require("./dispatcher"); var _errors = require("../errors"); var _frameDispatcher = require("./frameDispatcher"); var _networkDispatchers = require("./networkDispatchers"); var _jsHandleDispatcher = require("./jsHandleDispatcher"); var _elementHandlerDispatcher = require("./elementHandlerDispatcher"); var _artifactDispatcher = require("./artifactDispatcher"); var _utils = require("../../utils"); /** * 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. */ class PageDispatcher extends _dispatcher.Dispatcher { static from(parentScope, page) { return PageDispatcher.fromNullable(parentScope, page); } static fromNullable(parentScope, page) { if (!page) return undefined; const result = (0, _dispatcher.existingDispatcher)(page); return result || new PageDispatcher(parentScope, page); } constructor(parentScope, page) { // TODO: theoretically, there could be more than one frame already. // If we split pageCreated and pageReady, there should be no main frame during pageCreated. // We will reparent it to the page below using adopt. const mainFrame = _frameDispatcher.FrameDispatcher.from(parentScope, page.mainFrame()); super(parentScope, page, 'Page', { mainFrame, viewportSize: page.viewportSize() || undefined, isClosed: page.isClosed(), opener: PageDispatcher.fromNullable(parentScope, page.opener()) }); this._type_EventTarget = true; this._type_Page = true; this._page = void 0; this._subscriptions = new Set(); this.adopt(mainFrame); this._page = page; this.addObjectListener(_page.Page.Events.Close, () => { this._dispatchEvent('close'); this._dispose(); }); this.addObjectListener(_page.Page.Events.Crash, () => this._dispatchEvent('crash')); this.addObjectListener(_page.Page.Events.Download, download => { // Artifact can outlive the page, so bind to the context scope. this._dispatchEvent('download', { url: download.url, suggestedFilename: download.suggestedFilename(), artifact: _artifactDispatcher.ArtifactDispatcher.from(parentScope, download.artifact) }); }); this.addObjectListener(_page.Page.Events.FileChooser, fileChooser => this._dispatchEvent('fileChooser', { element: _elementHandlerDispatcher.ElementHandleDispatcher.from(mainFrame, fileChooser.element()), isMultiple: fileChooser.isMultiple() })); this.addObjectListener(_page.Page.Events.FrameAttached, frame => this._onFrameAttached(frame)); this.addObjectListener(_page.Page.Events.FrameDetached, frame => this._onFrameDetached(frame)); this.addObjectListener(_page.Page.Events.WebSocket, webSocket => this._dispatchEvent('webSocket', { webSocket: new _networkDispatchers.WebSocketDispatcher(this, webSocket) })); this.addObjectListener(_page.Page.Events.Worker, worker => this._dispatchEvent('worker', { worker: new WorkerDispatcher(this, worker) })); this.addObjectListener(_page.Page.Events.Video, artifact => this._dispatchEvent('video', { artifact: _artifactDispatcher.ArtifactDispatcher.from(parentScope, artifact) })); if (page._video) this._dispatchEvent('video', { artifact: _artifactDispatcher.ArtifactDispatcher.from(this.parentScope(), page._video) }); // Ensure client knows about all frames. const frames = page._frameManager.frames(); for (let i = 1; i < frames.length; i++) this._onFrameAttached(frames[i]); } page() { return this._page; } async setDefaultNavigationTimeoutNoReply(params, metadata) { this._page.setDefaultNavigationTimeout(params.timeout); } async setDefaultTimeoutNoReply(params, metadata) { this._page.setDefaultTimeout(params.timeout); } async exposeBinding(params, metadata) { await this._page.exposeBinding(params.name, !!params.needsHandle, (source, ...args) => { // When reusing the context, we might have some bindings called late enough, // after context and page dispatchers have been disposed. if (this._disposed) return; const binding = new BindingCallDispatcher(this, params.name, !!params.needsHandle, source, args); this._dispatchEvent('bindingCall', { binding }); return binding.promise(); }); } async setExtraHTTPHeaders(params, metadata) { await this._page.setExtraHTTPHeaders(params.headers); } async reload(params, metadata) { return { response: _networkDispatchers.ResponseDispatcher.fromNullable(this.parentScope(), await this._page.reload(metadata, params)) }; } async goBack(params, metadata) { return { response: _networkDispatchers.ResponseDispatcher.fromNullable(this.parentScope(), await this._page.goBack(metadata, params)) }; } async goForward(params, metadata) { return { response: _networkDispatchers.ResponseDispatcher.fromNullable(this.parentScope(), await this._page.goForward(metadata, params)) }; } async emulateMedia(params, metadata) { await this._page.emulateMedia({ media: params.media, colorScheme: params.colorScheme, reducedMotion: params.reducedMotion, forcedColors: params.forcedColors }); } async setViewportSize(params, metadata) { await this._page.setViewportSize(params.viewportSize); } async addInitScript(params, metadata) { await this._page.addInitScript(params.source); } async setNetworkInterceptionPatterns(params, metadata) { if (!params.patterns.length) { await this._page.setClientRequestInterceptor(undefined); return; } const urlMatchers = params.patterns.map(pattern => pattern.regexSource ? new RegExp(pattern.regexSource, pattern.regexFlags) : pattern.glob); await this._page.setClientRequestInterceptor((route, request) => { const matchesSome = urlMatchers.some(urlMatch => (0, _utils.urlMatches)(this._page._browserContext._options.baseURL, request.url(), urlMatch)); if (!matchesSome) return false; this._dispatchEvent('route', { route: _networkDispatchers.RouteDispatcher.from(_networkDispatchers.RequestDispatcher.from(this.parentScope(), request), route) }); return true; }); } async expectScreenshot(params, metadata) { var _params$screenshotOpt, _params$comparatorOpt; const mask = (((_params$screenshotOpt = params.screenshotOptions) === null || _params$screenshotOpt === void 0 ? void 0 : _params$screenshotOpt.mask) || []).map(({ frame, selector }) => ({ frame: frame._object, selector })); const locator = params.locator ? { frame: params.locator.frame._object, selector: params.locator.selector } : undefined; return await this._page.expectScreenshot(metadata, { ...params, locator, comparatorOptions: { ...params.comparatorOptions, _comparator: (_params$comparatorOpt = params.comparatorOptions) === null || _params$comparatorOpt === void 0 ? void 0 : _params$comparatorOpt.comparator }, screenshotOptions: { ...params.screenshotOptions, mask } }); } async screenshot(params, metadata) { const mask = (params.mask || []).map(({ frame, selector }) => ({ frame: frame._object, selector })); return { binary: await this._page.screenshot(metadata, { ...params, mask }) }; } async close(params, metadata) { if (!params.runBeforeUnload) metadata.potentiallyClosesScope = true; await this._page.close(metadata, params); } async updateSubscription(params) { if (params.event === 'fileChooser') await this._page.setFileChooserIntercepted(params.enabled); if (params.enabled) this._subscriptions.add(params.event);else this._subscriptions.delete(params.event); } async keyboardDown(params, metadata) { await this._page.keyboard.down(params.key); } async keyboardUp(params, metadata) { await this._page.keyboard.up(params.key); } async keyboardInsertText(params, metadata) { await this._page.keyboard.insertText(params.text); } async keyboardType(params, metadata) { await this._page.keyboard.type(params.text, params); } async keyboardPress(params, metadata) { await this._page.keyboard.press(params.key, params); } async mouseMove(params, metadata) { await this._page.mouse.move(params.x, params.y, params, metadata); } async mouseDown(params, metadata) { await this._page.mouse.down(params, metadata); } async mouseUp(params, metadata) { await this._page.mouse.up(params, metadata); } async mouseClick(params, metadata) { await this._page.mouse.click(params.x, params.y, params, metadata); } async mouseWheel(params, metadata) { await this._page.mouse.wheel(params.deltaX, params.deltaY); } async touchscreenTap(params, metadata) { await this._page.touchscreen.tap(params.x, params.y, metadata); } async accessibilitySnapshot(params, metadata) { const rootAXNode = await this._page.accessibility.snapshot({ interestingOnly: params.interestingOnly, root: params.root ? params.root._elementHandle : undefined }); return { rootAXNode: rootAXNode || undefined }; } async pdf(params, metadata) { if (!this._page.pdf) throw new Error('PDF generation is only supported for Headless Chromium'); const buffer = await this._page.pdf(params); return { pdf: buffer }; } async bringToFront(params, metadata) { await this._page.bringToFront(); } async startJSCoverage(params, metadata) { const coverage = this._page.coverage; await coverage.startJSCoverage(params); } async stopJSCoverage(params, metadata) { const coverage = this._page.coverage; return await coverage.stopJSCoverage(); } async startCSSCoverage(params, metadata) { const coverage = this._page.coverage; await coverage.startCSSCoverage(params); } async stopCSSCoverage(params, metadata) { const coverage = this._page.coverage; return await coverage.stopCSSCoverage(); } _onFrameAttached(frame) { this._dispatchEvent('frameAttached', { frame: _frameDispatcher.FrameDispatcher.from(this.parentScope(), frame) }); } _onFrameDetached(frame) { this._dispatchEvent('frameDetached', { frame: _frameDispatcher.FrameDispatcher.from(this.parentScope(), frame) }); } _onDispose() { // Avoid protocol calls for the closed page. if (!this._page.isClosedOrClosingOrCrashed()) this._page.setClientRequestInterceptor(undefined).catch(() => {}); } } exports.PageDispatcher = PageDispatcher; class WorkerDispatcher extends _dispatcher.Dispatcher { static fromNullable(scope, worker) { if (!worker) return undefined; const result = (0, _dispatcher.existingDispatcher)(worker); return result || new WorkerDispatcher(scope, worker); } constructor(scope, worker) { super(scope, worker, 'Worker', { url: worker.url() }); this._type_Worker = true; this.addObjectListener(_page.Worker.Events.Close, () => this._dispatchEvent('close')); } async evaluateExpression(params, metadata) { return { value: (0, _jsHandleDispatcher.serializeResult)(await this._object.evaluateExpression(params.expression, params.isFunction, (0, _jsHandleDispatcher.parseArgument)(params.arg))) }; } async evaluateExpressionHandle(params, metadata) { return { handle: _elementHandlerDispatcher.ElementHandleDispatcher.fromJSHandle(this, await this._object.evaluateExpressionHandle(params.expression, params.isFunction, (0, _jsHandleDispatcher.parseArgument)(params.arg))) }; } } exports.WorkerDispatcher = WorkerDispatcher; class BindingCallDispatcher extends _dispatcher.Dispatcher { constructor(scope, name, needsHandle, source, args) { super(scope, { guid: 'bindingCall@' + (0, _utils.createGuid)() }, 'BindingCall', { frame: _frameDispatcher.FrameDispatcher.from(scope.parentScope(), source.frame), name, args: needsHandle ? undefined : args.map(_jsHandleDispatcher.serializeResult), handle: needsHandle ? _elementHandlerDispatcher.ElementHandleDispatcher.fromJSHandle(scope, args[0]) : undefined }); this._type_BindingCall = true; this._resolve = void 0; this._reject = void 0; this._promise = void 0; this._promise = new Promise((resolve, reject) => { this._resolve = resolve; this._reject = reject; }); } promise() { return this._promise; } async resolve(params, metadata) { this._resolve((0, _jsHandleDispatcher.parseArgument)(params.result)); this._dispose(); } async reject(params, metadata) { this._reject((0, _errors.parseError)(params.error)); this._dispose(); } } exports.BindingCallDispatcher = BindingCallDispatcher;