Security News
JSR Working Group Kicks Off with Ambitious Roadmap and Plans for Open Governance
At its inaugural meeting, the JSR Working Group outlined plans for an open governance model and a roadmap to enhance JavaScript package management.
chromium-bidi
Advanced tools
An implementation of the WebDriver BiDi protocol for Chromium implemented as a JavaScript layer translating between BiDi and CDP, running inside a Chrome tab.
The chromium-bidi npm package provides a BiDi (Bidirectional) protocol implementation for Chromium-based browsers. It allows for remote control of the browser, enabling automation and interaction with web pages through a standardized protocol.
Browser Control
This feature allows you to launch a Chromium browser, navigate to a webpage, and interact with it. The code sample demonstrates launching the browser, opening a new page, navigating to 'https://example.com', printing the page title, and closing the browser.
const { chromiumBidi } = require('chromium-bidi');
(async () => {
const browser = await chromiumBidi.launch();
const page = await browser.newPage();
await page.goto('https://example.com');
console.log(await page.title());
await browser.close();
})();
Element Interaction
This feature allows you to interact with elements on a webpage. The code sample demonstrates launching the browser, opening a new page, navigating to 'https://example.com', selecting an 'h1' element, printing its text content, and closing the browser.
const { chromiumBidi } = require('chromium-bidi');
(async () => {
const browser = await chromiumBidi.launch();
const page = await browser.newPage();
await page.goto('https://example.com');
const element = await page.$('h1');
console.log(await element.textContent());
await browser.close();
})();
Screenshot Capture
This feature allows you to capture screenshots of web pages. The code sample demonstrates launching the browser, opening a new page, navigating to 'https://example.com', capturing a screenshot, and saving it as 'example.png'.
const { chromiumBidi } = require('chromium-bidi');
(async () => {
const browser = await chromiumBidi.launch();
const page = await browser.newPage();
await page.goto('https://example.com');
await page.screenshot({ path: 'example.png' });
await browser.close();
})();
Puppeteer is a Node library which provides a high-level API to control Chrome or Chromium over the DevTools Protocol. It is similar to chromium-bidi in that it allows for browser automation, but it uses the DevTools Protocol instead of the BiDi protocol.
Selenium WebDriver is a collection of language-specific bindings to drive a browser. It is widely used for browser automation and testing. Unlike chromium-bidi, Selenium WebDriver supports multiple browsers and is not limited to Chromium-based browsers.
Playwright is a Node library to automate Chromium, Firefox, and WebKit with a single API. It offers similar functionalities to chromium-bidi but supports multiple browser engines, making it more versatile for cross-browser testing.
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:
cdp.sendCommand
CdpSendCommandCommand = {
method: "cdp.sendCommand",
params: CdpSendCommandParameters,
}
CdpSendCommandParameters = {
method: text,
params: any,
session?: text,
}
CdpSendCommandResult = {
result: any,
session: text,
}
The command runs the described CDP command and returns the result.
cdp.getSession
CdpGetSessionCommand = {
method: "cdp.getSession",
params: CdpGetSessionParameters,
}
CdpGetSessionParameters = {
context: BrowsingContext,
}
CdpGetSessionResult = {
session: text,
}
The command returns the default CDP session for the selected browsing context.
cdp.resolveRealm
CdpResolveRealmCommand = {
method: "cdp.resolveRealm",
params: CdpResolveRealmParameters,
}
CdpResolveRealmParameters = {
realm: Script.Realm,
}
CdpResolveRealmResult = {
executionContextId: text,
}
The command returns resolves a BiDi realm to its CDP execution context ID.
cdp
CdpEventReceivedEvent = {
method: "cdp.<CDP Event Name>",
params: CdpEventReceivedParameters,
}
CdpEventReceivedParameters = {
event: text,
params: any,
session: text,
}
The event contains a CDP event.
channel
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,
}
npm
This is a Node.js project, so install dependencies as usual:
npm install
cargo
We use cddlconv to generate our WebDriverBidi types before building.
cargo install --git https://github.com/google/cddlconv.git cddlconv
Refer to the documentation at .pre-commit-config.yaml.
pre-commit install --hook-type pre-push
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 DEBUG_DEPTH
(default: 10
) environment variable to see debug deeply nested objects:
DEBUG_DEPTH=100 DEBUG=* npm run server
Use the CHANNEL=...
environment variable with one of the following values to run
the specific Chrome channel: stable
, beta
, canary
, dev
, local
. Default is
local
. The local
channel means the pinned in .browser
Chrome version will be
downloaded if it is not yet in cache. Otherwise, the requested Chrome version should
be installed.
CHANNEL=dev npm run server
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 npm run server
. It will write
output to the file log.txt
:
npm run server -- --port=8081 --headless=false
Sometimes it good to verify that a change will not affect thing downstream for other packages.
There is a useful puppeteer
label you can add to any PR to run Puppeteer test with your changes.
It will bundle chromium-bidi
and install it in Puppeteer project then run that package test.
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.10+ and some dependencies are required:
python -m pip install --user pipenv
pipenv install
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
This commands will run ./tools/run-e2e.mjs
, which will log the PyTest output to console,
Additionally the output is also recorded under ./logs/<DATE>.e2e.log
, this will contain
both the PyTest logs and in the event of FAILED
test all the Chromium-BiDi logs.
If you need to see the logs for all test run the command with VERBOSE=true
.
Simply pass npm run e2e -- tests/<PathOrFile>
and the e2e will run only the selected one.
You run a specific test by running npm run e2e -- -k <TestName>
.
Use CHROMEDRIVER
environment to run tests in chromedriver
instead of NodeJS runner:
CHROMEDRIVER=true npm run e2e
Use the PORT
environment variable to connect to another port:
PORT=8081 npm run e2e
Use the HEADLESS
to run the tests in headless (new or old) or headful modes.
Values: new
, old
, false
, default: new
.
HEADLESS=new npm run e2e
npm run e2e -- --snapshot-update
See https://github.com/tophat/syrupy for more information.
E2E tests use local http
server pytest-httpserver
, which is run
automatically with the tests. However,
sometimes it is useful to run the http server outside the test
case, for example for manual debugging. This can be done by running:
pipenv run local_http_server
...or directly:
python tests/tools/local_http_server.py
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.
hosts
fileFollow
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.
BROWSER_BIN
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:
src
. It runs webSocket server, and for each ws connection
runs an instance of browser with BiDi Mapper.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.
npm
releaseWe 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
, use minor
or major
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.
This section assumes you already have a Chromium set-up locally, and knowledge on how to submit changes to the repo. Otherwise submit an issue for a project maintainer.
src/
.third_party/bidimapper/pull.sh
third_party/bidimapper/build.sh
Submit a CL with bug chromedriver:4226
.
Regenerate WPT expectations or baselines:
4.1. Trigger a build and test run:
third_party/blink/tools/blink_tool.py rebaseline-cl --build="linux-blink-rel" --verbose
4.2. Once the test completes on the builder, rerun that command to update the baselines. Update test expectations if there are any crashes or timeouts. Commit the changes (if any), and upload the new patch to the CL.
Add appropriate reviewers or comment the CL link on the PR.
FAQs
An implementation of the WebDriver BiDi protocol for Chromium implemented as a JavaScript layer translating between BiDi and CDP, running inside a Chrome tab.
We found that chromium-bidi demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
At its inaugural meeting, the JSR Working Group outlined plans for an open governance model and a roadmap to enhance JavaScript package management.
Security News
Research
An advanced npm supply chain attack is leveraging Ethereum smart contracts for decentralized, persistent malware control, evading traditional defenses.
Security News
Research
Attackers are impersonating Sindre Sorhus on npm with a fake 'chalk-node' package containing a malicious backdoor to compromise developers' projects.