blob: a33f10a31d2a6369722a0b4cab53997585870681 [file] [log] [blame] [view]
Randolfb0fe9c12023-03-06 14:03:481# WebDriver BiDi for Chromium [![chromium-bidi on npm](https://img.shields.io/npm/v/chromium-bidi)](https://www.npmjs.com/package/chromium-bidi)
2
Randolf55431462023-03-29 13:00:363## CI status
Randolfb0fe9c12023-03-06 14:03:484
Randolf55431462023-03-29 13:00:365![E2E Tests](https://github.com/GoogleChromeLabs/chromium-bidi/actions/workflows/e2e.yml/badge.svg)
6![Unit Tests](https://github.com/GoogleChromeLabs/chromium-bidi/actions/workflows/unit.yml/badge.svg)
Randolf Jungbcb3bc82023-06-26 16:30:147![WPT Tests](https://github.com/GoogleChromeLabs/chromium-bidi/actions/workflows/wpt.yml/badge.svg)
Randolf55431462023-03-29 13:00:368
Randolf55431462023-03-29 13:00:369![Pre-commit](https://github.com/GoogleChromeLabs/chromium-bidi/actions/workflows/pre-commit.yml/badge.svg)
Randolfb0fe9c12023-03-06 14:03:4810
11This is an implementation of the
12[WebDriver BiDi](https://w3c.github.io/webdriver-bidi/) protocol with some
13extensions (**BiDi+**)
14for Chromium, implemented as a JavaScript layer translating between BiDi and CDP,
15running inside a Chrome tab.
16
17Current status can be checked
18at [WPT WebDriver BiDi status](https://wpt.fyi/results/webdriver/tests/bidi).
19
20## BiDi+
21
22**"BiDi+"** is an extension of the WebDriver BiDi protocol. In addition to [WebDriver BiDi](https://w3c.github.io/webdriver-bidi/) it has:
23
Alex Rudenkofd8226a2025-01-17 09:14:2024### Command `goog:cdp.sendCommand`
Randolfb0fe9c12023-03-06 14:03:4825
26```cddl
27CdpSendCommandCommand = {
Alex Rudenkofd8226a2025-01-17 09:14:2028 method: "goog:cdp.sendCommand",
Alex Rudenko55d5f672024-08-02 12:04:0029 params: CdpSendCommandParameters,
Randolfb0fe9c12023-03-06 14:03:4830}
31
32CdpSendCommandParameters = {
Alex Rudenko1552f2b2023-07-11 11:18:3233 method: text,
34 params: any,
35 session?: text,
Randolfb0fe9c12023-03-06 14:03:4836}
37
38CdpSendCommandResult = {
39 result: any,
Alex Rudenko1552f2b2023-07-11 11:18:3240 session: text,
Randolfb0fe9c12023-03-06 14:03:4841}
42```
43
44The command runs the
45described [CDP command](https://chromedevtools.github.io/devtools-protocol)
Alex Rudenko1552f2b2023-07-11 11:18:3246and returns the result.
Randolfb0fe9c12023-03-06 14:03:4847
Alex Rudenkofd8226a2025-01-17 09:14:2048### Command `goog:cdp.getSession`
Randolfb0fe9c12023-03-06 14:03:4849
50```cddl
51CdpGetSessionCommand = {
Alex Rudenkofd8226a2025-01-17 09:14:2052 method: "goog:cdp.getSession",
Alex Rudenko55d5f672024-08-02 12:04:0053 params: CdpGetSessionParameters,
Randolfb0fe9c12023-03-06 14:03:4854}
55
56CdpGetSessionParameters = {
57 context: BrowsingContext,
58}
59
60CdpGetSessionResult = {
Alex Rudenko1552f2b2023-07-11 11:18:3261 session: text,
Randolfb0fe9c12023-03-06 14:03:4862}
63```
64
65The command returns the default CDP session for the selected browsing context.
66
Alex Rudenkofd8226a2025-01-17 09:14:2067### Command `goog:cdp.resolveRealm`
Alex Rudenko5fda6462024-04-17 12:18:0368
69```cddl
70CdpResolveRealmCommand = {
Alex Rudenkofd8226a2025-01-17 09:14:2071 method: "goog:cdp.resolveRealm",
Alex Rudenko55d5f672024-08-02 12:04:0072 params: CdpResolveRealmParameters,
Alex Rudenko5fda6462024-04-17 12:18:0373}
74
75CdpResolveRealmParameters = {
76 realm: Script.Realm,
77}
78
79CdpResolveRealmResult = {
80 executionContextId: text,
81}
82```
83
84The command returns resolves a BiDi realm to its CDP execution context ID.
85
Alex Rudenkofd8226a2025-01-17 09:14:2086### Events `goog:cdp`
Randolfb0fe9c12023-03-06 14:03:4887
88```cddl
89CdpEventReceivedEvent = {
Alex Rudenkofd8226a2025-01-17 09:14:2090 method: "goog:cdp.<CDP Event Name>",
Alex Rudenko1552f2b2023-07-11 11:18:3291 params: CdpEventReceivedParameters,
Randolfb0fe9c12023-03-06 14:03:4892}
93
94CdpEventReceivedParameters = {
Alex Rudenko1552f2b2023-07-11 11:18:3295 event: text,
96 params: any,
97 session: text,
Randolfb0fe9c12023-03-06 14:03:4898}
99```
100
101The event contains a CDP event.
102
Adam Raineac00a7d2025-01-30 18:59:25103### Field `goog:channel`
Randolfb0fe9c12023-03-06 14:03:48104
Adam Raineac00a7d2025-01-30 18:59:25105Each command can be extended with a `goog:channel`:
Randolfb0fe9c12023-03-06 14:03:48106
107```cddl
108Command = {
109 id: js-uint,
Adam Raineac00a7d2025-01-30 18:59:25110 "goog:channel"?: text,
Randolfb0fe9c12023-03-06 14:03:48111 CommandData,
112 Extensible,
113}
114```
115
Adam Raineac00a7d2025-01-30 18:59:25116If provided and non-empty string, the very same `goog:channel` is added to the response:
Randolfb0fe9c12023-03-06 14:03:48117
118```cddl
119CommandResponse = {
120 id: js-uint,
Adam Raineac00a7d2025-01-30 18:59:25121 "goog:channel"?: text,
Randolfb0fe9c12023-03-06 14:03:48122 result: ResultData,
123 Extensible,
124}
125
126ErrorResponse = {
127 id: js-uint / null,
Adam Raineac00a7d2025-01-30 18:59:25128 "goog:channel"?: text,
Randolfb0fe9c12023-03-06 14:03:48129 error: ErrorCode,
130 message: text,
131 ?stacktrace: text,
132 Extensible
133}
134```
135
136When client uses
137commands [`session.subscribe`](https://w3c.github.io/webdriver-bidi/#command-session-subscribe)
138and [`session.unsubscribe`](https://w3c.github.io/webdriver-bidi/#command-session-unsubscribe)
Adam Raineac00a7d2025-01-30 18:59:25139with `goog:channel`, the subscriptions are handled per channel, and the corresponding
140`goog:channel` filed is added to the event message:
Randolfb0fe9c12023-03-06 14:03:48141
142```cddl
143Event = {
Adam Raineac00a7d2025-01-30 18:59:25144 "goog:channel"?: text,
Randolfb0fe9c12023-03-06 14:03:48145 EventData,
146 Extensible,
147}
148```
149
150## Dev Setup
151
152### `npm`
153
154This is a Node.js project, so install dependencies as usual:
155
156```sh
157npm install
158```
159
Randolf Jung3e526312023-08-08 06:20:39160### `cargo`
161
162<!-- TODO(jrandolf): Remove after binaries get published -->
163
Alex Rudenko09712c62024-11-21 09:06:05164We use [cddlconv](https://github.com/google/cddlconv) to generate our WebDriverBiDi types before building.
Randolf Jung3e526312023-08-08 06:20:39165
1661. Install [Rust](https://rustup.rs/).
Alex Rudenko662ce9c2023-08-29 08:05:301672. Run `cargo install --git https://github.com/google/cddlconv.git cddlconv`
Randolf Jung3e526312023-08-08 06:20:39168
Randolfb0fe9c12023-03-06 14:03:48169### pre-commit.com integration
170
171Refer to the documentation at [.pre-commit-config.yaml](.pre-commit-config.yaml).
172
Alex Rudenkof7ea7ab2023-10-24 09:40:51173```sh
174pre-commit install --hook-type pre-push
175```
176
Adam Raineac00a7d2025-01-30 18:59:25177Re-installing pre-commit locally:
178
179```
180pre-commit clean && pip install pre-commit
181```
182
Alex Rudenkof7ea7ab2023-10-24 09:40:51183### Starting WebDriver BiDi Server
Randolfb0fe9c12023-03-06 14:03:48184
185This will run the server on port `8080`:
186
187```sh
188npm run server
189```
190
191Use the `PORT=` environment variable or `--port=` argument to run it on another port:
192
193```sh
194PORT=8081 npm run server
195npm run server -- --port=8081
196```
197
198Use the `DEBUG` environment variable to see debug info:
199
200```sh
201DEBUG=* npm run server
202```
203
Alex Rudenko5fe99f82023-10-06 12:01:27204Use the `DEBUG_DEPTH` (default: `10`) environment variable to see debug deeply nested objects:
205
206```sh
207DEBUG_DEPTH=100 DEBUG=* npm run server
208```
209
Alex Rudenko5fda6462024-04-17 12:18:03210Use the `CHANNEL=...` environment variable with one of the following values to run
211the specific Chrome channel: `stable`, `beta`, `canary`, `dev`, `local`. Default is
212`local`. The `local` channel means the pinned in `.browser` Chrome version will be
213downloaded if it is not yet in cache. Otherwise, the requested Chrome version should
214be installed.
Randolfb0fe9c12023-03-06 14:03:48215
216```sh
Randolf55431462023-03-29 13:00:36217CHANNEL=dev npm run server
Randolf55431462023-03-29 13:00:36218```
219
Alex Rudenko1552f2b2023-07-11 11:18:32220Use the CLI argument `--verbose` to have CDP events printed to the console. Note: you have to enable debugging output `bidi:mapper:debug:*` as well.
Randolf55431462023-03-29 13:00:36221
222```sh
Alex Rudenko1552f2b2023-07-11 11:18:32223DEBUG=bidi:mapper:debug:* npm run server -- --verbose
Randolf55431462023-03-29 13:00:36224```
225
226or
227
228```sh
229DEBUG=* npm run server -- --verbose
Randolfb0fe9c12023-03-06 14:03:48230```
231
232### Starting on Linux and Mac
233
Randolf Jungbcb3bc82023-06-26 16:30:14234TODO: verify it works on Windows.
Randolfb0fe9c12023-03-06 14:03:48235
Randolf Jung3e526312023-08-08 06:20:39236You can also run the server by using `npm run server`. It will write
Randolfb0fe9c12023-03-06 14:03:48237output to the file `log.txt`:
238
239```sh
Randolf Jung3e526312023-08-08 06:20:39240npm run server -- --port=8081 --headless=false
Randolfb0fe9c12023-03-06 14:03:48241```
242
Alex Rudenko5fe99f82023-10-06 12:01:27243### Running with in other project
244
245Sometimes it good to verify that a change will not affect thing downstream for other packages.
246There is a useful `puppeteer` label you can add to any PR to run Puppeteer test with your changes.
247It will bundle `chromium-bidi` and install it in Puppeteer project then run that package test.
248
Randolfb0fe9c12023-03-06 14:03:48249## Running
250
251### Unit tests
252
253Running:
254
255```sh
Randolf Jungbcb3bc82023-06-26 16:30:14256npm run unit
Randolfb0fe9c12023-03-06 14:03:48257```
258
259### E2E tests
260
Alex Rudenkofd8226a2025-01-17 09:14:20261The e2e tests serve the following purposes:
262
2631. Brief checks of the scenarios (the detailed check is done in WPT)
2642. Test Chromium-specific behavior nuances
2653. Add a simple setup for engaging the specific command
266
267The E2E tests are written using Python, in order to more-or-less align with the web-platform-tests.
Randolfb0fe9c12023-03-06 14:03:48268
Alex Rudenko5fe99f82023-10-06 12:01:27269#### Installation
Randolfb0fe9c12023-03-06 14:03:48270
Alex Rudenkoaf11b7c2024-02-06 10:44:42271Python 3.10+ and some dependencies are required:
Randolfb0fe9c12023-03-06 14:03:48272
273```sh
Alex Rudenkoaf11b7c2024-02-06 10:44:42274python -m pip install --user pipenv
275pipenv install
Randolfb0fe9c12023-03-06 14:03:48276```
277
Alex Rudenko5fe99f82023-10-06 12:01:27278#### Running
Randolfb0fe9c12023-03-06 14:03:48279
280The E2E tests require BiDi server running on the same host. By default, tests
281try to connect to the port `8080`. The server can be run from the project root:
282
283```sh
Alex Rudenkod04dd452024-02-27 08:25:35284npm run e2e # alias to to e2e:headless
285npm run e2e:headful
286npm run e2e:headless
Randolfb0fe9c12023-03-06 14:03:48287```
288
Alex Rudenko5fda6462024-04-17 12:18:03289This commands will run `./tools/run-e2e.mjs`, which will log the PyTest output to console,
290Additionally the output is also recorded under `./logs/<DATE>.e2e.log`, this will contain
291both the PyTest logs and in the event of `FAILED` test all the Chromium-BiDi logs.
292
293If you need to see the logs for all test run the command with `VERBOSE=true`.
294
295Simply pass `npm run e2e -- tests/<PathOrFile>` and the e2e will run only the selected one.
296You run a specific test by running `npm run e2e -- -k <TestName>`.
297
298Use `CHROMEDRIVER` environment to run tests in `chromedriver` instead of NodeJS runner:
299
300```shell
301CHROMEDRIVER=true npm run e2e
302```
303
Randolfb0fe9c12023-03-06 14:03:48304Use the `PORT` environment variable to connect to another port:
305
306```sh
307PORT=8081 npm run e2e
308```
309
Alex Rudenko5fda6462024-04-17 12:18:03310Use the `HEADLESS` to run the tests in headless (new or old) or headful modes.
311Values: `new`, `old`, `false`, default: `new`.
312
313```sh
314HEADLESS=new npm run e2e
315```
316
Alex Rudenkoaf11b7c2024-02-06 10:44:42317#### Updating snapshots
318
319```sh
Alex Rudenkofd8226a2025-01-17 09:14:20320npm run e2e -- --snapshot-update true
Alex Rudenkoaf11b7c2024-02-06 10:44:42321```
322
323See https://github.com/tophat/syrupy for more information.
324
Alex Rudenkof7ea7ab2023-10-24 09:40:51325### Local http server
326
327E2E tests use local http
328server [`pytest-httpserver`](https://pytest-httpserver.readthedocs.io/), which is run
329automatically with the tests. However,
330sometimes it is useful to run the http server outside the test
331case, for example for manual debugging. This can be done by running:
332
333```sh
Alex Rudenkoaf11b7c2024-02-06 10:44:42334pipenv run local_http_server
Alex Rudenkof7ea7ab2023-10-24 09:40:51335```
336
Alex Rudenkoaf11b7c2024-02-06 10:44:42337...or directly:
Alex Rudenkof7ea7ab2023-10-24 09:40:51338
339```sh
Alex Rudenkoaf11b7c2024-02-06 10:44:42340python tests/tools/local_http_server.py
Alex Rudenkof7ea7ab2023-10-24 09:40:51341```
342
343### Examples
Randolfb0fe9c12023-03-06 14:03:48344
345Refer to [examples/README.md](examples/README.md).
346
347## WPT (Web Platform Tests)
348
349WPT is added as
350a [git submodule](https://git-scm.com/book/en/v2/Git-Tools-Submodules). To get run
351WPT tests:
352
353### Check out and setup WPT
354
355#### 1. Check out WPT
356
357```sh
358git submodule update --init
359```
360
361#### 2. Go to the WPT folder
362
363```sh
364cd wpt
365```
366
367#### 3. Set up virtualenv
368
369Follow the [_System
370Setup_](https://web-platform-tests.org/running-tests/from-local-system.html#system-setup)
371instructions.
372
373#### 4. Setup `hosts` file
374
375Follow
376the [`hosts` File Setup](https://web-platform-tests.org/running-tests/from-local-system.html#hosts-file-setup)
377instructions.
378
379##### 4.a On Linux, macOS or other UNIX-like system
380
381```sh
382./wpt make-hosts-file | sudo tee -a /etc/hosts
383```
384
385##### 4.b On **Windows**
386
387This must be run in a PowerShell session with Administrator privileges:
388
389```sh
390python wpt make-hosts-file | Out-File $env:SystemRoot\System32\drivers\etc\hosts -Encoding ascii -Append
391```
392
393If you are behind a proxy, you also need to make sure the domains above are excluded
394from your proxy lookups.
395
Randolf Jungbcb3bc82023-06-26 16:30:14396#### 5. Set `BROWSER_BIN`
Randolfb0fe9c12023-03-06 14:03:48397
Randolf Jungbcb3bc82023-06-26 16:30:14398Set the `BROWSER_BIN` environment variable to a Chrome, Edge or Chromium binary to launch.
Randolfb0fe9c12023-03-06 14:03:48399For example, on macOS:
400
401```sh
402# Chrome
Randolf Jungbcb3bc82023-06-26 16:30:14403export BROWSER_BIN="/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary"
404export BROWSER_BIN="/Applications/Google Chrome Dev.app/Contents/MacOS/Google Chrome Dev"
405export BROWSER_BIN="/Applications/Google Chrome Beta.app/Contents/MacOS/Google Chrome Beta"
406export BROWSER_BIN="/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
407export BROWSER_BIN="/Applications/Chromium.app/Contents/MacOS/Chromium"
Randolfb0fe9c12023-03-06 14:03:48408
409# Edge
Randolf Jungbcb3bc82023-06-26 16:30:14410export BROWSER_BIN="/Applications/Microsoft Edge Canary.app/Contents/MacOS/Microsoft Edge Canary"
411export BROWSER_BIN="/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge"
Randolfb0fe9c12023-03-06 14:03:48412```
413
414### Run WPT tests
415
416#### 1. Make sure you have Chrome Dev installed
417
418https://www.google.com/chrome/dev/
419
Randolf55431462023-03-29 13:00:36420#### 2. Build Chromedriver BiDi
Randolfb0fe9c12023-03-06 14:03:48421
422Oneshot:
423
424```sh
425npm run build
426```
427
428Continuously:
429
430```sh
Randolf Jungbcb3bc82023-06-26 16:30:14431npm run build --watch
Randolfb0fe9c12023-03-06 14:03:48432```
433
434#### 3. Run
435
436```sh
Randolf Jungbcb3bc82023-06-26 16:30:14437npm run wpt -- webdriver/tests/bidi/
Randolfb0fe9c12023-03-06 14:03:48438```
439
440### Update WPT expectations if needed
441
Randolfb0fe9c12023-03-06 14:03:48442```sh
Randolf Jungbcb3bc82023-06-26 16:30:14443UPDATE_EXPECTATIONS=true npm run wpt -- webdriver/tests/bidi/
Randolfb0fe9c12023-03-06 14:03:48444```
445
446## How does it work?
447
448The architecture is described in the
449[WebDriver BiDi in Chrome Context implementation plan](https://docs.google.com/document/d/1VfQ9tv0wPSnb5TI-MOobjoQ5CXLnJJx9F_PxOMQc8kY)
450.
451
452There are 2 main modules:
453
4541. backend WS server in `src`. It runs webSocket server, and for each ws connection
455 runs an instance of browser with BiDi Mapper.
4562. front-end BiDi Mapper in `src/bidiMapper`. Gets BiDi commands from the backend,
457 and map them to CDP commands.
458
Alex Rudenko5fe99f82023-10-06 12:01:27459## Contributing
Randolfb0fe9c12023-03-06 14:03:48460
461The BiDi commands are processed in the `src/bidiMapper/commandProcessor.ts`. To add a
462new command, add it to `_processCommand`, write and call processor for it.
463
464### Publish new `npm` release
465
Alex Rudenko09712c62024-11-21 09:06:05466#### Release branches
467
468`chromium-bidi` maintains release branches corresponding to Chrome releases. The
469branches are named using the following pattern: `releases/m$MAJOR_VERSION`.
470
471The new release branch is created as soon a new major browser version is
472published by the
473[update-browser-version](https://github.com/GoogleChromeLabs/chromium-bidi/blob/main/.github/workflows/update-browser-version.yml)
474job:
475
476- the PR created by this job should be marked as a feature and it should cause the
477 major package version to be bumped.
478- once the browser version is bumped, the commit preceding the version bump
479 should be used to create a release branch for major version pinned before the bump.
480
481Changes that need to be cherry-picked into the release branch should be marked
482as patches. Either major or minor version bumps are not allowed on the release
483branch.
484
485Example workflow:
486
487```mermaid
488gitGraph
489 commit id: "feat: featA"
490 commit id: "release: v0.5.0"
491 branch release/m129
492 checkout main
493 commit id: "feat: roll Chrome to M130 from 129"
494 commit id: "release: v0.6.0"
495 commit id: "fix: for m129"
496 checkout release/m129
497 cherry-pick id: "fix: for m129"
498 commit id: "release: v0.5.1 "
499```
500
501Currently, the releases from release branches are not automated.
502
Alex Rudenko1552f2b2023-07-11 11:18:32503#### Automatic release
Randolf Jungbcb3bc82023-06-26 16:30:14504
Alex Rudenko1552f2b2023-07-11 11:18:32505We use [release-please](https://github.com/googleapis/release-please) to automate releases. When a release should be done, check for the release PR in our [pull requests](https://github.com/GoogleChromeLabs/chromium-bidi/pulls) and merge it.
Randolf Jungbcb3bc82023-06-26 16:30:14506
507#### Manual release
508
5091. Dry-run
510
511 ```sh
512 npm publish --dry-run
513 ```
514
Randolf55431462023-03-29 13:00:365151. Open a PR bumping the chromium-bidi version number in `package.json` for review:
Randolfb0fe9c12023-03-06 14:03:48516
517 ```sh
Alex Rudenko1552f2b2023-07-11 11:18:32518 npm version patch -m 'chore: Release v%s' --no-git-tag-version
Randolfb0fe9c12023-03-06 14:03:48519 ```
520
521 Instead of `patch`, use `minor` or `major` [as needed](https://semver.org/).
522
Randolf55431462023-03-29 13:00:365231. After the PR is reviewed, [create a GitHub release](https://github.com/GoogleChromeLabs/chromium-bidi/releases/new) specifying the tag name matching the bumped version.
524 Our CI then automatically publishes the new release to npm based on the tag name.
Randolf Jung3e526312023-08-08 06:20:39525
526#### Roll into Chromium
527
Alex Rudenkob013f872023-09-29 05:56:03528This section assumes you already have a Chromium set-up locally,
529and knowledge on [how to submit changes to the repo](https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/contributing.md).
530Otherwise submit an issue for a project maintainer.
Randolf Jung3e526312023-08-08 06:20:39531
Alex Rudenkob013f872023-09-29 05:56:035321. Create a new branch in chromium `src/`.
5332. Update the mapper version:
Randolf Jung3e526312023-08-08 06:20:39534
Alex Rudenkob013f872023-09-29 05:56:03535```shell
Alex Rudenko09712c62024-11-21 09:06:05536third_party/bidimapper/roll_bidmapper
Randolf Jung3e526312023-08-08 06:20:39537```
538
Alex Rudenkofd8226a2025-01-17 09:14:205393. Submit a CL with bug `42323268` ([link](https://crbug.com/42323268)).
Alex Rudenkob013f872023-09-29 05:56:03540
Alex Rudenkoaf11b7c2024-02-06 10:44:425414. [Regenerate WPT expectations or baselines](https://chromium.googlesource.com/chromium/src/+/HEAD/docs/testing/run_web_platform_tests.md#test-expectations-and-baselines):
Alex Rudenkob013f872023-09-29 05:56:03542
Alex Rudenkoaf11b7c2024-02-06 10:44:42543 4.1. Trigger a build and test run:
Alex Rudenkob013f872023-09-29 05:56:03544
Alex Rudenkoaf11b7c2024-02-06 10:44:42545 ```shell
546 third_party/blink/tools/blink_tool.py rebaseline-cl --build="linux-blink-rel" --verbose
547 ```
548
549 4.2. Once the test completes on the builder, rerun that command to update the
550 baselines. Update test expectations if there are any crashes or timeouts.
551 Commit the changes (if any), and upload the new patch to the CL.
Alex Rudenkob013f872023-09-29 05:56:03552
5535. Add appropriate reviewers or comment the CL link on the PR.
Alex Rudenkofd8226a2025-01-17 09:14:20554
555## Adding new command
556
557Want to add a shiny new command to WebDriver BiDi for Chromium? Here's the playbook:
558
559### Prerequisites
560
561#### Specification
562
563The WebDriver BiDi [module](https://w3c.github.io/webdriver-bidi/#protocol-modules), [command](https://w3c.github.io/webdriver-bidi/#commands), or [event](https://w3c.github.io/webdriver-bidi/#events) must be specified either in the [WebDriver BiDi specification](https://w3c.github.io/webdriver-bidi) or as an extension in a separate specification (e.g., the [Permissions specification](https://www.w3.org/TR/permissions/#automation-webdriver-bidi)). The specification should include the command's type definitions in valid [CDDL](https://datatracker.ietf.org/doc/html/rfc8610) format.
564
565#### WPT wdspec tests
566
567You'll need tests to prove your command works as expected. These tests should be written using [WPT wdspec](https://web-platform-tests.org/writing-tests/wdspec.html) and submitted along with the spec itself. Don't forget to roll the WPT repo into the Mapper ([dependabot](https://github.com/GoogleChromeLabs/chromium-bidi/network/updates/10663151/jobs) can help, and you will likely need to tweak some expectations afterward).
568
569#### CDP implementation
570
571Make sure Chromium already has the CDP methods your command will rely on.
572
573### Update CDDL types
574
5751. If your command lives in a separate spec, add a link to that spec in the ["Build WebDriverBiDi types"](https://github.com/GoogleChromeLabs/chromium-bidi/blob/0f971303281aba1910786035facc5eb54a833232/.github/workflows/update-bidi-types.yml#L27) GitHub action (check out the ["bluetooth" pull request](https://github.com/GoogleChromeLabs/chromium-bidi/pull/2585) for an example).
5762. Run the ["Update WebdriverBiDi types"](https://github.com/GoogleChromeLabs/chromium-bidi/actions/workflows/update-bidi-types.yml) GitHub action. This will create a pull request with your new types. If you added a command, this PR will have a failing check complaining about a non-exhaustive switch statement:
577 > error: Switch is not exhaustive. Cases not matched: "{NEW_COMMAND_NAME}" @typescript-eslint/switch-exhaustiveness-check
5783. Update the created pull request. Add your new command to [`CommandProcessor.#processCommand`](https://github.com/GoogleChromeLabs/chromium-bidi/blob/0f971303281aba1910786035facc5eb54a833232/src/bidiMapper/CommandProcessor.ts#L140). For now, just have it throw an UnknownErrorException (see the [example](https://github.com/GoogleChromeLabs/chromium-bidi/pull/2647/files#diff-7f06ce28b8514fd75b759d217bff9f5a471b657bcf78bd893cc291c7945c1cacR169) for how to do this).
579
580```typescript
581case '{NEW_COMMAND_NAME}':
582 throw new UnknownErrorException(
583 `Method ${command.method} is not implemented.`,
584 );
585```
586
5874. Merge it! Standard PR process: create, review, merge.
588
589### Implement the new command
590
591[`CommandProcessor.#processCommand`](https://github.com/GoogleChromeLabs/chromium-bidi/blob/0f971303281aba1910786035facc5eb54a833232/src/bidiMapper/CommandProcessor.ts#L140) handles parsing parameters and running your command.
592
593#### (only if the new command has non-empty parameters) parse command parameters
594
595If your command has parameters, update the [`BidiCommandParameterParser`](https://github.com/GoogleChromeLabs/chromium-bidi/blob/0f971303281aba1910786035facc5eb54a833232/src/bidiMapper/BidiParser.ts#L31) and implement the parsing logic in [`BidiNoOpParser`](https://github.com/GoogleChromeLabs/chromium-bidi/blob/0f971303281aba1910786035facc5eb54a833232/src/bidiMapper/BidiNoOpParser.ts#L209), [`BidiParser`](https://github.com/GoogleChromeLabs/chromium-bidi/blob/0f971303281aba1910786035facc5eb54a833232/src/bidiTab/BidiParser.ts#L182) and [`protocol-parser`](https://github.com/GoogleChromeLabs/chromium-bidi/blob/0f971303281aba1910786035facc5eb54a833232/src/protocol-parser/protocol-parser.ts#L386). Look at the [example](https://github.com/GoogleChromeLabs/chromium-bidi/blob/0f971303281aba1910786035facc5eb54a833232/src/bidiMapper/BidiParser.ts#L97) for guidance.
596
597#### Implement the new command
598
599Write the core logic for your command in the appropriate domain processor. Again, [example](https://github.com/GoogleChromeLabs/chromium-bidi/blob/0f971303281aba1910786035facc5eb54a833232/src/bidiMapper/modules/permissions/PermissionsProcessor.ts#L32) is your friend.
600
601#### Call the module processor's method
602
603Call your new module processor method from `CommandProcessor.#processCommand`, passing in the parsed parameters. [Example](https://github.com/GoogleChromeLabs/chromium-bidi/blob/0f971303281aba1910786035facc5eb54a833232/src/bidiMapper/CommandProcessor.ts#L313).
604
605#### Add e2e tests
606
607Write end-to-end tests for your command, including the happy path and any edge cases that might trip things up. Focus on testing the code in the mapper.
608
609#### Update WPT expectations
610
611Your WPT tests will probably fail now.
612
613> Tests with unexpected results: PASS [expected FAIL] ...
614
615Update the expectations in a draft PR with the "update-expectations" label. This will trigger an automated PR "test: update the expectations for PR" that you'll need to merge to your branch.
616
617#### Merge it!
618
619Mark your PR as ready, get it reviewed, and merge it in.
620
621### Roll in ChromeDriver
622
623This bit usually involves the core devs:
624
6251. [Release](#automatic-release) your changes.
6262. [Roll the changes into ChromeDriver](#roll-into-chromium).