first commit
This commit is contained in:
72
node_modules/chromium-bidi/lib/cjs/bidiMapper/domains/context/BrowsingContextImpl.d.ts
generated
vendored
Normal file
72
node_modules/chromium-bidi/lib/cjs/bidiMapper/domains/context/BrowsingContextImpl.d.ts
generated
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* Copyright 2022 Google LLC.
|
||||
* 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 type { Protocol } from 'devtools-protocol';
|
||||
import { BrowsingContext } from '../../../protocol/protocol.js';
|
||||
import { type LoggerFn } from '../../../utils/log.js';
|
||||
import type { Realm } from '../script/Realm.js';
|
||||
import type { RealmStorage } from '../script/RealmStorage.js';
|
||||
import type { EventManager } from '../session/EventManager.js';
|
||||
import type { BrowsingContextStorage } from './BrowsingContextStorage.js';
|
||||
import type { CdpTarget } from './CdpTarget.js';
|
||||
export declare class BrowsingContextImpl {
|
||||
#private;
|
||||
static readonly LOGGER_PREFIX: "debug:browsingContext";
|
||||
readonly userContext: string;
|
||||
private constructor();
|
||||
static create(cdpTarget: CdpTarget, realmStorage: RealmStorage, id: BrowsingContext.BrowsingContext, parentId: BrowsingContext.BrowsingContext | null, userContext: string, eventManager: EventManager, browsingContextStorage: BrowsingContextStorage, sharedIdWithFrame: boolean, logger?: LoggerFn): BrowsingContextImpl;
|
||||
static getTimestamp(): number;
|
||||
/**
|
||||
* @see https://html.spec.whatwg.org/multipage/document-sequences.html#navigable
|
||||
*/
|
||||
get navigableId(): string | undefined;
|
||||
dispose(): void;
|
||||
/** Returns the ID of this context. */
|
||||
get id(): BrowsingContext.BrowsingContext;
|
||||
/** Returns the parent context ID. */
|
||||
get parentId(): BrowsingContext.BrowsingContext | null;
|
||||
/** Returns the parent context. */
|
||||
get parent(): BrowsingContextImpl | null;
|
||||
/** Returns all direct children contexts. */
|
||||
get directChildren(): BrowsingContextImpl[];
|
||||
/** Returns all children contexts, flattened. */
|
||||
get allChildren(): BrowsingContextImpl[];
|
||||
/**
|
||||
* Returns true if this is a top-level context.
|
||||
* This is the case whenever the parent context ID is null.
|
||||
*/
|
||||
isTopLevelContext(): boolean;
|
||||
get top(): BrowsingContextImpl;
|
||||
addChild(childId: BrowsingContext.BrowsingContext): void;
|
||||
get cdpTarget(): CdpTarget;
|
||||
updateCdpTarget(cdpTarget: CdpTarget): void;
|
||||
get url(): string;
|
||||
lifecycleLoaded(): Promise<void>;
|
||||
targetUnblockedOrThrow(): Promise<void>;
|
||||
getOrCreateSandbox(sandbox: string | undefined): Promise<Realm>;
|
||||
serializeToBidiValue(maxDepth?: number, addParentField?: boolean): BrowsingContext.Info;
|
||||
onTargetInfoChanged(params: Protocol.Target.TargetInfoChangedEvent): void;
|
||||
navigate(url: string, wait: BrowsingContext.ReadinessState): Promise<BrowsingContext.NavigateResult>;
|
||||
reload(ignoreCache: boolean, wait: BrowsingContext.ReadinessState): Promise<BrowsingContext.NavigateResult>;
|
||||
setViewport(viewport?: BrowsingContext.Viewport | null, devicePixelRatio?: number | null): Promise<void>;
|
||||
handleUserPrompt(params: BrowsingContext.HandleUserPromptParameters): Promise<void>;
|
||||
activate(): Promise<void>;
|
||||
captureScreenshot(params: BrowsingContext.CaptureScreenshotParameters): Promise<BrowsingContext.CaptureScreenshotResult>;
|
||||
print(params: BrowsingContext.PrintParameters): Promise<BrowsingContext.PrintResult>;
|
||||
close(): Promise<void>;
|
||||
traverseHistory(delta: number): Promise<void>;
|
||||
}
|
||||
export declare function serializeOrigin(origin: string): string;
|
||||
817
node_modules/chromium-bidi/lib/cjs/bidiMapper/domains/context/BrowsingContextImpl.js
generated
vendored
Normal file
817
node_modules/chromium-bidi/lib/cjs/bidiMapper/domains/context/BrowsingContextImpl.js
generated
vendored
Normal file
@@ -0,0 +1,817 @@
|
||||
"use strict";
|
||||
/**
|
||||
* Copyright 2022 Google LLC.
|
||||
* 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.
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.serializeOrigin = exports.BrowsingContextImpl = void 0;
|
||||
const protocol_js_1 = require("../../../protocol/protocol.js");
|
||||
const assert_js_1 = require("../../../utils/assert.js");
|
||||
const Deferred_js_1 = require("../../../utils/Deferred.js");
|
||||
const log_js_1 = require("../../../utils/log.js");
|
||||
const unitConversions_js_1 = require("../../../utils/unitConversions.js");
|
||||
const WindowRealm_js_1 = require("../script/WindowRealm.js");
|
||||
class BrowsingContextImpl {
|
||||
static LOGGER_PREFIX = `${log_js_1.LogType.debug}:browsingContext`;
|
||||
/** The ID of this browsing context. */
|
||||
#id;
|
||||
userContext;
|
||||
/**
|
||||
* The ID of the parent browsing context.
|
||||
* If null, this is a top-level context.
|
||||
*/
|
||||
#parentId;
|
||||
/** Direct children browsing contexts. */
|
||||
#children = new Set();
|
||||
#browsingContextStorage;
|
||||
#lifecycle = {
|
||||
DOMContentLoaded: new Deferred_js_1.Deferred(),
|
||||
load: new Deferred_js_1.Deferred(),
|
||||
};
|
||||
#navigation = {
|
||||
withinDocument: new Deferred_js_1.Deferred(),
|
||||
};
|
||||
#url = 'about:blank';
|
||||
#eventManager;
|
||||
#realmStorage;
|
||||
#loaderId;
|
||||
#cdpTarget;
|
||||
#maybeDefaultRealm;
|
||||
#sharedIdWithFrame;
|
||||
#logger;
|
||||
constructor(cdpTarget, realmStorage, id, parentId, userContext, eventManager, browsingContextStorage, sharedIdWithFrame, logger) {
|
||||
this.#cdpTarget = cdpTarget;
|
||||
this.#realmStorage = realmStorage;
|
||||
this.#id = id;
|
||||
this.#parentId = parentId;
|
||||
this.userContext = userContext;
|
||||
this.#eventManager = eventManager;
|
||||
this.#browsingContextStorage = browsingContextStorage;
|
||||
this.#sharedIdWithFrame = sharedIdWithFrame;
|
||||
this.#logger = logger;
|
||||
}
|
||||
static create(cdpTarget, realmStorage, id, parentId, userContext, eventManager, browsingContextStorage, sharedIdWithFrame, logger) {
|
||||
const context = new BrowsingContextImpl(cdpTarget, realmStorage, id, parentId, userContext, eventManager, browsingContextStorage, sharedIdWithFrame, logger);
|
||||
context.#initListeners();
|
||||
browsingContextStorage.addContext(context);
|
||||
if (!context.isTopLevelContext()) {
|
||||
context.parent.addChild(context.id);
|
||||
}
|
||||
eventManager.registerEvent({
|
||||
type: 'event',
|
||||
method: protocol_js_1.ChromiumBidi.BrowsingContext.EventNames.ContextCreated,
|
||||
params: context.serializeToBidiValue(),
|
||||
}, context.id);
|
||||
return context;
|
||||
}
|
||||
static getTimestamp() {
|
||||
// `timestamp` from the event is MonotonicTime, not real time, so
|
||||
// the best Mapper can do is to set the timestamp to the epoch time
|
||||
// of the event arrived.
|
||||
// https://chromedevtools.github.io/devtools-protocol/tot/Network/#type-MonotonicTime
|
||||
return new Date().getTime();
|
||||
}
|
||||
/**
|
||||
* @see https://html.spec.whatwg.org/multipage/document-sequences.html#navigable
|
||||
*/
|
||||
get navigableId() {
|
||||
return this.#loaderId;
|
||||
}
|
||||
dispose() {
|
||||
this.#deleteAllChildren();
|
||||
this.#realmStorage.deleteRealms({
|
||||
browsingContextId: this.id,
|
||||
});
|
||||
// Remove context from the parent.
|
||||
if (!this.isTopLevelContext()) {
|
||||
this.parent.#children.delete(this.id);
|
||||
}
|
||||
// Fail all ongoing navigations.
|
||||
this.#failLifecycleIfNotFinished();
|
||||
this.#eventManager.registerEvent({
|
||||
type: 'event',
|
||||
method: protocol_js_1.ChromiumBidi.BrowsingContext.EventNames.ContextDestroyed,
|
||||
params: this.serializeToBidiValue(),
|
||||
}, this.id);
|
||||
this.#browsingContextStorage.deleteContextById(this.id);
|
||||
}
|
||||
/** Returns the ID of this context. */
|
||||
get id() {
|
||||
return this.#id;
|
||||
}
|
||||
/** Returns the parent context ID. */
|
||||
get parentId() {
|
||||
return this.#parentId;
|
||||
}
|
||||
/** Returns the parent context. */
|
||||
get parent() {
|
||||
if (this.parentId === null) {
|
||||
return null;
|
||||
}
|
||||
return this.#browsingContextStorage.getContext(this.parentId);
|
||||
}
|
||||
/** Returns all direct children contexts. */
|
||||
get directChildren() {
|
||||
return [...this.#children].map((id) => this.#browsingContextStorage.getContext(id));
|
||||
}
|
||||
/** Returns all children contexts, flattened. */
|
||||
get allChildren() {
|
||||
const children = this.directChildren;
|
||||
return children.concat(...children.map((child) => child.allChildren));
|
||||
}
|
||||
/**
|
||||
* Returns true if this is a top-level context.
|
||||
* This is the case whenever the parent context ID is null.
|
||||
*/
|
||||
isTopLevelContext() {
|
||||
return this.#parentId === null;
|
||||
}
|
||||
get top() {
|
||||
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
||||
let topContext = this;
|
||||
let parent = topContext.parent;
|
||||
while (parent) {
|
||||
topContext = parent;
|
||||
parent = topContext.parent;
|
||||
}
|
||||
return topContext;
|
||||
}
|
||||
addChild(childId) {
|
||||
this.#children.add(childId);
|
||||
}
|
||||
#deleteAllChildren() {
|
||||
this.directChildren.map((child) => child.dispose());
|
||||
}
|
||||
get #defaultRealm() {
|
||||
(0, assert_js_1.assert)(this.#maybeDefaultRealm, `No default realm for browsing context ${this.#id}`);
|
||||
return this.#maybeDefaultRealm;
|
||||
}
|
||||
get cdpTarget() {
|
||||
return this.#cdpTarget;
|
||||
}
|
||||
updateCdpTarget(cdpTarget) {
|
||||
this.#cdpTarget = cdpTarget;
|
||||
this.#initListeners();
|
||||
}
|
||||
get url() {
|
||||
return this.#url;
|
||||
}
|
||||
async lifecycleLoaded() {
|
||||
await this.#lifecycle.load;
|
||||
}
|
||||
async targetUnblockedOrThrow() {
|
||||
const result = await this.#cdpTarget.unblocked;
|
||||
if (result.kind === 'error') {
|
||||
throw result.error;
|
||||
}
|
||||
}
|
||||
async getOrCreateSandbox(sandbox) {
|
||||
if (sandbox === undefined || sandbox === '') {
|
||||
return this.#defaultRealm;
|
||||
}
|
||||
let maybeSandboxes = this.#realmStorage.findRealms({
|
||||
browsingContextId: this.id,
|
||||
sandbox,
|
||||
});
|
||||
if (maybeSandboxes.length === 0) {
|
||||
await this.#cdpTarget.cdpClient.sendCommand('Page.createIsolatedWorld', {
|
||||
frameId: this.id,
|
||||
worldName: sandbox,
|
||||
});
|
||||
// `Runtime.executionContextCreated` should be emitted by the time the
|
||||
// previous command is done.
|
||||
maybeSandboxes = this.#realmStorage.findRealms({
|
||||
browsingContextId: this.id,
|
||||
sandbox,
|
||||
});
|
||||
(0, assert_js_1.assert)(maybeSandboxes.length !== 0);
|
||||
}
|
||||
// It's possible for more than one sandbox to be created due to provisional
|
||||
// frames. In this case, it's always the first one (i.e. the oldest one)
|
||||
// that is more relevant since the user may have set that one up already
|
||||
// through evaluation.
|
||||
return maybeSandboxes[0];
|
||||
}
|
||||
serializeToBidiValue(maxDepth = 0, addParentField = true) {
|
||||
return {
|
||||
context: this.#id,
|
||||
url: this.url,
|
||||
userContext: this.userContext,
|
||||
children: maxDepth > 0
|
||||
? this.directChildren.map((c) => c.serializeToBidiValue(maxDepth - 1, false))
|
||||
: null,
|
||||
...(addParentField ? { parent: this.#parentId } : {}),
|
||||
};
|
||||
}
|
||||
onTargetInfoChanged(params) {
|
||||
this.#url = params.targetInfo.url;
|
||||
}
|
||||
#initListeners() {
|
||||
this.#cdpTarget.cdpClient.on('Page.frameNavigated', (params) => {
|
||||
if (this.id !== params.frame.id) {
|
||||
return;
|
||||
}
|
||||
this.#url = params.frame.url + (params.frame.urlFragment ?? '');
|
||||
// At the point the page is initialized, all the nested iframes from the
|
||||
// previous page are detached and realms are destroyed.
|
||||
// Remove children from context.
|
||||
this.#deleteAllChildren();
|
||||
});
|
||||
this.#cdpTarget.cdpClient.on('Page.navigatedWithinDocument', (params) => {
|
||||
if (this.id !== params.frameId) {
|
||||
return;
|
||||
}
|
||||
const timestamp = BrowsingContextImpl.getTimestamp();
|
||||
this.#url = params.url;
|
||||
this.#navigation.withinDocument.resolve(params);
|
||||
this.#eventManager.registerEvent({
|
||||
type: 'event',
|
||||
method: protocol_js_1.ChromiumBidi.BrowsingContext.EventNames.FragmentNavigated,
|
||||
params: {
|
||||
context: this.id,
|
||||
navigation: null,
|
||||
timestamp,
|
||||
url: this.#url,
|
||||
},
|
||||
}, this.id);
|
||||
});
|
||||
this.#cdpTarget.cdpClient.on('Page.frameStartedLoading', (params) => {
|
||||
if (this.id !== params.frameId) {
|
||||
return;
|
||||
}
|
||||
this.#eventManager.registerEvent({
|
||||
type: 'event',
|
||||
method: protocol_js_1.ChromiumBidi.BrowsingContext.EventNames.NavigationStarted,
|
||||
params: {
|
||||
context: this.id,
|
||||
navigation: null,
|
||||
timestamp: BrowsingContextImpl.getTimestamp(),
|
||||
url: '',
|
||||
},
|
||||
}, this.id);
|
||||
});
|
||||
this.#cdpTarget.cdpClient.on('Page.lifecycleEvent', (params) => {
|
||||
if (this.id !== params.frameId) {
|
||||
return;
|
||||
}
|
||||
if (params.name === 'init') {
|
||||
this.#documentChanged(params.loaderId);
|
||||
return;
|
||||
}
|
||||
if (params.name === 'commit') {
|
||||
this.#loaderId = params.loaderId;
|
||||
return;
|
||||
}
|
||||
// Ignore event from not current navigation.
|
||||
if (params.loaderId !== this.#loaderId) {
|
||||
return;
|
||||
}
|
||||
const timestamp = BrowsingContextImpl.getTimestamp();
|
||||
switch (params.name) {
|
||||
case 'DOMContentLoaded':
|
||||
this.#eventManager.registerEvent({
|
||||
type: 'event',
|
||||
method: protocol_js_1.ChromiumBidi.BrowsingContext.EventNames.DomContentLoaded,
|
||||
params: {
|
||||
context: this.id,
|
||||
navigation: this.#loaderId ?? null,
|
||||
timestamp,
|
||||
url: this.#url,
|
||||
},
|
||||
}, this.id);
|
||||
this.#lifecycle.DOMContentLoaded.resolve(params);
|
||||
break;
|
||||
case 'load':
|
||||
this.#eventManager.registerEvent({
|
||||
type: 'event',
|
||||
method: protocol_js_1.ChromiumBidi.BrowsingContext.EventNames.Load,
|
||||
params: {
|
||||
context: this.id,
|
||||
navigation: this.#loaderId ?? null,
|
||||
timestamp,
|
||||
url: this.#url,
|
||||
},
|
||||
}, this.id);
|
||||
this.#lifecycle.load.resolve(params);
|
||||
break;
|
||||
}
|
||||
});
|
||||
this.#cdpTarget.cdpClient.on('Runtime.executionContextCreated', (params) => {
|
||||
const { auxData, name, uniqueId, id } = params.context;
|
||||
if (!auxData || auxData.frameId !== this.id) {
|
||||
return;
|
||||
}
|
||||
let origin;
|
||||
let sandbox;
|
||||
// Only these execution contexts are supported for now.
|
||||
switch (auxData.type) {
|
||||
case 'isolated':
|
||||
sandbox = name;
|
||||
// Sandbox should have the same origin as the context itself, but in CDP
|
||||
// it has an empty one.
|
||||
origin = this.#defaultRealm.origin;
|
||||
break;
|
||||
case 'default':
|
||||
origin = serializeOrigin(params.context.origin);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
const realm = new WindowRealm_js_1.WindowRealm(this.id, this.#browsingContextStorage, this.#cdpTarget.cdpClient, this.#eventManager, id, this.#logger, origin, uniqueId, this.#realmStorage, sandbox, this.#sharedIdWithFrame);
|
||||
if (auxData.isDefault) {
|
||||
this.#maybeDefaultRealm = realm;
|
||||
// Initialize ChannelProxy listeners for all the channels of all the
|
||||
// preload scripts related to this BrowsingContext.
|
||||
// TODO: extend for not default realms by the sandbox name.
|
||||
void Promise.all(this.#cdpTarget
|
||||
.getChannels()
|
||||
.map((channel) => channel.startListenerFromWindow(realm, this.#eventManager)));
|
||||
}
|
||||
});
|
||||
this.#cdpTarget.cdpClient.on('Runtime.executionContextDestroyed', (params) => {
|
||||
this.#realmStorage.deleteRealms({
|
||||
cdpSessionId: this.#cdpTarget.cdpSessionId,
|
||||
executionContextId: params.executionContextId,
|
||||
});
|
||||
});
|
||||
this.#cdpTarget.cdpClient.on('Runtime.executionContextsCleared', () => {
|
||||
this.#realmStorage.deleteRealms({
|
||||
cdpSessionId: this.#cdpTarget.cdpSessionId,
|
||||
});
|
||||
});
|
||||
this.#cdpTarget.cdpClient.on('Page.javascriptDialogClosed', (params) => {
|
||||
const accepted = params.result;
|
||||
this.#eventManager.registerEvent({
|
||||
type: 'event',
|
||||
method: protocol_js_1.ChromiumBidi.BrowsingContext.EventNames.UserPromptClosed,
|
||||
params: {
|
||||
context: this.id,
|
||||
accepted,
|
||||
userText: accepted && params.userInput ? params.userInput : undefined,
|
||||
},
|
||||
}, this.id);
|
||||
});
|
||||
this.#cdpTarget.cdpClient.on('Page.javascriptDialogOpening', (params) => {
|
||||
this.#eventManager.registerEvent({
|
||||
type: 'event',
|
||||
method: protocol_js_1.ChromiumBidi.BrowsingContext.EventNames.UserPromptOpened,
|
||||
params: {
|
||||
context: this.id,
|
||||
type: params.type,
|
||||
message: params.message,
|
||||
// Don't set the value if empty string
|
||||
defaultValue: params.defaultPrompt || undefined,
|
||||
},
|
||||
}, this.id);
|
||||
});
|
||||
}
|
||||
#documentChanged(loaderId) {
|
||||
// Same document navigation.
|
||||
if (loaderId === undefined || this.#loaderId === loaderId) {
|
||||
if (this.#navigation.withinDocument.isFinished) {
|
||||
this.#navigation.withinDocument =
|
||||
new Deferred_js_1.Deferred();
|
||||
}
|
||||
else {
|
||||
this.#logger?.(BrowsingContextImpl.LOGGER_PREFIX, 'Document changed (navigatedWithinDocument)');
|
||||
}
|
||||
return;
|
||||
}
|
||||
this.#resetLifecycleIfFinished();
|
||||
this.#loaderId = loaderId;
|
||||
}
|
||||
#resetLifecycleIfFinished() {
|
||||
if (this.#lifecycle.DOMContentLoaded.isFinished) {
|
||||
this.#lifecycle.DOMContentLoaded =
|
||||
new Deferred_js_1.Deferred();
|
||||
}
|
||||
else {
|
||||
this.#logger?.(BrowsingContextImpl.LOGGER_PREFIX, 'Document changed (DOMContentLoaded)');
|
||||
}
|
||||
if (this.#lifecycle.load.isFinished) {
|
||||
this.#lifecycle.load = new Deferred_js_1.Deferred();
|
||||
}
|
||||
else {
|
||||
this.#logger?.(BrowsingContextImpl.LOGGER_PREFIX, 'Document changed (load)');
|
||||
}
|
||||
}
|
||||
#failLifecycleIfNotFinished() {
|
||||
if (!this.#lifecycle.DOMContentLoaded.isFinished) {
|
||||
this.#lifecycle.DOMContentLoaded.reject(new protocol_js_1.UnknownErrorException('navigation canceled'));
|
||||
}
|
||||
if (!this.#lifecycle.load.isFinished) {
|
||||
this.#lifecycle.load.reject(new protocol_js_1.UnknownErrorException('navigation canceled'));
|
||||
}
|
||||
}
|
||||
async navigate(url, wait) {
|
||||
try {
|
||||
new URL(url);
|
||||
}
|
||||
catch {
|
||||
throw new protocol_js_1.InvalidArgumentException(`Invalid URL: ${url}`);
|
||||
}
|
||||
await this.targetUnblockedOrThrow();
|
||||
// TODO: handle loading errors.
|
||||
const cdpNavigateResult = await this.#cdpTarget.cdpClient.sendCommand('Page.navigate', {
|
||||
url,
|
||||
frameId: this.id,
|
||||
});
|
||||
if (cdpNavigateResult.errorText) {
|
||||
throw new protocol_js_1.UnknownErrorException(cdpNavigateResult.errorText);
|
||||
}
|
||||
this.#documentChanged(cdpNavigateResult.loaderId);
|
||||
switch (wait) {
|
||||
case "none" /* BrowsingContext.ReadinessState.None */:
|
||||
break;
|
||||
case "interactive" /* BrowsingContext.ReadinessState.Interactive */:
|
||||
// No `loaderId` means same-document navigation.
|
||||
if (cdpNavigateResult.loaderId === undefined) {
|
||||
await this.#navigation.withinDocument;
|
||||
}
|
||||
else {
|
||||
await this.#lifecycle.DOMContentLoaded;
|
||||
}
|
||||
break;
|
||||
case "complete" /* BrowsingContext.ReadinessState.Complete */:
|
||||
// No `loaderId` means same-document navigation.
|
||||
if (cdpNavigateResult.loaderId === undefined) {
|
||||
await this.#navigation.withinDocument;
|
||||
}
|
||||
else {
|
||||
await this.#lifecycle.load;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return {
|
||||
navigation: cdpNavigateResult.loaderId ?? null,
|
||||
// Url can change due to redirect get the latest one.
|
||||
url: wait === "none" /* BrowsingContext.ReadinessState.None */ ? url : this.#url,
|
||||
};
|
||||
}
|
||||
async reload(ignoreCache, wait) {
|
||||
await this.targetUnblockedOrThrow();
|
||||
await this.#cdpTarget.cdpClient.sendCommand('Page.reload', {
|
||||
ignoreCache,
|
||||
});
|
||||
this.#resetLifecycleIfFinished();
|
||||
switch (wait) {
|
||||
case "none" /* BrowsingContext.ReadinessState.None */:
|
||||
break;
|
||||
case "interactive" /* BrowsingContext.ReadinessState.Interactive */:
|
||||
await this.#lifecycle.DOMContentLoaded;
|
||||
break;
|
||||
case "complete" /* BrowsingContext.ReadinessState.Complete */:
|
||||
await this.#lifecycle.load;
|
||||
break;
|
||||
}
|
||||
return {
|
||||
navigation: wait === "none" /* BrowsingContext.ReadinessState.None */
|
||||
? null
|
||||
: this.navigableId ?? null,
|
||||
url: this.url,
|
||||
};
|
||||
}
|
||||
async setViewport(viewport, devicePixelRatio) {
|
||||
if (viewport === null && devicePixelRatio === null) {
|
||||
await this.#cdpTarget.cdpClient.sendCommand('Emulation.clearDeviceMetricsOverride');
|
||||
}
|
||||
else {
|
||||
try {
|
||||
await this.#cdpTarget.cdpClient.sendCommand('Emulation.setDeviceMetricsOverride', {
|
||||
width: viewport ? viewport.width : 0,
|
||||
height: viewport ? viewport.height : 0,
|
||||
deviceScaleFactor: devicePixelRatio ? devicePixelRatio : 0,
|
||||
mobile: false,
|
||||
dontSetVisibleSize: true,
|
||||
});
|
||||
}
|
||||
catch (err) {
|
||||
if (err.message.startsWith(
|
||||
// https://crsrc.org/c/content/browser/devtools/protocol/emulation_handler.cc;l=257;drc=2f6eee84cf98d4227e7c41718dd71b82f26d90ff
|
||||
'Width and height values must be positive')) {
|
||||
throw new protocol_js_1.UnsupportedOperationException('Provided viewport dimensions are not supported');
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
}
|
||||
async handleUserPrompt(params) {
|
||||
await this.#cdpTarget.cdpClient.sendCommand('Page.handleJavaScriptDialog', {
|
||||
accept: params.accept ?? true,
|
||||
promptText: params.userText,
|
||||
});
|
||||
}
|
||||
async activate() {
|
||||
await this.#cdpTarget.cdpClient.sendCommand('Page.bringToFront');
|
||||
}
|
||||
async captureScreenshot(params) {
|
||||
if (!this.isTopLevelContext()) {
|
||||
throw new protocol_js_1.UnsupportedOperationException(`Non-top-level 'context' (${params.context}) is currently not supported`);
|
||||
}
|
||||
const formatParameters = getImageFormatParameters(params);
|
||||
// XXX: Focus the original tab after the screenshot is taken.
|
||||
// This is needed because the screenshot gets blocked until the active tab gets focus.
|
||||
await this.#cdpTarget.cdpClient.sendCommand('Page.bringToFront');
|
||||
let captureBeyondViewport = false;
|
||||
let script;
|
||||
params.origin ??= 'viewport';
|
||||
switch (params.origin) {
|
||||
case 'document': {
|
||||
script = String(() => {
|
||||
const element = document.documentElement;
|
||||
return {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: element.scrollWidth,
|
||||
height: element.scrollHeight,
|
||||
};
|
||||
});
|
||||
captureBeyondViewport = true;
|
||||
break;
|
||||
}
|
||||
case 'viewport': {
|
||||
script = String(() => {
|
||||
const viewport = window.visualViewport;
|
||||
return {
|
||||
x: viewport.pageLeft,
|
||||
y: viewport.pageTop,
|
||||
width: viewport.width,
|
||||
height: viewport.height,
|
||||
};
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
const realm = await this.getOrCreateSandbox(undefined);
|
||||
const originResult = await realm.callFunction(script, { type: 'undefined' }, [], false, "none" /* Script.ResultOwnership.None */, {}, false);
|
||||
(0, assert_js_1.assert)(originResult.type === 'success');
|
||||
const origin = deserializeDOMRect(originResult.result);
|
||||
(0, assert_js_1.assert)(origin);
|
||||
const rect = params.clip
|
||||
? getIntersectionRect(await this.#parseRect(params.clip), origin)
|
||||
: origin;
|
||||
if (rect.width === 0 || rect.height === 0) {
|
||||
throw new protocol_js_1.UnableToCaptureScreenException(`Unable to capture screenshot with zero dimensions: width=${rect.width}, height=${rect.height}`);
|
||||
}
|
||||
return await this.#cdpTarget.cdpClient.sendCommand('Page.captureScreenshot', {
|
||||
clip: { ...rect, scale: 1.0 },
|
||||
...formatParameters,
|
||||
captureBeyondViewport,
|
||||
});
|
||||
}
|
||||
async print(params) {
|
||||
const cdpParams = {};
|
||||
if (params.background !== undefined) {
|
||||
cdpParams.printBackground = params.background;
|
||||
}
|
||||
if (params.margin?.bottom !== undefined) {
|
||||
cdpParams.marginBottom = (0, unitConversions_js_1.inchesFromCm)(params.margin.bottom);
|
||||
}
|
||||
if (params.margin?.left !== undefined) {
|
||||
cdpParams.marginLeft = (0, unitConversions_js_1.inchesFromCm)(params.margin.left);
|
||||
}
|
||||
if (params.margin?.right !== undefined) {
|
||||
cdpParams.marginRight = (0, unitConversions_js_1.inchesFromCm)(params.margin.right);
|
||||
}
|
||||
if (params.margin?.top !== undefined) {
|
||||
cdpParams.marginTop = (0, unitConversions_js_1.inchesFromCm)(params.margin.top);
|
||||
}
|
||||
if (params.orientation !== undefined) {
|
||||
cdpParams.landscape = params.orientation === 'landscape';
|
||||
}
|
||||
if (params.page?.height !== undefined) {
|
||||
cdpParams.paperHeight = (0, unitConversions_js_1.inchesFromCm)(params.page.height);
|
||||
}
|
||||
if (params.page?.width !== undefined) {
|
||||
cdpParams.paperWidth = (0, unitConversions_js_1.inchesFromCm)(params.page.width);
|
||||
}
|
||||
if (params.pageRanges !== undefined) {
|
||||
for (const range of params.pageRanges) {
|
||||
if (typeof range === 'number') {
|
||||
continue;
|
||||
}
|
||||
const rangeParts = range.split('-');
|
||||
if (rangeParts.length < 1 || rangeParts.length > 2) {
|
||||
throw new protocol_js_1.InvalidArgumentException(`Invalid page range: ${range} is not a valid integer range.`);
|
||||
}
|
||||
if (rangeParts.length === 1) {
|
||||
void parseInteger(rangeParts[0] ?? '');
|
||||
continue;
|
||||
}
|
||||
let lowerBound;
|
||||
let upperBound;
|
||||
const [rangeLowerPart = '', rangeUpperPart = ''] = rangeParts;
|
||||
if (rangeLowerPart === '') {
|
||||
lowerBound = 1;
|
||||
}
|
||||
else {
|
||||
lowerBound = parseInteger(rangeLowerPart);
|
||||
}
|
||||
if (rangeUpperPart === '') {
|
||||
upperBound = Number.MAX_SAFE_INTEGER;
|
||||
}
|
||||
else {
|
||||
upperBound = parseInteger(rangeUpperPart);
|
||||
}
|
||||
if (lowerBound > upperBound) {
|
||||
throw new protocol_js_1.InvalidArgumentException(`Invalid page range: ${rangeLowerPart} > ${rangeUpperPart}`);
|
||||
}
|
||||
}
|
||||
cdpParams.pageRanges = params.pageRanges.join(',');
|
||||
}
|
||||
if (params.scale !== undefined) {
|
||||
cdpParams.scale = params.scale;
|
||||
}
|
||||
if (params.shrinkToFit !== undefined) {
|
||||
cdpParams.preferCSSPageSize = !params.shrinkToFit;
|
||||
}
|
||||
try {
|
||||
const result = await this.#cdpTarget.cdpClient.sendCommand('Page.printToPDF', cdpParams);
|
||||
return {
|
||||
data: result.data,
|
||||
};
|
||||
}
|
||||
catch (error) {
|
||||
// Effectively zero dimensions.
|
||||
if (error.message ===
|
||||
'invalid print parameters: content area is empty') {
|
||||
throw new protocol_js_1.UnsupportedOperationException(error.message);
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* See
|
||||
* https://w3c.github.io/webdriver-bidi/#:~:text=If%20command%20parameters%20contains%20%22clip%22%3A
|
||||
*/
|
||||
async #parseRect(clip) {
|
||||
switch (clip.type) {
|
||||
case 'box':
|
||||
return { x: clip.x, y: clip.y, width: clip.width, height: clip.height };
|
||||
case 'element': {
|
||||
// TODO: #1213: Use custom sandbox specifically for Chromium BiDi
|
||||
const sandbox = await this.getOrCreateSandbox(undefined);
|
||||
const result = await sandbox.callFunction(String((element) => {
|
||||
return element instanceof Element;
|
||||
}), { type: 'undefined' }, [clip.element], false, "none" /* Script.ResultOwnership.None */, {});
|
||||
if (result.type === 'exception') {
|
||||
throw new protocol_js_1.NoSuchElementException(`Element '${clip.element.sharedId}' was not found`);
|
||||
}
|
||||
(0, assert_js_1.assert)(result.result.type === 'boolean');
|
||||
if (!result.result.value) {
|
||||
throw new protocol_js_1.NoSuchElementException(`Node '${clip.element.sharedId}' is not an Element`);
|
||||
}
|
||||
{
|
||||
const result = await sandbox.callFunction(String((element) => {
|
||||
const rect = element.getBoundingClientRect();
|
||||
return {
|
||||
x: rect.x,
|
||||
y: rect.y,
|
||||
height: rect.height,
|
||||
width: rect.width,
|
||||
};
|
||||
}), { type: 'undefined' }, [clip.element], false, "none" /* Script.ResultOwnership.None */, {});
|
||||
(0, assert_js_1.assert)(result.type === 'success');
|
||||
const rect = deserializeDOMRect(result.result);
|
||||
if (!rect) {
|
||||
throw new protocol_js_1.UnableToCaptureScreenException(`Could not get bounding box for Element '${clip.element.sharedId}'`);
|
||||
}
|
||||
return rect;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
async close() {
|
||||
await this.#cdpTarget.cdpClient.sendCommand('Page.close');
|
||||
}
|
||||
async traverseHistory(delta) {
|
||||
if (delta === 0) {
|
||||
return;
|
||||
}
|
||||
const history = await this.#cdpTarget.cdpClient.sendCommand('Page.getNavigationHistory');
|
||||
const entry = history.entries[history.currentIndex + delta];
|
||||
if (!entry) {
|
||||
throw new protocol_js_1.NoSuchHistoryEntryException(`No history entry at delta ${delta}`);
|
||||
}
|
||||
await this.#cdpTarget.cdpClient.sendCommand('Page.navigateToHistoryEntry', {
|
||||
entryId: entry.id,
|
||||
});
|
||||
}
|
||||
}
|
||||
exports.BrowsingContextImpl = BrowsingContextImpl;
|
||||
function serializeOrigin(origin) {
|
||||
// https://html.spec.whatwg.org/multipage/origin.html#ascii-serialisation-of-an-origin
|
||||
if (['://', ''].includes(origin)) {
|
||||
origin = 'null';
|
||||
}
|
||||
return origin;
|
||||
}
|
||||
exports.serializeOrigin = serializeOrigin;
|
||||
function getImageFormatParameters(params) {
|
||||
const { quality, type } = params.format ?? {
|
||||
type: 'image/png',
|
||||
};
|
||||
switch (type) {
|
||||
case 'image/png': {
|
||||
return { format: 'png' };
|
||||
}
|
||||
case 'image/jpeg': {
|
||||
return {
|
||||
format: 'jpeg',
|
||||
...(quality === undefined ? {} : { quality: Math.round(quality * 100) }),
|
||||
};
|
||||
}
|
||||
case 'image/webp': {
|
||||
return {
|
||||
format: 'webp',
|
||||
...(quality === undefined ? {} : { quality: Math.round(quality * 100) }),
|
||||
};
|
||||
}
|
||||
}
|
||||
throw new protocol_js_1.InvalidArgumentException(`Image format '${type}' is not a supported format`);
|
||||
}
|
||||
function deserializeDOMRect(result) {
|
||||
if (result.type !== 'object' || result.value === undefined) {
|
||||
return;
|
||||
}
|
||||
const x = result.value.find(([key]) => {
|
||||
return key === 'x';
|
||||
})?.[1];
|
||||
const y = result.value.find(([key]) => {
|
||||
return key === 'y';
|
||||
})?.[1];
|
||||
const height = result.value.find(([key]) => {
|
||||
return key === 'height';
|
||||
})?.[1];
|
||||
const width = result.value.find(([key]) => {
|
||||
return key === 'width';
|
||||
})?.[1];
|
||||
if (x?.type !== 'number' ||
|
||||
y?.type !== 'number' ||
|
||||
height?.type !== 'number' ||
|
||||
width?.type !== 'number') {
|
||||
return;
|
||||
}
|
||||
return {
|
||||
x: x.value,
|
||||
y: y.value,
|
||||
width: width.value,
|
||||
height: height.value,
|
||||
};
|
||||
}
|
||||
/** @see https://w3c.github.io/webdriver-bidi/#normalize-rect */
|
||||
function normalizeRect(box) {
|
||||
return {
|
||||
...(box.width < 0
|
||||
? {
|
||||
x: box.x + box.width,
|
||||
width: -box.width,
|
||||
}
|
||||
: {
|
||||
x: box.x,
|
||||
width: box.width,
|
||||
}),
|
||||
...(box.height < 0
|
||||
? {
|
||||
y: box.y + box.height,
|
||||
height: -box.height,
|
||||
}
|
||||
: {
|
||||
y: box.y,
|
||||
height: box.height,
|
||||
}),
|
||||
};
|
||||
}
|
||||
/** @see https://w3c.github.io/webdriver-bidi/#rectangle-intersection */
|
||||
function getIntersectionRect(first, second) {
|
||||
first = normalizeRect(first);
|
||||
second = normalizeRect(second);
|
||||
const x = Math.max(first.x, second.x);
|
||||
const y = Math.max(first.y, second.y);
|
||||
return {
|
||||
x,
|
||||
y,
|
||||
width: Math.max(Math.min(first.x + first.width, second.x + second.width) - x, 0),
|
||||
height: Math.max(Math.min(first.y + first.height, second.y + second.height) - y, 0),
|
||||
};
|
||||
}
|
||||
function parseInteger(value) {
|
||||
value = value.trim();
|
||||
if (!/^[0-9]+$/.test(value)) {
|
||||
throw new protocol_js_1.InvalidArgumentException(`Invalid integer: ${value}`);
|
||||
}
|
||||
return parseInt(value);
|
||||
}
|
||||
//# sourceMappingURL=BrowsingContextImpl.js.map
|
||||
1
node_modules/chromium-bidi/lib/cjs/bidiMapper/domains/context/BrowsingContextImpl.js.map
generated
vendored
Normal file
1
node_modules/chromium-bidi/lib/cjs/bidiMapper/domains/context/BrowsingContextImpl.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
24
node_modules/chromium-bidi/lib/cjs/bidiMapper/domains/context/BrowsingContextProcessor.d.ts
generated
vendored
Normal file
24
node_modules/chromium-bidi/lib/cjs/bidiMapper/domains/context/BrowsingContextProcessor.d.ts
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
import type { CdpClient } from '../../../cdp/CdpClient.js';
|
||||
import type { CdpConnection } from '../../../cdp/CdpConnection.js';
|
||||
import { BrowsingContext, type EmptyResult, type Browser } from '../../../protocol/protocol.js';
|
||||
import { type LoggerFn } from '../../../utils/log.js';
|
||||
import type { NetworkStorage } from '../network/NetworkStorage.js';
|
||||
import type { PreloadScriptStorage } from '../script/PreloadScriptStorage.js';
|
||||
import type { RealmStorage } from '../script/RealmStorage.js';
|
||||
import type { EventManager } from '../session/EventManager.js';
|
||||
import type { BrowsingContextStorage } from './BrowsingContextStorage.js';
|
||||
export declare class BrowsingContextProcessor {
|
||||
#private;
|
||||
constructor(cdpConnection: CdpConnection, browserCdpClient: CdpClient, selfTargetId: string, eventManager: EventManager, browsingContextStorage: BrowsingContextStorage, realmStorage: RealmStorage, networkStorage: NetworkStorage, preloadScriptStorage: PreloadScriptStorage, acceptInsecureCerts: boolean, sharedIdWithFrame: boolean, defaultUserContextId: Browser.UserContext, logger?: LoggerFn);
|
||||
getTree(params: BrowsingContext.GetTreeParameters): BrowsingContext.GetTreeResult;
|
||||
create(params: BrowsingContext.CreateParameters): Promise<BrowsingContext.CreateResult>;
|
||||
navigate(params: BrowsingContext.NavigateParameters): Promise<BrowsingContext.NavigateResult>;
|
||||
reload(params: BrowsingContext.ReloadParameters): Promise<EmptyResult>;
|
||||
activate(params: BrowsingContext.ActivateParameters): Promise<EmptyResult>;
|
||||
captureScreenshot(params: BrowsingContext.CaptureScreenshotParameters): Promise<BrowsingContext.CaptureScreenshotResult>;
|
||||
print(params: BrowsingContext.PrintParameters): Promise<BrowsingContext.PrintResult>;
|
||||
setViewport(params: BrowsingContext.SetViewportParameters): Promise<EmptyResult>;
|
||||
traverseHistory(params: BrowsingContext.TraverseHistoryParameters): Promise<BrowsingContext.TraverseHistoryResult>;
|
||||
handleUserPrompt(params: BrowsingContext.HandleUserPromptParameters): Promise<EmptyResult>;
|
||||
close(params: BrowsingContext.CloseParameters): Promise<EmptyResult>;
|
||||
}
|
||||
303
node_modules/chromium-bidi/lib/cjs/bidiMapper/domains/context/BrowsingContextProcessor.js
generated
vendored
Normal file
303
node_modules/chromium-bidi/lib/cjs/bidiMapper/domains/context/BrowsingContextProcessor.js
generated
vendored
Normal file
@@ -0,0 +1,303 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.BrowsingContextProcessor = void 0;
|
||||
const protocol_js_1 = require("../../../protocol/protocol.js");
|
||||
const log_js_1 = require("../../../utils/log.js");
|
||||
const DedicatedWorkerRealm_js_1 = require("../script/DedicatedWorkerRealm.js");
|
||||
const BrowsingContextImpl_js_1 = require("./BrowsingContextImpl.js");
|
||||
const CdpTarget_js_1 = require("./CdpTarget.js");
|
||||
class BrowsingContextProcessor {
|
||||
#browserCdpClient;
|
||||
#cdpConnection;
|
||||
#selfTargetId;
|
||||
#eventManager;
|
||||
#browsingContextStorage;
|
||||
#networkStorage;
|
||||
#acceptInsecureCerts;
|
||||
#sharedIdWithFrame;
|
||||
#preloadScriptStorage;
|
||||
#realmStorage;
|
||||
#defaultUserContextId;
|
||||
#logger;
|
||||
constructor(cdpConnection, browserCdpClient, selfTargetId, eventManager, browsingContextStorage, realmStorage, networkStorage, preloadScriptStorage, acceptInsecureCerts, sharedIdWithFrame, defaultUserContextId, logger) {
|
||||
this.#acceptInsecureCerts = acceptInsecureCerts;
|
||||
this.#cdpConnection = cdpConnection;
|
||||
this.#browserCdpClient = browserCdpClient;
|
||||
this.#selfTargetId = selfTargetId;
|
||||
this.#eventManager = eventManager;
|
||||
this.#browsingContextStorage = browsingContextStorage;
|
||||
this.#preloadScriptStorage = preloadScriptStorage;
|
||||
this.#networkStorage = networkStorage;
|
||||
this.#realmStorage = realmStorage;
|
||||
this.#sharedIdWithFrame = sharedIdWithFrame;
|
||||
this.#defaultUserContextId = defaultUserContextId;
|
||||
this.#logger = logger;
|
||||
this.#setEventListeners(browserCdpClient);
|
||||
}
|
||||
getTree(params) {
|
||||
const resultContexts = params.root === undefined
|
||||
? this.#browsingContextStorage.getTopLevelContexts()
|
||||
: [this.#browsingContextStorage.getContext(params.root)];
|
||||
return {
|
||||
contexts: resultContexts.map((c) => c.serializeToBidiValue(params.maxDepth ?? Number.MAX_VALUE)),
|
||||
};
|
||||
}
|
||||
async create(params) {
|
||||
let referenceContext;
|
||||
let userContext = params.userContext ?? 'default';
|
||||
if (params.referenceContext !== undefined) {
|
||||
referenceContext = this.#browsingContextStorage.getContext(params.referenceContext);
|
||||
if (!referenceContext.isTopLevelContext()) {
|
||||
throw new protocol_js_1.InvalidArgumentException(`referenceContext should be a top-level context`);
|
||||
}
|
||||
userContext = referenceContext.userContext;
|
||||
}
|
||||
let newWindow = false;
|
||||
switch (params.type) {
|
||||
case "tab" /* BrowsingContext.CreateType.Tab */:
|
||||
newWindow = false;
|
||||
break;
|
||||
case "window" /* BrowsingContext.CreateType.Window */:
|
||||
newWindow = true;
|
||||
break;
|
||||
}
|
||||
if (userContext !== 'default') {
|
||||
const existingContexts = this.#browsingContextStorage
|
||||
.getAllContexts()
|
||||
.filter((context) => context.userContext === userContext);
|
||||
if (!existingContexts.length) {
|
||||
// If there are no contexts in the given user context, we need to set
|
||||
// newWindow to true as newWindow=false will be rejected.
|
||||
newWindow = true;
|
||||
}
|
||||
}
|
||||
let result;
|
||||
try {
|
||||
result = await this.#browserCdpClient.sendCommand('Target.createTarget', {
|
||||
url: 'about:blank',
|
||||
newWindow,
|
||||
browserContextId: userContext === 'default' ? undefined : userContext,
|
||||
});
|
||||
}
|
||||
catch (err) {
|
||||
if (
|
||||
// See https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/devtools/protocol/target_handler.cc;l=90;drc=e80392ac11e48a691f4309964cab83a3a59e01c8
|
||||
err.message.startsWith('Failed to find browser context with id') ||
|
||||
// See https://source.chromium.org/chromium/chromium/src/+/main:headless/lib/browser/protocol/target_handler.cc;l=49;drc=e80392ac11e48a691f4309964cab83a3a59e01c8
|
||||
err.message === 'browserContextId') {
|
||||
throw new protocol_js_1.NoSuchUserContextException(`The context ${userContext} was not found`);
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
// Wait for the new tab to be loaded to avoid race conditions in the
|
||||
// `browsingContext` events, when the `browsingContext.domContentLoaded` and
|
||||
// `browsingContext.load` events from the initial `about:blank` navigation
|
||||
// are emitted after the next navigation is started.
|
||||
// Details: https://github.com/web-platform-tests/wpt/issues/35846
|
||||
const contextId = result.targetId;
|
||||
const context = this.#browsingContextStorage.getContext(contextId);
|
||||
await context.lifecycleLoaded();
|
||||
return { context: context.id };
|
||||
}
|
||||
navigate(params) {
|
||||
const context = this.#browsingContextStorage.getContext(params.context);
|
||||
return context.navigate(params.url, params.wait ?? "none" /* BrowsingContext.ReadinessState.None */);
|
||||
}
|
||||
reload(params) {
|
||||
const context = this.#browsingContextStorage.getContext(params.context);
|
||||
return context.reload(params.ignoreCache ?? false, params.wait ?? "none" /* BrowsingContext.ReadinessState.None */);
|
||||
}
|
||||
async activate(params) {
|
||||
const context = this.#browsingContextStorage.getContext(params.context);
|
||||
if (!context.isTopLevelContext()) {
|
||||
throw new protocol_js_1.InvalidArgumentException('Activation is only supported on the top-level context');
|
||||
}
|
||||
await context.activate();
|
||||
return {};
|
||||
}
|
||||
async captureScreenshot(params) {
|
||||
const context = this.#browsingContextStorage.getContext(params.context);
|
||||
return await context.captureScreenshot(params);
|
||||
}
|
||||
async print(params) {
|
||||
const context = this.#browsingContextStorage.getContext(params.context);
|
||||
return await context.print(params);
|
||||
}
|
||||
async setViewport(params) {
|
||||
const context = this.#browsingContextStorage.getContext(params.context);
|
||||
if (!context.isTopLevelContext()) {
|
||||
throw new protocol_js_1.InvalidArgumentException('Emulating viewport is only supported on the top-level context');
|
||||
}
|
||||
await context.setViewport(params.viewport, params.devicePixelRatio);
|
||||
return {};
|
||||
}
|
||||
async traverseHistory(params) {
|
||||
const context = this.#browsingContextStorage.getContext(params.context);
|
||||
if (!context) {
|
||||
throw new protocol_js_1.InvalidArgumentException(`No browsing context with id ${params.context}`);
|
||||
}
|
||||
await context.traverseHistory(params.delta);
|
||||
return {};
|
||||
}
|
||||
async handleUserPrompt(params) {
|
||||
const context = this.#browsingContextStorage.getContext(params.context);
|
||||
await context.handleUserPrompt(params);
|
||||
return {};
|
||||
}
|
||||
async close(params) {
|
||||
const context = this.#browsingContextStorage.getContext(params.context);
|
||||
if (!context.isTopLevelContext()) {
|
||||
throw new protocol_js_1.InvalidArgumentException(`Non top-level browsing context ${context.id} cannot be closed.`);
|
||||
}
|
||||
try {
|
||||
const detachedFromTargetPromise = new Promise((resolve) => {
|
||||
const onContextDestroyed = (event) => {
|
||||
if (event.targetId === params.context) {
|
||||
this.#browserCdpClient.off('Target.detachedFromTarget', onContextDestroyed);
|
||||
resolve();
|
||||
}
|
||||
};
|
||||
this.#browserCdpClient.on('Target.detachedFromTarget', onContextDestroyed);
|
||||
});
|
||||
if (params.promptUnload) {
|
||||
await context.close();
|
||||
}
|
||||
else {
|
||||
await this.#browserCdpClient.sendCommand('Target.closeTarget', {
|
||||
targetId: params.context,
|
||||
});
|
||||
}
|
||||
// Sometimes CDP command finishes before `detachedFromTarget` event,
|
||||
// sometimes after. Wait for the CDP command to be finished, and then wait
|
||||
// for `detachedFromTarget` if it hasn't emitted.
|
||||
await detachedFromTargetPromise;
|
||||
}
|
||||
catch (error) {
|
||||
// Swallow error that arise from the page being destroyed
|
||||
// Example is navigating to faulty SSL certificate
|
||||
if (!(error.code === -32000 /* CdpErrorConstants.GENERIC_ERROR */ &&
|
||||
error.message === 'Not attached to an active page')) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
/**
|
||||
* This method is called for each CDP session, since this class is responsible
|
||||
* for creating and destroying all targets and browsing contexts.
|
||||
*/
|
||||
#setEventListeners(cdpClient) {
|
||||
cdpClient.on('Target.attachedToTarget', (params) => {
|
||||
this.#handleAttachedToTargetEvent(params, cdpClient);
|
||||
});
|
||||
cdpClient.on('Target.detachedFromTarget', (params) => {
|
||||
this.#handleDetachedFromTargetEvent(params);
|
||||
});
|
||||
cdpClient.on('Target.targetInfoChanged', (params) => {
|
||||
this.#handleTargetInfoChangedEvent(params);
|
||||
});
|
||||
cdpClient.on('Page.frameAttached', (params) => {
|
||||
this.#handleFrameAttachedEvent(params);
|
||||
});
|
||||
cdpClient.on('Page.frameDetached', (params) => {
|
||||
this.#handleFrameDetachedEvent(params);
|
||||
});
|
||||
}
|
||||
#handleFrameAttachedEvent(params) {
|
||||
const parentBrowsingContext = this.#browsingContextStorage.findContext(params.parentFrameId);
|
||||
if (parentBrowsingContext !== undefined) {
|
||||
BrowsingContextImpl_js_1.BrowsingContextImpl.create(parentBrowsingContext.cdpTarget, this.#realmStorage, params.frameId, params.parentFrameId, parentBrowsingContext.userContext, this.#eventManager, this.#browsingContextStorage, this.#sharedIdWithFrame, this.#logger);
|
||||
}
|
||||
}
|
||||
#handleFrameDetachedEvent(params) {
|
||||
// In case of OOPiF no need in deleting BrowsingContext.
|
||||
if (params.reason === 'swap') {
|
||||
return;
|
||||
}
|
||||
this.#browsingContextStorage.findContext(params.frameId)?.dispose();
|
||||
}
|
||||
#handleAttachedToTargetEvent(params, parentSessionCdpClient) {
|
||||
const { sessionId, targetInfo } = params;
|
||||
const targetCdpClient = this.#cdpConnection.getCdpClient(sessionId);
|
||||
this.#logger?.(log_js_1.LogType.debugInfo, 'AttachedToTarget event received:', params);
|
||||
switch (targetInfo.type) {
|
||||
case 'page':
|
||||
case 'iframe': {
|
||||
if (targetInfo.targetId === this.#selfTargetId) {
|
||||
break;
|
||||
}
|
||||
const cdpTarget = this.#createCdpTarget(targetCdpClient, targetInfo);
|
||||
const maybeContext = this.#browsingContextStorage.findContext(targetInfo.targetId);
|
||||
if (maybeContext) {
|
||||
// OOPiF.
|
||||
maybeContext.updateCdpTarget(cdpTarget);
|
||||
}
|
||||
else {
|
||||
// New context.
|
||||
BrowsingContextImpl_js_1.BrowsingContextImpl.create(cdpTarget, this.#realmStorage, targetInfo.targetId, null, targetInfo.browserContextId &&
|
||||
targetInfo.browserContextId !== this.#defaultUserContextId
|
||||
? targetInfo.browserContextId
|
||||
: 'default', this.#eventManager, this.#browsingContextStorage, this.#sharedIdWithFrame, this.#logger);
|
||||
}
|
||||
return;
|
||||
}
|
||||
case 'worker': {
|
||||
const browsingContext = parentSessionCdpClient.sessionId &&
|
||||
this.#browsingContextStorage.findContextBySession(parentSessionCdpClient.sessionId);
|
||||
// If there is no browsing context, this worker is already terminated.
|
||||
if (!browsingContext) {
|
||||
break;
|
||||
}
|
||||
const cdpTarget = this.#createCdpTarget(targetCdpClient, targetInfo);
|
||||
this.#handleWorkerTarget(cdpTarget, this.#realmStorage.getRealm({
|
||||
browsingContextId: browsingContext.id,
|
||||
type: 'window',
|
||||
sandbox: undefined,
|
||||
}));
|
||||
return;
|
||||
}
|
||||
}
|
||||
// DevTools or some other not supported by BiDi target. Just release
|
||||
// debugger and ignore them.
|
||||
targetCdpClient
|
||||
.sendCommand('Runtime.runIfWaitingForDebugger')
|
||||
.then(() => parentSessionCdpClient.sendCommand('Target.detachFromTarget', params))
|
||||
.catch((error) => this.#logger?.(log_js_1.LogType.debugError, error));
|
||||
}
|
||||
#createCdpTarget(targetCdpClient, targetInfo) {
|
||||
this.#setEventListeners(targetCdpClient);
|
||||
return CdpTarget_js_1.CdpTarget.create(targetInfo.targetId, targetCdpClient, this.#browserCdpClient, this.#realmStorage, this.#eventManager, this.#preloadScriptStorage, this.#networkStorage, this.#acceptInsecureCerts, this.#logger);
|
||||
}
|
||||
#workers = new Map();
|
||||
#handleWorkerTarget(cdpTarget, ownerRealm) {
|
||||
cdpTarget.cdpClient.on('Runtime.executionContextCreated', (params) => {
|
||||
const { uniqueId, id, origin } = params.context;
|
||||
const workerRealm = new DedicatedWorkerRealm_js_1.DedicatedWorkerRealm(cdpTarget.cdpClient, this.#eventManager, id, this.#logger, (0, BrowsingContextImpl_js_1.serializeOrigin)(origin), ownerRealm, uniqueId, this.#realmStorage);
|
||||
this.#workers.set(cdpTarget.cdpSessionId, workerRealm);
|
||||
});
|
||||
}
|
||||
#handleDetachedFromTargetEvent(params) {
|
||||
const context = this.#browsingContextStorage.findContextBySession(params.sessionId);
|
||||
if (context) {
|
||||
context.dispose();
|
||||
this.#preloadScriptStorage
|
||||
.find({ targetId: context.id })
|
||||
.map((preloadScript) => preloadScript.dispose(context.id));
|
||||
return;
|
||||
}
|
||||
const worker = this.#workers.get(params.sessionId);
|
||||
if (worker) {
|
||||
this.#realmStorage.deleteRealms({
|
||||
cdpSessionId: worker.cdpClient.sessionId,
|
||||
});
|
||||
}
|
||||
}
|
||||
#handleTargetInfoChangedEvent(params) {
|
||||
const context = this.#browsingContextStorage.findContext(params.targetInfo.targetId);
|
||||
if (context) {
|
||||
context.onTargetInfoChanged(params);
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.BrowsingContextProcessor = BrowsingContextProcessor;
|
||||
//# sourceMappingURL=BrowsingContextProcessor.js.map
|
||||
1
node_modules/chromium-bidi/lib/cjs/bidiMapper/domains/context/BrowsingContextProcessor.js.map
generated
vendored
Normal file
1
node_modules/chromium-bidi/lib/cjs/bidiMapper/domains/context/BrowsingContextProcessor.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
41
node_modules/chromium-bidi/lib/cjs/bidiMapper/domains/context/BrowsingContextStorage.d.ts
generated
vendored
Normal file
41
node_modules/chromium-bidi/lib/cjs/bidiMapper/domains/context/BrowsingContextStorage.d.ts
generated
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* Copyright 2022 Google LLC.
|
||||
* 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 { type BrowsingContext } from '../../../protocol/protocol.js';
|
||||
import type { BrowsingContextImpl } from './BrowsingContextImpl.js';
|
||||
/** Container class for browsing contexts. */
|
||||
export declare class BrowsingContextStorage {
|
||||
#private;
|
||||
/** Gets all top-level contexts, i.e. those with no parent. */
|
||||
getTopLevelContexts(): BrowsingContextImpl[];
|
||||
/** Gets all contexts. */
|
||||
getAllContexts(): BrowsingContextImpl[];
|
||||
/** Deletes the context with the given ID. */
|
||||
deleteContextById(id: BrowsingContext.BrowsingContext): void;
|
||||
/** Deletes the given context. */
|
||||
deleteContext(context: BrowsingContextImpl): void;
|
||||
/** Tracks the given context. */
|
||||
addContext(context: BrowsingContextImpl): void;
|
||||
/** Returns true whether there is an existing context with the given ID. */
|
||||
hasContext(id: BrowsingContext.BrowsingContext): boolean;
|
||||
/** Gets the context with the given ID, if any. */
|
||||
findContext(id: BrowsingContext.BrowsingContext): BrowsingContextImpl | undefined;
|
||||
/** Returns the top-level context ID of the given context, if any. */
|
||||
findTopLevelContextId(id: BrowsingContext.BrowsingContext | null): BrowsingContext.BrowsingContext | null;
|
||||
findContextBySession(sessionId: string): BrowsingContextImpl | undefined;
|
||||
/** Gets the context with the given ID, if any, otherwise throws. */
|
||||
getContext(id: BrowsingContext.BrowsingContext): BrowsingContextImpl;
|
||||
}
|
||||
83
node_modules/chromium-bidi/lib/cjs/bidiMapper/domains/context/BrowsingContextStorage.js
generated
vendored
Normal file
83
node_modules/chromium-bidi/lib/cjs/bidiMapper/domains/context/BrowsingContextStorage.js
generated
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
"use strict";
|
||||
/**
|
||||
* Copyright 2022 Google LLC.
|
||||
* 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.
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.BrowsingContextStorage = void 0;
|
||||
const protocol_js_1 = require("../../../protocol/protocol.js");
|
||||
/** Container class for browsing contexts. */
|
||||
class BrowsingContextStorage {
|
||||
/** Map from context ID to context implementation. */
|
||||
#contexts = new Map();
|
||||
/** Gets all top-level contexts, i.e. those with no parent. */
|
||||
getTopLevelContexts() {
|
||||
return this.getAllContexts().filter((context) => context.isTopLevelContext());
|
||||
}
|
||||
/** Gets all contexts. */
|
||||
getAllContexts() {
|
||||
return Array.from(this.#contexts.values());
|
||||
}
|
||||
/** Deletes the context with the given ID. */
|
||||
deleteContextById(id) {
|
||||
this.#contexts.delete(id);
|
||||
}
|
||||
/** Deletes the given context. */
|
||||
deleteContext(context) {
|
||||
this.#contexts.delete(context.id);
|
||||
}
|
||||
/** Tracks the given context. */
|
||||
addContext(context) {
|
||||
this.#contexts.set(context.id, context);
|
||||
}
|
||||
/** Returns true whether there is an existing context with the given ID. */
|
||||
hasContext(id) {
|
||||
return this.#contexts.has(id);
|
||||
}
|
||||
/** Gets the context with the given ID, if any. */
|
||||
findContext(id) {
|
||||
return this.#contexts.get(id);
|
||||
}
|
||||
/** Returns the top-level context ID of the given context, if any. */
|
||||
findTopLevelContextId(id) {
|
||||
if (id === null) {
|
||||
return null;
|
||||
}
|
||||
const maybeContext = this.findContext(id);
|
||||
const parentId = maybeContext?.parentId ?? null;
|
||||
if (parentId === null) {
|
||||
return id;
|
||||
}
|
||||
return this.findTopLevelContextId(parentId);
|
||||
}
|
||||
findContextBySession(sessionId) {
|
||||
for (const context of this.#contexts.values()) {
|
||||
if (context.cdpTarget.cdpSessionId === sessionId) {
|
||||
return context;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
/** Gets the context with the given ID, if any, otherwise throws. */
|
||||
getContext(id) {
|
||||
const result = this.findContext(id);
|
||||
if (result === undefined) {
|
||||
throw new protocol_js_1.NoSuchFrameException(`Context ${id} not found`);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
exports.BrowsingContextStorage = BrowsingContextStorage;
|
||||
//# sourceMappingURL=BrowsingContextStorage.js.map
|
||||
1
node_modules/chromium-bidi/lib/cjs/bidiMapper/domains/context/BrowsingContextStorage.js.map
generated
vendored
Normal file
1
node_modules/chromium-bidi/lib/cjs/bidiMapper/domains/context/BrowsingContextStorage.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"BrowsingContextStorage.js","sourceRoot":"","sources":["../../../../../src/bidiMapper/domains/context/BrowsingContextStorage.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;GAeG;;;AAEH,+DAGuC;AAIvC,6CAA6C;AAC7C,MAAa,sBAAsB;IACjC,qDAAqD;IAC5C,SAAS,GAAG,IAAI,GAAG,EAGzB,CAAC;IAEJ,8DAA8D;IAC9D,mBAAmB;QACjB,OAAO,IAAI,CAAC,cAAc,EAAE,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAC9C,OAAO,CAAC,iBAAiB,EAAE,CAC5B,CAAC;IACJ,CAAC;IAED,yBAAyB;IACzB,cAAc;QACZ,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC;IAC7C,CAAC;IAED,6CAA6C;IAC7C,iBAAiB,CAAC,EAAmC;QACnD,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAC5B,CAAC;IAED,iCAAiC;IACjC,aAAa,CAAC,OAA4B;QACxC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACpC,CAAC;IAED,gCAAgC;IAChC,UAAU,CAAC,OAA4B;QACrC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;IAC1C,CAAC;IAED,2EAA2E;IAC3E,UAAU,CAAC,EAAmC;QAC5C,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChC,CAAC;IAED,kDAAkD;IAClD,WAAW,CACT,EAAmC;QAEnC,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChC,CAAC;IAED,qEAAqE;IACrE,qBAAqB,CACnB,EAA0C;QAE1C,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;YAChB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,YAAY,GAAG,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;QAC1C,MAAM,QAAQ,GAAG,YAAY,EAAE,QAAQ,IAAI,IAAI,CAAC;QAChD,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;YACtB,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,OAAO,IAAI,CAAC,qBAAqB,CAAC,QAAQ,CAAC,CAAC;IAC9C,CAAC;IAED,oBAAoB,CAAC,SAAiB;QACpC,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,CAAC;YAC9C,IAAI,OAAO,CAAC,SAAS,CAAC,YAAY,KAAK,SAAS,EAAE,CAAC;gBACjD,OAAO,OAAO,CAAC;YACjB,CAAC;QACH,CAAC;QACD,OAAO;IACT,CAAC;IAED,oEAAoE;IACpE,UAAU,CAAC,EAAmC;QAC5C,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;QACpC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,MAAM,IAAI,kCAAoB,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;QAC5D,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;CACF;AA9ED,wDA8EC"}
|
||||
31
node_modules/chromium-bidi/lib/cjs/bidiMapper/domains/context/CdpTarget.d.ts
generated
vendored
Normal file
31
node_modules/chromium-bidi/lib/cjs/bidiMapper/domains/context/CdpTarget.d.ts
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
import type { Protocol } from 'devtools-protocol';
|
||||
import type { CdpClient } from '../../../cdp/CdpClient.js';
|
||||
import { Deferred } from '../../../utils/Deferred.js';
|
||||
import type { LoggerFn } from '../../../utils/log.js';
|
||||
import type { Result } from '../../../utils/result.js';
|
||||
import type { NetworkStorage } from '../network/NetworkStorage.js';
|
||||
import type { ChannelProxy } from '../script/ChannelProxy.js';
|
||||
import type { PreloadScriptStorage } from '../script/PreloadScriptStorage.js';
|
||||
import type { RealmStorage } from '../script/RealmStorage.js';
|
||||
import type { EventManager } from '../session/EventManager.js';
|
||||
export declare class CdpTarget {
|
||||
#private;
|
||||
static create(targetId: Protocol.Target.TargetID, cdpClient: CdpClient, browserCdpClient: CdpClient, realmStorage: RealmStorage, eventManager: EventManager, preloadScriptStorage: PreloadScriptStorage, networkStorage: NetworkStorage, acceptInsecureCerts: boolean, logger?: LoggerFn): CdpTarget;
|
||||
constructor(targetId: Protocol.Target.TargetID, cdpClient: CdpClient, browserCdpClient: CdpClient, eventManager: EventManager, preloadScriptStorage: PreloadScriptStorage, networkStorage: NetworkStorage, acceptInsecureCerts: boolean);
|
||||
/** Returns a deferred that resolves when the target is unblocked. */
|
||||
get unblocked(): Deferred<Result<void>>;
|
||||
get id(): Protocol.Target.TargetID;
|
||||
get cdpClient(): CdpClient;
|
||||
get browserCdpClient(): CdpClient;
|
||||
/** Needed for CDP escape path. */
|
||||
get cdpSessionId(): Protocol.Target.SessionID;
|
||||
/** Calls `Fetch.enable` with the added network intercepts. */
|
||||
fetchEnable(): Promise<void>;
|
||||
/** Calls `Fetch.disable`. */
|
||||
fetchDisable(): Promise<void>;
|
||||
/**
|
||||
* All the ProxyChannels from all the preload scripts of the given
|
||||
* BrowsingContext.
|
||||
*/
|
||||
getChannels(): ChannelProxy[];
|
||||
}
|
||||
142
node_modules/chromium-bidi/lib/cjs/bidiMapper/domains/context/CdpTarget.js
generated
vendored
Normal file
142
node_modules/chromium-bidi/lib/cjs/bidiMapper/domains/context/CdpTarget.js
generated
vendored
Normal file
@@ -0,0 +1,142 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.CdpTarget = void 0;
|
||||
const Deferred_js_1 = require("../../../utils/Deferred.js");
|
||||
const LogManager_js_1 = require("../log/LogManager.js");
|
||||
const NetworkManager_js_1 = require("../network/NetworkManager.js");
|
||||
class CdpTarget {
|
||||
#id;
|
||||
#cdpClient;
|
||||
#browserCdpClient;
|
||||
#eventManager;
|
||||
#preloadScriptStorage;
|
||||
#networkStorage;
|
||||
#targetUnblocked = new Deferred_js_1.Deferred();
|
||||
#acceptInsecureCerts;
|
||||
static create(targetId, cdpClient, browserCdpClient, realmStorage, eventManager, preloadScriptStorage, networkStorage, acceptInsecureCerts, logger) {
|
||||
const cdpTarget = new CdpTarget(targetId, cdpClient, browserCdpClient, eventManager, preloadScriptStorage, networkStorage, acceptInsecureCerts);
|
||||
LogManager_js_1.LogManager.create(cdpTarget, realmStorage, eventManager, logger);
|
||||
NetworkManager_js_1.NetworkManager.create(cdpTarget, eventManager, networkStorage);
|
||||
cdpTarget.#setEventListeners();
|
||||
// No need to await.
|
||||
// Deferred will be resolved when the target is unblocked.
|
||||
void cdpTarget.#unblock();
|
||||
return cdpTarget;
|
||||
}
|
||||
constructor(targetId, cdpClient, browserCdpClient, eventManager, preloadScriptStorage, networkStorage, acceptInsecureCerts) {
|
||||
this.#id = targetId;
|
||||
this.#cdpClient = cdpClient;
|
||||
this.#eventManager = eventManager;
|
||||
this.#preloadScriptStorage = preloadScriptStorage;
|
||||
this.#networkStorage = networkStorage;
|
||||
this.#browserCdpClient = browserCdpClient;
|
||||
this.#acceptInsecureCerts = acceptInsecureCerts;
|
||||
}
|
||||
/** Returns a deferred that resolves when the target is unblocked. */
|
||||
get unblocked() {
|
||||
return this.#targetUnblocked;
|
||||
}
|
||||
get id() {
|
||||
return this.#id;
|
||||
}
|
||||
get cdpClient() {
|
||||
return this.#cdpClient;
|
||||
}
|
||||
get browserCdpClient() {
|
||||
return this.#browserCdpClient;
|
||||
}
|
||||
/** Needed for CDP escape path. */
|
||||
get cdpSessionId() {
|
||||
// SAFETY we got the client by it's id for creating
|
||||
return this.#cdpClient.sessionId;
|
||||
}
|
||||
/** Calls `Fetch.enable` with the added network intercepts. */
|
||||
async fetchEnable() {
|
||||
await this.#cdpClient.sendCommand('Fetch.enable', this.#networkStorage.getFetchEnableParams());
|
||||
}
|
||||
/** Calls `Fetch.disable`. */
|
||||
async fetchDisable() {
|
||||
await this.#cdpClient.sendCommand('Fetch.disable');
|
||||
}
|
||||
/**
|
||||
* Enables all the required CDP domains and unblocks the target.
|
||||
*/
|
||||
async #unblock() {
|
||||
try {
|
||||
await Promise.all([
|
||||
this.#cdpClient.sendCommand('Runtime.enable'),
|
||||
this.#cdpClient.sendCommand('Page.enable'),
|
||||
this.#cdpClient.sendCommand('Page.setLifecycleEventsEnabled', {
|
||||
enabled: true,
|
||||
}),
|
||||
// Set ignore certificate errors for each target.
|
||||
this.#cdpClient.sendCommand('Security.setIgnoreCertificateErrors', {
|
||||
ignore: this.#acceptInsecureCerts,
|
||||
}),
|
||||
// XXX: #1080: Do not always enable the network domain globally.
|
||||
// TODO: enable Network domain for OOPiF targets.
|
||||
this.#cdpClient.sendCommand('Network.enable'),
|
||||
// XXX: #1080: Do not always enable the fetch domain globally.
|
||||
this.fetchEnable(),
|
||||
this.#cdpClient.sendCommand('Target.setAutoAttach', {
|
||||
autoAttach: true,
|
||||
waitForDebuggerOnStart: true,
|
||||
flatten: true,
|
||||
}),
|
||||
this.#initAndEvaluatePreloadScripts(),
|
||||
this.#cdpClient.sendCommand('Runtime.runIfWaitingForDebugger'),
|
||||
]);
|
||||
}
|
||||
catch (error) {
|
||||
// The target might have been closed before the initialization finished.
|
||||
if (!this.#cdpClient.isCloseError(error)) {
|
||||
this.#targetUnblocked.resolve({
|
||||
kind: 'error',
|
||||
error,
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.#targetUnblocked.resolve({
|
||||
kind: 'success',
|
||||
value: undefined,
|
||||
});
|
||||
}
|
||||
#setEventListeners() {
|
||||
this.#cdpClient.on('*', (event, params) => {
|
||||
// We may encounter uses for EventEmitter other than CDP events,
|
||||
// which we want to skip.
|
||||
if (typeof event !== 'string') {
|
||||
return;
|
||||
}
|
||||
this.#eventManager.registerEvent({
|
||||
type: 'event',
|
||||
method: `cdp.${event}`,
|
||||
params: {
|
||||
event,
|
||||
params,
|
||||
session: this.cdpSessionId,
|
||||
},
|
||||
}, null);
|
||||
});
|
||||
}
|
||||
/**
|
||||
* All the ProxyChannels from all the preload scripts of the given
|
||||
* BrowsingContext.
|
||||
*/
|
||||
getChannels() {
|
||||
return this.#preloadScriptStorage
|
||||
.find()
|
||||
.flatMap((script) => script.channels);
|
||||
}
|
||||
/** Loads all top-level preload scripts. */
|
||||
async #initAndEvaluatePreloadScripts() {
|
||||
for (const script of this.#preloadScriptStorage.find({
|
||||
global: true,
|
||||
})) {
|
||||
await script.initInTarget(this, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.CdpTarget = CdpTarget;
|
||||
//# sourceMappingURL=CdpTarget.js.map
|
||||
1
node_modules/chromium-bidi/lib/cjs/bidiMapper/domains/context/CdpTarget.js.map
generated
vendored
Normal file
1
node_modules/chromium-bidi/lib/cjs/bidiMapper/domains/context/CdpTarget.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"CdpTarget.js","sourceRoot":"","sources":["../../../../../src/bidiMapper/domains/context/CdpTarget.ts"],"names":[],"mappings":"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"}
|
||||
Reference in New Issue
Block a user