Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
210 changes: 208 additions & 2 deletions index.bs
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,12 @@ spec: RFC9110; urlPrefix: https://httpwg.org/specs/rfc9110.html
spec: STREAMS; urlPrefix: https://streams.spec.whatwg.org/
type: dfn
text: ReadableStream; url: #readablestream
spec: WebSockets; urlPrefix: https://websockets.spec.whatwg.org/
type: dfn
text: WebSocket; url: #websocket
spec: WebTransport; urlPrefix: https://w3c.github.io/webtransport/
type: dfn
text: Cleanup WebTransport; url: #webtransport-cleanup
</pre>

<style>
Expand Down Expand Up @@ -766,7 +772,7 @@ The <dfn export>set of sessions for which an event is enabled</dfn> given |event

1. Let |sessions| be a new [=/set=].

1. For each |session| in [=active BiDI sessions=]:
1. For each |session| in [=active BiDi sessions=]:

1. If [=event is enabled=] with |session|, |event name| and |navigables|,
append |session| to |sessions|.
Expand Down Expand Up @@ -1543,6 +1549,20 @@ A [=BiDi session=] has a
A [=BiDi session=] has a <dfn>user context to proxy configuration map</dfn>, which is
a [=/map=] between [=user contexts=] and [=proxy configuration=].

An <dfn>emulated network conditions struct</dfn> is a [=struct=] with:
* [=struct/item=] named <dfn id="emulated-network-conditions-struct-offline"
for="emulated-network-conditions-struct">offline</dfn> which is a boolean or null.

A [=BiDi session=] has a <dfn for=session>emulated network conditions</dfn> which is
a [=struct=] with an [=struct/item=] named <dfn
for="emulated network conditions">default network conditions</dfn>, which is an
[=emulated network conditions struct=] or null, an [=struct/item=] named
<dfn for="emulated network conditions">user context network conditions</dfn>, which
is a weak map between [=user contexts=] and [=emulated network conditions struct=],
and a [=struct/item=] named
<dfn for="emulated network conditions">navigable network conditions</dfn>, which is a
weak map between [=navigables=] and [=emulated network conditions struct=].

When a [=user context=] is [=set/remove|removed=] from the
[=set of user contexts=], [=remove user context subscriptions=].

Expand Down Expand Up @@ -5930,6 +5950,7 @@ EmulationCommand = (
emulation.SetForcedColorsModeThemeOverride //
emulation.SetGeolocationOverride //
emulation.SetLocaleOverride //
emulation.SetNetworkConditions //
emulation.SetScreenOrientationOverride //
emulation.SetScriptingEnabled //
emulation.SetTimezoneOverride //
Expand Down Expand Up @@ -6276,6 +6297,128 @@ The [=remote end steps=] with |command parameters| are:

</div>

#### The emulation.setNetworkConditions Command #### {#command-emulation-setNetworkConditions}

The <dfn export for=commands>emulation.setNetworkConditions</dfn> command
emulates specific network conditions for the given browsing context or for a user
context.

<dl>
<dt>Command Type</dt>
<dd>
<pre class="cddl" data-cddl-module="remote-cddl">
emulation.SetNetworkConditions = (
method: "emulation.setNetworkConditions",
params: emulation.setNetworkConditionsParameters
)

emulation.setNetworkConditionsParameters = {
networkConditions: emulation.NetworkConditions / null,
? contexts: [+browsingContext.BrowsingContext],
? userContexts: [+browser.UserContext],
}

emulation.NetworkConditions = emulation.NetworkConditionsOffline

emulation.NetworkConditionsOffline = {
type: "offline"
}
</pre>
</dd>
<dt>Result Type</dt>
<dd>
<code>
EmptyResult
</code>
</dd>
</dl>

<div algorithm>

To <dfn>apply network conditions</dfn>:

1. For each [=WebSocket=] object |webSocket|:

1. Let |realm| be |webSocket|'s [=relevant Realm=].

1. Let |environment settings| be the [=environment settings object=] whose
[=realm execution context=]'s Realm component is |realm|.

1. If the result of [=WebDriver BiDi network is offline=] with |environment settings| is true:

1. [=Fail the WebSocket connection=] |webSocket|.

1. For each [=WebTransport=] object |webTransport|:

1. Let |realm| be |webSocket|'s [=relevant Realm=].

1. Let |environment settings| be the [=environment settings object=] whose
[=realm execution context=]'s Realm component is |realm|.

1. If the result of [=WebDriver BiDi network is offline=] with |environment settings| is true:

1. [=Cleanup WebTransport=] |webTransport|.

</div>

<div algorithm="remote end steps for emulation.setNetworkConditions">

The [=remote end steps=] with |command parameters| and |session| are:

1. If |command parameters| [=map/contains=] "<code>userContexts</code>"
and |command parameters| [=map/contains=] "<code>context</code>",
return [=error=] with [=error code=] [=invalid argument=].

1. Let |emulated network conditions| be null.

1. If |command parameters|["<code>networkConditions</code>"] is not null and
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For now the check for type can just be an assert. I see you're trying to define this for extensibility although it does make the API rather odd in the short term, and the obvious extensions into network conditions seem like they're going to be rather challenging to standardise. I wonder if we'd be better with just a network.setOffline({contexts, userContexts, offline: <bool>}) command for now.

Copy link
Contributor Author

@sadym-chromium sadym-chromium Sep 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we don't plan to extend for other network conditions (e.g. high-latency or low-bandwidth), I'd propose to:

  1. Move the method to emulation.setNetworkOffline, as it influences not only the network, but the navigator as well.
  2. Allow for only offline: true / null, as we cannot emulate being online when offline, we can only restore the default behavior.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, I believe that it still makes sense to keep it extendable and eventually introduce other conditions.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally, I still feel like a separate command would have been the better design for now. The only advantage I see of a single command is that it will make it easier in the future to switch atomically from a "network offline" state to an online state with some other configuration. But that would be possible either way (e.g. by allowing the configuration to be set when offline, and applying it when online).

This would have the advantage of not making the existing protocol more complex in service of uncertain future requirements.

However since there is already general agreement about the approach here I don't consider it a blocker.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ack, thanks for the clarification! I imagine we can extend the emulated conditions with some vendor-specific types in the nearest future until the proper specification is landed.

|command parameters|["<code>networkConditions</code>"]["<code>type</code>"]
equals "<code>offline</code>", set |emulated network conditions| to a new
[=emulated network conditions struct=] with
[=emulated-network-conditions-struct/offline=] set to true.

1. If the <code>contexts</code> field of |command parameters| is present:

1. Let |navigables| be the result of [=trying=] to
[=get valid top-level traversables by ids=] with
|command parameters|["<code>contexts</code>"].

1. For each |navigable| of |navigables|:

1. If |emulated network conditions| is null, [=map/remove=] |navigable| from
|session|'s [=emulated network conditions=]'s
[=emulated network conditions/navigable network conditions=]

1. Otherwise, [=map/set=] |session|'s [=emulated network conditions=]'s
[=emulated network conditions/navigable network conditions=][|navigable|] to
|emulated network conditions|.

1. If the <code>userContexts</code> field of |command parameters| is present:

1. Let |user contexts| be the result of [=trying=] to [=get valid user contexts=]
with |command parameters|["<code>userContexts</code>"].

1. For each |user context| of |user contexts|:

1. If |emulated network conditions| is null, [=map/remove=] |user context| from
|session|'s [=emulated network conditions=]'s
[=emulated network conditions/user context network conditions=].

1. Otherwise, [=map/set=] |session|'s [=emulated network conditions=]'s
[=emulated network conditions/user context network conditions=][|user context|]
to |emulated network conditions|.

1. If |command parameters| doesn't [=map/contain=] "<code>userContexts</code>"
and |command parameters| doesn't [=map/contain=] "<code>context</code>",
[=map/set=] |session|'s [=emulated network conditions=]'s
[=emulated network conditions/default network conditions=] to |emulated network conditions|.

1. [=Apply network conditions=].

1. Return [=success=] with data null.

</div>

#### The emulation.setScreenOrientationOverride Command #### {#command-emulation-setScreenOrientationOverride}

The <dfn export for=commands>emulation.setScreenOrientationOverride</dfn> command
Expand Down Expand Up @@ -9684,6 +9827,60 @@ and |user context| are:

</div>

<div algorithm>
The steps to <dfn>get emulated network conditions</dfn> given |related navigables|
are:

1. For each |navigable| of |related navigables|:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note: probably not important as long as we can only disable, but I'm wondering about scenarios where later we could support other network conditions eg throttling.

If navigable 1 is throttled and navigable 2 is offline, what should we do? We should probably defer that discussion to whenever we implement more conditions, but still curious if you have any thoughts about this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note: probably not important as long as we can only disable, but I'm wondering about scenarios where later we could support other network conditions eg throttling.

If navigable 1 is throttled and navigable 2 is offline, what should we do? We should probably defer that discussion to whenever we implement more conditions, but still curious if you have any thoughts about this.

This spec version defines the behavior as "the first created navigable wins". This scenario happens for shared workers. However IDK what exactly Chromium does in this case, and I don't have a strong opinion what it should do.


1. Let |top-level traversable| be |navigable|’s [=navigable/top-level traversable=].

1. Let |user context| be |top-level traversable|'s [=associated user context=].

1. For each |session| in [=active BiDi sessions=]:

1. If |session|'s [=emulated network conditions=]'s
[=emulated network conditions/navigable network conditions=]
[=map/contains=] |top-level traversable|, return |session|'s
[=emulated network conditions=]'s
[=emulated network conditions/navigable network conditions=][|top-level traversable|].

1. For each |session| in [=active BiDi sessions=]:

1. If |session|'s [=emulated network conditions=]'s
[=emulated network conditions/user context network conditions=]
[=map/contains=] |user context|, return |session|'s
[=emulated network conditions=]'s
[=emulated network conditions/user context network conditions=][|user context|].

1. For each |session| in [=active BiDi sessions=]:

1. If |session|'s [=emulated network conditions=]'s
[=emulated network conditions/default network conditions=] is not null,
return |session|'s [=emulated network conditions=]'s
[=emulated network conditions/default network conditions=].

1. Return null.

</div>

<div algorithm>
The <dfn export>WebDriver BiDi network is offline</dfn> steps given
[=environment settings object=] |settings| are:

1. Let |navigable| be |settings|'s [=relevant global object=]'s
<a>associated <code>Document</code></a>'s [=/node navigable=].

1. Let |emulated network conditions| be the result of
[=get emulated network conditions=] with [|navigable|].

1. If |emulated network conditions| is not null and |emulated network conditions|'s
[=emulated-network-conditions-struct/offline=] is true, return true.

1. Return false.

</div>

<div algorithm>
The [=remote end event trigger=] is the <dfn export>WebDriver BiDi before request sent</dfn> steps
given [=/request=] |request|:
Expand Down Expand Up @@ -9793,8 +9990,17 @@ given [=/request=] |request|:

Note: While waiting, no further processing of the request occurs.

1. Let |emulated network conditions| be the result of
[=get emulated network conditions=] with |related navigables|.

1. If |emulated network conditions| is not null and
|emulated network conditions|'s [=emulated-network-conditions-struct/offline=] is
true, return ([=network error=], "<code>complete</code>").

1. Return (|response|, |response status|).

Issue: Respect return value in Fetch's "HTTP-network-or-cache fetch" algorithm.

</div>

#### The network.fetchError Event #### {#event-network-fetchError}
Expand Down Expand Up @@ -13378,7 +13584,7 @@ The [=remote end event trigger=] is:
Define the following [=console steps=] with |method|, |args|, and
<var ignore>options</var>:

1. For each |session| in [=active BiDI sessions=]:
1. For each |session| in [=active BiDi sessions=]:

1. If |method| is "<code>error</code>" or "<code>assert</code>", let |level| be
"<code>error</code>". If |method| is "<code>debug</code>" or "<code>trace</code>"
Expand Down