googlechromelabs / chromium-bidi Goto Github PK
View Code? Open in Web Editor NEWImplementation of WebDriver BiDi for Chromium
Home Page: https://googlechromelabs.github.io/chromium-bidi/
License: Apache License 2.0
Implementation of WebDriver BiDi for Chromium
Home Page: https://googlechromelabs.github.io/chromium-bidi/
License: Apache License 2.0
After #64 and #65 are done, there will be no need in having the globalThis.__webdriver_objectCache
, so it should be deprecated.
Clients embedding the mapper should get an optimized bundle.
Cross-browser e2e scenario of
This includes
We'll need a way to connect a CdpClient to a different CDP target than the browser target. In other words, support the "flat" mode of the protocol where multiple CDP sessions may share a connection and use the "sessionId" property to route messages to a particular session.
This is already used in mapperServer.ts to create and communicate with the mapper tab, and we will likely need it later to attach to related targets such as OOPIFs or workers.
Proposed API: Add a new method to CdpClient:
public attachToSession(sessionId: string): CdpClient
Given an existing CdpClient (e.g. the initial browser client), calling this method returns a new CdpClient that shares the same transport and can be used to send messages to or receive events from the given session.
Cross-browser e2e scenario of navigating + taking a screenshot.
Includes:
Cross-browser e2e scenario of navigating + printing the page to PDF.
Includes:
The BrowsingContextProcessor is using attachedToTarget and detachedFromTarget to track known browsing contexts and fire contextCreated and contextDestroyed events.
These events are intended to track when a CDP client attaches to or detaches from a Target. This may not always map 1:1 with target creation and target destruction. For example, there can be multiple sessions attached to a Target, some may detach and re-attach, and the target doesn't necessarily go away once all sessions have ended.
This tracks updating BrowsingContextProcessor to use targetCreated/targetDestroyed instead. Note that we're already using targetInfoChanged which is in the same "family" of events as targetCreated/targetDestroyed.
Specification bases serialization logic on the JS internal slots. E.g. value has a [[DateValue]] internal slot.
In JS there is no way to implement this logic. Current BiDi implementation is based on checking the prototypes, which can lead to incorrect or unwanted results.
The only way to implement the serialization properly according to the spec is to move it to CDP level by adding a field bidiValue
to the CDP Runtime.RemoteObject
and a flag generateBiDiValue
to the CDP Runtime.callFunctionOn
method. On the CDP level there is an access to all the internals of the V8, and implementation can be done according to spec.
In the test case test_consoleLog_logEntryAddedEventEmitted, the line number returned from Bidi server starts from 1. Based on CDP definition of Runtime.CallFrame (link), the lineNumber should start from 0.
The WPT tests within this repo are currently all disabled.
Also, we should make sure the results are reported correctly to https://wpt.fyi/results/webdriver/tests/bidi?label=master&label=experimental&aligned&q=webdriver, i.e. by integrating with ChromeDriver.
Actual: the rolled-up Mapper script /src/.build/bidiMapper/mapper.js
has a size of 748K
, and the vast majority of the file is CDP string literals describing CDP methods, which are added for development convenience and are required for the functionality.
Removing those definitions reduces the size of the plain /src/.build/bidiMapper/mapper.js
to 68K
, and minimizing afterwards leads to only 28K
source size.
Expected: the rolled-up Mapper script /src/.build/bidiMapper/mapper.js
doesn't have unnecessary string literals and has a size of ~ 30K
.
Use the scripts at https://github.com/ChromeDevTools/devtools-protocol to generate a strongly-typed CDP API.
Consider adding filtering CDP.receivedEvent
events by session/method/etc in BiDi+
.
WebDriver BiDi-powered Puppeteer prototype capable of running a basic e2e testing scenario in Chrome and Firefox.
CDP.receivedEvent
events by session/method/etc in BiDi+
.
src/bidiMapper/domains/context/context.ts
Each time Runtime.executionContextCreated
event raised, Context
should keep the executionContextId
and use it to run `Runtime. callFunctionOn .
https://istanbul.js.org/ is the way to go for TS/JS for tests.
There's also https://www.npmjs.com/package/typescript-coverage-report which is a complement, for type annotations.
src/bidiMapper/scripts/eval.es
Cross-browser e2e scenario of loading a page with images blocked using request interception.
Includes:
To generate random Object IDs, proper method should be used, like:
chromium-bidi/src/bidiMapper/scripts/eval.es
Line 109 in 7f4df19
Minimal cross-browser e2e test example running in Chrome and Firefox, using raw WebDriver BiDi protocol commands & events.
Includes:
Implement ReadinessState = complete
parameter of the browsingContext.navigate
command.
https://w3c.github.io/webdriver-bidi/#command-browsingContext-navigate
With Firefox Nighty:
$ ./firefox --remote-debugging-port=9222
WebDriver BiDi listening on ws://localhost:9222
DevTools listening on ws://localhost:9222/devtools/browser/6cf65b2b-54e9-444e-a36e-0c04f12b47c9
…
$ # in another terminal / tab
$ PORT=9222 python3 examples/cross-browser.py
Traceback (most recent call last):
File "~/projects/chromium-bidi/examples/cross-browser.py", line 150, in <module>
result = loop.run_until_complete(main())
File "~/homebrew/Cellar/[email protected]/3.9.9/Frameworks/Python.framework/Versions/3.9/lib/python3.9/asyncio/base_events.py", line 642, in run_until_complete
return future.result()
File "~/projects/chromium-bidi/examples/cross-browser.py", line 53, in main
websocket = await get_websocket()
File "~/projects/chromium-bidi/examples/cross-browser.py", line 28, in get_websocket
return await websockets.connect(url)
File "~/Library/Python/3.9/lib/python/site-packages/websockets/client.py", line 542, in __await_impl__
await protocol.handshake(
File "~/Library/Python/3.9/lib/python/site-packages/websockets/client.py", line 296, in handshake
raise InvalidStatusCode(status_code)
websockets.exceptions.InvalidStatusCode: server rejected WebSocket connection: HTTP 200
We should figure out what’s going on here.
Currently, BigInt is serialized as {"type":"bigint","value":"12345678901234567168n"}
with a trailing n
at the end, while in the serialization spec written BigInt should be a result of calling BigInt.toString()
, which doesn't have a trailing n
character.
Implement browsingContext.contextCreated
.
Cross-browser e2e scenario of:
Includes:
There are a few instances of this pattern appearing in our code, used to listen for a single occurrence of an event:
const eventHandler = (params) => {
cdpClient.Page.removeEventListener('frameStoppedLoading', eventHandler);
// ... Do stuff ...
};
cdpClient.Page.addEventListener('frameStoppedLoading', eventHandler);
We could add a .once()
method to encapsulate this pattern instead:
const params = await cdpClient.Page.once('frameStoppedLoading');
// ... Do stuff ...
After #64 is implemented, there is no reason to keep the deserialization on the Mapper level.
CDP method Runtime.callFunctionOn
accepts Runtime.CallArgument
as an argument, which can be extended with a field bidiValue
.
This will reduce the overhead and will make deserialization and serialization unified.
Currently,
/session
endpoint on the server.Consider to implement reconnection like in classical WebDriver.
Open questions:
Related topics:
Chromium binary is needed to run BiDi server and to run tests against. There should be a way to download and keep up to date the Chromium version.
Idea: Support building/running the bidi mapper in two configurations:
exposeDevToolsProtocol
.Motivation:
Standalone mode would simplify development and testing of mapper code. The bidi server code and mapper code would all run in the same node process which simplifies debugging.
The _handleDetachedFromTargetEvent function in browsingContextProcessor.ts uses the targetId
parameter on the detachedFromTarget
event which is depreacted. The sessionId
parameter is recommended instead. This is likely because CDP supports multiple CDP sessions attached to the same Target (although we only use 1 CDP session for our purposes).
This tracks updating our code to use the sessionId
parameter here instead. We would likely need to maintain a map in the browsingContextProcessor mapping CDP session IDs to Context objects.
Instead of adding global bindings, pass bindings as deserializable arguments to
script.callFunction
.
...
The argument can be something like:{ type: "binding", value: "SOME_BINDING_NAME" }
, which will be deserialized to a callback. Calling that callback with any arguments will cause the BiDi event with those arguments like:
{ method: "script.bindingCalled", params: { arguments: [... remote values ...], name: "SOME_BINDING_NAME" } }
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.