From 8f8c1f50158736b3cf16188377a0974a20367c8b Mon Sep 17 00:00:00 2001 From: Mustaq Ahmed Date: Wed, 4 Dec 2019 14:09:23 -0500 Subject: [PATCH] Revamp the user activation model This replaces the previous concept of "triggered by user activation" with a more nuanced model, introducing new concepts and a more detailed processing model. This aligns with Chromium's "user activation v2" work, which gained consensus during the discussion at TPAC [1]. (The previous specification did not align with any implementation.) This serves mostly as a foundational improvement. Interop work remains to be done on individual APIs and how they use user activation, as well as the exact set of events which count as user activation. Those issues are tracked in [2] and elsewhere. Fixes #1903. Fixes #3859. [1]: https://docs.google.com/document/d/1gHxQMdXGX4UjjoPXi0c1vhwYregQzWNEHqgbydopCoo/edit#heading=h.9hw95kikso76 [2]: https://github.com/whatwg/html/labels/topic%3A%20user%20activation --- source | 269 +++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 202 insertions(+), 67 deletions(-) diff --git a/source b/source index f146ee97e82..9512a55ddd1 100644 --- a/source +++ b/source @@ -30276,10 +30276,10 @@ interface HTMLIFrameElement : HTMLElement { keyword allows the content to navigate its top-level browsing context; the allow-top-navigation-by-user-activation - keyword behaves similarly but only allows such navigation when - triggered by user activation; and the allow-forms, allow-modals, navigation only when the + browsing context's WindowProxy's [[Window]] value has transient + activation; and the allow-forms, + allow-modals, allow-orientation-lock, allow-pointer-lock, allow-popups, MediaError {

A media element is said to be allowed to play if the user agent and the system allow media playback in the current context.

-

For example, a user agent could require that playback is triggered by user - activation, but an exception could be made to allow playback while For example, a user agent could allow playback only when the media + element's Window object has transient activation, but an + exception could be made to allow playback while muted.

A media element is said to have ended playback when:

@@ -47911,8 +47912,8 @@ ldh-str = < as defined in click
event.

+

To prevent abuse of certain APIs that could be annoying to users (e.g., opening popups or + vibrating phones), user agents allow these APIs only when the user is actively interacting with + the web page or has interacted with the page at least once. This "active interaction" state is + maintained through the mechanisms defined in this section.

-

The user agent should allow the user to manually trigger elements that have an activation - behavior, for instance using keyboard or voice input, or through mouse clicks. When the - user triggers an element with a defined activation behavior in a manner other than - clicking it, the default action of the interaction event must be to fire a click event at the element.

- +

Data model

-

An algorithm is triggered by user - activation if any of the following conditions is true:

+

For the purpose of tracking user activation, each Window W has a + last activation timestamp. This is a number indicating the last time W got + an activation notification. It corresponds to a + DOMHighResTimeStamp value except for two cases: positive infinity + indicates that W has never been activated, while negative infinity indicates that a user activation-gated API has consumed the last user activation of W. The initial value is + positive infinity.

-
    -
  • The task in which the algorithm is running is currently - processing an activation behavior whose click - event's isTrusted attribute is true.

  • +

    A user agent also defines a transient activation duration, which is a constant + number indicating how long a user activation is available for certain user activation-gated APIs (e.g., for opening popups).

    -
  • -

    The task in which the algorithm is running is currently - running the event listener for an event whose isTrusted attribute is true and whose type is one of:

    +

    The transient activation duration is expected be at most a few + seconds, so that the user can possibly perceive the link between an interaction with the page and + the page calling the activation-gated API.

    -
      -
    • change
    • -
    • click
    • -
    • contextmenu
    • -
    • dblclick
    • -
    • mouseup
    • -
    • pointerup
    • -
    • reset
    • -
    • submit
    • -
    • touchend
    • -
    +

    These two values imply two boolean user activation states for W:

    -
  • +
    +
    Sticky activation
    +
    +

    When the current high resolution time is greater than or equal to the last + activation timestamp in W, W is said to have sticky + activation.

    + +

    This is W's historical activation state, indicating whether the user has ever + interacted in W. It starts false, then changes to true (and never changes back to + false) when W gets the very first activation notification.

    +
    +
    Transient activation
    +
    +

    When the current high resolution time is greater than or equal to the last + activation timestamp in W, and less than the last activation + timestamp in W plus the transient activation duration, then + W is said to have transient activation.

    + +

    This is W's current activation state, indicating whether the user has interacted + in W recently. This starts with a false value, and remains true for a limited time + after every activation notification W gets.

    + +

    The transient activation state is considered expired if it becomes false because the transient + activation duration time has elapsed since the last user activation. Note that it can + become false even before the expiry time through an activation consumption.

    +
    +
    + +

    Processing model

    + +

    When a user interaction in a browsing context B causes firing of an + activation triggering input event in B's active document + D, the user agent must perform the following activation notification steps + before dispatching the event:

    + +
    1. -

      The task in which the algorithm is running was queued by an algorithm that was triggered by user - activation, and the chain of such algorithms started within a user-agent defined - timeframe.

      +

      Let browsingContexts be a list consisting of:

      +
        +
      • B,

      • -

        For example, if a user clicked a button, it might be acceptable for a popup - to result from that after 4 seconds, but it would likely not be acceptable for a popup to result - from that after 4 hours.

        +
      • all ancestor browsing contexts of + B, and

      • + +
      • all the descendant browsing + contexts of D that have active + documents from the same origin as that of D.

      • +
    2. + +
    3. Let windows be the list of Window objects constructed by taking + the [[Window]] internal slot value of browsingContext's WindowProxy + object for each browsingContext in browsingContexts.

    4. + +
    5. For each window in windows, set + window's last activation timestamp to the current high resolution + time.

    6. +
    + +

    An activation triggering input event is any event whose isTrusted attribute is true and whose type is one of:

    + +
      +
    • change
    • +
    • click
    • +
    • contextmenu
    • +
    • dblclick
    • +
    • mouseup
    • +
    • pointerup
    • +
    • reset
    • +
    • submit
    • +
    • touchend
    +

    The event set is inconsistent across major browsers. See issue #3849.

    + +

    Activation consuming APIs defined in this and + other specifications can consume user activation by performing the + following steps, given a Window W:

    + +
      +
    1. If W's browsing context is null, then + return.

    2. + +
    3. Let top be W's browsing context's + top-level browsing context.

    4. + +
    5. Let browsingContexts be the list of the descendant browsing + contexts of top's active document.

    6. + +
    7. Append top to + browsingContexts.

    8. + +
    9. Let windows be the list of Window objects constructed by taking + the [[Window]] internal slot value of browsingContext's WindowProxy + object for each browsingContext of browsingContexts.

    10. + +
    11. For each window in windows, if + window's last activation timestamp is not positive infinity, then set + window's last activation timestamp to negative infinity.

    12. +
    + +

    The spec is not clear about how to traverse a tree of documents. See issue #5020.

    + +

    Note the asymmetry in the sets of browsing + contexts in the page that are affected by an activation notification vs an + activation consumption: an activation consumption + changes (to false) the transient activation states for all browsing contexts in the + page, but an activation notification changes (to true) the states for a subset of those browsing + contexts. The exhaustive nature of consumption here is deliberate: it prevents malicious sites + from making multiple calls to an activation consuming API from a single user + activation (possibly by exploiting a deep hierarchy of iframes).

    + +

    APIs gated by user activation

    +
+

APIs that are dependent on user activation are classified into three different levels. The + levels are as follows, sorted by their "strength of dependence" on user activation (from weakest + to strongest):

+ +
+
Sticky activation-gated APIs
+

These APIs require the sticky activation state to be true, so they are blocked + until the very first user activation.

+ +
Transient activation-gated APIs
+

These APIs require the transient activation state to be true, but they don't + consume it, so multiple calls are allowed per user + activation until the transient state expires.

+ +
Transient activation-consuming APIs
+

These APIs require the transient activation state to be true, and they + consume user activation in each call to prevent multiple calls per user + activation.

+
+ + + +

Activation behavior of elements

+ +

Certain elements in HTML have an activation behavior, which means that the user + can activate them. This is always caused by a click event.

+ +
+ +

The user agent should allow the user to manually trigger elements that have an activation + behavior, for instance using keyboard or voice input, or through mouse clicks. When the + user triggers an element with a defined activation behavior in a manner other than + clicking it, the default action of the interaction event must be to fire a click event at the element.

+ +