1. Introduction
This is an introduction.
This introduction needs to be more of an introduction.
2. Pending Beacon Framework
2.1. Concepts
A pending beacon represents a piece of data which has been registered with the user agent for later sending to an origin server.
A pending beacon has a url, which is a URL.
A pending beacon has a method, which is a
string, which is initally "POST"
.
A pending beacon has a foreground timeout, which is either null or an integer, and which is initially null.
A pending beacon has a background timeout, which is either null or an integer, and which is initially null.
A pending beacon has an is_pending flag, which is a boolean, which is initially true.
A pending beacon has a payload, which is a byte sequence. It is initially empty.
A Document has a pending beacon set, which is an ordered set of pending beacons.
Note: In this spec, the pending beacon set is associated with a Document. In an actual implementation, this set will likely need to be stored in the user agent, separate from the document itself, in order to be able to send beacons when the document is destroyed (either by being unloaded, or because of a crash).
Define these to be part of the user agent formally.
2.2. Updating beacons
-
If beacon’s is_pending is false, return false.
-
If url is not a valid URL, return false.
-
If url is not a potentially trustworthy URL, return false.
-
Set beacon’s url to url.
-
Return true.
-
If beacon’s is_pending is false, return false.
-
If timeout is negative, return false.
-
Set beacon’s foreground timeout to timeout.
-
Return true.
This algorithm should also synchronously set or clear a timer to send the beacon.
-
If beacon’s is_pending is false, return false.
-
If timeout is negative, return false.
-
Set beacon’s background timeout to timeout.
-
Return true.
-
If beacon’s is_pending is false, return false.
-
Set beacon’s payload to payload.
-
Return true.
Note: Once canceled, a pending beacon's payload will no longer be used, and it is safe for a user agent to discard that, and to cancel any associated timers. However, other attributes may still be read, and so this algorithm does not destroy the beacon itself.
2.3. Sending beacons
Note: This is written as though Fetch were used as the underlying mechanism. However, since these are sent out-of-band, an implementation might not use the actual web-exposed Fetch API, and may instead use the underlying HTTP primitives directly.
-
For each pending beacon beacon in document’s pending beacon set,
-
Call send a queued pending beacon with beacon.
-
-
If beacon’s is_pending flag is false, then return.
-
Set beacon’s is_pending flag to false.
-
Check permission.
-
If beacon’s method is "GET", then call send a pending beacon over GET with beacon.
-
Else call send a pending beacon over POST with beacon.
"Check permission" is not defined. A specific permission should be used here, and this should integrate with the permissions API.
-
Let query be the result of running the urlencoded serializer with pairs.
-
Let url be a clone of beacon’s url.
-
Set url’s query component to query.
-
Let req be a new request initialized as follows:
- method
-
GET
- client
- url
-
url
- credentials mode
-
same-origin
-
Fetch req.
-
Let transmittedData be the result of serializing beacon’s payload.
-
Let req be a new request initialized as follows:
- method
-
POST
- client
- url
-
beacon’s url
- header list
-
headerList
- origin
-
The entry settings object’s origin
- keep-alive flag
-
true
- body
-
transmittedData
- mode
-
cors
- credentials mode
-
same-origin
-
Fetch req.
3. Integration with HTML
Note: The following sections modify the [HTML] standard to enable sending of beacons automatically by the user agent. These should be removed from this spec as appropriate changes are made to [HTML].
When a document with a non-empty pending beacon set is to be discarded, send the document’s pending beacons.
"discarded" is not well defined.
When a process hosting a document with a non-empty pending beacon set crashes, send the document’s pending beacons.
The concepts of "process" and "crashes" are not well defined.
-
For each pending beacon beacon in document’s pending beacon set,
-
Let timeout be beacon’s background timeout.
-
If timeout is not null, start a timer to run a task in timeout ms.
Note: The user agent may choose to coalesce multiple timers in order to send multiple beacons at the same time.
-
When the timer expires, call send a queued pending beacon with beacon.
Note: The pending beacons may have been sent before this time, in cases where the document is unloaded, or its hosting process crashes before the timer fires. In that case, if the user agent still reaches this step, then the beacons will not be sent again, as their is_pending flag will be false.
"visibility state change" should be more specific here, and should refer to specific steps in either [PAGE-VISIBILITY] or [HTML]
This should also disable any foreground timers for the document’s beacons, and there should be a step to reinstate them if the document becomes visible again before they are sent.
4. The PendingBeacon interface
enum {
BeaconMethod ,
"POST" };
"GET" dictionary {
PendingBeaconOptions unsigned long ;
timeout unsigned long ; }; [
backgroundTimeout Exposed =(Window ,Worker )]interface {
PendingBeacon readonly attribute USVString url ;readonly attribute BeaconMethod method ;attribute unsigned long timeout ;attribute unsigned long backgroundTimeout ;readonly attribute boolean pending ;undefined deactivate ();undefined sendNow (); }; [Exposed =(Window ,Worker )]interface :
PendingGetBeacon PendingBeacon {constructor (USVString ,
url optional PendingBeaconOptions = {});
options undefined setURL (USVString ); }; [
url Exposed =(Window ,Worker )]interface :
PendingPostBeacon PendingBeacon {constructor (USVString ,
url optional PendingBeaconOptions = {});
options undefined setData (object ); };
data
A PendingBeacon
object has an associated beacon, which is a pending beacon.
new PendingGetBeacon(url, options)
constructor steps are:
-
Let beacon be a new pending beacon.
-
Call the common beacon initialization steps with this, "GET", url and options.
-
Insert beacon into the user agent’s pending beacon set.
new PendingPostBeacon(url, options)
constructor steps are:
-
Let beacon be a new pending beacon.
-
Call the common beacon initialization steps with this, "POST", url and options.
-
Insert beacon into the user agent’s pending beacon set.
PendingBeacon
pendingBeacon, a string method, a USVString
url, and a PendingBeaconOptions
options, are:
-
Let beacon be pendingBeacon’s beacon.
-
If url is not a valid URL string, throw a
TypeError
. -
Let base be the entry settings object’s API base URL.
-
Let parsedUrl be the result of running the URL parser on url and base.
-
If parsedUrl is failure, throw a
TypeError
. -
If the result of setting beacon’s url to parsedUrl is false, throw a
TypeError
. -
Set beacon’s method to method.
-
If options has a
timeout
member, then set pendingBeacon’stimeout
to options’stimeout
. -
If options has a
backgroundTimeout
member, then set pendingBeacon’sbackgroundTimeout
to options’sbackgroundTimeout
.
timeout
setter steps are:
-
If beacon’s is_pending is not true, throw a
"NoModificationAllowedError"
DOMException
. -
Let timeout be the argument to the setter.
-
If timeout is not a non-negative integer, throw a
TypeError
. -
If the result of setting beacon’s foreground timeout to timeout is false, throw a
TypeError
.
backgroundTimeout
setter steps are:
-
If beacon’s is_pending is not true, throw a
"NoModificationAllowedError"
DOMException
. -
Let timeout be the argument to the setter.
-
If timeout is not a non-negative integer, throw a
TypeError
. -
If the result of setting beacon’s background timeout to timeout is false, throw a
TypeError
.
deactivate()
steps are:
-
If beacon’s is_pending is not true, throw an
"InvalidStateError"
DOMException
. -
cancel beacon.
sendNow()
steps are:
-
If beacon’s is_pending is not true, throw an
"InvalidStateError"
DOMException
. -
Call send a queued pending beacon with beacon.
setURL(url)
steps are:
-
If beacon’s is_pending is not true, throw a
"NoModificationAllowedError"
DOMException
. -
If url is not a valid URL string, throw a
TypeError
. -
Let base be the entry settings object’s API base URL.
-
Let parsedUrl be the result of running the URL parser on url and base.
-
If parsedUrl is failure, throw a
TypeError
. -
If the result of setting beacon’s url to parsedUrl is false, throw a
TypeError
.
setData(data)
steps are:
-
If beacon’s is_pending is not true, throw a
"NoModificationAllowedError"
DOMException
. -
Let (body, contentType) be the result of extracting a body with type from data with keepalive set to true.
-
Let bytes be the byte sequence obtained by reading body’s stream.
-
If the result of setting beacon’s payload to bytes is false, throw a
TypeError
.
5. Privacy
This section is woefully incomplete. These all need to be fleshed out in enough detail to accurately describe the privacy issues and suggested or prescribed mitigations.
-
When the network changes, drop all queued beacons
-
Clear-site-data?
-
Incognito?