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