blob: 81400ea076ba22550af067bd3acfd6f11bc60568 [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)
7![WPT Tests (chromedriver)](https://github.com/GoogleChromeLabs/chromium-bidi/actions/workflows/wpt-chromedriver.yml/badge.svg)
8![WPT Tests (mapper)](https://github.com/GoogleChromeLabs/chromium-bidi/actions/workflows/wpt-mapper.yml/badge.svg)
9
10![Generate WPT Report](https://github.com/GoogleChromeLabs/chromium-bidi/actions/workflows/generate-wpt-report.yml/badge.svg)
11![Pre-commit](https://github.com/GoogleChromeLabs/chromium-bidi/actions/workflows/pre-commit.yml/badge.svg)
Randolfb0fe9c12023-03-06 14:03:4812
13This 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 = {
35 cdpMethod: text,
36 cdpParams: any,
37 cdpSession?: text,
38}
39
40CdpSendCommandResult = {
41 result: any,
42 cdpSession: text,
43}
44```
45
46The command runs the
47described [CDP command](https://chromedevtools.github.io/devtools-protocol)
48and returns result.
49
50### Command `cdp.getSession`
51
52```cddl
53CdpGetSessionCommand = {
54 method: "cdp.sendCommand",
55 params: ScriptEvaluateParameters,
56}
57
58CdpGetSessionParameters = {
59 context: BrowsingContext,
60}
61
62CdpGetSessionResult = {
63 cdpSession: text,
64}
65```
66
67The command returns the default CDP session for the selected browsing context.
68
69### Event `cdp.eventReceived`
70
71```cddl
72CdpEventReceivedEvent = {
73 method: "cdp.eventReceived",
74 params: ScriptEvaluateParameters,
75}
76
77CdpEventReceivedParameters = {
78 cdpMethod: text,
79 cdpParams: any,
80 cdpSession: string,
81}
82```
83
84The event contains a CDP event.
85
86### Field `channel`
87
88Each command can be extended with a `channel`:
89
90```cddl
91Command = {
92 id: js-uint,
93 channel?: text,
94 CommandData,
95 Extensible,
96}
97```
98
99If provided and non-empty string, the very same `channel` is added to the response:
100
101```cddl
102CommandResponse = {
103 id: js-uint,
104 channel?: text,
105 result: ResultData,
106 Extensible,
107}
108
109ErrorResponse = {
110 id: js-uint / null,
111 channel?: text,
112 error: ErrorCode,
113 message: text,
114 ?stacktrace: text,
115 Extensible
116}
117```
118
119When client uses
120commands [`session.subscribe`](https://w3c.github.io/webdriver-bidi/#command-session-subscribe)
121and [`session.unsubscribe`](https://w3c.github.io/webdriver-bidi/#command-session-unsubscribe)
122with `channel`, the subscriptions are handled per channel, and the corresponding
123`channel` filed is added to the event message:
124
125```cddl
126Event = {
127 channel?: text,
128 EventData,
129 Extensible,
130}
131```
132
133## Dev Setup
134
135### `npm`
136
137This is a Node.js project, so install dependencies as usual:
138
139```sh
140npm install
141```
142
143### pre-commit.com integration
144
145Refer to the documentation at [.pre-commit-config.yaml](.pre-commit-config.yaml).
146
147### Starting the Server
148
149This will run the server on port `8080`:
150
151```sh
152npm run server
153```
154
155Use the `PORT=` environment variable or `--port=` argument to run it on another port:
156
157```sh
158PORT=8081 npm run server
159npm run server -- --port=8081
160```
161
162Use the `DEBUG` environment variable to see debug info:
163
164```sh
165DEBUG=* npm run server
166```
167
168Use the CLI argument `--headless=false` to run browser in headful mode:
169
170```sh
171npm run server -- --headless=false
172```
173
174Use the `CHANNEL=...` environment variable or `--channel=...` argument with one of
Randolf55431462023-03-29 13:00:36175the following values to run the specific Chrome channel: `stable`,
176`beta`, `canary`, `dev`.
Randolfb0fe9c12023-03-06 14:03:48177
178The requested Chrome version should be installed.
179
180```sh
Randolf55431462023-03-29 13:00:36181CHANNEL=dev npm run server
182npm run server -- --channel=dev
183```
184
185Use the CLI argument `--verbose` to have CDP events printed to the console. Note: you have to enable debugging output `bidiMapper:mapperDebug:*` as well.
186
187```sh
188DEBUG=bidiMapper:mapperDebug:* npm run server -- --verbose
189```
190
191or
192
193```sh
194DEBUG=* npm run server -- --verbose
Randolfb0fe9c12023-03-06 14:03:48195```
196
197### Starting on Linux and Mac
198
199TODO: verify if it works on Windows.
200
201You can also run the server by using script `./runBiDiServer.sh`. It will write
202output to the file `log.txt`:
203
204```sh
205./runBiDiServer.sh --port=8081 --headless=false
206```
207
208## Running
209
210### Unit tests
211
212Running:
213
214```sh
215npm test
216```
217
218### E2E tests
219
220The E2E tests are written using Python, in order to learn how to eventually do
221this in web-platform-tests.
222
223### Installation
224
225Python 3.6+ and some dependencies are required:
226
227```sh
228python3 -m pip install --user -r tests/requirements.txt
229```
230
231### Running
232
233The E2E tests require BiDi server running on the same host. By default, tests
234try to connect to the port `8080`. The server can be run from the project root:
235
236```sh
237npm run e2e
238```
239
240Use the `PORT` environment variable to connect to another port:
241
242```sh
243PORT=8081 npm run e2e
244```
245
246### Examples
247
248Refer to [examples/README.md](examples/README.md).
249
250## WPT (Web Platform Tests)
251
252WPT is added as
253a [git submodule](https://git-scm.com/book/en/v2/Git-Tools-Submodules). To get run
254WPT tests:
255
256### Check out and setup WPT
257
258#### 1. Check out WPT
259
260```sh
261git submodule update --init
262```
263
264#### 2. Go to the WPT folder
265
266```sh
267cd wpt
268```
269
270#### 3. Set up virtualenv
271
272Follow the [_System
273Setup_](https://web-platform-tests.org/running-tests/from-local-system.html#system-setup)
274instructions.
275
276#### 4. Setup `hosts` file
277
278Follow
279the [`hosts` File Setup](https://web-platform-tests.org/running-tests/from-local-system.html#hosts-file-setup)
280instructions.
281
282##### 4.a On Linux, macOS or other UNIX-like system
283
284```sh
285./wpt make-hosts-file | sudo tee -a /etc/hosts
286```
287
288##### 4.b On **Windows**
289
290This must be run in a PowerShell session with Administrator privileges:
291
292```sh
293python wpt make-hosts-file | Out-File $env:SystemRoot\System32\drivers\etc\hosts -Encoding ascii -Append
294```
295
296If you are behind a proxy, you also need to make sure the domains above are excluded
297from your proxy lookups.
298
299#### 5. Set `WPT_BROWSER_PATH`
300
301Set the `WPT_BROWSER_PATH` environment variable to a Chrome, Edge or Chromium binary to launch.
302For example, on macOS:
303
304```sh
305# Chrome
306export WPT_BROWSER_PATH="/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary"
307export WPT_BROWSER_PATH="/Applications/Google Chrome Dev.app/Contents/MacOS/Google Chrome Dev"
308export WPT_BROWSER_PATH="/Applications/Google Chrome Beta.app/Contents/MacOS/Google Chrome Beta"
309export WPT_BROWSER_PATH="/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
310export WPT_BROWSER_PATH="/Applications/Chromium.app/Contents/MacOS/Chromium"
311
312# Edge
313export WPT_BROWSER_PATH="/Applications/Microsoft Edge Canary.app/Contents/MacOS/Microsoft Edge Canary"
314export WPT_BROWSER_PATH="/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge"
315```
316
317### Run WPT tests
318
319#### 1. Make sure you have Chrome Dev installed
320
321https://www.google.com/chrome/dev/
322
Randolf55431462023-03-29 13:00:36323#### 2. Build Chromedriver BiDi
Randolfb0fe9c12023-03-06 14:03:48324
325Oneshot:
326
327```sh
328npm run build
329```
330
331Continuously:
332
333```sh
334npm run watch
335```
336
337#### 3. Run
338
339```sh
340./wpt/wpt run \
Randolf55431462023-03-29 13:00:36341 --webdriver-binary runBiDiServer.sh \
Randolfb0fe9c12023-03-06 14:03:48342 --binary "$WPT_BROWSER_PATH" \
Randolf55431462023-03-29 13:00:36343 --manifest wpt/MANIFEST.json \
344 --metadata wpt-metadata/mapper/headless \
Randolfb0fe9c12023-03-06 14:03:48345 chromium \
346 webdriver/tests/bidi/
347```
348
349### Update WPT expectations if needed
350
351#### 1. Run WPT tests with custom `log-wptreport`:
352
353```sh
354./wpt/wpt run \
Randolf55431462023-03-29 13:00:36355 --webdriver-binary runBiDiServer.sh \
Randolfb0fe9c12023-03-06 14:03:48356 --binary "$WPT_BROWSER_PATH" \
Randolf55431462023-03-29 13:00:36357 --manifest wpt/MANIFEST.json \
358 --metadata wpt-metadata/mapper/headless \
Randolfb0fe9c12023-03-06 14:03:48359 --log-wptreport wptreport.json \
360 chromium \
361 webdriver/tests/bidi/
362```
363
364#### 2. Update expectations based on the previous test run:
365
366```sh
367./wpt/wpt update-expectations \
368 --product chromium \
Randolf55431462023-03-29 13:00:36369 --manifest wpt/MANIFEST.json \
370 --metadata wpt-metadata/mapper/headless \
371 wptreport.json
Randolfb0fe9c12023-03-06 14:03:48372```
373
374## How does it work?
375
376The architecture is described in the
377[WebDriver BiDi in Chrome Context implementation plan](https://docs.google.com/document/d/1VfQ9tv0wPSnb5TI-MOobjoQ5CXLnJJx9F_PxOMQc8kY)
378.
379
380There are 2 main modules:
381
3821. backend WS server in `src`. It runs webSocket server, and for each ws connection
383 runs an instance of browser with BiDi Mapper.
3842. front-end BiDi Mapper in `src/bidiMapper`. Gets BiDi commands from the backend,
385 and map them to CDP commands.
386
387### Contributing
388
389The BiDi commands are processed in the `src/bidiMapper/commandProcessor.ts`. To add a
390new command, add it to `_processCommand`, write and call processor for it.
391
392### Publish new `npm` release
393
Randolf55431462023-03-29 13:00:363941. Open a PR bumping the chromium-bidi version number in `package.json` for review:
Randolfb0fe9c12023-03-06 14:03:48395
396 ```sh
Randolf55431462023-03-29 13:00:36397 npm version patch -m 'Release v%s' --no-git-tag-version
Randolfb0fe9c12023-03-06 14:03:48398 ```
399
400 Instead of `patch`, use `minor` or `major` [as needed](https://semver.org/).
401
Randolf55431462023-03-29 13:00:364021. 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.
403 Our CI then automatically publishes the new release to npm based on the tag name.