1. Prerendering infrastructure
1.1. Extensions to the Document
interface
We’d modify [HTML]'s centralized definition of Document
as follows:
partial interface Document {readonly attribute boolean prerendering ; // Under "special event handler IDL attributes that only apply to Document objects"attribute EventHandler onprerenderingchange ; };
The onprerenderingchange
attribute is an event handler IDL attribute corresponding to the prerenderingchange
event handler event type. (We would update the corresponding table in [HTML], which currently only contains onreadystatechange
.)
As is customary for [HTML], the definition of prerendering
would be located in another section of the spec; we’d place it in the new section introduced below:
1.2. Prerendering navigables
The following section would be added as a new sub-section of [HTML]'s Navigables section.
Every navigable has a loading mode, which is one of the following:
- "
default
" -
No special considerations are applied to content loaded in this navigable
- "
prerender
" -
This navigable is displaying prerendered content
By default, a navigable's loading mode is "default
". A navigable whose loading mode is "prerender
" is known as a prerendering navigable. A prerendering navigable that is also a top-level traversable is known as a prerendering traversable.
Although there are only two values for the loading mode, we use a flexible structure in anticipation of other future loading modes, such as those provided by fenced frames, portals, and uncredentialed (cross-site) prerendering. It’s not yet clear whether that anticipation is correct; if, as those features gain full specifications, it turns out not to be, we will instead convert this into a boolean.
Every prerendering traversable has a prerender initial response search variance, which is a URL search variance or null, and is initially null.
document.
prerendering
- Returns true if the page is being presented in a non-interactive "prerendering-like" context. In the future, this would include a visible document in a
<portal>
element, both when loaded into it or via predecessor adoption.
The prerendering
getter steps are to return true if this has a non-null node navigable that is a prerendering navigable; otherwise, false.
Every Document
has prerender records, which is a list of prerender records. This is used to fulfill navigations to a given URL by instead activating the corresponding prerendering traversable.
A prerender record is a struct with the following items:
-
starting URL, a URL
-
No-Vary-Search hint, a URL search variance (the default URL search variance by default)
-
start time, a
DOMHighResTimeStamp
(0.0 by default) -
prerendering traversable, a prerendering traversable
-
If prerenderRecord’s starting URL is equal to url, return true.
-
Let searchVariance be prerenderRecord’s prerendering traversable's prerender initial response search variance.
-
If searchVariance is not null:
-
If prerenderRecord’s starting URL and url are equivalent modulo search variance given searchVariance, return true.
-
-
Return false.
-
If prerenderRecord matches a URL given url, return true.
-
If prerenderRecord’s prerendering traversable's prerender initial response search variance is null:
-
Let expectedSearchVariance be prerenderRecord’s No-Vary-Search hint.
-
If prerenderRecord’s starting URL and url are equivalent modulo search variance given expectedSearchVariance, return true.
-
-
Return false.
Every Document
has a post-prerendering activation steps list, which is a list where each item is a series of algorithm steps. For convenience, we define the post-prerendering activation steps list for any platform object platformObject as:
- If platformObject is a node
-
-
Return platformObject’s node document's post-prerendering activation steps list.
-
- Otherwise
-
-
Assert: platformObject’s relevant global object is a
Window
object.
-
Return platformObject’s relevant global object's associated Document's post-prerendering activation steps list.
-
Every Document
has an activation start time, which is initially a DOMHighResTimeStamp
with a time value of zero.
To start user-agent initiated prerendering given a URL startingURL:
-
Assert: startingURL’s scheme is an HTTP(S) scheme.
-
Let prerenderingTraversable be the result of creating a new top-level traversable given null and the empty string.
-
Set prerenderingTraversable’s loading mode to "
prerender
". -
Navigate prerenderingTraversable to startingURL using prerenderingTraversable’s active document.
We treat this initial navigations as prerenderingTraversable navigating itself, which will ensure all relevant security checks pass.
-
Let record be a prerender record with starting URL startingURL and prerendering traversable prerenderingTraversable.
-
When the user indicates they wish to commit a navigation to an activationURL which is a URL such that record matches a URL given activationURL:
-
If the user indicates they wish to create a new user-visible top-level traversable while doing so (e.g., by pressing Shift+Enter after typing in the address bar):
-
Update the successor for activation given prerenderingTraversable, startingURL, and activationURL.
-
Update the user agent’s user interface to present prerenderingTraversable, e.g., by creating a new tab/window.
-
Finalize activation for prerenderingTraversable given startingURL’s origin.
-
-
Alternately, if the user indicates they wish to commit the navigation into an existing top-level traversable predecessorTraversable (e.g., by pressing Enter after typing in the address bar):
-
Activate prerenderingTraversable in place of predecessorTraversable given "
push
", startingURL, and activationURL.
-
-
The user might never indicate such a commitment, or might take long enough to do so that the user agent needs to reclaim the resources used by the prerender for some more immediate task. In that case the user agent can destroy prerenderingTraversable.
Document
referrerDoc, a referrer policy referrerPolicy, and a URL search variance nvsHint:
-
Assert: startingURL’s scheme is an HTTP(S) scheme.
-
If referrerDoc’s node navigable is not a top-level traversable, then return.
Currently, prerendering from inside a child navigable is not specified or implemented. Doing so would involve tricky considerations around how the prerendered navigable appears in the navigable tree.
-
If referrerDoc’s browsing context is an auxiliary browsing context, then return.
This avoids having to deal with any potential opener relationship between the prerendering traversable and referrerDoc’s browsing context's opener browsing context.
-
If referrerDoc’s origin is not same site with startingURL’s origin, then return.
Currently, cross-site prerendering is not specified or implemented, although we have various ideas about how it could work in this repository’s explainers.
-
For each record of referrerDoc’s prerender records:
-
If record’s starting URL is startingURL, then return.
-
-
Let prerenderingTraversable be the result of creating a new top-level traversable.
-
Set prerenderingTraversable’s loading mode to "
prerender
". -
Let prerenderRecord be a prerender record with starting URL startingURL, No-Vary-Search hint nvsHint, start time the current high resolution time for the relevant global object of referrerDoc, and prerendering traversable prerenderingTraversable.
-
Append prerenderRecord to referrerDoc’s prerender records.
-
Set prerenderingTraversable’s remove from referrer to be an algorithm which removes prerenderRecord from referrerDoc’s prerender records.
As with all top-level traversables, the prerendering traversable can be destroyed for any reason, for example if it becomes unresponsive, performs a restricted operation, or if the user agent believes prerendering takes too many resources.
-
Navigate prerenderingTraversable to startingURL using referrerDoc, with referrerPolicy set to referrerPolicy.
To update the successor for activation given a prerendering traversable successorTraversable, a URL startingURL, and a URL activationURL:
-
Let successorDocument be successorTraversable’s active document.
-
If startingURL equals successorDocument’s URL and startingURL does not equal activationURL:
-
Assert: successorDocument can have its URL rewritten to activationURL.
-
Let navigation be successorDocument’s relevant global object's navigation API.
-
Let continue be the result of firing a push/replace/reload
navigate
event at navigation given "replace", activationURL, and true. -
If continue is true, run the URL and history update steps given successorDocument and activationURL.
This allows for the URL of the prerender to match the URL actually navigated to, in the case of inexact matching based on `
No-Vary-Search
`. -
To activate a prerendering traversable successorTraversable in place of a top-level traversable predecessorTraversable given a history handling behavior historyHandling, a URL startingURL, a URL activationURL, an optional navigation ID navigationId:
-
Assert: successorTraversable’s active document's is initial about:blank is false.
-
If navigationId is not given, then let navigationId be the result of generating a random UUID.
-
Let referrerOrigin be predecessorTraversable’s active document's origin.
-
Set predecessorTraversable’s ongoing navigation to navigationId.
This will have the effect of aborting any other ongoing navigations of predecessorTraversable.
-
In parallel, run these steps:
-
Let unloadPromptCanceled be the result of checking if unloading is user-canceled for predecessorTraversable’s active document's inclusive descendant navigables.
-
If unloadPromptCanceled is true, or predecessorTraversable’s ongoing navigation is no longer navigationId, then abort these steps.
-
Queue a global task on the navigation and traversal task source given predecessorTraversable’s active window to abort predecessorTraversable’s active document.
-
Update the successor for activation given successorTraversable, startingURL, and activationURL.
-
Append session history traversal steps to predecessorTraversable to perform the following steps:
-
Assert: successorTraversable’s current session history step is 0.
-
Assert: successorTraversable’s session history entries's size is 1.
-
Let successorEntry be successorTraversable’s session history entries[0].
-
Remove successorEntry from successorTraversable’s session history entries.
At this point, successorTraversable is empty and can be unobservably destroyed. (As long as the implementation takes care to keep successorEntry, including its document and that
Document
's browsing context, alive for the next step.) -
Finalize a cross-document navigation given predecessorTraversable, historyHandling, and successorEntry.
Because we have moved the entire session history entry, including the contained document's browsing context, this means traversing across the associated history entries will cause a browsing context group switch, similar to what happens with the `
Cross-Origin-Opener-Policy
` header. Importantly, this will sever any opener relationships, in the same way as COOP. Such traversal includes both the actual activation process here, where we make successorEntry active, but also e.g. the user pressing the back button (or the page usinghistory.back()
) after activation, which will switch in the other direction. -
Update the user agent’s user interface to reflect this change, e.g., by updating the tab/window contents and the browser chrome.
-
Finalize activation for successorTraversable given referrerOrigin.
-
Perhaps we should do something with WebDriver BiDi here? See w3c/webdriver-bidi#321. Right now the pre-in parallel part of the navigate algorithm will send WebDriver BiDi navigation started as if it were a normal navigation, but then nothing will happen to indicate the navigation finishes.
-
-
-
For each navigable of traversable’s active document's inclusive descendant navigables, queue a global task on the navigation and traversal task source, given navigable’s active window, to perform the following steps:
-
For each origin → hintSet in navigable’s prerender-scoped Accept-CH cache:
-
Set Accept-CH cache[origin] to hintSet.
-
-
Let doc be navigable’s active document.
-
We should really propagate the loading mode change here, in the posted task. This is where implementations would update what is returned by
document.prerendering
. However, right now it lives on the traversable, so it gets magically updated when we move over the session history entry. Probably we need to move it to theDocument
. -
If doc’s origin is the same as origin, then set doc’s activation start time to the current high resolution time for doc’s relevant global object.
-
Fire an event named
prerenderingchange
at doc. -
For each steps in doc’s post-prerendering activation steps list:
-
Run steps.
These steps might return something, like a
Promise
. That is just an artifact of how the spec is modified; such return values can always be ignored. -
Assert: running steps did not throw an exception.
The order here is observable for
Document
s that share an event loop, but not for those in separate event loops. -
-
To ensure that the references for a prerendering traversable are cleared once it is destroyed, modify destroy a top-level traversable by appending the following step:
-
If traversable is a prerendering traversable and traversable’s remove from referrer is not null, then call traversable’s remove from referrer.
1.3. Modifications to creating navigables
-
Set navigable’s loading mode to element’s node navigable's loading mode.
2. Navigation and session history
2.1. Allowing activation in place of navigation
Document
predecessorDocument and URL url:
-
Let recordToUse be null.
-
For each record of predecessorDocument’s prerender records:
-
If record’s prerendering traversable's active document's is initial about:blank is true, then continue.
-
If record’s starting URL is equal to url:
-
Set recordToUse to record.
-
-
If recordToUse is null and record matches a URL given url:
-
Set recordToUse to record.
-
-
-
If recordToUse is not null:
-
Remove recordToUse from predecessorDocument’s prerender records.
-
-
Return recordToUse.
-
Assert: this is running in parallel.
-
If any of the following conditions hold:
-
navigable is not a top-level traversable;
-
navigable is a prerendering traversable;
-
navigable is a fenced frame;
The concept of a fenced frame navigable is not yet defined but we need to link to it once it exists.
-
cspNavigationType is not "
other
"; or -
documentResource is not null
then return null.
-
-
Let predecessorDocument be navigable’s active document.
-
Let cutoffTime be null.
-
While true:
-
Let completeRecord be the result of finding a matching complete prerender record given predecessorDocument and url.
-
If completeRecord is not null, return completeRecord.
-
Let potentialRecords be an empty list.
-
For each record of predecessorDocument’s prerender records:
-
If all of the following are true, then append record to potentialRecords:
-
record’s prerendering traversable's active document's is initial about:blank is true.
-
record is expected to match a URL given url.
-
cutoffTime is null or record’s start time is less than cutoffTime.
-
-
-
If potentialRecords is empty, return null.
-
Wait until the ongoing navigation of the prerendering traversable of any element of predecessorDocument’s prerender records changes.
-
If cutoffTime is null and any element of potentialRecords has a prerendering traversable whose active document's is initial about:blank is false, set cutoffTime to the current high resolution time for the relevant global object of predecessorDocument.
See also: wait for a matching prefetch record. The logic for blocking on ongoing prerenders is similar to the prefetch case.
-
Patch the navigate algorithm to allow the activation of a prerendering traversable in place of a normal navigation as follows:
-
Let matchingPrerenderRecord be the result of waiting for a matching prerendering record given navigable, url, cspNavigationType, and documentResource.
-
If matchingPrerenderRecord is not null, then:
-
Let matchingPrerenderedNavigable be matchingPrerenderRecord’s prerendering traversable.
-
Let startingURL be matchingPrerenderRecord’s starting URL.
-
Activate matchingPrerenderedNavigable in place of navigable given historyHandling, startingURL, url, and navigationId.
-
Abort these steps.
-
2.2. Navigation fetch changes
-
Let initiatorOrigin be entry’s document state's initiator origin.
Append the following steps after the first sub-step under "While true:":
-
If navigable is a prerendering navigable and currentURL’s origin is not same site with initiatorOrigin, then:
-
If navigable is a top-level traversable, then return null.
-
Otherwise, the user agent must wait to continue this algorithm until navigable’s loading mode becomes "
normal
". At any point during this wait (including immediately), it may instead choose to destroy navigable’s top-level traversable and return null from this algorithm.
-
Append the following steps toward the end of the algorithm, after the steps which check locationURL:
-
If navigable is a prerendering navigable, and responseOrigin is not same origin with initiatorOrigin, then:
-
Let loadingModes be the result of getting the supported loading modes for response.
-
If loadingModes does not contain `
credentialed-prerender
`, then return null.In the future we could possibly also allow the
uncredentialed-prerender
token to work here. However, since that is primarily intended for the cross site case, which isn’t specified or implemented yet, we don’t want to encourage its use in the wild, so for now we specify that prerendering fails if only theuncredentialed-prerender
token is found.
-
-
If navigable is a prerendering navigable, and any of the following hold:
-
failure is true;
-
navigationParams’s request is null;
-
navigationParams’s request's current URL's scheme is not a HTTP(S) scheme;
-
navigationParams’s response does not support prefetch;
Responses which are ineligible for prefetch, e.g. because they have an error status, are not eligible for prerender either. A future version of this specification might allow responses to more clearly delineate the two. -
navigationParams’s response has a `
Content-Disposition
` header specifying theattachment
disposition type; or
then:
-
Destroy navigable’s top-level traversable.
-
Return.
-
-
If navigable is a prerendering traversable and navigable’s prerender initial response search variance is null:
-
Set navigable’s prerender initial response search variance to the result of obtaining a URL search variance given navigationParams’s response.
-
-
If navigable is a prerendering navigable, then return without invoking the external software package.
We could also allow prerendering activations in place of redirects, not just in place of navigations. We’ve omitted that for now as it adds complexity and is not yet implemented anywhere to our knowledge.
2.3. Maintaining a trivial session history
-
If navigable is a prerendering navigable, then set historyHandling to "
replace
".
-
If navigable is a prerendering navigable, then set historyHandling to "
replace
".
2.4. Interaction with worker lifetime
A worker is said to be an active needed worker if any of its owners are either Document
objects that are fully active and their node navigable is not a prerendering navigable, or active needed workers.
This means that the worker’s script would load, but the execution would be suspended until the document is activated.
2.5. Cleanup upon discarding a Document
Modify the destroy algorithm for Document
s by appending the following step:
-
Empty document’s post-prerendering activation steps list.
3. Interaction with other specifications and concepts
3.1. Interaction with Page Visibility
Documents in prerendering navigables always have a visibility state of "hidden
".
We should probably explicitly update this, similar to how we need to update document.prerendering
.
3.2. Interaction with system focus
Prerendering traversables never have system focus.
3.3. Extensions to the PerformanceNavigationTiming
interface
Extend the PerformanceNavigationTiming
interface as follows:
partial interface PerformanceNavigationTiming {readonly attribute DOMHighResTimeStamp activationStart ; };
The activationStart
getter steps are:
-
Return this's relevant global object's associated Document's activation start time.
3.4. Interaction with Client Hint Cache
We need to ensure that the Accept-CH cache, which is owned by user agent as a global storage, is not modified while prerendering, but is properly updated after activation. The following modifications ensure this.
Each prerendering navigable has a prerender-scoped Accept-CH cache, which is an ordered map of origin to client hints sets.
This stores which client hints each origin has opted into receiving, until it can be copied to the global Accept-CH cache when activation is finalized.
-
Let navigable be settingsObject’s global object's navigable.
-
Let originMatchingEntries be the entries in the Accept-CH cache whose origin is same origin with settingsObject’s origin.
-
If navigable is a prerendering navigable, then:
-
Let prerenderAcceptClientHintsCache be navigable’s prerender-scoped Accept-CH cache.
-
Let origin be settingsObject’s origin.
-
If prerenderAcceptClientHintsCache[origin] exists, then let originMatchingEntries be the entries in the prerenderAcceptClientHintsCache whose origin is same origin with origin.
-
-
Let navigable be settingsObject’s global object's navigable.
-
If navigable is a prerendering navigable, set navigable’s prerender-scoped Accept-CH cache[origin] to hintSet.
-
Otherwise, set Accept-CH cache[origin] to hintSet.
4. The `Supports-Loading-Mode
` HTTP response header
The following section would be added as a sub-section of [HTML]'s Loading web pages section.
In some cases, cross-origin web pages might not be prepared to be loaded in a novel context. To allow them to opt in to being loaded in such ways, the `Supports-Loading-Mode
` HTTP response header can be used. This header is a structured header; if present its value must be one or more of the tokens listed below.
The parsing is actually done as a list of tokens, and unknown tokens will be ignored.
The `credentialed-prerender
` token indicates that the response can be used to create a prerendering navigable, despite the prerendering being initiated by a cross-origin same-site referrer. Without this opt-in, such prerenders will fail, as outlined in § 2.2 Navigation fetch changes.
The `uncredentialed-prefetch
` token indicates that the response is suitable to use even if a top-level navigation to this URL would ordinarily send credentials such as cookies. For instance, the response may be identical or it may be semantically equivalent (e.g., an HTML resource containing script which can update the document after navigation, when local user state is available).
To get the supported loading modes for a response response:
-
If response is a network error, then return an empty list.
-
Let slmHeader be the result of getting a structured field value given `
Supports-Loading-Mode
` and "list
" from response’s header list. -
Return a list containing all elements of slmHeader that are tokens.
5. Preventing intrusive behaviors
Various behaviors are disallowed in prerendering navigables because they would be intrusive to the user, since the prerendered content is not being actively interacted with.
5.1. Downloading resources
Modify the download the hyperlink algorithm to ensure that downloads inside prerendering navigable are delayed until activation, by inserting the following before the step which goes in parallel:
-
If subject’s node navigable is a prerendering navigable, then append the following step to subject’s post-prerendering activation steps list and return.
5.2. User prompts
Window
window, by prepending the following step:
-
If window’s navigable is a prerendering navigable, then return true.
print()
method steps by prepending the following step:
-
If this's navigable is a prerendering navigable, then return.
5.3. Delaying async API results
Many specifications need to be patched so that, if a given algorithm invoked in a prerendering navigable, most of its work is deferred until the navigable’s top-level traversable is activated. This is tricky to do uniformly, as many of these specifications do not have great hygeine around using the event loop. Nevertheless, the following sections give our best attempt.
5.3.1. The [DelayWhilePrerendering]
extended attribute
To abstract away some of the boilerplate involved in delaying the action of asynchronous methods until activation, we introduce the [DelayWhilePrerendering]
Web IDL extended attribute. It indicates that when a given method is called in a prerendering navigable, it will immediately return a pending promise and do nothing else. Only upon activation will the usual method steps take place, with their result being used to resolve or reject the previously-returned promise.
The [DelayWhilePrerendering]
extended attribute must take no arguments, and must only appear on a regular or static operation whose return type is a promise type or undefined
, and whose exposure set contains only Window
.
[DelayWhilePrerendering]
extended attribute are replaced with the following:
-
Let realm be the current realm.
-
If the operation in question is a regular operation, then set realm to the relevant realm of this.
-
If realm’s global object's navigable is a prerendering navigable, then:
-
Let promise be a new promise, created in realm.
-
Append the following steps to this's post-prerendering activation steps list:
-
If this operation’s return type is a promise type, then return promise.
-
-
Otherwise, return the result of running the originally-specified steps for this operation, with the same this and arguments.
5.3.2. Service Workers
Add [DelayWhilePrerendering]
to update()
, unregister()
, register(scriptURL, options)
, postMessage(message, transfer)
, and postMessage(message, options)
.
This allows prerendered page to take advantage of existing service workers, but not have any effect on the state of service worker registrations.
5.3.3. BroadcastChannel
Add [DelayWhilePrerendering]
to postMessage()
.
5.3.4. Geolocation API
getCurrentPosition()
method steps by prepending the following step:
-
If this's relevant global object's navigable is a prerendering navigable, then append the following steps to this's post-prerendering activation steps list and return.
watchPosition()
method steps by prepending the following step:
-
If this's relevant global object's navigable is a prerendering navigable, then:
-
Let watchId be an implementation-defined
unsigned long
, and note it as a post-prerendering activation geolocation watch process ID. -
Append the following steps to this's post-prerendering activation steps list, with the modification that the watchId generated must use watchId as its ID, and return watchId.
-
clearWatch(watchId)
method steps by prepending the following step:
-
If this's relevant global object's navigable is a prerendering navigable, then:
-
If watchId is a post-prerendering activation geolocation watch process ID, then remove its corresponding steps from this's post-prerendering activation steps list.
-
Return.
-
5.3.5. Web Serial API
Add [DelayWhilePrerendering]
to requestPort()
.
TODO: the below could probably be done by generalizing [DelayWhilePrerendering]
to use owner document while in dedicated workers.
getPorts()
method steps by inserting the following steps after the initial creation of promise:
-
Let document be this's relevant global object's associated Document, if this's relevant global object is a
Window
, or this's relevant global object's owner document, if this's relevant global object is aDedicatedWorkerGlobalScope
. -
If document is null, then return a promise rejected with a "
SecurityError
"DOMException
. -
If document’s node navigable is a prerendering navigable, then append the following steps to document’s post-prerendering activation steps list and return promise.
5.3.6. Notifications API
Add [DelayWhilePrerendering]
to requestPermission()
.
Notification()
constructor steps by replacing the step which goes in parallel with the following:
-
If this's relevant global object's navigable is a prerendering navigable, then append these steps to this's post-prerendering activation steps list. Otherwise, run these steps in parallel.
permission
static getter steps by replacing them with the following:
-
If the current global object's navigable is a prerendering navigable, then return "
default
".This allows implementations to avoid looking up the actual permission state, which might not be synchronously accessible especially in the case of prerendering navigables. Web developers can then call
Notification.requestPermission()
, which per the above modifications will only actually do anything after activation. At that time we might discover that the permission is "granted
" or "denied
", so the browser might not actually ask the user like would normally be the case with "default
". But that’s OK: it’s not observable to web developer code. -
Otherwise, get the notifications permission state and return it.
5.3.7. Web MIDI API
Add [DelayWhilePrerendering]
to requestMIDIAccess()
.
5.3.8. Idle Detection API
Add [DelayWhilePrerendering]
to start()
.
The other interesting method, IdleDetector.requestPermission()
, is gated on transient activation. However, even if permission was previously granted for the origin in question, we delay starting any idle detectors while prerendering.
5.3.9. Generic Sensor API
start()
method steps by inserting the following steps after the state is set to "activating
":
-
If this's relevant global object's navigable is a prerendering navigable, then append the following steps to this's post-prerendering activation steps list and return.
-
If this.
[[state]]
is "idle
", then return.This ensures that if this portion of the algorithm was delayed due to prerendering, and in the meantime
stop()
was called, we do nothing upon activating the prerender.
5.3.10. Web NFC
Add [DelayWhilePrerendering]
to write()
and scan()
.
5.3.11. Battery Status API
getBattery()
method steps by prepending the following step:
-
If this's relevant global object's navigable is a prerendering navigable, then append the following steps to this's post-prerendering activation steps list and return this.[[BatteryPromise]].
5.3.12. Screen Orientation API
-
Let promise be a new promise.
-
If this's relevant global object's navigable is a prerendering navigable, then append the following steps to this's post-prerendering activation steps list and return promise.
-
If the user agent does not support locking the screen orientation, then reject promise with a "
NotSupportedError
"DOMException
and return promise. -
If the document's active sandboxing flag set has the sandboxed orientation lock browsing context flag set, or the user agent doesn’t meet the pre-lock conditions to perform an orientation change, then reject promise with a "
SecurityError
"DOMException
and return promise. -
Set the document's [[orientationPendingPromise]] to promise.
Add [DelayWhilePrerendering]
to unlock()
.
This latter modification is necessary to ensure that code that calls screen.orientation.lock()
followed by screen.orientation.unlock()
produces the expected results.
5.3.13. Gamepad
getGamepads()
method steps by prepending the following step:
-
If this's relevant global object's navigable is a prerendering navigable, then return an empty sequence.
Modify the discussion of the gamepadconnected
and gamepaddisconnected
events to specify that the user agent must not dispatch these events if the Window
object’s navigable is a prerendering navigable.
gamepadconnected
section to indicate that every Document
document’s post-prerendering activation steps list should gain the following steps:
-
If document is allowed to use the "
gamepad
" feature, and document’s relevant settings object is a secure context, and any gamepads are connected, then for each connected gamepad, fire an event namedgamepadconnected
at document’s relevant global object usingGamepadEvent
, with itsgamepad
attribute initialized to a newGamepad
object representing the connected gamepad.
5.3.14. Encrypted Media Extensions
Add [DelayWhilePrerendering]
to requestMediaKeySystemAccess()
.
5.3.15. Media Autoplay
Modify the playing the media resource section to indicate that the the current playback position of a HTMLMediaElement
must increase monotonically only when the Document
is not prerendering
.
5.3.16. Media Capture and Streams
Add [DelayWhilePrerendering]
to getUserMedia()
, getUserMedia()
and enumerateDevices()
.
MediaDevices
section by prepending the following step to the device change notification steps:
-
If this's relevant global object's navigable is a prerendering navigable, then return.
5.3.17. Web Audio API
The concept, allowed to start, is used in the spec, but details are left implementation-defined.
To restrict auto playback while prerendering, add the following rule in the AudioContext
interface section.
The AudioContext
is never allowed to start while prerendering.
Also modify AudioContext()
constructor steps to have the following step before returning the constructed object.
-
Else if context is not allow to start only due to the prerendering, then append the following steps to context’s post-prerendering activation steps list.
-
Set the [[control thread state]] on context to running.
-
Queue a control message to resume context.
-
Developers might call resume()
while prerendering. In that case, the context is not allow to start, and appends a Promise
to [[pending resume promises]].
The Promise
will be resolved in the activation steps above.
The AudioScheduledSourceNode
interface has a start(when)
method and the AudioBufferSourceNode
interface has a start(when, offset, duration)
method that might affect [[control thread state]].
But they don’t as the context is not allowed to start and it prevents the algorithm from setting the [[control thread state]].
This would not matter because the node can automatically start when the context starts.
5.3.18. Audio Output Devices API
Add [DelayWhilePrerendering]
to selectAudioOutput()
.
5.3.19. Push API
Add [DelayWhilePrerendering]
to subscribe()
.
5.3.20. Background Fetch
Add [DelayWhilePrerendering]
to fetch()
.
5.3.21. Storage API
Add [DelayWhilePrerendering]
to persist()
.
5.3.22. WebUSB API
Add [DelayWhilePrerendering]
to getDevices()
and requestDevice()
.
5.3.23. Web Bluetooth
Add [DelayWhilePrerendering]
to getDevices()
and requestDevice()
.
5.3.24. WebHID API
Add [DelayWhilePrerendering]
to getDevices()
and requestDevice()
.
5.3.25. WebXR Device API
Add [DelayWhilePrerendering]
to requestSession()
.
5.3.26. Credential Management
Add [DelayWhilePrerendering]
to get()
, store()
, and create()
.
5.3.27. Web Speech API
Add [DelayWhilePrerendering]
to speak(utterance)
, cancel()
, pause()
, and resume()
.
Add [DelayWhilePrerendering]
to start()
, stop()
, and abort()
.
5.3.28. Web Locks API
Add [DelayWhilePrerendering]
to request(name, callback)
, request(name, options, callback)
, and query()
.
5.3.29. Custom Scheme Handlers
registerProtocolHandler(scheme, url)
method steps by overwriting the first few steps, before it goes in parallel, as follows:
-
Let (normalizedScheme, normalizedURLString) be the result of running normalize protocol handler parameters with scheme, url, and this's relevant settings object.
-
If this's relevant global object's navigable is a prerendering navigable, then append the following steps to this's post-prerendering activation steps list and return.
unregisterProtocolHandler(scheme, url)
method steps by overwriting the first few steps, before it goes in parallel, as follows:
-
Let (normalizedScheme, normalizedURLString) be the result of running normalize protocol handler parameters with scheme, url, and this's relevant settings object.
-
If this's relevant global object's navigable is a prerendering navigable, then append the following steps to this's post-prerendering activation steps list and return.
5.4. Implicitly restricted APIs
Some APIs do not need modifications because they will automatically fail or no-op without a property that a prerendering navigable, its active window, or its active document will never have. These properties include:
-
the "
visible
" visibility state
We list known APIs here for completeness, to show which API surfaces we’ve audited.
APIs that require transient activation or sticky activation:
-
The prompt generated by the
beforeunload
event [HTML] -
element.requestFullscreen()
[FULLSCREEN]-
navigator.keyboard.lock()
[KEYBOARD-LOCK], which requires fullscreen[KEYBOARD-LOCK] allows browsing contexts to enable keyboard lock easily but it has no effect except in fullscreen, which requires a user gesture. If that changes then this needs to be revisited.
-
-
showOpenFilePicker()
,showSaveFilePicker()
, andshowDirectoryPicker()
[FILE-SYSTEM-ACCESS] -
Firing of clipboard events. [CLIPBOARD-APIS]
APIs that require system focus:
-
The Asynchronous Clipboard API:
navigator.clipboard.read()
,navigator.clipboard.readText()
,navigator.clipboard.write()
,navigator.clipboard.writeText()
. [CLIPBOARD-APIS]
APIs that require the "visible
" visibility state:
More complicated cases:
-
Request Picture-in-Picture as invoked due to
video.requestPictureInPicture()
requires either transient activation, or the visibility state to have been "visible
". [PICTURE-IN-PICTURE]
6. Security considerations
See Security considerations (Speculation Rules).
For the integration of this spec with No-Vary-Search, see No-Vary-Search Security considerations.
Add security considerations that are specific to prerendering. See issue #319.
7. Privacy considerations
See Privacy considerations (Speculation Rules).
For the integration of this spec with No-Vary-Search, see No-Vary-Search Privacy considerations.
Add privacy considerations that are specific to prerendering. See issue #319.