add hw2
This commit is contained in:
27
node_modules/chromium-bidi/lib/esm/bidiMapper/modules/cdp/CdpProcessor.d.ts
generated
vendored
Normal file
27
node_modules/chromium-bidi/lib/esm/bidiMapper/modules/cdp/CdpProcessor.d.ts
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Copyright 2023 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 Cdp } from '../../../protocol/protocol.js';
|
||||
import type { CdpClient, CdpConnection } from '../../BidiMapper.js';
|
||||
import type { BrowsingContextStorage } from '../context/BrowsingContextStorage.js';
|
||||
import type { RealmStorage } from '../script/RealmStorage.js';
|
||||
export declare class CdpProcessor {
|
||||
#private;
|
||||
constructor(browsingContextStorage: BrowsingContextStorage, realmStorage: RealmStorage, cdpConnection: CdpConnection, browserCdpClient: CdpClient);
|
||||
getSession(params: Cdp.GetSessionParameters): Cdp.GetSessionResult;
|
||||
resolveRealm(params: Cdp.ResolveRealmParameters): Cdp.ResolveRealmResult;
|
||||
sendCommand(params: Cdp.SendCommandParameters): Promise<Cdp.SendCommandResult>;
|
||||
}
|
||||
56
node_modules/chromium-bidi/lib/esm/bidiMapper/modules/cdp/CdpProcessor.js
generated
vendored
Normal file
56
node_modules/chromium-bidi/lib/esm/bidiMapper/modules/cdp/CdpProcessor.js
generated
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* Copyright 2023 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 { UnknownErrorException } from '../../../protocol/protocol.js';
|
||||
export class CdpProcessor {
|
||||
#browsingContextStorage;
|
||||
#realmStorage;
|
||||
#cdpConnection;
|
||||
#browserCdpClient;
|
||||
constructor(browsingContextStorage, realmStorage, cdpConnection, browserCdpClient) {
|
||||
this.#browsingContextStorage = browsingContextStorage;
|
||||
this.#realmStorage = realmStorage;
|
||||
this.#cdpConnection = cdpConnection;
|
||||
this.#browserCdpClient = browserCdpClient;
|
||||
}
|
||||
getSession(params) {
|
||||
const context = params.context;
|
||||
const sessionId = this.#browsingContextStorage.getContext(context).cdpTarget.cdpSessionId;
|
||||
if (sessionId === undefined) {
|
||||
return {};
|
||||
}
|
||||
return { session: sessionId };
|
||||
}
|
||||
resolveRealm(params) {
|
||||
const context = params.realm;
|
||||
const realm = this.#realmStorage.getRealm({ realmId: context });
|
||||
if (realm === undefined) {
|
||||
throw new UnknownErrorException(`Could not find realm ${params.realm}`);
|
||||
}
|
||||
return { executionContextId: realm.executionContextId };
|
||||
}
|
||||
async sendCommand(params) {
|
||||
const client = params.session
|
||||
? this.#cdpConnection.getCdpClient(params.session)
|
||||
: this.#browserCdpClient;
|
||||
const result = await client.sendCommand(params.method, params.params);
|
||||
return {
|
||||
result,
|
||||
session: params.session,
|
||||
};
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=CdpProcessor.js.map
|
||||
1
node_modules/chromium-bidi/lib/esm/bidiMapper/modules/cdp/CdpProcessor.js.map
generated
vendored
Normal file
1
node_modules/chromium-bidi/lib/esm/bidiMapper/modules/cdp/CdpProcessor.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"CdpProcessor.js","sourceRoot":"","sources":["../../../../../src/bidiMapper/modules/cdp/CdpProcessor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAC,qBAAqB,EAAW,MAAM,+BAA+B,CAAC;AAK9E,MAAM,OAAO,YAAY;IACd,uBAAuB,CAAyB;IAChD,aAAa,CAAe;IAC5B,cAAc,CAAgB;IAC9B,iBAAiB,CAAY;IAEtC,YACE,sBAA8C,EAC9C,YAA0B,EAC1B,aAA4B,EAC5B,gBAA2B;QAE3B,IAAI,CAAC,uBAAuB,GAAG,sBAAsB,CAAC;QACtD,IAAI,CAAC,aAAa,GAAG,YAAY,CAAC;QAClC,IAAI,CAAC,cAAc,GAAG,aAAa,CAAC;QACpC,IAAI,CAAC,iBAAiB,GAAG,gBAAgB,CAAC;IAC5C,CAAC;IAED,UAAU,CAAC,MAAgC;QACzC,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;QAC/B,MAAM,SAAS,GACb,IAAI,CAAC,uBAAuB,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC;QAC1E,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;YAC5B,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,OAAO,EAAC,OAAO,EAAE,SAAS,EAAC,CAAC;IAC9B,CAAC;IAED,YAAY,CAAC,MAAkC;QAC7C,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC;QAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,EAAC,OAAO,EAAE,OAAO,EAAC,CAAC,CAAC;QAC9D,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,MAAM,IAAI,qBAAqB,CAAC,wBAAwB,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;QAC1E,CAAC;QACD,OAAO,EAAC,kBAAkB,EAAE,KAAK,CAAC,kBAAkB,EAAC,CAAC;IACxD,CAAC;IAED,KAAK,CAAC,WAAW,CACf,MAAiC;QAEjC,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO;YAC3B,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,YAAY,CAAC,MAAM,CAAC,OAAO,CAAC;YAClD,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC;QAC3B,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;QACtE,OAAO;YACL,MAAM;YACN,OAAO,EAAE,MAAM,CAAC,OAAO;SACxB,CAAC;IACJ,CAAC;CACF"}
|
||||
42
node_modules/chromium-bidi/lib/esm/bidiMapper/modules/cdp/CdpTarget.d.ts
generated
vendored
Normal file
42
node_modules/chromium-bidi/lib/esm/bidiMapper/modules/cdp/CdpTarget.d.ts
generated
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
import type { Protocol } from 'devtools-protocol';
|
||||
import type { CdpClient } from '../../../cdp/CdpClient.js';
|
||||
import type { ChromiumBidi, Session } from '../../../protocol/protocol.js';
|
||||
import { Deferred } from '../../../utils/Deferred.js';
|
||||
import { EventEmitter } from '../../../utils/EventEmitter.js';
|
||||
import type { LoggerFn } from '../../../utils/log.js';
|
||||
import type { Result } from '../../../utils/result.js';
|
||||
import type { BrowsingContextStorage } from '../context/BrowsingContextStorage.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';
|
||||
import { type TargetEventMap } from './TargetEvents.js';
|
||||
export declare class CdpTarget extends EventEmitter<TargetEventMap> {
|
||||
#private;
|
||||
static create(targetId: Protocol.Target.TargetID, cdpClient: CdpClient, browserCdpClient: CdpClient, parentCdpClient: CdpClient, realmStorage: RealmStorage, eventManager: EventManager, preloadScriptStorage: PreloadScriptStorage, browsingContextStorage: BrowsingContextStorage, networkStorage: NetworkStorage, prerenderingDisabled: boolean, unhandledPromptBehavior?: Session.UserPromptHandler, logger?: LoggerFn): CdpTarget;
|
||||
constructor(targetId: Protocol.Target.TargetID, cdpClient: CdpClient, browserCdpClient: CdpClient, parentCdpClient: CdpClient, eventManager: EventManager, realmStorage: RealmStorage, preloadScriptStorage: PreloadScriptStorage, browsingContextStorage: BrowsingContextStorage, networkStorage: NetworkStorage, prerenderingDisabled: boolean, unhandledPromptBehavior?: Session.UserPromptHandler, logger?: LoggerFn);
|
||||
/** Returns a deferred that resolves when the target is unblocked. */
|
||||
get unblocked(): Deferred<Result<void>>;
|
||||
get id(): Protocol.Target.TargetID;
|
||||
get cdpClient(): CdpClient;
|
||||
get parentCdpClient(): CdpClient;
|
||||
get browserCdpClient(): CdpClient;
|
||||
/** Needed for CDP escape path. */
|
||||
get cdpSessionId(): Protocol.Target.SessionID;
|
||||
toggleFetchIfNeeded(): Promise<void>;
|
||||
/**
|
||||
* Toggles CDP "Fetch" domain and enable/disable network cache.
|
||||
*/
|
||||
toggleNetworkIfNeeded(): Promise<void>;
|
||||
toggleSetCacheDisabled(disable?: boolean): Promise<void>;
|
||||
toggleDeviceAccessIfNeeded(): Promise<void>;
|
||||
toggleNetwork(): Promise<void>;
|
||||
/**
|
||||
* All the ProxyChannels from all the preload scripts of the given
|
||||
* BrowsingContext.
|
||||
*/
|
||||
getChannels(): ChannelProxy[];
|
||||
get topLevelId(): string;
|
||||
isSubscribedTo(moduleOrEvent: ChromiumBidi.EventNames): boolean;
|
||||
}
|
||||
392
node_modules/chromium-bidi/lib/esm/bidiMapper/modules/cdp/CdpTarget.js
generated
vendored
Normal file
392
node_modules/chromium-bidi/lib/esm/bidiMapper/modules/cdp/CdpTarget.js
generated
vendored
Normal file
@@ -0,0 +1,392 @@
|
||||
import { BiDiModule } from '../../../protocol/chromium-bidi.js';
|
||||
import { Deferred } from '../../../utils/Deferred.js';
|
||||
import { EventEmitter } from '../../../utils/EventEmitter.js';
|
||||
import { LogType } from '../../../utils/log.js';
|
||||
import { BrowsingContextImpl } from '../context/BrowsingContextImpl.js';
|
||||
import { LogManager } from '../log/LogManager.js';
|
||||
export class CdpTarget extends EventEmitter {
|
||||
#id;
|
||||
#cdpClient;
|
||||
#browserCdpClient;
|
||||
#parentCdpClient;
|
||||
#realmStorage;
|
||||
#eventManager;
|
||||
#preloadScriptStorage;
|
||||
#browsingContextStorage;
|
||||
#prerenderingDisabled;
|
||||
#networkStorage;
|
||||
#unblocked = new Deferred();
|
||||
#unhandledPromptBehavior;
|
||||
#logger;
|
||||
#deviceAccessEnabled = false;
|
||||
#cacheDisableState = false;
|
||||
#fetchDomainStages = {
|
||||
request: false,
|
||||
response: false,
|
||||
auth: false,
|
||||
};
|
||||
static create(targetId, cdpClient, browserCdpClient, parentCdpClient, realmStorage, eventManager, preloadScriptStorage, browsingContextStorage, networkStorage, prerenderingDisabled, unhandledPromptBehavior, logger) {
|
||||
const cdpTarget = new CdpTarget(targetId, cdpClient, browserCdpClient, parentCdpClient, eventManager, realmStorage, preloadScriptStorage, browsingContextStorage, networkStorage, prerenderingDisabled, unhandledPromptBehavior, logger);
|
||||
LogManager.create(cdpTarget, realmStorage, eventManager, logger);
|
||||
cdpTarget.#setEventListeners();
|
||||
// No need to await.
|
||||
// Deferred will be resolved when the target is unblocked.
|
||||
void cdpTarget.#unblock();
|
||||
return cdpTarget;
|
||||
}
|
||||
constructor(targetId, cdpClient, browserCdpClient, parentCdpClient, eventManager, realmStorage, preloadScriptStorage, browsingContextStorage, networkStorage, prerenderingDisabled, unhandledPromptBehavior, logger) {
|
||||
super();
|
||||
this.#id = targetId;
|
||||
this.#cdpClient = cdpClient;
|
||||
this.#browserCdpClient = browserCdpClient;
|
||||
this.#parentCdpClient = parentCdpClient;
|
||||
this.#eventManager = eventManager;
|
||||
this.#realmStorage = realmStorage;
|
||||
this.#preloadScriptStorage = preloadScriptStorage;
|
||||
this.#networkStorage = networkStorage;
|
||||
this.#browsingContextStorage = browsingContextStorage;
|
||||
this.#prerenderingDisabled = prerenderingDisabled;
|
||||
this.#unhandledPromptBehavior = unhandledPromptBehavior;
|
||||
this.#logger = logger;
|
||||
}
|
||||
/** Returns a deferred that resolves when the target is unblocked. */
|
||||
get unblocked() {
|
||||
return this.#unblocked;
|
||||
}
|
||||
get id() {
|
||||
return this.#id;
|
||||
}
|
||||
get cdpClient() {
|
||||
return this.#cdpClient;
|
||||
}
|
||||
get parentCdpClient() {
|
||||
return this.#parentCdpClient;
|
||||
}
|
||||
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;
|
||||
}
|
||||
/**
|
||||
* Enables all the required CDP domains and unblocks the target.
|
||||
*/
|
||||
async #unblock() {
|
||||
try {
|
||||
await Promise.all([
|
||||
this.#cdpClient.sendCommand('Page.enable'),
|
||||
// There can be some existing frames in the target, if reconnecting to an
|
||||
// existing browser instance, e.g. via Puppeteer. Need to restore the browsing
|
||||
// contexts for the frames to correctly handle further events, like
|
||||
// `Runtime.executionContextCreated`.
|
||||
// It's important to schedule this task together with enabling domains commands to
|
||||
// prepare the tree before the events (e.g. Runtime.executionContextCreated) start
|
||||
// coming.
|
||||
// https://github.com/GoogleChromeLabs/chromium-bidi/issues/2282
|
||||
this.#cdpClient
|
||||
.sendCommand('Page.getFrameTree')
|
||||
.then((frameTree) => this.#restoreFrameTreeState(frameTree.frameTree)),
|
||||
this.#cdpClient.sendCommand('Runtime.enable'),
|
||||
this.#cdpClient.sendCommand('Page.setLifecycleEventsEnabled', {
|
||||
enabled: true,
|
||||
}),
|
||||
this.#cdpClient
|
||||
.sendCommand('Page.setPrerenderingAllowed', {
|
||||
isAllowed: !this.#prerenderingDisabled,
|
||||
})
|
||||
.catch(() => {
|
||||
// Ignore CDP errors, as the command is not supported by iframe targets or
|
||||
// prerendered pages. Generic catch, as the error can vary between CdpClient
|
||||
// implementations: Tab vs Puppeteer.
|
||||
}),
|
||||
// Enabling CDP Network domain is required for navigation detection:
|
||||
// https://github.com/GoogleChromeLabs/chromium-bidi/issues/2856.
|
||||
this.#cdpClient
|
||||
.sendCommand('Network.enable')
|
||||
.then(() => this.toggleNetworkIfNeeded()),
|
||||
this.#cdpClient.sendCommand('Target.setAutoAttach', {
|
||||
autoAttach: true,
|
||||
waitForDebuggerOnStart: true,
|
||||
flatten: true,
|
||||
}),
|
||||
this.#initAndEvaluatePreloadScripts(),
|
||||
this.#cdpClient.sendCommand('Runtime.runIfWaitingForDebugger'),
|
||||
// Resume tab execution as well if it was paused by the debugger.
|
||||
this.#parentCdpClient.sendCommand('Runtime.runIfWaitingForDebugger'),
|
||||
this.toggleDeviceAccessIfNeeded(),
|
||||
]);
|
||||
}
|
||||
catch (error) {
|
||||
this.#logger?.(LogType.debugError, 'Failed to unblock target', error);
|
||||
// The target might have been closed before the initialization finished.
|
||||
if (!this.#cdpClient.isCloseError(error)) {
|
||||
this.#unblocked.resolve({
|
||||
kind: 'error',
|
||||
error,
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.#unblocked.resolve({
|
||||
kind: 'success',
|
||||
value: undefined,
|
||||
});
|
||||
}
|
||||
#restoreFrameTreeState(frameTree) {
|
||||
const frame = frameTree.frame;
|
||||
const maybeContext = this.#browsingContextStorage.findContext(frame.id);
|
||||
if (maybeContext !== undefined) {
|
||||
// Restoring parent of already known browsing context. This means the target is
|
||||
// OOPiF and the BiDi session was connected to already existing browser instance.
|
||||
if (maybeContext.parentId === null &&
|
||||
frame.parentId !== null &&
|
||||
frame.parentId !== undefined) {
|
||||
maybeContext.parentId = frame.parentId;
|
||||
}
|
||||
}
|
||||
if (maybeContext === undefined && frame.parentId !== undefined) {
|
||||
// Restore not yet known nested frames. The top-level frame is created when the
|
||||
// target is attached.
|
||||
const parentBrowsingContext = this.#browsingContextStorage.getContext(frame.parentId);
|
||||
BrowsingContextImpl.create(frame.id, frame.parentId, parentBrowsingContext.userContext, parentBrowsingContext.cdpTarget, this.#eventManager, this.#browsingContextStorage, this.#realmStorage, frame.url, undefined, this.#unhandledPromptBehavior, this.#logger);
|
||||
}
|
||||
frameTree.childFrames?.map((frameTree) => this.#restoreFrameTreeState(frameTree));
|
||||
}
|
||||
async toggleFetchIfNeeded() {
|
||||
const stages = this.#networkStorage.getInterceptionStages(this.topLevelId);
|
||||
if (this.#fetchDomainStages.request === stages.request &&
|
||||
this.#fetchDomainStages.response === stages.response &&
|
||||
this.#fetchDomainStages.auth === stages.auth) {
|
||||
return;
|
||||
}
|
||||
const patterns = [];
|
||||
this.#fetchDomainStages = stages;
|
||||
if (stages.request || stages.auth) {
|
||||
// CDP quirk we need request interception when we intercept auth
|
||||
patterns.push({
|
||||
urlPattern: '*',
|
||||
requestStage: 'Request',
|
||||
});
|
||||
}
|
||||
if (stages.response) {
|
||||
patterns.push({
|
||||
urlPattern: '*',
|
||||
requestStage: 'Response',
|
||||
});
|
||||
}
|
||||
if (patterns.length) {
|
||||
await this.#cdpClient.sendCommand('Fetch.enable', {
|
||||
patterns,
|
||||
handleAuthRequests: stages.auth,
|
||||
});
|
||||
}
|
||||
else {
|
||||
const blockedRequest = this.#networkStorage
|
||||
.getRequestsByTarget(this)
|
||||
.filter((request) => request.interceptPhase);
|
||||
void Promise.allSettled(blockedRequest.map((request) => request.waitNextPhase))
|
||||
.then(async () => {
|
||||
const blockedRequest = this.#networkStorage
|
||||
.getRequestsByTarget(this)
|
||||
.filter((request) => request.interceptPhase);
|
||||
if (blockedRequest.length) {
|
||||
return await this.toggleFetchIfNeeded();
|
||||
}
|
||||
return await this.#cdpClient.sendCommand('Fetch.disable');
|
||||
})
|
||||
.catch((error) => {
|
||||
this.#logger?.(LogType.bidi, 'Disable failed', error);
|
||||
});
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Toggles CDP "Fetch" domain and enable/disable network cache.
|
||||
*/
|
||||
async toggleNetworkIfNeeded() {
|
||||
// Although the Network domain remains active, Fetch domain activation and caching
|
||||
// settings should be managed dynamically.
|
||||
try {
|
||||
await Promise.all([
|
||||
this.toggleSetCacheDisabled(),
|
||||
this.toggleFetchIfNeeded(),
|
||||
]);
|
||||
}
|
||||
catch (err) {
|
||||
this.#logger?.(LogType.debugError, err);
|
||||
if (!this.#isExpectedError(err)) {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
}
|
||||
async toggleSetCacheDisabled(disable) {
|
||||
const defaultCacheDisabled = this.#networkStorage.defaultCacheBehavior === 'bypass';
|
||||
const cacheDisabled = disable ?? defaultCacheDisabled;
|
||||
if (this.#cacheDisableState === cacheDisabled) {
|
||||
return;
|
||||
}
|
||||
this.#cacheDisableState = cacheDisabled;
|
||||
try {
|
||||
await this.#cdpClient.sendCommand('Network.setCacheDisabled', {
|
||||
cacheDisabled,
|
||||
});
|
||||
}
|
||||
catch (err) {
|
||||
this.#logger?.(LogType.debugError, err);
|
||||
this.#cacheDisableState = !cacheDisabled;
|
||||
if (!this.#isExpectedError(err)) {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
}
|
||||
async toggleDeviceAccessIfNeeded() {
|
||||
const enabled = this.isSubscribedTo(BiDiModule.Bluetooth);
|
||||
if (this.#deviceAccessEnabled === enabled) {
|
||||
return;
|
||||
}
|
||||
this.#deviceAccessEnabled = enabled;
|
||||
try {
|
||||
await this.#cdpClient.sendCommand(enabled ? 'DeviceAccess.enable' : 'DeviceAccess.disable');
|
||||
}
|
||||
catch (err) {
|
||||
this.#logger?.(LogType.debugError, err);
|
||||
this.#deviceAccessEnabled = !enabled;
|
||||
if (!this.#isExpectedError(err)) {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Heuristic checking if the error is due to the session being closed. If so, ignore the
|
||||
* error.
|
||||
*/
|
||||
#isExpectedError(err) {
|
||||
const error = err;
|
||||
return ((error.code === -32001 &&
|
||||
error.message === 'Session with given id not found.') ||
|
||||
this.#cdpClient.isCloseError(err));
|
||||
}
|
||||
#setEventListeners() {
|
||||
this.#cdpClient.on('Network.requestWillBeSent', (eventParams) => {
|
||||
if (eventParams.loaderId === eventParams.requestId) {
|
||||
this.emit("frameStartedNavigating" /* TargetEvents.FrameStartedNavigating */, {
|
||||
loaderId: eventParams.loaderId,
|
||||
url: eventParams.request.url,
|
||||
frameId: eventParams.frameId,
|
||||
});
|
||||
}
|
||||
});
|
||||
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: `goog:cdp.${event}`,
|
||||
params: {
|
||||
event,
|
||||
params,
|
||||
session: this.cdpSessionId,
|
||||
},
|
||||
}, this.id);
|
||||
// Duplicate the event to the deprecated event name.
|
||||
// https://github.com/GoogleChromeLabs/chromium-bidi/issues/2844
|
||||
this.#eventManager.registerEvent({
|
||||
type: 'event',
|
||||
method: `cdp.${event}`,
|
||||
params: {
|
||||
event,
|
||||
params,
|
||||
session: this.cdpSessionId,
|
||||
},
|
||||
}, this.id);
|
||||
});
|
||||
}
|
||||
async #enableFetch(stages) {
|
||||
const patterns = [];
|
||||
if (stages.request || stages.auth) {
|
||||
// CDP quirk we need request interception when we intercept auth
|
||||
patterns.push({
|
||||
urlPattern: '*',
|
||||
requestStage: 'Request',
|
||||
});
|
||||
}
|
||||
if (stages.response) {
|
||||
patterns.push({
|
||||
urlPattern: '*',
|
||||
requestStage: 'Response',
|
||||
});
|
||||
}
|
||||
if (patterns.length) {
|
||||
const oldStages = this.#fetchDomainStages;
|
||||
this.#fetchDomainStages = stages;
|
||||
try {
|
||||
await this.#cdpClient.sendCommand('Fetch.enable', {
|
||||
patterns,
|
||||
handleAuthRequests: stages.auth,
|
||||
});
|
||||
}
|
||||
catch {
|
||||
this.#fetchDomainStages = oldStages;
|
||||
}
|
||||
}
|
||||
}
|
||||
async #disableFetch() {
|
||||
const blockedRequest = this.#networkStorage
|
||||
.getRequestsByTarget(this)
|
||||
.filter((request) => request.interceptPhase);
|
||||
if (blockedRequest.length === 0) {
|
||||
this.#fetchDomainStages = {
|
||||
request: false,
|
||||
response: false,
|
||||
auth: false,
|
||||
};
|
||||
await this.#cdpClient.sendCommand('Fetch.disable');
|
||||
}
|
||||
}
|
||||
async toggleNetwork() {
|
||||
const stages = this.#networkStorage.getInterceptionStages(this.topLevelId);
|
||||
const fetchEnable = Object.values(stages).some((value) => value);
|
||||
const fetchChanged = this.#fetchDomainStages.request !== stages.request ||
|
||||
this.#fetchDomainStages.response !== stages.response ||
|
||||
this.#fetchDomainStages.auth !== stages.auth;
|
||||
this.#logger?.(LogType.debugInfo, 'Toggle Network', `Fetch (${fetchEnable}) ${fetchChanged}`);
|
||||
if (fetchEnable && fetchChanged) {
|
||||
await this.#enableFetch(stages);
|
||||
}
|
||||
if (!fetchEnable && fetchChanged) {
|
||||
await this.#disableFetch();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 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() {
|
||||
await Promise.all(this.#preloadScriptStorage
|
||||
.find({
|
||||
// Needed for OOPIF
|
||||
targetId: this.topLevelId,
|
||||
global: true,
|
||||
})
|
||||
.map((script) => {
|
||||
return script.initInTarget(this, true);
|
||||
}));
|
||||
}
|
||||
get topLevelId() {
|
||||
return (this.#browsingContextStorage.findTopLevelContextId(this.id) ?? this.id);
|
||||
}
|
||||
isSubscribedTo(moduleOrEvent) {
|
||||
return this.#eventManager.subscriptionManager.isSubscribedTo(moduleOrEvent, this.topLevelId);
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=CdpTarget.js.map
|
||||
1
node_modules/chromium-bidi/lib/esm/bidiMapper/modules/cdp/CdpTarget.js.map
generated
vendored
Normal file
1
node_modules/chromium-bidi/lib/esm/bidiMapper/modules/cdp/CdpTarget.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
14
node_modules/chromium-bidi/lib/esm/bidiMapper/modules/cdp/CdpTargetManager.d.ts
generated
vendored
Normal file
14
node_modules/chromium-bidi/lib/esm/bidiMapper/modules/cdp/CdpTargetManager.d.ts
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
import type { CdpClient } from '../../../cdp/CdpClient.js';
|
||||
import type { CdpConnection } from '../../../cdp/CdpConnection.js';
|
||||
import type { Browser, Session } from '../../../protocol/protocol.js';
|
||||
import { type LoggerFn } from '../../../utils/log.js';
|
||||
import type { BluetoothProcessor } from '../bluetooth/BluetoothProcessor.js';
|
||||
import type { BrowsingContextStorage } from '../context/BrowsingContextStorage.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';
|
||||
export declare class CdpTargetManager {
|
||||
#private;
|
||||
constructor(cdpConnection: CdpConnection, browserCdpClient: CdpClient, selfTargetId: string, eventManager: EventManager, browsingContextStorage: BrowsingContextStorage, realmStorage: RealmStorage, networkStorage: NetworkStorage, bluetoothProcessor: BluetoothProcessor, preloadScriptStorage: PreloadScriptStorage, defaultUserContextId: Browser.UserContext, prerenderingDisabled: boolean, unhandledPromptBehavior?: Session.UserPromptHandler, logger?: LoggerFn);
|
||||
}
|
||||
248
node_modules/chromium-bidi/lib/esm/bidiMapper/modules/cdp/CdpTargetManager.js
generated
vendored
Normal file
248
node_modules/chromium-bidi/lib/esm/bidiMapper/modules/cdp/CdpTargetManager.js
generated
vendored
Normal file
@@ -0,0 +1,248 @@
|
||||
import { LogType } from '../../../utils/log.js';
|
||||
import { BrowsingContextImpl, serializeOrigin, } from '../context/BrowsingContextImpl.js';
|
||||
import { WorkerRealm } from '../script/WorkerRealm.js';
|
||||
import { CdpTarget } from './CdpTarget.js';
|
||||
const cdpToBidiTargetTypes = {
|
||||
service_worker: 'service-worker',
|
||||
shared_worker: 'shared-worker',
|
||||
worker: 'dedicated-worker',
|
||||
};
|
||||
export class CdpTargetManager {
|
||||
#browserCdpClient;
|
||||
#cdpConnection;
|
||||
#targetKeysToBeIgnoredByAutoAttach = new Set();
|
||||
#selfTargetId;
|
||||
#eventManager;
|
||||
#browsingContextStorage;
|
||||
#networkStorage;
|
||||
#bluetoothProcessor;
|
||||
#preloadScriptStorage;
|
||||
#realmStorage;
|
||||
#defaultUserContextId;
|
||||
#logger;
|
||||
#unhandledPromptBehavior;
|
||||
#prerenderingDisabled;
|
||||
constructor(cdpConnection, browserCdpClient, selfTargetId, eventManager, browsingContextStorage, realmStorage, networkStorage, bluetoothProcessor, preloadScriptStorage, defaultUserContextId, prerenderingDisabled, unhandledPromptBehavior, logger) {
|
||||
this.#cdpConnection = cdpConnection;
|
||||
this.#browserCdpClient = browserCdpClient;
|
||||
this.#targetKeysToBeIgnoredByAutoAttach.add(selfTargetId);
|
||||
this.#selfTargetId = selfTargetId;
|
||||
this.#eventManager = eventManager;
|
||||
this.#browsingContextStorage = browsingContextStorage;
|
||||
this.#preloadScriptStorage = preloadScriptStorage;
|
||||
this.#networkStorage = networkStorage;
|
||||
this.#bluetoothProcessor = bluetoothProcessor;
|
||||
this.#realmStorage = realmStorage;
|
||||
this.#defaultUserContextId = defaultUserContextId;
|
||||
this.#prerenderingDisabled = prerenderingDisabled;
|
||||
this.#unhandledPromptBehavior = unhandledPromptBehavior;
|
||||
this.#logger = logger;
|
||||
this.#setEventListeners(browserCdpClient);
|
||||
}
|
||||
/**
|
||||
* 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', this.#handleDetachedFromTargetEvent.bind(this));
|
||||
cdpClient.on('Target.targetInfoChanged', this.#handleTargetInfoChangedEvent.bind(this));
|
||||
cdpClient.on('Inspector.targetCrashed', () => {
|
||||
this.#handleTargetCrashedEvent(cdpClient);
|
||||
});
|
||||
cdpClient.on('Page.frameAttached', this.#handleFrameAttachedEvent.bind(this));
|
||||
cdpClient.on('Page.frameDetached', this.#handleFrameDetachedEvent.bind(this));
|
||||
cdpClient.on('Page.frameSubtreeWillBeDetached', this.#handleFrameSubtreeWillBeDetached.bind(this));
|
||||
}
|
||||
#handleFrameAttachedEvent(params) {
|
||||
const parentBrowsingContext = this.#browsingContextStorage.findContext(params.parentFrameId);
|
||||
if (parentBrowsingContext !== undefined) {
|
||||
BrowsingContextImpl.create(params.frameId, params.parentFrameId, parentBrowsingContext.userContext, parentBrowsingContext.cdpTarget, this.#eventManager, this.#browsingContextStorage, this.#realmStorage,
|
||||
// At this point, we don't know the URL of the frame yet, so it will be updated
|
||||
// later.
|
||||
'about:blank', undefined, this.#unhandledPromptBehavior, this.#logger);
|
||||
}
|
||||
}
|
||||
#handleFrameDetachedEvent(params) {
|
||||
// In case of OOPiF no need in deleting BrowsingContext.
|
||||
if (params.reason === 'swap') {
|
||||
return;
|
||||
}
|
||||
this.#browsingContextStorage.findContext(params.frameId)?.dispose(true);
|
||||
}
|
||||
#handleFrameSubtreeWillBeDetached(params) {
|
||||
this.#browsingContextStorage.findContext(params.frameId)?.dispose(true);
|
||||
}
|
||||
#handleAttachedToTargetEvent(params, parentSessionCdpClient) {
|
||||
const { sessionId, targetInfo } = params;
|
||||
const targetCdpClient = this.#cdpConnection.getCdpClient(sessionId);
|
||||
const detach = async () => {
|
||||
// Detaches and resumes the target suppressing errors.
|
||||
await targetCdpClient
|
||||
.sendCommand('Runtime.runIfWaitingForDebugger')
|
||||
.then(() => parentSessionCdpClient.sendCommand('Target.detachFromTarget', params))
|
||||
.catch((error) => this.#logger?.(LogType.debugError, error));
|
||||
};
|
||||
// Do not attach to the Mapper target.
|
||||
if (this.#selfTargetId === targetInfo.targetId) {
|
||||
void detach();
|
||||
return;
|
||||
}
|
||||
// Service workers are special case because they attach to the
|
||||
// browser target and the page target (so twice per worker) during
|
||||
// the regular auto-attach and might hang if the CDP session on
|
||||
// the browser level is not detached. The logic to detach the
|
||||
// right session is handled in the switch below.
|
||||
const targetKey = targetInfo.type === 'service_worker'
|
||||
? `${parentSessionCdpClient.sessionId}_${targetInfo.targetId}`
|
||||
: targetInfo.targetId;
|
||||
// Mapper generally only needs one session per target. If we
|
||||
// receive additional auto-attached sessions, that is very likely
|
||||
// coming from custom CDP sessions.
|
||||
if (this.#targetKeysToBeIgnoredByAutoAttach.has(targetKey)) {
|
||||
// Return to leave the session untouched.
|
||||
return;
|
||||
}
|
||||
this.#targetKeysToBeIgnoredByAutoAttach.add(targetKey);
|
||||
switch (targetInfo.type) {
|
||||
case 'tab':
|
||||
// Tab targets are required only to handle page targets beneath them.
|
||||
this.#setEventListeners(targetCdpClient);
|
||||
// Auto-attach to the page target. No need in resuming tab target debugger, as it
|
||||
// should preserve the page target debugger state, and will be resumed by the page
|
||||
// target.
|
||||
void (async () => {
|
||||
await targetCdpClient.sendCommand('Target.setAutoAttach', {
|
||||
autoAttach: true,
|
||||
waitForDebuggerOnStart: true,
|
||||
flatten: true,
|
||||
});
|
||||
})();
|
||||
return;
|
||||
case 'page':
|
||||
case 'iframe': {
|
||||
const cdpTarget = this.#createCdpTarget(targetCdpClient, parentSessionCdpClient, targetInfo);
|
||||
const maybeContext = this.#browsingContextStorage.findContext(targetInfo.targetId);
|
||||
if (maybeContext && targetInfo.type === 'iframe') {
|
||||
// OOPiF.
|
||||
maybeContext.updateCdpTarget(cdpTarget);
|
||||
}
|
||||
else {
|
||||
// If attaching to existing browser instance, there could be OOPiF targets. This
|
||||
// case is handled by the `findFrameParentId` method.
|
||||
const parentId = this.#findFrameParentId(targetInfo, parentSessionCdpClient.sessionId);
|
||||
const userContext = targetInfo.browserContextId &&
|
||||
targetInfo.browserContextId !== this.#defaultUserContextId
|
||||
? targetInfo.browserContextId
|
||||
: 'default';
|
||||
// New context.
|
||||
BrowsingContextImpl.create(targetInfo.targetId, parentId, userContext, cdpTarget, this.#eventManager, this.#browsingContextStorage, this.#realmStorage,
|
||||
// Hack: when a new target created, CDP emits targetInfoChanged with an empty
|
||||
// url, and navigates it to about:blank later. When the event is emitted for
|
||||
// an existing target (reconnect), the url is already known, and navigation
|
||||
// events will not be emitted anymore. Replacing empty url with `about:blank`
|
||||
// allows to handle both cases in the same way.
|
||||
// "7.3.2.1 Creating browsing contexts".
|
||||
// https://html.spec.whatwg.org/multipage/document-sequences.html#creating-browsing-contexts
|
||||
// TODO: check who to deal with non-null creator and its `creatorOrigin`.
|
||||
targetInfo.url === '' ? 'about:blank' : targetInfo.url, targetInfo.openerFrameId ?? targetInfo.openerId, this.#unhandledPromptBehavior, this.#logger);
|
||||
}
|
||||
return;
|
||||
}
|
||||
case 'service_worker':
|
||||
case 'worker': {
|
||||
const realm = this.#realmStorage.findRealm({
|
||||
cdpSessionId: parentSessionCdpClient.sessionId,
|
||||
});
|
||||
// If there is no browsing context, this worker is already terminated.
|
||||
if (!realm) {
|
||||
void detach();
|
||||
return;
|
||||
}
|
||||
const cdpTarget = this.#createCdpTarget(targetCdpClient, parentSessionCdpClient, targetInfo);
|
||||
this.#handleWorkerTarget(cdpToBidiTargetTypes[targetInfo.type], cdpTarget, realm);
|
||||
return;
|
||||
}
|
||||
// In CDP, we only emit shared workers on the browser and not the set of
|
||||
// frames that use the shared worker. If we change this in the future to
|
||||
// behave like service workers (emits on both browser and frame targets),
|
||||
// we can remove this block and merge service workers with the above one.
|
||||
case 'shared_worker': {
|
||||
const cdpTarget = this.#createCdpTarget(targetCdpClient, parentSessionCdpClient, targetInfo);
|
||||
this.#handleWorkerTarget(cdpToBidiTargetTypes[targetInfo.type], cdpTarget);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// DevTools or some other not supported by BiDi target. Just release
|
||||
// debugger and ignore them.
|
||||
void detach();
|
||||
}
|
||||
/** Try to find the parent browsing context ID for the given attached target. */
|
||||
#findFrameParentId(targetInfo, parentSessionId) {
|
||||
if (targetInfo.type !== 'iframe') {
|
||||
return null;
|
||||
}
|
||||
const parentId = targetInfo.openerFrameId ?? targetInfo.openerId;
|
||||
if (parentId !== undefined) {
|
||||
return parentId;
|
||||
}
|
||||
if (parentSessionId !== undefined) {
|
||||
return (this.#browsingContextStorage.findContextBySession(parentSessionId)
|
||||
?.id ?? null);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
#createCdpTarget(targetCdpClient, parentCdpClient, targetInfo) {
|
||||
this.#setEventListeners(targetCdpClient);
|
||||
const target = CdpTarget.create(targetInfo.targetId, targetCdpClient, this.#browserCdpClient, parentCdpClient, this.#realmStorage, this.#eventManager, this.#preloadScriptStorage, this.#browsingContextStorage, this.#networkStorage, this.#prerenderingDisabled, this.#unhandledPromptBehavior, this.#logger);
|
||||
this.#networkStorage.onCdpTargetCreated(target);
|
||||
this.#bluetoothProcessor.onCdpTargetCreated(target);
|
||||
return target;
|
||||
}
|
||||
#workers = new Map();
|
||||
#handleWorkerTarget(realmType, cdpTarget, ownerRealm) {
|
||||
cdpTarget.cdpClient.on('Runtime.executionContextCreated', (params) => {
|
||||
const { uniqueId, id, origin } = params.context;
|
||||
const workerRealm = new WorkerRealm(cdpTarget.cdpClient, this.#eventManager, id, this.#logger, serializeOrigin(origin), ownerRealm ? [ownerRealm] : [], uniqueId, this.#realmStorage, realmType);
|
||||
this.#workers.set(cdpTarget.cdpSessionId, workerRealm);
|
||||
});
|
||||
}
|
||||
#handleDetachedFromTargetEvent({ sessionId, targetId, }) {
|
||||
if (targetId) {
|
||||
this.#preloadScriptStorage.find({ targetId }).map((preloadScript) => {
|
||||
preloadScript.dispose(targetId);
|
||||
});
|
||||
}
|
||||
const context = this.#browsingContextStorage.findContextBySession(sessionId);
|
||||
if (context) {
|
||||
context.dispose(true);
|
||||
return;
|
||||
}
|
||||
const worker = this.#workers.get(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);
|
||||
}
|
||||
}
|
||||
#handleTargetCrashedEvent(cdpClient) {
|
||||
// This is primarily used for service and shared workers. CDP tends to not
|
||||
// signal they closed gracefully and instead says they crashed to signal
|
||||
// they are closed.
|
||||
const realms = this.#realmStorage.findRealms({
|
||||
cdpSessionId: cdpClient.sessionId,
|
||||
});
|
||||
for (const realm of realms) {
|
||||
realm.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=CdpTargetManager.js.map
|
||||
1
node_modules/chromium-bidi/lib/esm/bidiMapper/modules/cdp/CdpTargetManager.js.map
generated
vendored
Normal file
1
node_modules/chromium-bidi/lib/esm/bidiMapper/modules/cdp/CdpTargetManager.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
17
node_modules/chromium-bidi/lib/esm/bidiMapper/modules/cdp/TargetEvents.d.ts
generated
vendored
Normal file
17
node_modules/chromium-bidi/lib/esm/bidiMapper/modules/cdp/TargetEvents.d.ts
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* `FrameStartedNavigating` event addressing lack of such an event in CDP. It is emitted
|
||||
* on CdpTarget before each `Network.requestWillBeSent` event. Note that there can be
|
||||
* several `Network.requestWillBeSent` events for a single navigation e.g. on redirection,
|
||||
* so the `FrameStartedNavigating` can be duplicated as well.
|
||||
* http://go/webdriver:detect-navigation-started#bookmark=id.64balpqrmadv
|
||||
*/
|
||||
export declare const enum TargetEvents {
|
||||
FrameStartedNavigating = "frameStartedNavigating"
|
||||
}
|
||||
export type TargetEventMap = {
|
||||
[TargetEvents.FrameStartedNavigating]: {
|
||||
loaderId: string;
|
||||
url: string;
|
||||
frameId: string | undefined;
|
||||
};
|
||||
};
|
||||
19
node_modules/chromium-bidi/lib/esm/bidiMapper/modules/cdp/TargetEvents.js
generated
vendored
Normal file
19
node_modules/chromium-bidi/lib/esm/bidiMapper/modules/cdp/TargetEvents.js
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright 2024 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.
|
||||
*
|
||||
*/
|
||||
export {};
|
||||
//# sourceMappingURL=TargetEvents.js.map
|
||||
1
node_modules/chromium-bidi/lib/esm/bidiMapper/modules/cdp/TargetEvents.js.map
generated
vendored
Normal file
1
node_modules/chromium-bidi/lib/esm/bidiMapper/modules/cdp/TargetEvents.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"TargetEvents.js","sourceRoot":"","sources":["../../../../../src/bidiMapper/modules/cdp/TargetEvents.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG"}
|
||||
Reference in New Issue
Block a user