blob: 96bfbf964af22ffcfcf84e6e2a9dd906fe19b439 [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
Randolfb0fe9c12023-03-06 14:03:4811This 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
24### Command `cdp.sendCommand`
25
26```cddl
27CdpSendCommandCommand = {
28 method: "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
48### Command `cdp.getSession`
49
50```cddl
51CdpGetSessionCommand = {
Alex Rudenko5fda6462024-04-17 12:18:0352 method: "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 Rudenko5fda6462024-04-17 12:18:0367### Command `cdp.resolveRealm`
68
69```cddl
70CdpResolveRealmCommand = {
71 method: "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 Rudenko1552f2b2023-07-11 11:18:3286### Events `cdp`
Randolfb0fe9c12023-03-06 14:03:4887
88```cddl
89CdpEventReceivedEvent = {
Alex Rudenko1552f2b2023-07-11 11:18:3290 method: "cdp.<CDP Event Name>",
91 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
103### Field `channel`
104
105Each command can be extended with a `channel`:
106
107```cddl
108Command = {
109 id: js-uint,
110 channel?: text,
111 CommandData,
112 Extensible,
113}
114```
115
116If provided and non-empty string, the very same `channel` is added to the response:
117
118```cddl
119CommandResponse = {
120 id: js-uint,
121 channel?: text,
122 result: ResultData,
123 Extensible,
124}
125
126ErrorResponse = {
127 id: js-uint / null,
128 channel?: text,
129 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)
139with `channel`, the subscriptions are handled per channel, and the corresponding
140`channel` filed is added to the event message:
141
142```cddl
143Event = {
144 channel?: text,
145 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 Rudenko662ce9c2023-08-29 08:05:30164We 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
177### Starting WebDriver BiDi Server
Randolfb0fe9c12023-03-06 14:03:48178
179This will run the server on port `8080`:
180
181```sh
182npm run server
183```
184
185Use the `PORT=` environment variable or `--port=` argument to run it on another port:
186
187```sh
188PORT=8081 npm run server
189npm run server -- --port=8081
190```
191
192Use the `DEBUG` environment variable to see debug info:
193
194```sh
195DEBUG=* npm run server
196```
197
Alex Rudenko5fe99f82023-10-06 12:01:27198Use the `DEBUG_DEPTH` (default: `10`) environment variable to see debug deeply nested objects:
199
200```sh
201DEBUG_DEPTH=100 DEBUG=* npm run server
202```
203
Alex Rudenko5fda6462024-04-17 12:18:03204Use the `CHANNEL=...` environment variable with one of the following values to run
205the specific Chrome channel: `stable`, `beta`, `canary`, `dev`, `local`. Default is
206`local`. The `local` channel means the pinned in `.browser` Chrome version will be
207downloaded if it is not yet in cache. Otherwise, the requested Chrome version should
208be installed.
Randolfb0fe9c12023-03-06 14:03:48209
210```sh
Randolf55431462023-03-29 13:00:36211CHANNEL=dev npm run server
Randolf55431462023-03-29 13:00:36212```
213
Alex Rudenko1552f2b2023-07-11 11:18:32214Use 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:36215
216```sh
Alex Rudenko1552f2b2023-07-11 11:18:32217DEBUG=bidi:mapper:debug:* npm run server -- --verbose
Randolf55431462023-03-29 13:00:36218```
219
220or
221
222```sh
223DEBUG=* npm run server -- --verbose
Randolfb0fe9c12023-03-06 14:03:48224```
225
226### Starting on Linux and Mac
227
Randolf Jungbcb3bc82023-06-26 16:30:14228TODO: verify it works on Windows.
Randolfb0fe9c12023-03-06 14:03:48229
Randolf Jung3e526312023-08-08 06:20:39230You can also run the server by using `npm run server`. It will write
Randolfb0fe9c12023-03-06 14:03:48231output to the file `log.txt`:
232
233```sh
Randolf Jung3e526312023-08-08 06:20:39234npm run server -- --port=8081 --headless=false
Randolfb0fe9c12023-03-06 14:03:48235```
236
Alex Rudenko5fe99f82023-10-06 12:01:27237### Running with in other project
238
239Sometimes it good to verify that a change will not affect thing downstream for other packages.
240There is a useful `puppeteer` label you can add to any PR to run Puppeteer test with your changes.
241It will bundle `chromium-bidi` and install it in Puppeteer project then run that package test.
242
Randolfb0fe9c12023-03-06 14:03:48243## Running
244
245### Unit tests
246
247Running:
248
249```sh
Randolf Jungbcb3bc82023-06-26 16:30:14250npm run unit
Randolfb0fe9c12023-03-06 14:03:48251```
252
253### E2E tests
254
255The E2E tests are written using Python, in order to learn how to eventually do
256this in web-platform-tests.
257
Alex Rudenko5fe99f82023-10-06 12:01:27258#### Installation
Randolfb0fe9c12023-03-06 14:03:48259
Alex Rudenkoaf11b7c2024-02-06 10:44:42260Python 3.10+ and some dependencies are required:
Randolfb0fe9c12023-03-06 14:03:48261
262```sh
Alex Rudenkoaf11b7c2024-02-06 10:44:42263python -m pip install --user pipenv
264pipenv install
Randolfb0fe9c12023-03-06 14:03:48265```
266
Alex Rudenko5fe99f82023-10-06 12:01:27267#### Running
Randolfb0fe9c12023-03-06 14:03:48268
269The E2E tests require BiDi server running on the same host. By default, tests
270try to connect to the port `8080`. The server can be run from the project root:
271
272```sh
Alex Rudenkod04dd452024-02-27 08:25:35273npm run e2e # alias to to e2e:headless
274npm run e2e:headful
275npm run e2e:headless
Randolfb0fe9c12023-03-06 14:03:48276```
277
Alex Rudenko5fda6462024-04-17 12:18:03278This commands will run `./tools/run-e2e.mjs`, which will log the PyTest output to console,
279Additionally the output is also recorded under `./logs/<DATE>.e2e.log`, this will contain
280both the PyTest logs and in the event of `FAILED` test all the Chromium-BiDi logs.
281
282If you need to see the logs for all test run the command with `VERBOSE=true`.
283
284Simply pass `npm run e2e -- tests/<PathOrFile>` and the e2e will run only the selected one.
285You run a specific test by running `npm run e2e -- -k <TestName>`.
286
287Use `CHROMEDRIVER` environment to run tests in `chromedriver` instead of NodeJS runner:
288
289```shell
290CHROMEDRIVER=true npm run e2e
291```
292
Randolfb0fe9c12023-03-06 14:03:48293Use the `PORT` environment variable to connect to another port:
294
295```sh
296PORT=8081 npm run e2e
297```
298
Alex Rudenko5fda6462024-04-17 12:18:03299Use the `HEADLESS` to run the tests in headless (new or old) or headful modes.
300Values: `new`, `old`, `false`, default: `new`.
301
302```sh
303HEADLESS=new npm run e2e
304```
305
Alex Rudenkoaf11b7c2024-02-06 10:44:42306#### Updating snapshots
307
308```sh
309npm run e2e -- --snapshot-update
310```
311
312See https://github.com/tophat/syrupy for more information.
313
Alex Rudenkof7ea7ab2023-10-24 09:40:51314### Local http server
315
316E2E tests use local http
317server [`pytest-httpserver`](https://pytest-httpserver.readthedocs.io/), which is run
318automatically with the tests. However,
319sometimes it is useful to run the http server outside the test
320case, for example for manual debugging. This can be done by running:
321
322```sh
Alex Rudenkoaf11b7c2024-02-06 10:44:42323pipenv run local_http_server
Alex Rudenkof7ea7ab2023-10-24 09:40:51324```
325
Alex Rudenkoaf11b7c2024-02-06 10:44:42326...or directly:
Alex Rudenkof7ea7ab2023-10-24 09:40:51327
328```sh
Alex Rudenkoaf11b7c2024-02-06 10:44:42329python tests/tools/local_http_server.py
Alex Rudenkof7ea7ab2023-10-24 09:40:51330```
331
332### Examples
Randolfb0fe9c12023-03-06 14:03:48333
334Refer to [examples/README.md](examples/README.md).
335
336## WPT (Web Platform Tests)
337
338WPT is added as
339a [git submodule](https://git-scm.com/book/en/v2/Git-Tools-Submodules). To get run
340WPT tests:
341
342### Check out and setup WPT
343
344#### 1. Check out WPT
345
346```sh
347git submodule update --init
348```
349
350#### 2. Go to the WPT folder
351
352```sh
353cd wpt
354```
355
356#### 3. Set up virtualenv
357
358Follow the [_System
359Setup_](https://web-platform-tests.org/running-tests/from-local-system.html#system-setup)
360instructions.
361
362#### 4. Setup `hosts` file
363
364Follow
365the [`hosts` File Setup](https://web-platform-tests.org/running-tests/from-local-system.html#hosts-file-setup)
366instructions.
367
368##### 4.a On Linux, macOS or other UNIX-like system
369
370```sh
371./wpt make-hosts-file | sudo tee -a /etc/hosts
372```
373
374##### 4.b On **Windows**
375
376This must be run in a PowerShell session with Administrator privileges:
377
378```sh
379python wpt make-hosts-file | Out-File $env:SystemRoot\System32\drivers\etc\hosts -Encoding ascii -Append
380```
381
382If you are behind a proxy, you also need to make sure the domains above are excluded
383from your proxy lookups.
384
Randolf Jungbcb3bc82023-06-26 16:30:14385#### 5. Set `BROWSER_BIN`
Randolfb0fe9c12023-03-06 14:03:48386
Randolf Jungbcb3bc82023-06-26 16:30:14387Set the `BROWSER_BIN` environment variable to a Chrome, Edge or Chromium binary to launch.
Randolfb0fe9c12023-03-06 14:03:48388For example, on macOS:
389
390```sh
391# Chrome
Randolf Jungbcb3bc82023-06-26 16:30:14392export BROWSER_BIN="/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary"
393export BROWSER_BIN="/Applications/Google Chrome Dev.app/Contents/MacOS/Google Chrome Dev"
394export BROWSER_BIN="/Applications/Google Chrome Beta.app/Contents/MacOS/Google Chrome Beta"
395export BROWSER_BIN="/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
396export BROWSER_BIN="/Applications/Chromium.app/Contents/MacOS/Chromium"
Randolfb0fe9c12023-03-06 14:03:48397
398# Edge
Randolf Jungbcb3bc82023-06-26 16:30:14399export BROWSER_BIN="/Applications/Microsoft Edge Canary.app/Contents/MacOS/Microsoft Edge Canary"
400export BROWSER_BIN="/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge"
Randolfb0fe9c12023-03-06 14:03:48401```
402
403### Run WPT tests
404
405#### 1. Make sure you have Chrome Dev installed
406
407https://www.google.com/chrome/dev/
408
Randolf55431462023-03-29 13:00:36409#### 2. Build Chromedriver BiDi
Randolfb0fe9c12023-03-06 14:03:48410
411Oneshot:
412
413```sh
414npm run build
415```
416
417Continuously:
418
419```sh
Randolf Jungbcb3bc82023-06-26 16:30:14420npm run build --watch
Randolfb0fe9c12023-03-06 14:03:48421```
422
423#### 3. Run
424
425```sh
Randolf Jungbcb3bc82023-06-26 16:30:14426npm run wpt -- webdriver/tests/bidi/
Randolfb0fe9c12023-03-06 14:03:48427```
428
429### Update WPT expectations if needed
430
Randolfb0fe9c12023-03-06 14:03:48431```sh
Randolf Jungbcb3bc82023-06-26 16:30:14432UPDATE_EXPECTATIONS=true npm run wpt -- webdriver/tests/bidi/
Randolfb0fe9c12023-03-06 14:03:48433```
434
435## How does it work?
436
437The architecture is described in the
438[WebDriver BiDi in Chrome Context implementation plan](https://docs.google.com/document/d/1VfQ9tv0wPSnb5TI-MOobjoQ5CXLnJJx9F_PxOMQc8kY)
439.
440
441There are 2 main modules:
442
4431. backend WS server in `src`. It runs webSocket server, and for each ws connection
444 runs an instance of browser with BiDi Mapper.
4452. front-end BiDi Mapper in `src/bidiMapper`. Gets BiDi commands from the backend,
446 and map them to CDP commands.
447
Alex Rudenko5fe99f82023-10-06 12:01:27448## Contributing
Randolfb0fe9c12023-03-06 14:03:48449
450The BiDi commands are processed in the `src/bidiMapper/commandProcessor.ts`. To add a
451new command, add it to `_processCommand`, write and call processor for it.
452
453### Publish new `npm` release
454
Alex Rudenko1552f2b2023-07-11 11:18:32455#### Automatic release
Randolf Jungbcb3bc82023-06-26 16:30:14456
Alex Rudenko1552f2b2023-07-11 11:18:32457We 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:14458
459#### Manual release
460
4611. Dry-run
462
463 ```sh
464 npm publish --dry-run
465 ```
466
Randolf55431462023-03-29 13:00:364671. Open a PR bumping the chromium-bidi version number in `package.json` for review:
Randolfb0fe9c12023-03-06 14:03:48468
469 ```sh
Alex Rudenko1552f2b2023-07-11 11:18:32470 npm version patch -m 'chore: Release v%s' --no-git-tag-version
Randolfb0fe9c12023-03-06 14:03:48471 ```
472
473 Instead of `patch`, use `minor` or `major` [as needed](https://semver.org/).
474
Randolf55431462023-03-29 13:00:364751. 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.
476 Our CI then automatically publishes the new release to npm based on the tag name.
Randolf Jung3e526312023-08-08 06:20:39477
478#### Roll into Chromium
479
Alex Rudenkob013f872023-09-29 05:56:03480This section assumes you already have a Chromium set-up locally,
481and knowledge on [how to submit changes to the repo](https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/contributing.md).
482Otherwise submit an issue for a project maintainer.
Randolf Jung3e526312023-08-08 06:20:39483
Alex Rudenkob013f872023-09-29 05:56:034841. Create a new branch in chromium `src/`.
4852. Update the mapper version:
Randolf Jung3e526312023-08-08 06:20:39486
Alex Rudenkob013f872023-09-29 05:56:03487```shell
488third_party/bidimapper/pull.sh
489third_party/bidimapper/build.sh
Randolf Jung3e526312023-08-08 06:20:39490```
491
Alex Rudenkob013f872023-09-29 05:56:034923. Submit a CL with bug `chromedriver:4226`.
Alex Rudenkob013f872023-09-29 05:56:03493
Alex Rudenkoaf11b7c2024-02-06 10:44:424944. [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:03495
Alex Rudenkoaf11b7c2024-02-06 10:44:42496 4.1. Trigger a build and test run:
Alex Rudenkob013f872023-09-29 05:56:03497
Alex Rudenkoaf11b7c2024-02-06 10:44:42498 ```shell
499 third_party/blink/tools/blink_tool.py rebaseline-cl --build="linux-blink-rel" --verbose
500 ```
501
502 4.2. Once the test completes on the builder, rerun that command to update the
503 baselines. Update test expectations if there are any crashes or timeouts.
504 Commit the changes (if any), and upload the new patch to the CL.
Alex Rudenkob013f872023-09-29 05:56:03505
5065. Add appropriate reviewers or comment the CL link on the PR.