chromium-bidi
Advanced tools
Comparing version 0.4.32 to 0.4.33
@@ -22,2 +22,3 @@ /** | ||
import type { Result } from '../utils/result.js'; | ||
import type { ICdpClient } from '../cdp/CdpClient'; | ||
import type { IBidiParser } from './BidiParser.js'; | ||
@@ -33,3 +34,3 @@ import type { IBidiTransport } from './BidiTransport.js'; | ||
private constructor(); | ||
static createAndStart(bidiTransport: IBidiTransport, cdpConnection: ICdpConnection, selfTargetId: string, parser?: IBidiParser, logger?: LoggerFn): Promise<BidiServer>; | ||
static createAndStart(bidiTransport: IBidiTransport, cdpConnection: ICdpConnection, browserCdpClient: ICdpClient, selfTargetId: string, parser?: IBidiParser, logger?: LoggerFn): Promise<BidiServer>; | ||
/** | ||
@@ -36,0 +37,0 @@ * Sends BiDi message. |
@@ -45,3 +45,3 @@ "use strict"; | ||
}; | ||
constructor(bidiTransport, cdpConnection, selfTargetId, parser, logger) { | ||
constructor(bidiTransport, cdpConnection, browserCdpClient, selfTargetId, parser, logger) { | ||
super(); | ||
@@ -52,3 +52,3 @@ this.#logger = logger; | ||
this.#transport.setOnMessage(this.#handleIncomingMessage); | ||
this.#commandProcessor = new CommandProcessor_js_1.CommandProcessor(cdpConnection, new EventManager_js_1.EventManager(this), selfTargetId, this.#browsingContextStorage, new RealmStorage_js_1.RealmStorage(), parser, this.#logger); | ||
this.#commandProcessor = new CommandProcessor_js_1.CommandProcessor(cdpConnection, browserCdpClient, new EventManager_js_1.EventManager(this), selfTargetId, this.#browsingContextStorage, new RealmStorage_js_1.RealmStorage(), parser, this.#logger); | ||
this.#commandProcessor.on("response" /* CommandProcessorEvents.Response */, ({ message, event }) => { | ||
@@ -58,9 +58,10 @@ this.emitOutgoingMessage(message, event); | ||
} | ||
static async createAndStart(bidiTransport, cdpConnection, selfTargetId, parser, logger) { | ||
const server = new BidiServer(bidiTransport, cdpConnection, selfTargetId, parser, logger); | ||
const cdpClient = cdpConnection.browserClient(); | ||
static async createAndStart(bidiTransport, cdpConnection, browserCdpClient, selfTargetId, parser, logger) { | ||
const server = new BidiServer(bidiTransport, cdpConnection, browserCdpClient, selfTargetId, parser, logger); | ||
// Needed to get events about new targets. | ||
await cdpClient.sendCommand('Target.setDiscoverTargets', { discover: true }); | ||
await browserCdpClient.sendCommand('Target.setDiscoverTargets', { | ||
discover: true, | ||
}); | ||
// Needed to automatically attach to new targets. | ||
await cdpClient.sendCommand('Target.setAutoAttach', { | ||
await browserCdpClient.sendCommand('Target.setAutoAttach', { | ||
autoAttach: true, | ||
@@ -67,0 +68,0 @@ waitForDebuggerOnStart: true, |
@@ -22,2 +22,3 @@ /** | ||
import type { Result } from '../utils/result.js'; | ||
import type { ICdpClient } from '../cdp/CdpClient'; | ||
import type { IBidiParser } from './BidiParser.js'; | ||
@@ -39,5 +40,5 @@ import { OutgoingMessage } from './OutgoingMessage.js'; | ||
#private; | ||
constructor(cdpConnection: ICdpConnection, eventManager: EventManager, selfTargetId: string, browsingContextStorage: BrowsingContextStorage, realmStorage: RealmStorage, parser?: IBidiParser, logger?: LoggerFn); | ||
constructor(cdpConnection: ICdpConnection, browserCdpClient: ICdpClient, eventManager: EventManager, selfTargetId: string, browsingContextStorage: BrowsingContextStorage, realmStorage: RealmStorage, parser?: IBidiParser, logger?: LoggerFn); | ||
processCommand(command: ChromiumBidi.Command): Promise<void>; | ||
} | ||
export {}; |
@@ -46,3 +46,3 @@ "use strict"; | ||
#logger; | ||
constructor(cdpConnection, eventManager, selfTargetId, browsingContextStorage, realmStorage, parser = new BidiNoOpParser_js_1.BidiNoOpParser(), logger) { | ||
constructor(cdpConnection, browserCdpClient, eventManager, selfTargetId, browsingContextStorage, realmStorage, parser = new BidiNoOpParser_js_1.BidiNoOpParser(), logger) { | ||
super(); | ||
@@ -54,5 +54,5 @@ this.#parser = parser; | ||
// keep-sorted start block=yes | ||
this.#browserProcessor = new BrowserProcessor_js_1.BrowserProcessor(cdpConnection); | ||
this.#browsingContextProcessor = new BrowsingContextProcessor_js_1.BrowsingContextProcessor(cdpConnection, selfTargetId, eventManager, browsingContextStorage, realmStorage, networkStorage, preloadScriptStorage, logger); | ||
this.#cdpProcessor = new CdpProcessor_js_1.CdpProcessor(browsingContextStorage, cdpConnection); | ||
this.#browserProcessor = new BrowserProcessor_js_1.BrowserProcessor(browserCdpClient); | ||
this.#browsingContextProcessor = new BrowsingContextProcessor_js_1.BrowsingContextProcessor(cdpConnection, browserCdpClient, selfTargetId, eventManager, browsingContextStorage, realmStorage, networkStorage, preloadScriptStorage, logger); | ||
this.#cdpProcessor = new CdpProcessor_js_1.CdpProcessor(browsingContextStorage, cdpConnection, browserCdpClient); | ||
this.#inputProcessor = new InputProcessor_js_1.InputProcessor(browsingContextStorage); | ||
@@ -78,21 +78,21 @@ this.#networkProcessor = new NetworkProcessor_js_1.NetworkProcessor(browsingContextStorage, networkStorage); | ||
case 'browsingContext.activate': | ||
return this.#browsingContextProcessor.activate(this.#parser.parseActivateParams(command.params)); | ||
return await this.#browsingContextProcessor.activate(this.#parser.parseActivateParams(command.params)); | ||
case 'browsingContext.captureScreenshot': | ||
return this.#browsingContextProcessor.captureScreenshot(this.#parser.parseCaptureScreenshotParams(command.params)); | ||
return await this.#browsingContextProcessor.captureScreenshot(this.#parser.parseCaptureScreenshotParams(command.params)); | ||
case 'browsingContext.close': | ||
return this.#browsingContextProcessor.close(this.#parser.parseCloseParams(command.params)); | ||
return await this.#browsingContextProcessor.close(this.#parser.parseCloseParams(command.params)); | ||
case 'browsingContext.create': | ||
return this.#browsingContextProcessor.create(this.#parser.parseCreateParams(command.params)); | ||
return await this.#browsingContextProcessor.create(this.#parser.parseCreateParams(command.params)); | ||
case 'browsingContext.getTree': | ||
return this.#browsingContextProcessor.getTree(this.#parser.parseGetTreeParams(command.params)); | ||
case 'browsingContext.handleUserPrompt': | ||
return this.#browsingContextProcessor.handleUserPrompt(this.#parser.parseHandleUserPromptParams(command.params)); | ||
return await this.#browsingContextProcessor.handleUserPrompt(this.#parser.parseHandleUserPromptParams(command.params)); | ||
case 'browsingContext.navigate': | ||
return this.#browsingContextProcessor.navigate(this.#parser.parseNavigateParams(command.params)); | ||
return await this.#browsingContextProcessor.navigate(this.#parser.parseNavigateParams(command.params)); | ||
case 'browsingContext.print': | ||
return this.#browsingContextProcessor.print(this.#parser.parsePrintParams(command.params)); | ||
return await this.#browsingContextProcessor.print(this.#parser.parsePrintParams(command.params)); | ||
case 'browsingContext.reload': | ||
return this.#browsingContextProcessor.reload(this.#parser.parseReloadParams(command.params)); | ||
return await this.#browsingContextProcessor.reload(this.#parser.parseReloadParams(command.params)); | ||
case 'browsingContext.setViewport': | ||
return this.#browsingContextProcessor.setViewport(this.#parser.parseSetViewportParams(command.params)); | ||
return await this.#browsingContextProcessor.setViewport(this.#parser.parseSetViewportParams(command.params)); | ||
// keep-sorted end | ||
@@ -104,3 +104,3 @@ // CDP domain | ||
case 'cdp.sendCommand': | ||
return this.#cdpProcessor.sendCommand(this.#parser.parseSendCommandParams(command.params)); | ||
return await this.#cdpProcessor.sendCommand(this.#parser.parseSendCommandParams(command.params)); | ||
// keep-sorted end | ||
@@ -110,5 +110,5 @@ // Input domain | ||
case 'input.performActions': | ||
return this.#inputProcessor.performActions(this.#parser.parsePerformActionsParams(command.params)); | ||
return await this.#inputProcessor.performActions(this.#parser.parsePerformActionsParams(command.params)); | ||
case 'input.releaseActions': | ||
return this.#inputProcessor.releaseActions(this.#parser.parseReleaseActionsParams(command.params)); | ||
return await this.#inputProcessor.releaseActions(this.#parser.parseReleaseActionsParams(command.params)); | ||
// keep-sorted end | ||
@@ -118,15 +118,15 @@ // Network domain | ||
case 'network.addIntercept': | ||
return this.#networkProcessor.addIntercept(this.#parser.parseAddInterceptParams(command.params)); | ||
return await this.#networkProcessor.addIntercept(this.#parser.parseAddInterceptParams(command.params)); | ||
case 'network.continueRequest': | ||
return this.#networkProcessor.continueRequest(this.#parser.parseContinueRequestParams(command.params)); | ||
return await this.#networkProcessor.continueRequest(this.#parser.parseContinueRequestParams(command.params)); | ||
case 'network.continueResponse': | ||
return this.#networkProcessor.continueResponse(this.#parser.parseContinueResponseParams(command.params)); | ||
return await this.#networkProcessor.continueResponse(this.#parser.parseContinueResponseParams(command.params)); | ||
case 'network.continueWithAuth': | ||
return this.#networkProcessor.continueWithAuth(this.#parser.parseContinueWithAuthParams(command.params)); | ||
return await this.#networkProcessor.continueWithAuth(this.#parser.parseContinueWithAuthParams(command.params)); | ||
case 'network.failRequest': | ||
return this.#networkProcessor.failRequest(this.#parser.parseFailRequestParams(command.params)); | ||
return await this.#networkProcessor.failRequest(this.#parser.parseFailRequestParams(command.params)); | ||
case 'network.provideResponse': | ||
return this.#networkProcessor.provideResponse(this.#parser.parseProvideResponseParams(command.params)); | ||
return await this.#networkProcessor.provideResponse(this.#parser.parseProvideResponseParams(command.params)); | ||
case 'network.removeIntercept': | ||
return this.#networkProcessor.removeIntercept(this.#parser.parseRemoveInterceptParams(command.params)); | ||
return await this.#networkProcessor.removeIntercept(this.#parser.parseRemoveInterceptParams(command.params)); | ||
// keep-sorted end | ||
@@ -136,13 +136,13 @@ // Script domain | ||
case 'script.addPreloadScript': | ||
return this.#scriptProcessor.addPreloadScript(this.#parser.parseAddPreloadScriptParams(command.params)); | ||
return await this.#scriptProcessor.addPreloadScript(this.#parser.parseAddPreloadScriptParams(command.params)); | ||
case 'script.callFunction': | ||
return this.#scriptProcessor.callFunction(this.#parser.parseCallFunctionParams(command.params)); | ||
return await this.#scriptProcessor.callFunction(this.#parser.parseCallFunctionParams(command.params)); | ||
case 'script.disown': | ||
return this.#scriptProcessor.disown(this.#parser.parseDisownParams(command.params)); | ||
return await this.#scriptProcessor.disown(this.#parser.parseDisownParams(command.params)); | ||
case 'script.evaluate': | ||
return this.#scriptProcessor.evaluate(this.#parser.parseEvaluateParams(command.params)); | ||
return await this.#scriptProcessor.evaluate(this.#parser.parseEvaluateParams(command.params)); | ||
case 'script.getRealms': | ||
return this.#scriptProcessor.getRealms(this.#parser.parseGetRealmsParams(command.params)); | ||
case 'script.removePreloadScript': | ||
return this.#scriptProcessor.removePreloadScript(this.#parser.parseRemovePreloadScriptParams(command.params)); | ||
return await this.#scriptProcessor.removePreloadScript(this.#parser.parseRemovePreloadScriptParams(command.params)); | ||
// keep-sorted end | ||
@@ -149,0 +149,0 @@ // Session domain |
@@ -18,7 +18,7 @@ /** | ||
import type { EmptyResult } from '../../../protocol/protocol.js'; | ||
import type { ICdpConnection } from '../../BidiMapper.js'; | ||
import type { ICdpClient } from '../../BidiMapper.js'; | ||
export declare class BrowserProcessor { | ||
#private; | ||
constructor(cdpConnection: ICdpConnection); | ||
constructor(browserCdpClient: ICdpClient); | ||
close(): EmptyResult; | ||
} |
@@ -21,11 +21,10 @@ "use strict"; | ||
class BrowserProcessor { | ||
#cdpConnection; | ||
constructor(cdpConnection) { | ||
this.#cdpConnection = cdpConnection; | ||
#browserCdpClient; | ||
constructor(browserCdpClient) { | ||
this.#browserCdpClient = browserCdpClient; | ||
} | ||
close() { | ||
const client = this.#cdpConnection.browserClient(); | ||
// Ensure that it is put at the end of the event loop. | ||
// This way we send back the response before closing the tab. | ||
setTimeout(() => client.sendCommand('Browser.close'), 0); | ||
setTimeout(() => this.#browserCdpClient.sendCommand('Browser.close'), 0); | ||
return {}; | ||
@@ -32,0 +31,0 @@ } |
@@ -18,9 +18,9 @@ /** | ||
import type { Cdp } from '../../../protocol/protocol.js'; | ||
import type { ICdpConnection } from '../../BidiMapper.js'; | ||
import type { ICdpClient, ICdpConnection } from '../../BidiMapper.js'; | ||
import type { BrowsingContextStorage } from '../context/BrowsingContextStorage.js'; | ||
export declare class CdpProcessor { | ||
#private; | ||
constructor(browsingContextStorage: BrowsingContextStorage, cdpConnection: ICdpConnection); | ||
constructor(browsingContextStorage: BrowsingContextStorage, cdpConnection: ICdpConnection, browserCdpClient: ICdpClient); | ||
getSession(params: Cdp.GetSessionParameters): Cdp.GetSessionResult; | ||
sendCommand(params: Cdp.SendCommandParameters): Promise<Cdp.SendCommandResult>; | ||
} |
@@ -23,5 +23,7 @@ "use strict"; | ||
#cdpConnection; | ||
constructor(browsingContextStorage, cdpConnection) { | ||
#browserCdpClient; | ||
constructor(browsingContextStorage, cdpConnection, browserCdpClient) { | ||
this.#browsingContextStorage = browsingContextStorage; | ||
this.#cdpConnection = cdpConnection; | ||
this.#browserCdpClient = browserCdpClient; | ||
} | ||
@@ -39,3 +41,3 @@ getSession(params) { | ||
? this.#cdpConnection.getCdpClient(params.session) | ||
: this.#cdpConnection.browserClient(); | ||
: this.#browserCdpClient; | ||
const result = await client.sendCommand(params.method, params.params); | ||
@@ -42,0 +44,0 @@ return { |
@@ -561,3 +561,3 @@ "use strict"; | ||
} | ||
return this.#cdpTarget.cdpClient.sendCommand('Page.captureScreenshot', { | ||
return await this.#cdpTarget.cdpClient.sendCommand('Page.captureScreenshot', { | ||
clip: { ...rect, scale: 1.0 }, | ||
@@ -564,0 +564,0 @@ ...formatParameters, |
@@ -0,1 +1,2 @@ | ||
import type { ICdpClient } from '../../../cdp/CdpClient.js'; | ||
import type { ICdpConnection } from '../../../cdp/CdpConnection.js'; | ||
@@ -11,3 +12,3 @@ import { BrowsingContext, type EmptyResult } from '../../../protocol/protocol.js'; | ||
#private; | ||
constructor(cdpConnection: ICdpConnection, selfTargetId: string, eventManager: EventManager, browsingContextStorage: BrowsingContextStorage, realmStorage: RealmStorage, networkStorage: NetworkStorage, preloadScriptStorage: PreloadScriptStorage, logger?: LoggerFn); | ||
constructor(cdpConnection: ICdpConnection, browserCdpClient: ICdpClient, selfTargetId: string, eventManager: EventManager, browsingContextStorage: BrowsingContextStorage, realmStorage: RealmStorage, networkStorage: NetworkStorage, preloadScriptStorage: PreloadScriptStorage, logger?: LoggerFn); | ||
getTree(params: BrowsingContext.GetTreeParameters): BrowsingContext.GetTreeResult; | ||
@@ -14,0 +15,0 @@ create(params: BrowsingContext.CreateParameters): Promise<BrowsingContext.CreateResult>; |
@@ -9,2 +9,3 @@ "use strict"; | ||
class BrowsingContextProcessor { | ||
#browserCdpClient; | ||
#cdpConnection; | ||
@@ -18,4 +19,5 @@ #selfTargetId; | ||
#logger; | ||
constructor(cdpConnection, selfTargetId, eventManager, browsingContextStorage, realmStorage, networkStorage, preloadScriptStorage, logger) { | ||
constructor(cdpConnection, browserCdpClient, selfTargetId, eventManager, browsingContextStorage, realmStorage, networkStorage, preloadScriptStorage, logger) { | ||
this.#cdpConnection = cdpConnection; | ||
this.#browserCdpClient = browserCdpClient; | ||
this.#selfTargetId = selfTargetId; | ||
@@ -28,3 +30,3 @@ this.#eventManager = eventManager; | ||
this.#logger = logger; | ||
this.#setEventListeners(this.#cdpConnection.browserClient()); | ||
this.#setEventListeners(browserCdpClient); | ||
} | ||
@@ -40,3 +42,2 @@ getTree(params) { | ||
async create(params) { | ||
const browserCdpClient = this.#cdpConnection.browserClient(); | ||
let referenceContext; | ||
@@ -52,3 +53,3 @@ if (params.referenceContext !== undefined) { | ||
case "tab" /* BrowsingContext.CreateType.Tab */: | ||
result = await browserCdpClient.sendCommand('Target.createTarget', { | ||
result = await this.#browserCdpClient.sendCommand('Target.createTarget', { | ||
url: 'about:blank', | ||
@@ -59,3 +60,3 @@ newWindow: false, | ||
case "window" /* BrowsingContext.CreateType.Window */: | ||
result = await browserCdpClient.sendCommand('Target.createTarget', { | ||
result = await this.#browserCdpClient.sendCommand('Target.createTarget', { | ||
url: 'about:blank', | ||
@@ -94,7 +95,7 @@ newWindow: true, | ||
const context = this.#browsingContextStorage.getContext(params.context); | ||
return context.captureScreenshot(params); | ||
return await context.captureScreenshot(params); | ||
} | ||
async print(params) { | ||
const context = this.#browsingContextStorage.getContext(params.context); | ||
return context.print(params); | ||
return await context.print(params); | ||
} | ||
@@ -120,11 +121,10 @@ async setViewport(params) { | ||
try { | ||
const browserCdpClient = this.#cdpConnection.browserClient(); | ||
const detachedFromTargetPromise = new Promise((resolve) => { | ||
const onContextDestroyed = (event) => { | ||
if (event.targetId === commandParams.context) { | ||
browserCdpClient.off('Target.detachedFromTarget', onContextDestroyed); | ||
this.#browserCdpClient.off('Target.detachedFromTarget', onContextDestroyed); | ||
resolve(); | ||
} | ||
}; | ||
browserCdpClient.on('Target.detachedFromTarget', onContextDestroyed); | ||
this.#browserCdpClient.on('Target.detachedFromTarget', onContextDestroyed); | ||
}); | ||
@@ -196,3 +196,3 @@ await context.close(); | ||
const maybeContext = this.#browsingContextStorage.findContext(targetInfo.targetId); | ||
const cdpTarget = CdpTarget_js_1.CdpTarget.create(targetInfo.targetId, targetCdpClient, sessionId, this.#realmStorage, this.#eventManager, this.#preloadScriptStorage, this.#networkStorage); | ||
const cdpTarget = CdpTarget_js_1.CdpTarget.create(targetInfo.targetId, targetCdpClient, this.#browserCdpClient, sessionId, this.#realmStorage, this.#eventManager, this.#preloadScriptStorage, this.#networkStorage); | ||
if (maybeContext) { | ||
@@ -199,0 +199,0 @@ // OOPiF. |
@@ -12,4 +12,4 @@ import type Protocol from 'devtools-protocol'; | ||
#private; | ||
static create(targetId: Protocol.Target.TargetID, cdpClient: ICdpClient, cdpSessionId: Protocol.Target.SessionID, realmStorage: RealmStorage, eventManager: EventManager, preloadScriptStorage: PreloadScriptStorage, networkStorage: NetworkStorage): CdpTarget; | ||
private constructor(); | ||
static create(targetId: Protocol.Target.TargetID, cdpClient: ICdpClient, browserCdpClient: ICdpClient, cdpSessionId: Protocol.Target.SessionID, realmStorage: RealmStorage, eventManager: EventManager, preloadScriptStorage: PreloadScriptStorage, networkStorage: NetworkStorage): CdpTarget; | ||
constructor(targetId: Protocol.Target.TargetID, cdpClient: ICdpClient, browserCdpClient: ICdpClient, cdpSessionId: Protocol.Target.SessionID, eventManager: EventManager, preloadScriptStorage: PreloadScriptStorage, networkStorage: NetworkStorage); | ||
/** Returns a promise that resolves when the target is unblocked. */ | ||
@@ -19,2 +19,3 @@ get targetUnblocked(): Deferred<Result<void>>; | ||
get cdpClient(): ICdpClient; | ||
get browserCdpClient(): ICdpClient; | ||
/** Needed for CDP escape path. */ | ||
@@ -21,0 +22,0 @@ get cdpSessionId(): Protocol.Target.SessionID; |
@@ -10,2 +10,3 @@ "use strict"; | ||
#cdpClient; | ||
#browserCdpClient; | ||
#cdpSessionId; | ||
@@ -16,4 +17,4 @@ #eventManager; | ||
#targetUnblocked = new Deferred_js_1.Deferred(); | ||
static create(targetId, cdpClient, cdpSessionId, realmStorage, eventManager, preloadScriptStorage, networkStorage) { | ||
const cdpTarget = new CdpTarget(targetId, cdpClient, cdpSessionId, eventManager, preloadScriptStorage, networkStorage); | ||
static create(targetId, cdpClient, browserCdpClient, cdpSessionId, realmStorage, eventManager, preloadScriptStorage, networkStorage) { | ||
const cdpTarget = new CdpTarget(targetId, cdpClient, browserCdpClient, cdpSessionId, eventManager, preloadScriptStorage, networkStorage); | ||
LogManager_js_1.LogManager.create(cdpTarget, realmStorage, eventManager); | ||
@@ -27,3 +28,3 @@ NetworkManager_js_1.NetworkManager.create(cdpTarget, networkStorage); | ||
} | ||
constructor(targetId, cdpClient, cdpSessionId, eventManager, preloadScriptStorage, networkStorage) { | ||
constructor(targetId, cdpClient, browserCdpClient, cdpSessionId, eventManager, preloadScriptStorage, networkStorage) { | ||
this.#targetId = targetId; | ||
@@ -35,2 +36,3 @@ this.#cdpClient = cdpClient; | ||
this.#networkStorage = networkStorage; | ||
this.#browserCdpClient = browserCdpClient; | ||
} | ||
@@ -47,2 +49,5 @@ /** Returns a promise that resolves when the target is unblocked. */ | ||
} | ||
get browserCdpClient() { | ||
return this.#browserCdpClient; | ||
} | ||
/** Needed for CDP escape path. */ | ||
@@ -129,3 +134,5 @@ get cdpSessionId() { | ||
async #initAndEvaluatePreloadScripts() { | ||
for (const script of this.#preloadScriptStorage.find()) { | ||
for (const script of this.#preloadScriptStorage.find({ | ||
global: true, | ||
})) { | ||
await script.initInTarget(this, true); | ||
@@ -132,0 +139,0 @@ } |
@@ -54,9 +54,9 @@ /** | ||
count: number; | ||
"__#82257@#x": number; | ||
"__#82257@#y": number; | ||
"__#82257@#time": number; | ||
"__#86748@#x": number; | ||
"__#86748@#y": number; | ||
"__#86748@#time": number; | ||
compare(context: any): boolean; | ||
}; | ||
"__#82257@#DOUBLE_CLICK_TIME_MS": number; | ||
"__#82257@#MAX_DOUBLE_CLICK_RADIUS": number; | ||
"__#86748@#DOUBLE_CLICK_TIME_MS": number; | ||
"__#86748@#MAX_DOUBLE_CLICK_RADIUS": number; | ||
}; | ||
@@ -63,0 +63,0 @@ setClickCount(button: number, context: InstanceType<typeof PointerSource.ClickContext>): number; |
@@ -117,3 +117,3 @@ "use strict"; | ||
} | ||
return realm.stringifyObject(params.exceptionDetails.exception); | ||
return await realm.stringifyObject(params.exceptionDetails.exception); | ||
} | ||
@@ -120,0 +120,0 @@ } |
@@ -48,5 +48,3 @@ "use strict"; | ||
const networkManager = new NetworkManager(cdpTarget, networkStorage); | ||
cdpTarget.cdpClient | ||
.browserClient() | ||
.on('Target.detachedFromTarget', (params) => { | ||
cdpTarget.browserCdpClient.on('Target.detachedFromTarget', (params) => { | ||
if (cdpTarget.cdpClient.sessionId === params.sessionId) { | ||
@@ -53,0 +51,0 @@ networkManager.#networkStorage.disposeRequestMap(); |
@@ -10,6 +10,6 @@ import { Network, type EmptyResult } from '../../../protocol/protocol.js'; | ||
continueRequest(params: Network.ContinueRequestParameters): Promise<EmptyResult>; | ||
continueResponse(_params: Network.ContinueResponseParameters): EmptyResult; | ||
continueWithAuth(_params: Network.ContinueWithAuthParameters): EmptyResult; | ||
continueResponse(params: Network.ContinueResponseParameters): Promise<EmptyResult>; | ||
continueWithAuth(params: Network.ContinueWithAuthParameters): Promise<EmptyResult>; | ||
failRequest(params: Network.FailRequestParameters): Promise<EmptyResult>; | ||
provideResponse(_params: Network.ProvideResponseParameters): EmptyResult; | ||
provideResponse(params: Network.ProvideResponseParameters): Promise<EmptyResult>; | ||
removeIntercept(params: Network.RemoveInterceptParameters): Promise<EmptyResult>; | ||
@@ -16,0 +16,0 @@ /** |
@@ -5,2 +5,4 @@ "use strict"; | ||
const protocol_js_1 = require("../../../protocol/protocol.js"); | ||
const assert_js_1 = require("../../../utils/assert.js"); | ||
const NetworkUtils_js_1 = require("./NetworkUtils.js"); | ||
const NetworkStorage_js_1 = require("./NetworkStorage.js"); | ||
@@ -19,2 +21,8 @@ /** Dispatches Network domain commands. */ | ||
} | ||
// If AuthRequired is specified, BeforeRequestSent must also be specified. | ||
// This is a CDP quirk. | ||
if (params.phases.includes("authRequired" /* Network.InterceptPhase.AuthRequired */) && | ||
!params.phases.includes("beforeRequestSent" /* Network.InterceptPhase.BeforeRequestSent */)) { | ||
params.phases.unshift("beforeRequestSent" /* Network.InterceptPhase.BeforeRequestSent */); | ||
} | ||
const urlPatterns = params.urlPatterns ?? []; | ||
@@ -33,4 +41,3 @@ const parsedUrlPatterns = NetworkProcessor.parseUrlPatterns(urlPatterns); | ||
const networkId = params.request; | ||
const blockedRequest = this.#getBlockedRequest(networkId); | ||
const { request: fetchId, phase } = blockedRequest; | ||
const { request: fetchId, phase } = this.#getBlockedRequest(networkId); | ||
if (phase !== "beforeRequestSent" /* Network.InterceptPhase.BeforeRequestSent */) { | ||
@@ -42,18 +49,49 @@ throw new protocol_js_1.InvalidArgumentException(`Blocked request for network id '${networkId}' is not in 'BeforeRequestSent' phase`); | ||
} | ||
const { url, method } = params; | ||
const { url, method, headers } = params; | ||
// TODO: Set / expand. | ||
// ; headers | ||
// ; cookies | ||
// ; body | ||
await this.#networkStorage | ||
.getRequest(networkId) | ||
?.continueRequest(fetchId, url, method); | ||
// ; Step 9. cookies | ||
// ; Step 10. body | ||
const requestHeaders = (0, NetworkUtils_js_1.cdpFetchHeadersFromBidiNetworkHeaders)(headers); | ||
const request = this.#networkStorage.getRequest(networkId); | ||
(0, assert_js_1.assert)(request, `Network request with ID ${networkId} doesn't exist`); | ||
await request.continueRequest(fetchId, url, method, requestHeaders); | ||
this.#networkStorage.removeBlockedRequest(networkId); | ||
return {}; | ||
} | ||
continueResponse(_params) { | ||
throw new protocol_js_1.UnknownCommandException('Not implemented yet.'); | ||
async continueResponse(params) { | ||
const networkId = params.request; | ||
const { request: fetchId, phase } = this.#getBlockedRequest(networkId); | ||
if (phase === "beforeRequestSent" /* Network.InterceptPhase.BeforeRequestSent */) { | ||
throw new protocol_js_1.InvalidArgumentException(`Blocked request for network id '${networkId}' is in 'BeforeRequestSent' phase`); | ||
} | ||
const { statusCode, reasonPhrase, headers } = params; | ||
const responseHeaders = (0, NetworkUtils_js_1.cdpFetchHeadersFromBidiNetworkHeaders)(headers); | ||
// TODO: Set / expand. | ||
// ; Step 10. cookies | ||
// ; Step 11. credentials | ||
const request = this.#networkStorage.getRequest(networkId); | ||
(0, assert_js_1.assert)(request, `Network request with ID ${networkId} doesn't exist`); | ||
await request.continueResponse(fetchId, statusCode, reasonPhrase, responseHeaders); | ||
this.#networkStorage.removeBlockedRequest(networkId); | ||
return {}; | ||
} | ||
continueWithAuth(_params) { | ||
throw new protocol_js_1.UnknownCommandException('Not implemented yet.'); | ||
async continueWithAuth(params) { | ||
const networkId = params.request; | ||
const { request: fetchId, phase } = this.#getBlockedRequest(networkId); | ||
if (phase !== "authRequired" /* Network.InterceptPhase.AuthRequired */) { | ||
throw new protocol_js_1.InvalidArgumentException(`Blocked request for network id '${networkId}' is not in 'AuthRequired' phase`); | ||
} | ||
const request = this.#networkStorage.getRequest(networkId); | ||
(0, assert_js_1.assert)(request, `Network request with ID ${networkId} doesn't exist`); | ||
let username; | ||
let password; | ||
if (params.action === 'provideCredentials') { | ||
const { credentials } = params; | ||
username = params.credentials.username; | ||
password = params.credentials.password; | ||
(0, assert_js_1.assert)(credentials.type === 'password', `Credentials type ${credentials.type} must be 'password'`); | ||
} | ||
const response = (0, NetworkUtils_js_1.cdpAuthChallengeResponseFromBidiAuthContinueWithAuthAction)(params.action); | ||
await request.continueWithAuth(fetchId, response, username, password); | ||
return {}; | ||
} | ||
@@ -67,10 +105,24 @@ async failRequest(params) { | ||
} | ||
await this.#networkStorage | ||
.getRequest(networkId) | ||
?.failRequest(fetchId, 'Failed'); | ||
const request = this.#networkStorage.getRequest(networkId); | ||
(0, assert_js_1.assert)(request, `Network request with ID ${networkId} doesn't exist`); | ||
await request.failRequest(fetchId, 'Failed'); | ||
this.#networkStorage.removeBlockedRequest(networkId); | ||
return {}; | ||
} | ||
provideResponse(_params) { | ||
throw new protocol_js_1.UnknownCommandException('Not implemented yet.'); | ||
async provideResponse(params) { | ||
const networkId = params.request; | ||
const { request: fetchId } = this.#getBlockedRequest(networkId); | ||
const { statusCode, reasonPhrase, headers, body } = params; | ||
// TODO: Step 6 | ||
// https://w3c.github.io/webdriver-bidi/#command-network-continueResponse | ||
const responseHeaders = (0, NetworkUtils_js_1.cdpFetchHeadersFromBidiNetworkHeaders)(headers); | ||
// TODO: Set / expand. | ||
// ; Step 10. cookies | ||
// ; Step 11. credentials | ||
const request = this.#networkStorage.getRequest(networkId); | ||
(0, assert_js_1.assert)(request, `Network request with ID ${networkId} doesn't exist`); | ||
await request.provideResponse(fetchId, statusCode ?? request.statusCode, reasonPhrase, responseHeaders, body?.value // TODO: Differ base64 / string | ||
); | ||
this.#networkStorage.removeBlockedRequest(networkId); | ||
return {}; | ||
} | ||
@@ -105,3 +157,4 @@ async removeIntercept(params) { | ||
if (this.#networkStorage.hasIntercepts() || | ||
this.#networkStorage.hasBlockedRequests()) { | ||
this.#networkStorage.hasBlockedRequests() || | ||
this.#networkStorage.hasNetworkRequests()) { | ||
// TODO: Add try/catch. Remove the intercept if CDP Fetch commands fail. | ||
@@ -108,0 +161,0 @@ await this.#fetchEnable(); |
@@ -7,3 +7,3 @@ /** | ||
import type { EventManager } from '../events/EventManager.js'; | ||
import { Network } from '../../../protocol/protocol.js'; | ||
import { Network, type JsUint } from '../../../protocol/protocol.js'; | ||
import type { CdpTarget } from '../context/CdpTarget.js'; | ||
@@ -39,4 +39,12 @@ import type { NetworkStorage } from './NetworkStorage.js'; | ||
/** @see https://chromedevtools.github.io/devtools-protocol/tot/Fetch/#method-continueRequest */ | ||
continueRequest(networkId: Protocol.Fetch.RequestId, url?: string, method?: string): Promise<void>; | ||
continueRequest(cdpFetchRequestId: Protocol.Fetch.RequestId, url?: string, method?: string, headers?: Protocol.Fetch.HeaderEntry[]): Promise<void>; | ||
/** @see https://chromedevtools.github.io/devtools-protocol/tot/Fetch/#method-continueResponse */ | ||
continueResponse(cdpFetchRequestId: Protocol.Fetch.RequestId, responseCode?: JsUint, responsePhrase?: string, responseHeaders?: Protocol.Fetch.HeaderEntry[]): Promise<void>; | ||
/** @see https://chromedevtools.github.io/devtools-protocol/tot/Fetch/#method-continueWithAuth */ | ||
continueWithAuth(cdpFetchRequestId: Protocol.Fetch.RequestId, response: 'Default' | 'CancelAuth' | 'ProvideCredentials', username?: string, password?: string): Promise<void>; | ||
/** @see https://chromedevtools.github.io/devtools-protocol/tot/Fetch/#method-provideResponse */ | ||
provideResponse(cdpFetchRequestId: Protocol.Fetch.RequestId, responseCode: JsUint, responsePhrase?: string, responseHeaders?: Protocol.Fetch.HeaderEntry[], body?: string): Promise<void>; | ||
dispose(): void; | ||
/** Returns the HTTP status code associated with this request if any. */ | ||
get statusCode(): number; | ||
} |
@@ -48,2 +48,3 @@ "use strict"; | ||
#beforeRequestSentDeferred = new Deferred_js_1.Deferred(); | ||
#responseStartedDeferred = new Deferred_js_1.Deferred(); | ||
#responseCompletedDeferred = new Deferred_js_1.Deferred(); | ||
@@ -58,3 +59,3 @@ #cdpTarget; | ||
get url() { | ||
return this.#response.info?.response.url ?? this.#request.info?.request.url; | ||
return this.#response.info?.url ?? this.#request.info?.request.url; | ||
} | ||
@@ -71,7 +72,6 @@ get redirectCount() { | ||
handleRedirect(event) { | ||
this.#queueResponseStartedEvent(); | ||
this.#queueResponseCompletedEvent(); | ||
this.#response.info = { | ||
hasExtraInfo: event.redirectHasExtraInfo, | ||
response: event.redirectResponse, | ||
}; | ||
this.#response.hasExtraInfo = event.redirectHasExtraInfo; | ||
this.#response.info = event.redirectResponse; | ||
this.#emitEventsIfReady(true); | ||
@@ -88,3 +88,3 @@ } | ||
// is the only place we can find out | ||
Boolean(this.#response.info && !this.#response.info.hasExtraInfo) || | ||
Boolean(this.#response.info && !this.#response.hasExtraInfo) || | ||
this.#interceptPhase === "beforeRequestSent" /* Network.InterceptPhase.BeforeRequestSent */; | ||
@@ -101,5 +101,9 @@ if (this.#request.info && requestExtraInfoCompleted) { | ||
// Don't expect extra info if the flag is false | ||
Boolean(this.#response.info && !this.#response.info.hasExtraInfo) || | ||
Boolean(this.#response.info && !this.#response.hasExtraInfo) || | ||
this.#interceptPhase === "responseStarted" /* Network.InterceptPhase.ResponseStarted */; | ||
if (this.#response.info && responseExtraInfoCompleted) { | ||
this.#responseStartedDeferred.resolve({ | ||
kind: 'success', | ||
value: undefined, | ||
}); | ||
this.#responseCompletedDeferred.resolve({ | ||
@@ -125,3 +129,5 @@ kind: 'success', | ||
onResponseReceivedEvent(event) { | ||
this.#response.info = event; | ||
this.#response.hasExtraInfo = event.hasExtraInfo; | ||
this.#response.info = event.response; | ||
this.#queueResponseStartedEvent(); | ||
this.#queueResponseCompletedEvent(); | ||
@@ -139,2 +145,6 @@ this.#emitEventsIfReady(); | ||
}); | ||
this.#responseStartedDeferred.resolve({ | ||
kind: 'error', | ||
error: new Error('Network event loading failed'), | ||
}); | ||
this.#responseCompletedDeferred.resolve({ | ||
@@ -172,3 +182,3 @@ kind: 'error', | ||
} | ||
const headers = (0, NetworkUtils_js_1.bidiNetworkHeadersFromCdpFetchHeaderEntryArray)( | ||
const headers = (0, NetworkUtils_js_1.bidiNetworkHeadersFromCdpFetchHeaders)( | ||
// TODO: Use params.request.headers if request? | ||
@@ -194,3 +204,3 @@ params.responseHeaders); | ||
bytesReceived: 0, | ||
headersSize: (0, NetworkUtils_js_1.computeResponseHeadersSize)(headers), | ||
headersSize: (0, NetworkUtils_js_1.computeHeadersSize)(headers), | ||
// TODO: consider removing from spec. | ||
@@ -218,11 +228,11 @@ bodySize: 0, | ||
/** @see https://chromedevtools.github.io/devtools-protocol/tot/Fetch/#method-continueRequest */ | ||
async continueRequest(networkId, url, method) { | ||
async continueRequest(cdpFetchRequestId, url, method, headers) { | ||
// TODO: Expand. | ||
await this.#cdpTarget.cdpClient.sendCommand('Fetch.continueRequest', { | ||
requestId: networkId, | ||
requestId: cdpFetchRequestId, | ||
url, | ||
method, | ||
headers, | ||
// TODO: Set? | ||
// postData:, | ||
// headers:, | ||
// interceptResponse:, | ||
@@ -232,2 +242,35 @@ }); | ||
} | ||
/** @see https://chromedevtools.github.io/devtools-protocol/tot/Fetch/#method-continueResponse */ | ||
async continueResponse(cdpFetchRequestId, responseCode, responsePhrase, responseHeaders) { | ||
await this.#cdpTarget.cdpClient.sendCommand('Fetch.continueResponse', { | ||
requestId: cdpFetchRequestId, | ||
responseCode, | ||
responsePhrase, | ||
responseHeaders, | ||
}); | ||
this.#interceptPhase = undefined; | ||
} | ||
/** @see https://chromedevtools.github.io/devtools-protocol/tot/Fetch/#method-continueWithAuth */ | ||
async continueWithAuth(cdpFetchRequestId, response, username, password) { | ||
await this.#cdpTarget.cdpClient.sendCommand('Fetch.continueWithAuth', { | ||
requestId: cdpFetchRequestId, | ||
authChallengeResponse: { | ||
response, | ||
username, | ||
password, | ||
}, | ||
}); | ||
this.#interceptPhase = undefined; | ||
} | ||
/** @see https://chromedevtools.github.io/devtools-protocol/tot/Fetch/#method-provideResponse */ | ||
async provideResponse(cdpFetchRequestId, responseCode, responsePhrase, responseHeaders, body) { | ||
await this.#cdpTarget.cdpClient.sendCommand('Fetch.fulfillRequest', { | ||
requestId: cdpFetchRequestId, | ||
responseCode, | ||
responsePhrase, | ||
responseHeaders, | ||
...(body ? { body: btoa(body) } : {}), // TODO: Double-check if btoa usage is correct. | ||
}); | ||
this.#interceptPhase = undefined; | ||
} | ||
dispose() { | ||
@@ -239,2 +282,3 @@ const result = { | ||
this.#beforeRequestSentDeferred.resolve(result); | ||
this.#responseStartedDeferred.resolve(result); | ||
this.#responseCompletedDeferred.resolve(result); | ||
@@ -245,2 +289,7 @@ } | ||
} | ||
/** Returns the HTTP status code associated with this request if any. */ | ||
get statusCode() { | ||
return (this.#response.info?.status ?? this.#response.extraInfo?.statusCode ?? -1 // TODO: Throw an exception or use some other status code? | ||
); | ||
} | ||
#getBaseEventParams(phase) { | ||
@@ -279,5 +328,4 @@ return { | ||
cookies, | ||
headersSize: (0, NetworkUtils_js_1.computeHeadersSize)(headers), | ||
// TODO: implement. | ||
headersSize: -1, | ||
// TODO: implement. | ||
bodySize: 0, | ||
@@ -311,8 +359,16 @@ timings: this.#getTimings(), | ||
if (result.kind === 'success') { | ||
return { | ||
kind: 'success', | ||
value: Object.assign(this.#getBeforeRequestEvent(), { | ||
type: 'event', | ||
}), | ||
}; | ||
try { | ||
return { | ||
kind: 'success', | ||
value: Object.assign(this.#getBeforeRequestEvent(), { | ||
type: 'event', | ||
}), | ||
}; | ||
} | ||
catch (error) { | ||
return { | ||
kind: 'error', | ||
error: error instanceof Error ? error : new Error('Unknown'), | ||
}; | ||
} | ||
} | ||
@@ -334,2 +390,62 @@ return result; | ||
} | ||
#queueResponseStartedEvent() { | ||
if (this.#isIgnoredEvent()) { | ||
return; | ||
} | ||
this.#eventManager.registerPromiseEvent(this.#responseStartedDeferred.then((result) => { | ||
if (result.kind === 'success') { | ||
try { | ||
return { | ||
kind: 'success', | ||
value: Object.assign(this.#getResponseStartedEvent(), { | ||
type: 'event', | ||
}), | ||
}; | ||
} | ||
catch (error) { | ||
return { | ||
kind: 'error', | ||
error: error instanceof Error ? error : new Error('Unknown'), | ||
}; | ||
} | ||
} | ||
return result; | ||
}), this.#context, protocol_js_1.ChromiumBidi.Network.EventNames.ResponseStarted); | ||
} | ||
#getResponseStartedEvent() { | ||
(0, assert_js_1.assert)(this.#request.info, 'RequestWillBeSentEvent is not set'); | ||
(0, assert_js_1.assert)(this.#response.info, 'ResponseReceivedEvent is not set'); | ||
// Chromium sends wrong extraInfo events for responses served from cache. | ||
// See https://github.com/puppeteer/puppeteer/issues/9965 and | ||
// https://crbug.com/1340398. | ||
if (this.#response.info.fromDiskCache) { | ||
this.#response.extraInfo = undefined; | ||
} | ||
const headers = (0, NetworkUtils_js_1.bidiNetworkHeadersFromCdpNetworkHeaders)(this.#response.info.headers); | ||
return { | ||
method: protocol_js_1.ChromiumBidi.Network.EventNames.ResponseStarted, | ||
params: { | ||
...this.#getBaseEventParams(), | ||
response: { | ||
url: this.#response.info.url ?? NetworkRequest.#unknown, | ||
protocol: this.#response.info.protocol ?? '', | ||
status: this.statusCode, | ||
statusText: this.#response.info.statusText, | ||
fromCache: this.#response.info.fromDiskCache || | ||
this.#response.info.fromPrefetchCache || | ||
this.#servedFromCache, | ||
headers, | ||
mimeType: this.#response.info.mimeType, | ||
bytesReceived: this.#response.info.encodedDataLength, | ||
headersSize: (0, NetworkUtils_js_1.computeHeadersSize)(headers), | ||
// TODO: consider removing from spec. | ||
bodySize: 0, | ||
content: { | ||
// TODO: consider removing from spec. | ||
size: 0, | ||
}, | ||
}, | ||
}, | ||
}; | ||
} | ||
#queueResponseCompletedEvent() { | ||
@@ -341,8 +457,16 @@ if (this.#isIgnoredEvent()) { | ||
if (result.kind === 'success') { | ||
return { | ||
kind: 'success', | ||
value: Object.assign(this.#getResponseReceivedEvent(), { | ||
type: 'event', | ||
}), | ||
}; | ||
try { | ||
return { | ||
kind: 'success', | ||
value: Object.assign(this.#getResponseReceivedEvent(), { | ||
type: 'event', | ||
}), | ||
}; | ||
} | ||
catch (error) { | ||
return { | ||
kind: 'error', | ||
error: error instanceof Error ? error : new Error('Unknown'), | ||
}; | ||
} | ||
} | ||
@@ -358,6 +482,6 @@ return result; | ||
// https://crbug.com/1340398. | ||
if (this.#response.info.response.fromDiskCache) { | ||
if (this.#response.info.fromDiskCache) { | ||
this.#response.extraInfo = undefined; | ||
} | ||
const headers = (0, NetworkUtils_js_1.bidiNetworkHeadersFromCdpNetworkHeaders)(this.#response.info.response.headers); | ||
const headers = (0, NetworkUtils_js_1.bidiNetworkHeadersFromCdpNetworkHeaders)(this.#response.info.headers); | ||
return { | ||
@@ -368,14 +492,13 @@ method: protocol_js_1.ChromiumBidi.Network.EventNames.ResponseCompleted, | ||
response: { | ||
url: this.#response.info.response.url ?? NetworkRequest.#unknown, | ||
protocol: this.#response.info.response.protocol ?? '', | ||
status: this.#response.extraInfo?.statusCode ?? | ||
this.#response.info.response.status, | ||
statusText: this.#response.info.response.statusText, | ||
fromCache: this.#response.info.response.fromDiskCache || | ||
this.#response.info.response.fromPrefetchCache || | ||
url: this.#response.info.url ?? NetworkRequest.#unknown, | ||
protocol: this.#response.info.protocol ?? '', | ||
status: this.statusCode, | ||
statusText: this.#response.info.statusText, | ||
fromCache: this.#response.info.fromDiskCache || | ||
this.#response.info.fromPrefetchCache || | ||
this.#servedFromCache, | ||
headers, | ||
mimeType: this.#response.info.response.mimeType, | ||
bytesReceived: this.#response.info.response.encodedDataLength, | ||
headersSize: (0, NetworkUtils_js_1.computeResponseHeadersSize)(headers), | ||
mimeType: this.#response.info.mimeType, | ||
bytesReceived: this.#response.info.encodedDataLength, | ||
headersSize: (0, NetworkUtils_js_1.computeHeadersSize)(headers), | ||
// TODO: consider removing from spec. | ||
@@ -382,0 +505,0 @@ bodySize: 0, |
@@ -42,3 +42,3 @@ /** | ||
removeIntercept(intercept: Network.Intercept): void; | ||
/** Returns true iff there's at least one added intercept. */ | ||
/** Returns true if there's at least one added intercept. */ | ||
hasIntercepts(): boolean; | ||
@@ -50,3 +50,5 @@ /** Gets parameters for CDP 'Fetch.enable' command from the intercept map. */ | ||
deleteRequest(id: Network.Request): void; | ||
/** Returns true iff there's at least one blocked network request. */ | ||
/** Returns true if there's at least one network request. */ | ||
hasNetworkRequests(): boolean; | ||
/** Returns true if there's at least one blocked network request. */ | ||
hasBlockedRequests(): boolean; | ||
@@ -53,0 +55,0 @@ /** Converts a URL pattern from the spec to a CDP URL pattern. */ |
@@ -59,3 +59,3 @@ "use strict"; | ||
} | ||
/** Returns true iff there's at least one added intercept. */ | ||
/** Returns true if there's at least one added intercept. */ | ||
hasIntercepts() { | ||
@@ -100,3 +100,7 @@ return this.#interceptMap.size > 0; | ||
} | ||
/** Returns true iff there's at least one blocked network request. */ | ||
/** Returns true if there's at least one network request. */ | ||
hasNetworkRequests() { | ||
return this.#requestMap.size > 0; | ||
} | ||
/** Returns true if there's at least one blocked network request. */ | ||
hasBlockedRequests() { | ||
@@ -103,0 +107,0 @@ return this.#blockedRequestMap.size > 0; |
@@ -6,6 +6,12 @@ /** | ||
import type { Network } from '../../../protocol/protocol.js'; | ||
export declare function computeResponseHeadersSize(headers: Network.Header[]): number; | ||
export declare function computeHeadersSize(headers: Network.Header[]): number; | ||
/** Converts from CDP Network domain headers to Bidi network headers. */ | ||
export declare function bidiNetworkHeadersFromCdpNetworkHeaders(headers?: Protocol.Network.Headers): Network.Header[]; | ||
/** Converts from Bidi network headers to CDP Network domain headers. */ | ||
export declare function cdpNetworkHeadersFromBidiNetworkHeaders(headers?: Network.Header[]): Protocol.Network.Headers | undefined; | ||
/** Converts from CDP Fetch domain header entries to Bidi network headers. */ | ||
export declare function bidiNetworkHeadersFromCdpFetchHeaderEntryArray(headers?: Protocol.Fetch.HeaderEntry[]): Network.Header[]; | ||
export declare function bidiNetworkHeadersFromCdpFetchHeaders(headers?: Protocol.Fetch.HeaderEntry[]): Network.Header[]; | ||
/** Converts from Bidi network headers to CDP Fetch domain header entries. */ | ||
export declare function cdpFetchHeadersFromBidiNetworkHeaders(headers?: Network.Header[]): Protocol.Fetch.HeaderEntry[] | undefined; | ||
/** Converts from Bidi auth action to CDP auth challenge response. */ | ||
export declare function cdpAuthChallengeResponseFromBidiAuthContinueWithAuthAction(action: 'default' | 'cancel' | 'provideCredentials'): "Default" | "CancelAuth" | "ProvideCredentials"; |
@@ -20,10 +20,10 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.bidiNetworkHeadersFromCdpFetchHeaderEntryArray = exports.bidiNetworkHeadersFromCdpNetworkHeaders = exports.computeResponseHeadersSize = void 0; | ||
function computeResponseHeadersSize(headers) { | ||
return headers.reduce((total, header) => { | ||
return (total + header.name.length + header.value.value.length + 4 // 4 = ': ' + '\r\n' | ||
); | ||
}, 0); | ||
exports.cdpAuthChallengeResponseFromBidiAuthContinueWithAuthAction = exports.cdpFetchHeadersFromBidiNetworkHeaders = exports.bidiNetworkHeadersFromCdpFetchHeaders = exports.cdpNetworkHeadersFromBidiNetworkHeaders = exports.bidiNetworkHeadersFromCdpNetworkHeaders = exports.computeHeadersSize = void 0; | ||
function computeHeadersSize(headers) { | ||
const requestHeaders = headers.reduce((acc, header) => { | ||
return `${acc}${header.name}: ${header.value.value}\r\n`; | ||
}, ''); | ||
return new TextEncoder().encode(requestHeaders).length; | ||
} | ||
exports.computeResponseHeadersSize = computeResponseHeadersSize; | ||
exports.computeHeadersSize = computeHeadersSize; | ||
/** Converts from CDP Network domain headers to Bidi network headers. */ | ||
@@ -43,4 +43,16 @@ function bidiNetworkHeadersFromCdpNetworkHeaders(headers) { | ||
exports.bidiNetworkHeadersFromCdpNetworkHeaders = bidiNetworkHeadersFromCdpNetworkHeaders; | ||
/** Converts from Bidi network headers to CDP Network domain headers. */ | ||
function cdpNetworkHeadersFromBidiNetworkHeaders(headers) { | ||
if (headers === undefined) { | ||
return undefined; | ||
} | ||
return headers.reduce((result, header) => { | ||
// TODO: Distinguish between string and bytes? | ||
result[header.name] = header.value.value; | ||
return result; | ||
}, {}); | ||
} | ||
exports.cdpNetworkHeadersFromBidiNetworkHeaders = cdpNetworkHeadersFromBidiNetworkHeaders; | ||
/** Converts from CDP Fetch domain header entries to Bidi network headers. */ | ||
function bidiNetworkHeadersFromCdpFetchHeaderEntryArray(headers) { | ||
function bidiNetworkHeadersFromCdpFetchHeaders(headers) { | ||
if (!headers) { | ||
@@ -57,3 +69,26 @@ return []; | ||
} | ||
exports.bidiNetworkHeadersFromCdpFetchHeaderEntryArray = bidiNetworkHeadersFromCdpFetchHeaderEntryArray; | ||
exports.bidiNetworkHeadersFromCdpFetchHeaders = bidiNetworkHeadersFromCdpFetchHeaders; | ||
/** Converts from Bidi network headers to CDP Fetch domain header entries. */ | ||
function cdpFetchHeadersFromBidiNetworkHeaders(headers) { | ||
if (headers === undefined) { | ||
return undefined; | ||
} | ||
return headers.map(({ name, value }) => ({ | ||
name, | ||
value: value.value, | ||
})); | ||
} | ||
exports.cdpFetchHeadersFromBidiNetworkHeaders = cdpFetchHeadersFromBidiNetworkHeaders; | ||
/** Converts from Bidi auth action to CDP auth challenge response. */ | ||
function cdpAuthChallengeResponseFromBidiAuthContinueWithAuthAction(action) { | ||
switch (action) { | ||
case 'default': | ||
return 'Default'; | ||
case 'cancel': | ||
return 'CancelAuth'; | ||
case 'provideCredentials': | ||
return 'ProvideCredentials'; | ||
} | ||
} | ||
exports.cdpAuthChallengeResponseFromBidiAuthContinueWithAuthAction = cdpAuthChallengeResponseFromBidiAuthContinueWithAuthAction; | ||
//# sourceMappingURL=NetworkUtils.js.map |
@@ -127,3 +127,3 @@ "use strict"; | ||
const message = await realm.cdpClient.sendCommand('Runtime.callFunctionOn', { | ||
functionDeclaration: String(async (channelHandle) => channelHandle.getMessage()), | ||
functionDeclaration: String(async (channelHandle) => await channelHandle.getMessage()), | ||
arguments: [ | ||
@@ -130,0 +130,0 @@ { |
import type Protocol from 'devtools-protocol'; | ||
import type { Script } from '../../../protocol/protocol.js'; | ||
import type { BrowsingContext, Script } from '../../../protocol/protocol.js'; | ||
import type { CdpTarget } from '../context/CdpTarget.js'; | ||
@@ -23,2 +23,4 @@ import type { LoggerFn } from '../../../utils/log.js'; | ||
get channels(): ChannelProxy[]; | ||
/** Contexts of the preload script, if any */ | ||
get contexts(): BrowsingContext.BrowsingContext[] | undefined; | ||
/** | ||
@@ -25,0 +27,0 @@ * Adds the script to the given CDP targets by calling the |
@@ -46,2 +46,4 @@ "use strict"; | ||
#sandbox; | ||
/** The browsing contexts to execute the preload scripts in, if any. */ | ||
#contexts; | ||
get id() { | ||
@@ -58,2 +60,3 @@ return this.#id; | ||
this.#sandbox = params.sandbox; | ||
this.#contexts = params.contexts; | ||
} | ||
@@ -64,2 +67,6 @@ /** Channels of the preload script. */ | ||
} | ||
/** Contexts of the preload script, if any */ | ||
get contexts() { | ||
return this.#contexts; | ||
} | ||
/** | ||
@@ -66,0 +73,0 @@ * String to be evaluated. Wraps user-provided function so that the following |
import type { CdpTarget } from '../context/CdpTarget.js'; | ||
import type { PreloadScript } from './PreloadScript.js'; | ||
/** PreloadScripts can be filtered by BiDi ID or target ID. */ | ||
export type PreloadScriptFilter = Partial<Pick<PreloadScript, 'id'> & Pick<CdpTarget, 'targetId'>>; | ||
export type PreloadScriptFilter = Partial<Pick<PreloadScript, 'id'> & Pick<CdpTarget, 'targetId'> & { | ||
global: boolean; | ||
}>; | ||
/** | ||
@@ -6,0 +8,0 @@ * Container class for preload scripts. |
@@ -23,2 +23,9 @@ "use strict"; | ||
} | ||
if (filter.global !== undefined && | ||
// Global scripts have no contexts | ||
((filter.global && script.contexts !== undefined) || | ||
// Non global scripts always have contexts | ||
(!filter.global && script.contexts === undefined))) { | ||
return false; | ||
} | ||
return true; | ||
@@ -25,0 +32,0 @@ }); |
@@ -164,3 +164,3 @@ "use strict"; | ||
if (cdpEvaluateResult.exceptionDetails) { | ||
return this.#getExceptionResult(cdpEvaluateResult.exceptionDetails, 0, resultOwnership); | ||
return await this.#getExceptionResult(cdpEvaluateResult.exceptionDetails, 0, resultOwnership); | ||
} | ||
@@ -232,3 +232,3 @@ return { | ||
async #flattenValueList(listLocalValue) { | ||
return Promise.all(listLocalValue.map((localValue) => this.#deserializeToCdpArg(localValue))); | ||
return await Promise.all(listLocalValue.map((localValue) => this.#deserializeToCdpArg(localValue))); | ||
} | ||
@@ -270,3 +270,3 @@ async #serializeCdpExceptionDetails(cdpExceptionDetails, lineOffset, resultOwnership) { | ||
await this.#deserializeToCdpArg(thisLocalValue), | ||
...(await Promise.all(argumentsLocalValues.map(async (argumentLocalValue) => this.#deserializeToCdpArg(argumentLocalValue)))), | ||
...(await Promise.all(argumentsLocalValues.map(async (argumentLocalValue) => await this.#deserializeToCdpArg(argumentLocalValue)))), | ||
]; | ||
@@ -299,3 +299,3 @@ let cdpCallFunctionResult; | ||
if (cdpCallFunctionResult.exceptionDetails) { | ||
return this.#getExceptionResult(cdpCallFunctionResult.exceptionDetails, 1, resultOwnership); | ||
return await this.#getExceptionResult(cdpCallFunctionResult.exceptionDetails, 1, resultOwnership); | ||
} | ||
@@ -302,0 +302,0 @@ return { |
@@ -34,7 +34,25 @@ "use strict"; | ||
async addPreloadScript(params) { | ||
const contexts = new Set(); | ||
if (params.contexts) { | ||
// XXX: Remove once https://github.com/google/cddlconv/issues/16 is implemented | ||
if (params.contexts.length === 0) { | ||
throw new protocol_1.InvalidArgumentException('Contexts list is empty.'); | ||
} | ||
for (const contextId of params.contexts) { | ||
const context = this.#browsingContextStorage.getContext(contextId); | ||
if (context.isTopLevelContext()) { | ||
contexts.add(context); | ||
} | ||
else { | ||
throw new protocol_1.InvalidArgumentException(`Non top-level context '${contextId}' given.`); | ||
} | ||
} | ||
} | ||
const preloadScript = new PreloadScript_1.PreloadScript(params, this.#logger); | ||
this.#preloadScriptStorage.add(preloadScript); | ||
const cdpTargets = new Set(this.#browsingContextStorage | ||
.getTopLevelContexts() | ||
.map((context) => context.cdpTarget)); | ||
const cdpTargets = contexts.size === 0 | ||
? new Set(this.#browsingContextStorage | ||
.getTopLevelContexts() | ||
.map((context) => context.cdpTarget)) | ||
: new Set([...contexts.values()].map((context) => context.cdpTarget)); | ||
await preloadScript.initInTargets(cdpTargets, false); | ||
@@ -61,3 +79,3 @@ return { | ||
const realm = await this.#getRealm(params.target); | ||
return realm.callFunction(params.functionDeclaration, params.this ?? { | ||
return await realm.callFunction(params.functionDeclaration, params.this ?? { | ||
type: 'undefined', | ||
@@ -70,7 +88,7 @@ }, // `this` is `undefined` by default. | ||
const realm = await this.#getRealm(params.target); | ||
return realm.evaluate(params.expression, params.awaitPromise, params.resultOwnership ?? "none" /* Script.ResultOwnership.None */, params.serializationOptions ?? {}, params.userActivation ?? false); | ||
return await realm.evaluate(params.expression, params.awaitPromise, params.resultOwnership ?? "none" /* Script.ResultOwnership.None */, params.serializationOptions ?? {}, params.userActivation ?? false); | ||
} | ||
async disown(params) { | ||
const realm = await this.#getRealm(params.target); | ||
await Promise.all(params.handles.map(async (handle) => realm.disown(handle))); | ||
await Promise.all(params.handles.map(async (handle) => await realm.disown(handle))); | ||
return {}; | ||
@@ -98,3 +116,3 @@ } | ||
const context = this.#browsingContextStorage.getContext(target.context); | ||
return context.getOrCreateSandbox(target.sandbox); | ||
return await context.getOrCreateSandbox(target.sandbox); | ||
} | ||
@@ -101,0 +119,0 @@ } |
import { type ChromeReleaseChannel, type Process } from '@puppeteer/browsers'; | ||
import { EventEmitter } from '../utils/EventEmitter.js'; | ||
import { MapperCdpConnection } from './MapperCdpConnection.js'; | ||
import type { SimpleTransport } from './SimpleTransport.js'; | ||
/** | ||
@@ -13,8 +13,8 @@ * BrowserProcess is responsible for running the browser and BiDi Mapper within | ||
*/ | ||
export declare class BrowserInstance extends EventEmitter<Record<'message', string>> { | ||
export declare class BrowserInstance { | ||
#private; | ||
static run(channel: ChromeReleaseChannel, headless: boolean, verbose: boolean, chromeArgs?: string[]): Promise<BrowserInstance>; | ||
constructor(mapperCdpConnection: MapperCdpConnection, browserProcess: Process); | ||
sendCommand(plainCommand: string): Promise<void>; | ||
close(): Promise<void>; | ||
bidiSession(): SimpleTransport; | ||
} |
@@ -32,3 +32,2 @@ "use strict"; | ||
const WebsocketTransport_js_1 = require("../utils/WebsocketTransport.js"); | ||
const EventEmitter_js_1 = require("../utils/EventEmitter.js"); | ||
const MapperCdpConnection_js_1 = require("./MapperCdpConnection.js"); | ||
@@ -46,3 +45,3 @@ const reader_js_1 = require("./reader.js"); | ||
*/ | ||
class BrowserInstance extends EventEmitter_js_1.EventEmitter { | ||
class BrowserInstance { | ||
#mapperCdpConnection; | ||
@@ -95,19 +94,8 @@ #browserProcess; | ||
const mapperCdpConnection = await MapperCdpConnection_js_1.MapperCdpConnection.create(cdpConnection, mapperTabSource, verbose); | ||
const browserInstance = new BrowserInstance(mapperCdpConnection, browserProcess); | ||
// 4. Bind `BiDi-CDP` mapper to the `BiDi server` to forward messages from | ||
// BiDi Mapper to the client. | ||
mapperCdpConnection.on('message', (message) => { | ||
browserInstance.emit('message', message); | ||
}); | ||
return browserInstance; | ||
return new BrowserInstance(mapperCdpConnection, browserProcess); | ||
} | ||
constructor(mapperCdpConnection, browserProcess) { | ||
super(); | ||
this.#mapperCdpConnection = mapperCdpConnection; | ||
this.#browserProcess = browserProcess; | ||
} | ||
// Forward messages from the client to BiDi Mapper. | ||
async sendCommand(plainCommand) { | ||
await this.#mapperCdpConnection.sendMessage(plainCommand); | ||
} | ||
async close() { | ||
@@ -119,2 +107,5 @@ // Close the mapper tab. | ||
} | ||
bidiSession() { | ||
return this.#mapperCdpConnection.bidiSession(); | ||
} | ||
static #establishCdpConnection(cdpUrl) { | ||
@@ -121,0 +112,0 @@ return new Promise((resolve, reject) => { |
@@ -18,9 +18,9 @@ /** | ||
import type { CdpConnection } from '../cdp/CdpConnection.js'; | ||
import { EventEmitter } from '../utils/EventEmitter.js'; | ||
export declare class MapperCdpConnection extends EventEmitter<Record<'message', string>> { | ||
import { SimpleTransport } from './SimpleTransport.js'; | ||
export declare class MapperCdpConnection { | ||
#private; | ||
static create(cdpConnection: CdpConnection, mapperTabSource: string, verbose: boolean): Promise<MapperCdpConnection>; | ||
private constructor(); | ||
sendMessage(message: string): Promise<void>; | ||
close(): void; | ||
bidiSession(): SimpleTransport; | ||
} |
@@ -24,3 +24,3 @@ "use strict"; | ||
const debug_1 = __importDefault(require("debug")); | ||
const EventEmitter_js_1 = require("../utils/EventEmitter.js"); | ||
const SimpleTransport_js_1 = require("./SimpleTransport.js"); | ||
const debugInternal = (0, debug_1.default)('bidi:mapper:internal'); | ||
@@ -40,5 +40,6 @@ const debugInfo = (0, debug_1.default)('bidi:mapper:info'); | ||
}; | ||
class MapperCdpConnection extends EventEmitter_js_1.EventEmitter { | ||
class MapperCdpConnection { | ||
#cdpConnection; | ||
#mapperCdpClient; | ||
#bidiSession; | ||
static async create(cdpConnection, mapperTabSource, verbose) { | ||
@@ -55,5 +56,5 @@ try { | ||
constructor(cdpConnection, mapperCdpClient) { | ||
super(); | ||
this.#cdpConnection = cdpConnection; | ||
this.#mapperCdpClient = mapperCdpClient; | ||
this.#bidiSession = new SimpleTransport_js_1.SimpleTransport(async (message) => await this.#sendMessage(message)); | ||
this.#mapperCdpClient.on('Runtime.bindingCalled', this.#onBindingCalled); | ||
@@ -64,3 +65,3 @@ this.#mapperCdpClient.on('Runtime.consoleAPICalled', this.#onConsoleAPICalled); | ||
} | ||
async sendMessage(message) { | ||
async #sendMessage(message) { | ||
try { | ||
@@ -78,8 +79,8 @@ await this.#mapperCdpClient.sendCommand('Runtime.evaluate', { | ||
} | ||
#onBidiMessage(message) { | ||
this.emit('message', message); | ||
bidiSession() { | ||
return this.#bidiSession; | ||
} | ||
#onBindingCalled = (params) => { | ||
if (params.name === 'sendBidiResponse') { | ||
this.#onBidiMessage(params.payload); | ||
this.#bidiSession.emit('message', params.payload); | ||
} | ||
@@ -111,3 +112,3 @@ else if (params.name === 'sendDebugMessage') { | ||
debugInternal('Connection opened.'); | ||
const browserClient = cdpConnection.browserClient(); | ||
const browserClient = await cdpConnection.createBrowserSession(); | ||
const { targetId: mapperTabTargetId } = await browserClient.sendCommand('Target.createTarget', { | ||
@@ -114,0 +115,0 @@ url: 'about:blank', |
@@ -26,5 +26,5 @@ "use strict"; | ||
async function getMapperTabSource() { | ||
return promises_1.default.readFile(path_1.default.join(__dirname, '../../iife/mapperTab.js'), 'utf8'); | ||
return await promises_1.default.readFile(path_1.default.join(__dirname, '../../iife/mapperTab.js'), 'utf8'); | ||
} | ||
exports.getMapperTabSource = getMapperTabSource; | ||
//# sourceMappingURL=reader.js.map |
@@ -7,4 +7,3 @@ import debug from 'debug'; | ||
/** | ||
* | ||
* @param bidiPort port to start ws server on. | ||
* @param bidiPort Port to start ws server on. | ||
* @param channel | ||
@@ -11,0 +10,0 @@ * @param headless |
@@ -33,4 +33,3 @@ "use strict"; | ||
/** | ||
* | ||
* @param bidiPort port to start ws server on. | ||
* @param bidiPort Port to start ws server on. | ||
* @param channel | ||
@@ -100,3 +99,3 @@ * @param headless | ||
// Forward messages from BiDi Mapper to the client unconditionally. | ||
browserInstance.on('message', (message) => { | ||
browserInstance.bidiSession().on('message', (message) => { | ||
void this.#sendClientMessageString(message, connection); | ||
@@ -112,3 +111,10 @@ }); | ||
const plainCommandData = message.utf8Data; | ||
debugRecv(plainCommandData); | ||
if (debugRecv.enabled) { | ||
try { | ||
debugRecv(JSON.parse(plainCommandData)); | ||
} | ||
catch { | ||
debugRecv(plainCommandData); | ||
} | ||
} | ||
// Try to parse the message to handle some of BiDi commands. | ||
@@ -134,3 +140,3 @@ let parsedCommandData; | ||
// Forward all other commands to BiDi Mapper. | ||
await browserInstance.sendCommand(plainCommandData); | ||
await browserInstance.bidiSession().sendCommand(plainCommandData); | ||
}); | ||
@@ -146,3 +152,10 @@ connection.on('close', async () => { | ||
static #sendClientMessageString(message, connection) { | ||
debugSend(message); | ||
if (debugSend.enabled) { | ||
try { | ||
debugSend(JSON.parse(message)); | ||
} | ||
catch { | ||
debugSend(message); | ||
} | ||
} | ||
connection.sendUTF(message); | ||
@@ -149,0 +162,0 @@ return Promise.resolve(); |
@@ -29,4 +29,9 @@ /** | ||
sendDebugMessage?: ((message: string) => void) | null; | ||
/** | ||
* @deprecated Use `runMapperInstance` instead. Used for backward compatibility | ||
* with ChromeDriver. | ||
*/ | ||
setSelfTargetId: (targetId: string) => void; | ||
} | ||
} | ||
export {}; |
@@ -31,15 +31,38 @@ "use strict"; | ||
/** | ||
* Set `window.runMapper` to a function which launches the BiDi mapper instance. | ||
* @param selfTargetId Needed to filter out info related to BiDi target. | ||
* A CdpTransport implementation that uses the window.cdp bindings | ||
* injected by Target.exposeDevToolsProtocol. | ||
*/ | ||
window.runMapperInstance = async (selfTargetId) => { | ||
const cdpConnection = new CdpConnection_js_1.CdpConnection(cdpTransport, mapperTabPage_js_1.log); | ||
/** | ||
* Launches the BiDi mapper instance. | ||
* @param {string} selfTargetId | ||
*/ | ||
async function runMapperInstance(selfTargetId) { | ||
console.log('Launching Mapper instance with selfTargetId:', selfTargetId); | ||
await BidiMapper_js_1.BidiServer.createAndStart(mapperTabToServerTransport, | ||
const bidiServer = await BidiMapper_js_1.BidiServer.createAndStart(mapperTabToServerTransport, cdpConnection, | ||
/** | ||
* A CdpTransport implementation that uses the window.cdp bindings | ||
* injected by Target.exposeDevToolsProtocol. | ||
* Create a Browser CDP Session per Mapper instance. | ||
*/ | ||
new CdpConnection_js_1.CdpConnection(cdpTransport, mapperTabPage_js_1.log), selfTargetId, new BidiParser_js_1.BidiParser(), mapperTabPage_js_1.log); | ||
await cdpConnection.createBrowserSession(), selfTargetId, new BidiParser_js_1.BidiParser(), mapperTabPage_js_1.log); | ||
(0, mapperTabPage_js_1.log)(log_js_1.LogType.debugInfo, 'Mapper instance has been launched'); | ||
return bidiServer; | ||
} | ||
/** | ||
* Set `window.runMapper` to a function which launches the BiDi mapper instance. | ||
* @param selfTargetId Needed to filter out info related to BiDi target. | ||
*/ | ||
window.runMapperInstance = async (selfTargetId) => { | ||
await runMapperInstance(selfTargetId); | ||
}; | ||
/** | ||
* @deprecated Use `runMapperInstance` instead. Used for backward compatibility | ||
* with ChromeDriver. | ||
*/ | ||
// TODO: Remove this after https://crrev.com/c/4952609 reaches stable. | ||
window.setSelfTargetId = async (selfTargetId) => { | ||
const bidiServer = await runMapperInstance(selfTargetId); | ||
bidiServer.emitOutgoingMessage(BidiMapper_js_1.OutgoingMessage.createResolved({ | ||
launched: true, | ||
}), 'launched'); | ||
}; | ||
//# sourceMappingURL=bidiTab.js.map |
@@ -31,6 +31,2 @@ /** | ||
/** | ||
* Get the default browser client (no sessionId) | ||
*/ | ||
browserClient(): ICdpClient; | ||
/** | ||
* Provides an unique way to detect if an error was caused by the closure of a | ||
@@ -57,5 +53,4 @@ * Target or Session. | ||
get sessionId(): Protocol.Target.SessionID | undefined; | ||
browserClient(): ICdpClient; | ||
sendCommand<CdpMethod extends keyof ProtocolMapping.Commands>(method: CdpMethod, ...params: ProtocolMapping.Commands[CdpMethod]['paramsType']): Promise<ProtocolMapping.Commands[CdpMethod]['returnType']>; | ||
isCloseError(error: unknown): boolean; | ||
} |
@@ -37,5 +37,2 @@ "use strict"; | ||
} | ||
browserClient() { | ||
return this.#cdpConnection.browserClient(); | ||
} | ||
sendCommand(method, ...params) { | ||
@@ -42,0 +39,0 @@ return this.#cdpConnection.sendCommand(method, params[0], this.#sessionId); |
@@ -23,3 +23,2 @@ /** | ||
export interface ICdpConnection { | ||
browserClient(): ICdpClient; | ||
getCdpClient(sessionId: Protocol.Target.SessionID): ICdpClient; | ||
@@ -40,4 +39,3 @@ } | ||
close(): void; | ||
/** The CdpClient object attached to the root browser session. */ | ||
browserClient(): CdpClient; | ||
createBrowserSession(): Promise<ICdpClient>; | ||
/** | ||
@@ -44,0 +42,0 @@ * Gets a CdpClient instance attached to the given session ID, |
@@ -15,6 +15,6 @@ "use strict"; | ||
static LOGGER_PREFIX_SEND = `${log_js_1.LogType.cdp}:SEND ▸`; | ||
#mainBrowserCdpClient; | ||
#transport; | ||
/** The CdpClient object attached to the root browser session. */ | ||
#browserCdpClient; | ||
/** Map from session ID to CdpClient. */ | ||
/** Map from session ID to CdpClient. | ||
* `undefined` points to the main browser session. */ | ||
#sessionCdpClients = new Map(); | ||
@@ -28,3 +28,4 @@ #commandCallbacks = new Map(); | ||
this.#transport.setOnMessage(this.#onMessage); | ||
this.#browserCdpClient = new CdpClient_js_1.CdpClient(this, undefined); | ||
// Create default Browser CDP Session. | ||
this.#mainBrowserCdpClient = this.#createCdpClient(undefined); | ||
} | ||
@@ -40,5 +41,5 @@ /** Closes the connection to the browser. */ | ||
} | ||
/** The CdpClient object attached to the root browser session. */ | ||
browserClient() { | ||
return this.#browserCdpClient; | ||
async createBrowserSession() { | ||
const { sessionId } = await this.#mainBrowserCdpClient.sendCommand('Target.attachToBrowserTarget'); | ||
return this.#createCdpClient(sessionId); | ||
} | ||
@@ -84,3 +85,3 @@ /** | ||
const { sessionId } = message.params; | ||
this.#sessionCdpClients.set(sessionId, new CdpClient_js_1.CdpClient(this, sessionId)); | ||
this.#createCdpClient(sessionId); | ||
} | ||
@@ -101,5 +102,3 @@ if (message.id !== undefined) { | ||
else if (message.method) { | ||
const client = message.sessionId | ||
? this.#sessionCdpClients.get(message.sessionId) | ||
: this.#browserCdpClient; | ||
const client = this.#sessionCdpClients.get(message.sessionId ?? undefined); | ||
client?.emit(message.method, message.params || {}); | ||
@@ -118,4 +117,15 @@ // Update client map if a session is detached | ||
}; | ||
/** | ||
* Creates a new CdpClient instance for the given session ID. | ||
* @param sessionId either a string, or undefined for the main browser session. | ||
* The main browser session is used only to create new browser sessions. | ||
* @private | ||
*/ | ||
#createCdpClient(sessionId) { | ||
const cdpClient = new CdpClient_js_1.CdpClient(this, sessionId); | ||
this.#sessionCdpClients.set(sessionId, cdpClient); | ||
return cdpClient; | ||
} | ||
} | ||
exports.CdpConnection = CdpConnection; | ||
//# sourceMappingURL=CdpConnection.js.map |
@@ -49,15 +49,13 @@ "use strict"; | ||
this.#logger?.(ProcessingQueue.LOGGER_PREFIX, 'Processing event:', name); | ||
if (entryPromise !== undefined) { | ||
await entryPromise | ||
.then((entry) => { | ||
if (entry.kind === 'error') { | ||
this.#logger?.(log_js_1.LogType.debugError, 'Event threw before sending:', entry.error.message, entry.error.stack); | ||
return; | ||
} | ||
return this.#processor(entry.value); | ||
}) | ||
.catch((error) => { | ||
this.#logger?.(log_js_1.LogType.debugError, 'Event was not processed:', error?.message); | ||
}); | ||
} | ||
await entryPromise | ||
.then((entry) => { | ||
if (entry.kind === 'error') { | ||
this.#logger?.(log_js_1.LogType.debugError, 'Event threw before sending:', entry.error.message, entry.error.stack); | ||
return; | ||
} | ||
return this.#processor(entry.value); | ||
}) | ||
.catch((error) => { | ||
this.#logger?.(log_js_1.LogType.debugError, 'Event was not processed:', error?.message); | ||
}); | ||
} | ||
@@ -64,0 +62,0 @@ this.#isProcessing = false; |
{ | ||
"name": "chromium-bidi", | ||
"version": "0.4.32", | ||
"version": "0.4.33", | ||
"description": "An implementation of the WebDriver BiDi protocol for Chromium implemented as a JavaScript layer translating between BiDi and CDP, running inside a Chrome tab.", | ||
@@ -9,3 +9,2 @@ "scripts": { | ||
"clean": "rimraf lib .eslintcache .wireit", | ||
"local-http-server": "python3 tools/run_local_http_server.py", | ||
"e2e-headful": "wireit", | ||
@@ -17,3 +16,3 @@ "e2e-headless": "wireit", | ||
"format": "npm run pre-commit --", | ||
"pre-commit": "pre-commit run --all-files", | ||
"pre-commit": "pre-commit run --hook-stage manual --all-files", | ||
"prepare": "wireit", | ||
@@ -51,3 +50,3 @@ "prettier": "prettier --write .", | ||
"e2e-headful": { | ||
"command": "python3 -m pytest", | ||
"command": "pipenv run python -m pytest --ignore=tests/input", | ||
"dependencies": [ | ||
@@ -62,3 +61,3 @@ "server-headful" | ||
"e2e-headless": { | ||
"command": "python3 -m pytest", | ||
"command": "pipenv run python -m pytest", | ||
"dependencies": [ | ||
@@ -156,3 +155,6 @@ "server-headless" | ||
"files": [ | ||
"tools/run-wpt.mjs" | ||
"tools/run-wpt.mjs", | ||
"wpt/tools/webdriver/**/*.py", | ||
"wpt/webdriver/tests/**/*.py", | ||
"wpt-metadata/**/*.ini" | ||
], | ||
@@ -166,3 +168,7 @@ "dependencies": [ | ||
"files": [ | ||
"tools/runWPTAll.sh" | ||
"tools/run-wpt.mjs", | ||
"tools/runWPTAll.sh", | ||
"wpt/tools/webdriver/**/*.py", | ||
"wpt/webdriver/tests/**/*.py", | ||
"wpt-metadata/**/*.ini" | ||
], | ||
@@ -190,31 +196,31 @@ "dependencies": [ | ||
"devDependencies": { | ||
"@actions/core": "1.10.0", | ||
"@puppeteer/browsers": "1.5.0", | ||
"@rollup/plugin-commonjs": "25.0.4", | ||
"@rollup/plugin-node-resolve": "15.2.1", | ||
"@rollup/plugin-terser": "0.4.3", | ||
"@actions/core": "1.10.1", | ||
"@puppeteer/browsers": "1.7.1", | ||
"@rollup/plugin-commonjs": "25.0.7", | ||
"@rollup/plugin-node-resolve": "15.2.3", | ||
"@rollup/plugin-terser": "0.4.4", | ||
"@types/argparse": "2.0.11", | ||
"@types/chai": "4.3.5", | ||
"@types/chai": "4.3.8", | ||
"@types/chai-as-promised": "7.1.6", | ||
"@types/debug": "4.1.8", | ||
"@types/mocha": "10.0.1", | ||
"@types/node": "20.4.6", | ||
"@types/sinon": "10.0.16", | ||
"@types/websocket": "1.0.5", | ||
"@types/ws": "8.5.5", | ||
"@typescript-eslint/eslint-plugin": "6.5.0", | ||
"@typescript-eslint/parser": "6.7.3", | ||
"@types/debug": "4.1.9", | ||
"@types/mocha": "10.0.2", | ||
"@types/node": "20.8.6", | ||
"@types/sinon": "10.0.19", | ||
"@types/websocket": "1.0.7", | ||
"@types/ws": "8.5.7", | ||
"@typescript-eslint/eslint-plugin": "6.8.0", | ||
"@typescript-eslint/parser": "6.8.0", | ||
"argparse": "2.0.1", | ||
"chai": "4.3.7", | ||
"chai": "4.3.10", | ||
"chai-as-promised": "7.1.1", | ||
"chai-exclude": "2.1.0", | ||
"debug": "4.3.4", | ||
"devtools-protocol": "0.0.1208070", | ||
"eslint": "8.50.0", | ||
"eslint-config-prettier": "8.10.0", | ||
"devtools-protocol": "0.0.1213968", | ||
"eslint": "8.51.0", | ||
"eslint-config-prettier": "9.0.0", | ||
"eslint-plugin-import": "2.28.1", | ||
"eslint-plugin-mocha": "10.1.0", | ||
"eslint-plugin-prettier": "5.0.0", | ||
"eslint-plugin-mocha": "10.2.0", | ||
"eslint-plugin-prettier": "5.0.1", | ||
"eslint-plugin-promise": "6.1.1", | ||
"gts": "5.0.0", | ||
"gts": "5.2.0", | ||
"mocha": "10.2.0", | ||
@@ -224,14 +230,14 @@ "nyc": "15.1.0", | ||
"prettier": "3.0.3", | ||
"rimraf": "5.0.1", | ||
"rollup": "3.27.0", | ||
"sinon": "15.2.0", | ||
"rimraf": "5.0.5", | ||
"rollup": "3.29.4", | ||
"sinon": "16.1.0", | ||
"source-map-support": "0.5.21", | ||
"terser": "5.19.2", | ||
"tslib": "2.6.1", | ||
"typescript": "5.1.6", | ||
"terser": "5.22.0", | ||
"tslib": "2.6.2", | ||
"typescript": "5.2.2", | ||
"websocket": "1.0.34", | ||
"wireit": "0.10.0", | ||
"ws": "8.13.0", | ||
"wireit": "0.14.0", | ||
"ws": "8.14.2", | ||
"yargs": "17.7.2", | ||
"zod": "3.22.2" | ||
"zod": "3.22.4" | ||
}, | ||
@@ -238,0 +244,0 @@ "dependencies": { |
@@ -250,6 +250,7 @@ # WebDriver BiDi for Chromium [![chromium-bidi on npm](https://img.shields.io/npm/v/chromium-bidi)](https://www.npmjs.com/package/chromium-bidi) | ||
Python 3.6+ and some dependencies are required: | ||
Python 3.10+ and some dependencies are required: | ||
```sh | ||
python3 -m pip install --user -r tests/requirements.txt | ||
python -m pip install --user pipenv | ||
pipenv install | ||
``` | ||
@@ -283,9 +284,9 @@ | ||
```sh | ||
python3 tools/run_local_http_server.py | ||
pipenv run local_http_server | ||
``` | ||
or use npm: | ||
...or directly: | ||
```sh | ||
npm run local-http-server | ||
python tests/tools/local_http_server.py | ||
``` | ||
@@ -459,3 +460,3 @@ | ||
```shell | ||
third_party/blink/tools/blink_tool.py update-metadata --build="linux-blink-rel" | ||
third_party/blink/tools/blink_tool.py update-metadata --build="linux-blink-rel" --verbose | ||
``` | ||
@@ -462,0 +463,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
3995575
228
74307
465