WebDriver is a remote control interface that enables introspection and control of user agents. As such it can help developers to verify that their websites are working and performing well with all major browsers. The protocol is standardized by the W3C and consists of two separate specifications: WebDriver classic (HTTP) and the new WebDriver BiDi (Bi-Directional).
This newsletter gives an overview of the work we’ve done as part of the Firefox 136 release cycle.
Contributions
Firefox is an open source project, and we are always happy to receive external code contributions to our WebDriver implementation. We want to give special thanks to everyone who filed issues, bugs and submitted patches.
In Firefox 136, several contributors managed to land fixes and improvements in our codebase:
- Liam (ldebeasi) improved the
browsingContext.contextDestroyed
event in WebDriver BiDi. - Krzysztof Jan Modras (chrmod) refactored an internal module for handling addons/webextensions.
WebDriver code is written in JavaScript, Python, and Rust so any web developer can contribute! Read how to setup the work environment and check the list of mentored issues for Marionette, or the list of mentored JavaScript bugs for WebDriver BiDi. Join our chatroom if you need any help to get started!
General
Bug Fixes
- Firefox now handles WebSocket port conflicts for the RemoteAgent more efficiently. If the port specified via the
--remote-debugging-port
command-line argument cannot be acquired within 5 seconds, such as when another Firefox process is already using it, Firefox will now shut down instead of hanging. - Navigations using the HTTP scheme, triggered by the
WebDriver:Navigate
command in Marionette orbrowsingContext.navigate
in WebDriver BiDi, will no longer be automatically upgraded to HTTPS. These requests will now remain on HTTP, as originally intended.
WebDriver BiDi
Updated: session.subscribe
now returns a subscription ID
The return value of the session.subscribe
command has been updated to include a session.Subscription
which is a unique ID identifying the event subscription.
Example: adding a global subscription for network
events:
-> {
"method": "session.subscribe",
"params": {
"events": ["network"]
},
"id": 1
}
<- {
"type": "success",
"id": 1,
"result": {
"subscription": "9a29c77b-5e7b-43f1-bc6f-20b5228bf207"
}
}
New: subscriptions
parameter for session.unsubscribe
The subscription IDs can be used with the new subscriptions
parameters of session.unsubscribe
to remove specific event subscriptions. Previously, it was necessary to unsubscribe using the same attributes provided to session.subscribe
. And if there were several calls to session.unsubscribe
performed from different areas of the test, there could be unexpected side-effects.
With the new subscriptions
parameter, only the subscriptions matching the provided subscription IDs will be removed. The parameter must be an array of subscription IDs. If any ID doesn’t match a known (and not yet removed) subscription ID, an InvalidArgumentError
is raised.
When subscriptions
is provided, the events
or contexts
parameters should not be present, otherwise an InvalidArgumentError
will be raised.
Example: adding a second subscription for a specific context:
-> {
"method": "session.subscribe",
"params": {
"events": ["browsingContext.contextCreated"],
"contexts": ["304a76e3-e177-4355-b598-9f5f02808556"]
},
"id": 2
}
<- {
"type": "success",
"id": 2,
"result": {
"subscription": "e1a54927-dc48-4301-b219-812ceca13496"
}
}
Now removing both subscriptions at once:
-> {
"method": "session.unsubscribe",
"params": {
"subscriptions": ["9a29c77b-5e7b-43f1-bc6f-20b5228bf207", "e1a54927-dc48-4301-b219-812ceca13496"]
},
"id": 3
}
<- { "type": "success", "id": 3, "result": {} }
Using the subscriptions
parameter allows to remove global and context-specific subscriptions simultaneously, without unexpected side effects.
Deprecated: contexts
parameter for session.unsubscribe
It remains possible to globally unsubscribe by using only the events
parameter. However the additional contexts
parameter is now deprecated and will be removed in a future version. To remove context-specific subscriptions, please use the subscriptions
parameter instead.
New: userContexts
parameter for script.addPreloadScript
The script.addPreloadScript
command now supports a userContexts
parameter, allowing clients to specify in which user contexts (containers) a script should be automatically loaded — including new browsing contexts created within those user contexts.
Note: If userContexts
is provided, the contexts
parameter must not be included. Using both at the same time will raise an InvalidArgumentError
.
Example: adding a preload script for a specific user context:
-> {
"method": "script.addPreloadScript",
"params": {
"arguments": [],
"functionDeclaration": "(arg) => { console.log('Context created in test user context'); }",
"userContexts": ["528545b6-89d6-486e-a85c-517212654c13"]
},
"id": 4
}
<- { "type": "success", "id": 4, "result": { "script": "168cff9c-9de0-44e7-af95-0c478ad2596f" } }
Updated: browsingContext.contextDestroyed
event returns full tree
Thanks to Liam’s contribution, the browsingContext.contextDestroyed
event now returns the full serialized tree of destroyed contexts — including all its child contexts.
Example: closing a tab with two iframes:
{
"type": "event",
"method": "browsingContext.contextDestroyed",
"params": {
"children": [
{
"children": [],
"context": "30064771075",
"originalOpener": null,
"url": "https://example.bidi.com/frame1",
"userContext": "1c88a947-3297-4733-9cd7-c16a863a602d"
},
{
"children": [],
"context": "30064771076",
"originalOpener": null,
"url": "about:blank",
"userContext": "1c88a947-3297-4733-9cd7-c16a863a602d"
}
],
"context": "ab8c33a7-6bc8-45cc-a068-7cdcef518577",
"originalOpener": null,
"url": "https://example.bidi.com/",
"userContext": "1c88a947-3297-4733-9cd7-c16a863a602d",
"parent": null
}
}
Leave a Reply