This is an implementation of the WebDriver BiDi protocol with some extensions (BiDi+) for Chromium, implemented as a JavaScript layer translating between BiDi and CDP, running inside a Chrome tab.
Current status can be checked at WPT WebDriver BiDi status.
"BiDi+" is an extension of the WebDriver BiDi protocol. In addition to WebDriver BiDi it has:
CdpSendCommandCommand = {
method: "cdp.sendCommand",
params: ScriptEvaluateParameters,
}
CdpSendCommandParameters = {
method: text,
params: any,
session?: text,
}
CdpSendCommandResult = {
result: any,
session: text,
}
The command runs the described CDP command and returns the result.
CdpGetSessionCommand = {
method: "cdp.sendCommand",
params: ScriptEvaluateParameters,
}
CdpGetSessionParameters = {
context: BrowsingContext,
}
CdpGetSessionResult = {
session: text,
}
The command returns the default CDP session for the selected browsing context.
CdpEventReceivedEvent = {
method: "cdp.<CDP Event Name>",
params: CdpEventReceivedParameters,
}
CdpEventReceivedParameters = {
event: text,
params: any,
session: text,
}
The event contains a CDP event.
Each command can be extended with a channel
:
Command = {
id: js-uint,
channel?: text,
CommandData,
Extensible,
}
If provided and non-empty string, the very same channel
is added to the response:
CommandResponse = {
id: js-uint,
channel?: text,
result: ResultData,
Extensible,
}
ErrorResponse = {
id: js-uint / null,
channel?: text,
error: ErrorCode,
message: text,
?stacktrace: text,
Extensible
}
When client uses
commands session.subscribe
and session.unsubscribe
with channel
, the subscriptions are handled per channel, and the corresponding
channel
filed is added to the event message:
Event = {
channel?: text,
EventData,
Extensible,
}
This is a Node.js project, so install dependencies as usual:
npm install
We use cddlconv to generate our WebDriverBidi types before building.
- Install Rust.
- Run
cargo install --git https://github.com/jrandolf/cddlconv.git cddlconv
Refer to the documentation at .pre-commit-config.yaml.
This will run the server on port 8080
:
npm run server
Use the PORT=
environment variable or --port=
argument to run it on another port:
PORT=8081 npm run server
npm run server -- --port=8081
Use the DEBUG
environment variable to see debug info:
DEBUG=* npm run server
Use the CLI argument --headless=false
to run browser in headful mode:
npm run server -- --headless=false
Use the CHANNEL=...
environment variable or --channel=...
argument with one of
the following values to run the specific Chrome channel: stable
,
beta
, canary
, dev
.
The requested Chrome version should be installed.
CHANNEL=dev npm run server
npm run server -- --channel=dev
Use the CLI argument --verbose
to have CDP events printed to the console. Note: you have to enable debugging output bidi:mapper:debug:*
as well.
DEBUG=bidi:mapper:debug:* npm run server -- --verbose
or
DEBUG=* npm run server -- --verbose
TODO: verify it works on Windows.
You can also run the server by using script ./runBiDiServer.sh
. It will write
output to the file log.txt
:
./runBiDiServer.sh --port=8081 --headless=false
Running:
npm run unit
The E2E tests are written using Python, in order to learn how to eventually do this in web-platform-tests.
Python 3.6+ and some dependencies are required:
python3 -m pip install --user -r tests/requirements.txt
The E2E tests require BiDi server running on the same host. By default, tests
try to connect to the port 8080
. The server can be run from the project root:
npm run e2e # alias to to e2e-headless
npm run e2e-headful
npm run e2e-headless
Use the PORT
environment variable to connect to another port:
PORT=8081 npm run e2e
Refer to examples/README.md.
WPT is added as a git submodule. To get run WPT tests:
git submodule update --init
cd wpt
Follow the System Setup instructions.
Follow
the hosts
File Setup
instructions.
./wpt make-hosts-file | sudo tee -a /etc/hosts
This must be run in a PowerShell session with Administrator privileges:
python wpt make-hosts-file | Out-File $env:SystemRoot\System32\drivers\etc\hosts -Encoding ascii -Append
If you are behind a proxy, you also need to make sure the domains above are excluded from your proxy lookups.
Set the BROWSER_BIN
environment variable to a Chrome, Edge or Chromium binary to launch.
For example, on macOS:
# Chrome
export BROWSER_BIN="/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary"
export BROWSER_BIN="/Applications/Google Chrome Dev.app/Contents/MacOS/Google Chrome Dev"
export BROWSER_BIN="/Applications/Google Chrome Beta.app/Contents/MacOS/Google Chrome Beta"
export BROWSER_BIN="/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
export BROWSER_BIN="/Applications/Chromium.app/Contents/MacOS/Chromium"
# Edge
export BROWSER_BIN="/Applications/Microsoft Edge Canary.app/Contents/MacOS/Microsoft Edge Canary"
export BROWSER_BIN="/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge"
https://www.google.com/chrome/dev/
Oneshot:
npm run build
Continuously:
npm run build --watch
npm run wpt -- webdriver/tests/bidi/
UPDATE_EXPECTATIONS=true npm run wpt -- webdriver/tests/bidi/
The architecture is described in the WebDriver BiDi in Chrome Context implementation plan .
There are 2 main modules:
- backend WS server in
src
. It runs webSocket server, and for each ws connection runs an instance of browser with BiDi Mapper. - front-end BiDi Mapper in
src/bidiMapper
. Gets BiDi commands from the backend, and map them to CDP commands.
The BiDi commands are processed in the src/bidiMapper/commandProcessor.ts
. To add a
new command, add it to _processCommand
, write and call processor for it.
We use release-please to automate releases. When a release should be done, check for the release PR in our pull requests and merge it.
-
Dry-run
npm publish --dry-run
-
Open a PR bumping the chromium-bidi version number in
package.json
for review:npm version patch -m 'chore: Release v%s' --no-git-tag-version
Instead of
patch
, useminor
ormajor
as needed. -
After the PR is reviewed, create a GitHub release specifying the tag name matching the bumped version. Our CI then automatically publishes the new release to npm based on the tag name.