From 1c08cbec50d06014b5ec1571011a8d030b31d3d2 Mon Sep 17 00:00:00 2001 From: Maksim Sadym Date: Thu, 7 Oct 2021 09:15:27 +0000 Subject: [PATCH] Command typification. --- src/bidiMapper/bidiProtocolTypes.ts | 78 +++++++++++++++++-- src/bidiMapper/commandProcessor.ts | 49 ++++++++---- .../context/browsingContextProcessor.ts | 15 ++-- tests/test_bidi.py | 22 ++++-- 4 files changed, 131 insertions(+), 33 deletions(-) diff --git a/src/bidiMapper/bidiProtocolTypes.ts b/src/bidiMapper/bidiProtocolTypes.ts index 21e3f34140..4c1d08248b 100644 --- a/src/bidiMapper/bidiProtocolTypes.ts +++ b/src/bidiMapper/bidiProtocolTypes.ts @@ -2,6 +2,7 @@ export namespace CommonDataTypes { // TODO sadym: declare `RemoteValue` properly according to // https://w3c.github.io/webdriver-bidi/#type-common-RemoteValue. export type RemoteValue = any; + export type EmptyParams = {}; export type ExceptionDetails = { columnNumber: number; @@ -10,9 +11,11 @@ export namespace CommonDataTypes { stackTrace: StackTrace; text: string; }; + export type StackTrace = { callFrames: StackFrame[]; }; + export type StackFrame = { url: string; functionName: string; @@ -20,14 +23,22 @@ export namespace CommonDataTypes { columnNumber: number; }; } + export namespace Script { - export type RealTarget = { + export type RealmTarget = { // TODO sadym: implement. }; + export type ContextTarget = { context: BrowsingContext.BrowsingContext; }; - export type Target = ContextTarget | RealTarget; + + export type Target = ContextTarget | RealmTarget; + + export type ScriptEvaluateCommand = { + method: 'script.evaluate'; + params: ScriptEvaluateParameters; + }; export type ScriptExceptionResult = { exceptionDetails: CommonDataTypes.ExceptionDetails; @@ -48,6 +59,11 @@ export namespace Script { }; export namespace PROTO { + export type ScriptInvokeCommand = { + method: 'PROTO.script.invoke'; + params: ScriptInvokeParameters; + }; + export type ScriptInvokeParameters = { functionDeclaration: string; args: InvokeArgument[]; @@ -74,9 +90,59 @@ export namespace Script { value: any; }; } +} - // https://w3c.github.io/webdriver-bidi/#module-browsingContext - export namespace BrowsingContext { - export type BrowsingContext = string; - } +// https://w3c.github.io/webdriver-bidi/#module-browsingContext +export namespace BrowsingContext { + export type BrowsingContext = string; + + export type BrowsingContextGetTreeCommand = { + method: 'browsingContext.getTree'; + params: BrowsingContextGetTreeParameters; + }; + + export type BrowsingContextGetTreeParameters = { + maxDepth?: number; + parent?: BrowsingContext; + }; + + export type BrowsingContextGetTreeResult = { + contexts: BrowsingContextInfoList; + }; + + export type BrowsingContextInfoList = BrowsingContextInfo[]; + + export type BrowsingContextInfo = { + context: BrowsingContext; + parent?: BrowsingContext; + url: string; + children: BrowsingContextInfoList; + }; + + // `browsingContext.create` + export type BrowsingContextCreateCommand = { + method: 'browsingContext.create'; + params: BrowsingContextCreateParameters; + }; + + export type BrowsingContextCreateType = 'tab' | 'window'; + + export type BrowsingContextCreateParameters = { + type: BrowsingContextCreateType; + }; + export type BrowsingContextCreateResult = { + context: BrowsingContext; + }; +} + +export namespace Session { + export type SessionStatusCommand = { + method: 'session.status'; + params: CommonDataTypes.EmptyParams; + }; + + export type SessionStatusResult = { + ready: boolean; + message: string; + }; } diff --git a/src/bidiMapper/commandProcessor.ts b/src/bidiMapper/commandProcessor.ts index 2822a58189..ce05442e20 100644 --- a/src/bidiMapper/commandProcessor.ts +++ b/src/bidiMapper/commandProcessor.ts @@ -20,7 +20,7 @@ import { BrowsingContextProcessor } from './domains/context/browsingContextProce import { Context } from './domains/context/context'; import { Protocol } from 'devtools-protocol'; import { BidiCommandMessage, IBidiServer } from './utils/bidiServer'; -import { Script } from './bidiProtocolTypes'; +import { BrowsingContext, Script, Session } from './bidiProtocolTypes'; export class CommandProcessor { private _browserCdpClient: CdpClient; @@ -114,16 +114,25 @@ export class CommandProcessor { this._bidiServer.sendMessage(errorResponse); } - private _targetToContext(target: Protocol.Target.TargetInfo) { + private _targetToContext( + target: Protocol.Target.TargetInfo + ): BrowsingContext.BrowsingContextInfo { return { context: target.targetId, - parent: target.openerId ? target.openerId : null, + parent: target.openerId ? target.openerId : undefined, url: target.url, + // TODO sadym: implement. + children: [], }; } - private async _process_browsingContext_getTree(params: object) { + private async _process_browsingContext_getTree( + commandData: BrowsingContext.BrowsingContextGetTreeCommand + ): Promise { const { targetInfos } = await this._browserCdpClient.Target.getTargets(); + // TODO sadym: implement. + if (commandData.params.maxDepth || commandData.params.parent) + throw new Error('not implemented yet'); const contexts = targetInfos // Don't expose any information about the tab with Mapper running. .filter(this._isValidTarget) @@ -138,7 +147,9 @@ export class CommandProcessor { return {}; } - private _process_session_status = async function (params: object) { + private _process_session_status = async function ( + commandData: Session.SessionStatusCommand + ): Promise { return { ready: true, message: 'ready' }; }; @@ -148,6 +159,7 @@ export class CommandProcessor { params: context.toBidi(), }); } + private async _onContextDestroyed(context: Context) { await this._bidiServer.sendMessage({ method: 'browsingContext.contextDestroyed', @@ -158,21 +170,25 @@ export class CommandProcessor { private async _processCommand(commandData: BidiCommandMessage) { switch (commandData.method) { case 'session.status': - return await this._process_session_status(commandData.params); + return await this._process_session_status( + commandData as Session.SessionStatusCommand + ); case 'browsingContext.getTree': - return await this._process_browsingContext_getTree(commandData.params); + return await this._process_browsingContext_getTree( + commandData as BrowsingContext.BrowsingContextGetTreeCommand + ); case 'script.evaluate': return await this._contextProcessor.process_script_evaluate( - commandData.params as Script.ScriptEvaluateParameters + commandData as Script.ScriptEvaluateCommand + ); + case 'browsingContext.create': + return await this._contextProcessor.process_createContext( + commandData as BrowsingContext.BrowsingContextCreateCommand ); case 'PROTO.script.invoke': return await this._contextProcessor.process_PROTO_script_invoke( - commandData.params as Script.PROTO.ScriptInvokeParameters - ); - case 'PROTO.browsingContext.createContext': - return await this._contextProcessor.process_createContext( - commandData.params + commandData as Script.PROTO.ScriptInvokeCommand ); case 'DEBUG.Page.close': @@ -193,9 +209,10 @@ export class CommandProcessor { }; this._bidiServer.sendMessage(response); - } catch (e: any) { - console.error(e); - this._respondWithError(message, 'unknown error', e.message); + } catch (e) { + const error = e as Error; + console.error(error); + this._respondWithError(message, 'unknown error', error.message); } }; } diff --git a/src/bidiMapper/domains/context/browsingContextProcessor.ts b/src/bidiMapper/domains/context/browsingContextProcessor.ts index 891c6a0b60..e895e835ba 100644 --- a/src/bidiMapper/domains/context/browsingContextProcessor.ts +++ b/src/bidiMapper/domains/context/browsingContextProcessor.ts @@ -18,7 +18,7 @@ import { log } from '../../../utils/log'; import { CdpConnection } from '../../../cdp'; import { Context } from './context'; -import { Script } from '../../bidiProtocolTypes'; +import { BrowsingContext, Script } from '../../bidiProtocolTypes'; import Protocol from 'devtools-protocol'; const logContext = log('context'); @@ -122,7 +122,10 @@ export class BrowsingContextProcessor { } } - async process_createContext(params: any): Promise { + async process_createContext( + commandData: BrowsingContext.BrowsingContextCreateCommand + ): Promise { + const params = commandData.params; return new Promise(async (resolve) => { let targetId: string; @@ -147,15 +150,16 @@ export class BrowsingContextProcessor { browserCdpClient.Target.on('attachedToTarget', onAttachedToTarget); const result = await browserCdpClient.Target.createTarget({ - url: params.url, + url: 'about:blank', }); targetId = result.targetId; }); } async process_script_evaluate( - params: Script.ScriptEvaluateParameters + commandData: Script.ScriptEvaluateCommand ): Promise { + const params = commandData.params; const context = this._getKnownContext( (params.target as Script.ContextTarget).context ); @@ -166,8 +170,9 @@ export class BrowsingContextProcessor { } async process_PROTO_script_invoke( - params: Script.PROTO.ScriptInvokeParameters + commandData: Script.PROTO.ScriptInvokeCommand ): Promise { + const params = commandData.params; const context = this._getKnownContext( (params.target as Script.ContextTarget).context ); diff --git a/tests/test_bidi.py b/tests/test_bidi.py index 3735375f19..d3b0751e6a 100644 --- a/tests/test_bidi.py +++ b/tests/test_bidi.py @@ -153,9 +153,20 @@ async def test_getTree_contextReturned(websocket): "result": { "contexts": [{ "context": contextID, - "parent": None, + "children": [], "url": "about:blank"}]}} +@pytest.mark.asyncio +# Not implemented yet. +async def ignore_test_getTreeWithGivenParent_contextReturned(websocket): + ignore = True + # TODO sadym: implement + +@pytest.mark.asyncio +# Not implemented yet. +async def ignore_test_getTreeWithNestedContexts_contextReturned(websocket): + ignore = True + # TODO sadym: implement @pytest.mark.asyncio # Not implemented yet. @@ -163,9 +174,8 @@ async def _ignore_test_createContext_eventContextCreatedEmittedAndContextCreated # Send command. command = { "id": 9, - "method": "PROTO.browsingContext.createContext", - "params": { - "url": "data:text/html,

test

"}} + "method": "browsingContext.create", + "params": {}} await send_JSON_command(websocket, command) # Assert "browsingContext.contextCreated" event emitted. @@ -176,7 +186,7 @@ async def _ignore_test_createContext_eventContextCreatedEmittedAndContextCreated "params": { "context":contextID, "parent": None, - "url": "data:text/html,

test

"}} + "url": ""}} # Assert command done. resp = await read_JSON_message(websocket) @@ -185,7 +195,7 @@ async def _ignore_test_createContext_eventContextCreatedEmittedAndContextCreated "result": { "context": contextID, "parent": None, - "url": "data:text/html,

test

"}} + "url": ""}} @pytest.mark.asyncio # Not implemented yet.