blob: f96535a6e9d388499dff1be593147bc74ecabb80 [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
Randolf Jung3e526312023-08-08 06:20:3911[![codecov](https://codecov.io/gh/GoogleChromeLabs/chromium-bidi/branch/main/graph/badge.svg?token=LJSXSC9L09)](https://codecov.io/gh/GoogleChromeLabs/chromium-bidi)
12
Randolfb0fe9c12023-03-06 14:03:4813This is an implementation of the
14[WebDriver BiDi](https://w3c.github.io/webdriver-bidi/) protocol with some
15extensions (**BiDi+**)
16for Chromium, implemented as a JavaScript layer translating between BiDi and CDP,
17running inside a Chrome tab.
18
19Current status can be checked
20at [WPT WebDriver BiDi status](https://wpt.fyi/results/webdriver/tests/bidi).
21
22## BiDi+
23
24**"BiDi+"** is an extension of the WebDriver BiDi protocol. In addition to [WebDriver BiDi](https://w3c.github.io/webdriver-bidi/) it has:
25
26### Command `cdp.sendCommand`
27
28```cddl
29CdpSendCommandCommand = {
30 method: "cdp.sendCommand",
31 params: ScriptEvaluateParameters,
32}
33
34CdpSendCommandParameters = {
Alex Rudenko1552f2b2023-07-11 11:18:3235 method: text,
36 params: any,
37 session?: text,
Randolfb0fe9c12023-03-06 14:03:4838}
39
40CdpSendCommandResult = {
41 result: any,
Alex Rudenko1552f2b2023-07-11 11:18:3242 session: text,
Randolfb0fe9c12023-03-06 14:03:4843}
44```
45
46The command runs the
47described [CDP command](https://chromedevtools.github.io/devtools-protocol)
Alex Rudenko1552f2b2023-07-11 11:18:3248and returns the result.
Randolfb0fe9c12023-03-06 14:03:4849
50### Command `cdp.getSession`
51
52```cddl
53CdpGetSessionCommand = {
Alex Rudenko5fda6462024-04-17 12:18:0354 method: "cdp.getSession",
Randolfb0fe9c12023-03-06 14:03:4855 params: ScriptEvaluateParameters,
56}
57
58CdpGetSessionParameters = {
59 context: BrowsingContext,
60}
61
62CdpGetSessionResult = {
Alex Rudenko1552f2b2023-07-11 11:18:3263 session: text,
Randolfb0fe9c12023-03-06 14:03:4864}
65```
66
67The command returns the default CDP session for the selected browsing context.
68
Alex Rudenko5fda6462024-04-17 12:18:0369### Command `cdp.resolveRealm`
70
71```cddl
72CdpResolveRealmCommand = {
73 method: "cdp.resolveRealm",
74 params: ScriptEvaluateParameters,
75}
76
77CdpResolveRealmParameters = {
78 realm: Script.Realm,
79}
80
81CdpResolveRealmResult = {
82 executionContextId: text,
83}
84```
85
86The command returns resolves a BiDi realm to its CDP execution context ID.
87
Alex Rudenko1552f2b2023-07-11 11:18:3288### Events `cdp`
Randolfb0fe9c12023-03-06 14:03:4889
90```cddl
91CdpEventReceivedEvent = {
Alex Rudenko1552f2b2023-07-11 11:18:3292 method: "cdp.<CDP Event Name>",
93 params: CdpEventReceivedParameters,
Randolfb0fe9c12023-03-06 14:03:4894}
95
96CdpEventReceivedParameters = {
Alex Rudenko1552f2b2023-07-11 11:18:3297 event: text,
98 params: any,
99 session: text,
Randolfb0fe9c12023-03-06 14:03:48100}
101```
102
103The event contains a CDP event.
104
105### Field `channel`
106
107Each command can be extended with a `channel`:
108
109```cddl
110Command = {
111 id: js-uint,
112 channel?: text,
113 CommandData,
114 Extensible,
115}
116```
117
118If provided and non-empty string, the very same `channel` is added to the response:
119
120```cddl
121CommandResponse = {
122 id: js-uint,
123 channel?: text,
124 result: ResultData,
125 Extensible,
126}
127
128ErrorResponse = {
129 id: js-uint / null,
130 channel?: text,
131 error: ErrorCode,
132 message: text,
133 ?stacktrace: text,
134 Extensible
135}
136```
137
138When client uses
139commands [`session.subscribe`](https://w3c.github.io/webdriver-bidi/#command-session-subscribe)
140and [`session.unsubscribe`](https://w3c.github.io/webdriver-bidi/#command-session-unsubscribe)
141with `channel`, the subscriptions are handled per channel, and the corresponding
142`channel` filed is added to the event message:
143
144```cddl
145Event = {
146 channel?: text,
147 EventData,
148 Extensible,
149}
150```
151
152## Dev Setup
153
154### `npm`
155
156This is a Node.js project, so install dependencies as usual:
157
158```sh
159npm install
160```
161
Randolf Jung3e526312023-08-08 06:20:39162### `cargo`
163
164<!-- TODO(jrandolf): Remove after binaries get published -->
165
Alex Rudenko662ce9c2023-08-29 08:05:30166We use [cddlconv](https://github.com/google/cddlconv) to generate our WebDriverBidi types before building.
Randolf Jung3e526312023-08-08 06:20:39167
1681. Install [Rust](https://rustup.rs/).
Alex Rudenko662ce9c2023-08-29 08:05:301692. Run `cargo install --git https://github.com/google/cddlconv.git cddlconv`
Randolf Jung3e526312023-08-08 06:20:39170
Randolfb0fe9c12023-03-06 14:03:48171### pre-commit.com integration
172
173Refer to the documentation at [.pre-commit-config.yaml](.pre-commit-config.yaml).
174
Alex Rudenkof7ea7ab2023-10-24 09:40:51175```sh
176pre-commit install --hook-type pre-push
177```
178
179### Starting WebDriver BiDi Server
Randolfb0fe9c12023-03-06 14:03:48180
181This will run the server on port `8080`:
182
183```sh
184npm run server
185```
186
187Use the `PORT=` environment variable or `--port=` argument to run it on another port:
188
189```sh
190PORT=8081 npm run server
191npm run server -- --port=8081
192```
193
194Use the `DEBUG` environment variable to see debug info:
195
196```sh
197DEBUG=* npm run server
198```
199
Alex Rudenko5fe99f82023-10-06 12:01:27200Use the `DEBUG_DEPTH` (default: `10`) environment variable to see debug deeply nested objects:
201
202```sh
203DEBUG_DEPTH=100 DEBUG=* npm run server
204```
205
Alex Rudenko5fda6462024-04-17 12:18:03206Use the `CHANNEL=...` environment variable with one of the following values to run
207the specific Chrome channel: `stable`, `beta`, `canary`, `dev`, `local`. Default is
208`local`. The `local` channel means the pinned in `.browser` Chrome version will be
209downloaded if it is not yet in cache. Otherwise, the requested Chrome version should
210be installed.
Randolfb0fe9c12023-03-06 14:03:48211
212```sh
Randolf55431462023-03-29 13:00:36213CHANNEL=dev npm run server
Randolf55431462023-03-29 13:00:36214```
215
Alex Rudenko1552f2b2023-07-11 11:18:32216Use 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:36217
218```sh
Alex Rudenko1552f2b2023-07-11 11:18:32219DEBUG=bidi:mapper:debug:* npm run server -- --verbose
Randolf55431462023-03-29 13:00:36220```
221
222or
223
224```sh
225DEBUG=* npm run server -- --verbose
Randolfb0fe9c12023-03-06 14:03:48226```
227
228### Starting on Linux and Mac
229
Randolf Jungbcb3bc82023-06-26 16:30:14230TODO: verify it works on Windows.
Randolfb0fe9c12023-03-06 14:03:48231
Randolf Jung3e526312023-08-08 06:20:39232You can also run the server by using `npm run server`. It will write
Randolfb0fe9c12023-03-06 14:03:48233output to the file `log.txt`:
234
235```sh
Randolf Jung3e526312023-08-08 06:20:39236npm run server -- --port=8081 --headless=false
Randolfb0fe9c12023-03-06 14:03:48237```
238
Alex Rudenko5fe99f82023-10-06 12:01:27239### Running with in other project
240
241Sometimes it good to verify that a change will not affect thing downstream for other packages.
242There is a useful `puppeteer` label you can add to any PR to run Puppeteer test with your changes.
243It will bundle `chromium-bidi` and install it in Puppeteer project then run that package test.
244
Randolfb0fe9c12023-03-06 14:03:48245## Running
246
247### Unit tests
248
249Running:
250
251```sh
Randolf Jungbcb3bc82023-06-26 16:30:14252npm run unit
Randolfb0fe9c12023-03-06 14:03:48253```
254
255### E2E tests
256
257The E2E tests are written using Python, in order to learn how to eventually do
258this in web-platform-tests.
259
Alex Rudenko5fe99f82023-10-06 12:01:27260#### Installation
Randolfb0fe9c12023-03-06 14:03:48261
Alex Rudenkoaf11b7c2024-02-06 10:44:42262Python 3.10+ and some dependencies are required:
Randolfb0fe9c12023-03-06 14:03:48263
264```sh
Alex Rudenkoaf11b7c2024-02-06 10:44:42265python -m pip install --user pipenv
266pipenv install
Randolfb0fe9c12023-03-06 14:03:48267```
268
Alex Rudenko5fe99f82023-10-06 12:01:27269#### Running
Randolfb0fe9c12023-03-06 14:03:48270
271The E2E tests require BiDi server running on the same host. By default, tests
272try to connect to the port `8080`. The server can be run from the project root:
273
274```sh
Alex Rudenkod04dd452024-02-27 08:25:35275npm run e2e # alias to to e2e:headless
276npm run e2e:headful
277npm run e2e:headless
Randolfb0fe9c12023-03-06 14:03:48278```
279
Alex Rudenko5fda6462024-04-17 12:18:03280This commands will run `./tools/run-e2e.mjs`, which will log the PyTest output to console,
281Additionally the output is also recorded under `./logs/<DATE>.e2e.log`, this will contain
282both the PyTest logs and in the event of `FAILED` test all the Chromium-BiDi logs.
283
284If you need to see the logs for all test run the command with `VERBOSE=true`.
285
286Simply pass `npm run e2e -- tests/<PathOrFile>` and the e2e will run only the selected one.
287You run a specific test by running `npm run e2e -- -k <TestName>`.
288
289Use `CHROMEDRIVER` environment to run tests in `chromedriver` instead of NodeJS runner:
290
291```shell
292CHROMEDRIVER=true npm run e2e
293```
294
Randolfb0fe9c12023-03-06 14:03:48295Use the `PORT` environment variable to connect to another port:
296
297```sh
298PORT=8081 npm run e2e
299```
300
Alex Rudenko5fda6462024-04-17 12:18:03301Use the `HEADLESS` to run the tests in headless (new or old) or headful modes.
302Values: `new`, `old`, `false`, default: `new`.
303
304```sh
305HEADLESS=new npm run e2e
306```
307
Alex Rudenkoaf11b7c2024-02-06 10:44:42308#### Updating snapshots
309
310```sh
311npm run e2e -- --snapshot-update
312```
313
314See https://github.com/tophat/syrupy for more information.
315
Alex Rudenkof7ea7ab2023-10-24 09:40:51316### Local http server
317
318E2E tests use local http
319server [`pytest-httpserver`](https://pytest-httpserver.readthedocs.io/), which is run
320automatically with the tests. However,
321sometimes it is useful to run the http server outside the test
322case, for example for manual debugging. This can be done by running:
323
324```sh
Alex Rudenkoaf11b7c2024-02-06 10:44:42325pipenv run local_http_server
Alex Rudenkof7ea7ab2023-10-24 09:40:51326```
327
Alex Rudenkoaf11b7c2024-02-06 10:44:42328...or directly:
Alex Rudenkof7ea7ab2023-10-24 09:40:51329
330```sh
Alex Rudenkoaf11b7c2024-02-06 10:44:42331python tests/tools/local_http_server.py
Alex Rudenkof7ea7ab2023-10-24 09:40:51332```
333
334### Examples
Randolfb0fe9c12023-03-06 14:03:48335
336Refer to [examples/README.md](examples/README.md).
337
338## WPT (Web Platform Tests)
339
340WPT is added as
341a [git submodule](https://git-scm.com/book/en/v2/Git-Tools-Submodules). To get run
342WPT tests:
343
344### Check out and setup WPT
345
346#### 1. Check out WPT
347
348```sh
349git submodule update --init
350```
351
352#### 2. Go to the WPT folder
353
354```sh
355cd wpt
356```
357
358#### 3. Set up virtualenv
359
360Follow the [_System
361Setup_](https://web-platform-tests.org/running-tests/from-local-system.html#system-setup)
362instructions.
363
364#### 4. Setup `hosts` file
365
366Follow
367the [`hosts` File Setup](https://web-platform-tests.org/running-tests/from-local-system.html#hosts-file-setup)
368instructions.
369
370##### 4.a On Linux, macOS or other UNIX-like system
371
372```sh
373./wpt make-hosts-file | sudo tee -a /etc/hosts
374```
375
376##### 4.b On **Windows**
377
378This must be run in a PowerShell session with Administrator privileges:
379
380```sh
381python wpt make-hosts-file | Out-File $env:SystemRoot\System32\drivers\etc\hosts -Encoding ascii -Append
382```
383
384If you are behind a proxy, you also need to make sure the domains above are excluded
385from your proxy lookups.
386
Randolf Jungbcb3bc82023-06-26 16:30:14387#### 5. Set `BROWSER_BIN`
Randolfb0fe9c12023-03-06 14:03:48388
Randolf Jungbcb3bc82023-06-26 16:30:14389Set the `BROWSER_BIN` environment variable to a Chrome, Edge or Chromium binary to launch.
Randolfb0fe9c12023-03-06 14:03:48390For example, on macOS:
391
392```sh
393# Chrome
Randolf Jungbcb3bc82023-06-26 16:30:14394export BROWSER_BIN="/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary"
395export BROWSER_BIN="/Applications/Google Chrome Dev.app/Contents/MacOS/Google Chrome Dev"
396export BROWSER_BIN="/Applications/Google Chrome Beta.app/Contents/MacOS/Google Chrome Beta"
397export BROWSER_BIN="/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
398export BROWSER_BIN="/Applications/Chromium.app/Contents/MacOS/Chromium"
Randolfb0fe9c12023-03-06 14:03:48399
400# Edge
Randolf Jungbcb3bc82023-06-26 16:30:14401export BROWSER_BIN="/Applications/Microsoft Edge Canary.app/Contents/MacOS/Microsoft Edge Canary"
402export BROWSER_BIN="/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge"
Randolfb0fe9c12023-03-06 14:03:48403```
404
405### Run WPT tests
406
407#### 1. Make sure you have Chrome Dev installed
408
409https://www.google.com/chrome/dev/
410
Randolf55431462023-03-29 13:00:36411#### 2. Build Chromedriver BiDi
Randolfb0fe9c12023-03-06 14:03:48412
413Oneshot:
414
415```sh
416npm run build
417```
418
419Continuously:
420
421```sh
Randolf Jungbcb3bc82023-06-26 16:30:14422npm run build --watch
Randolfb0fe9c12023-03-06 14:03:48423```
424
425#### 3. Run
426
427```sh
Randolf Jungbcb3bc82023-06-26 16:30:14428npm run wpt -- webdriver/tests/bidi/
Randolfb0fe9c12023-03-06 14:03:48429```
430
431### Update WPT expectations if needed
432
Randolfb0fe9c12023-03-06 14:03:48433```sh
Randolf Jungbcb3bc82023-06-26 16:30:14434UPDATE_EXPECTATIONS=true npm run wpt -- webdriver/tests/bidi/
Randolfb0fe9c12023-03-06 14:03:48435```
436
437## How does it work?
438
439The architecture is described in the
440[WebDriver BiDi in Chrome Context implementation plan](https://docs.google.com/document/d/1VfQ9tv0wPSnb5TI-MOobjoQ5CXLnJJx9F_PxOMQc8kY)
441.
442
443There are 2 main modules:
444
4451. backend WS server in `src`. It runs webSocket server, and for each ws connection
446 runs an instance of browser with BiDi Mapper.
4472. front-end BiDi Mapper in `src/bidiMapper`. Gets BiDi commands from the backend,
448 and map them to CDP commands.
449
Alex Rudenko5fe99f82023-10-06 12:01:27450## Contributing
Randolfb0fe9c12023-03-06 14:03:48451
452The BiDi commands are processed in the `src/bidiMapper/commandProcessor.ts`. To add a
453new command, add it to `_processCommand`, write and call processor for it.
454
455### Publish new `npm` release
456
Alex Rudenko1552f2b2023-07-11 11:18:32457#### Automatic release
Randolf Jungbcb3bc82023-06-26 16:30:14458
Alex Rudenko1552f2b2023-07-11 11:18:32459We 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:14460
461#### Manual release
462
4631. Dry-run
464
465 ```sh
466 npm publish --dry-run
467 ```
468
Randolf55431462023-03-29 13:00:364691. Open a PR bumping the chromium-bidi version number in `package.json` for review:
Randolfb0fe9c12023-03-06 14:03:48470
471 ```sh
Alex Rudenko1552f2b2023-07-11 11:18:32472 npm version patch -m 'chore: Release v%s' --no-git-tag-version
Randolfb0fe9c12023-03-06 14:03:48473 ```
474
475 Instead of `patch`, use `minor` or `major` [as needed](https://semver.org/).
476
Randolf55431462023-03-29 13:00:364771. 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.
478 Our CI then automatically publishes the new release to npm based on the tag name.
Randolf Jung3e526312023-08-08 06:20:39479
480#### Roll into Chromium
481
Alex Rudenkob013f872023-09-29 05:56:03482This section assumes you already have a Chromium set-up locally,
483and knowledge on [how to submit changes to the repo](https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/contributing.md).
484Otherwise submit an issue for a project maintainer.
Randolf Jung3e526312023-08-08 06:20:39485
Alex Rudenkob013f872023-09-29 05:56:034861. Create a new branch in chromium `src/`.
4872. Update the mapper version:
Randolf Jung3e526312023-08-08 06:20:39488
Alex Rudenkob013f872023-09-29 05:56:03489```shell
490third_party/bidimapper/pull.sh
491third_party/bidimapper/build.sh
Randolf Jung3e526312023-08-08 06:20:39492```
493
Alex Rudenkob013f872023-09-29 05:56:034943. Submit a CL with bug `chromedriver:4226`.
Alex Rudenkob013f872023-09-29 05:56:03495
Alex Rudenkoaf11b7c2024-02-06 10:44:424964. [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:03497
Alex Rudenkoaf11b7c2024-02-06 10:44:42498 4.1. Trigger a build and test run:
Alex Rudenkob013f872023-09-29 05:56:03499
Alex Rudenkoaf11b7c2024-02-06 10:44:42500 ```shell
501 third_party/blink/tools/blink_tool.py rebaseline-cl --build="linux-blink-rel" --verbose
502 ```
503
504 4.2. Once the test completes on the builder, rerun that command to update the
505 baselines. Update test expectations if there are any crashes or timeouts.
506 Commit the changes (if any), and upload the new patch to the CL.
Alex Rudenkob013f872023-09-29 05:56:03507
5085. Add appropriate reviewers or comment the CL link on the PR.