A frame-hierarchy based model to track active user interaction.
The term user activation means the state of a browsing session with respect to user actions: an “active” state typically implies either the user is currently interacting with the page through some input mechanism (typing, clicking with mouse etc.), or the user has completed some interaction since the page got loaded. (User gesture is a misleading term occasionally used to express the same idea, e.g. “allowing something only with a user gesture”, even though a swipe gesture doesn’t typically activate a page.)
Browsers control access to “abusable” of APIs through user activation. The most
obvious example of such an API is opening popups through
rogue developers started to abuse the API to open popups arbitrarily, most
(all?) browsers began to block popups when the user is not actively
interacting with the page. Since then, browsers have gradually made many other
APIs dependent on activation (more precisely, made them user activation
gated), like making an element fullscreen, vibrating a mobile device,
autoplaying media etc. To highlight the scope, ~30 different
in Chrome are user activation gated.
More importantly, the current HTML spec can’t really fix the broken situation in the Web today because it needs to add important details and doesn’t fully reflect any current implementation.
User Activation v2 (UAv2) introduces a new user activation model that is simple
enough for cross-browser implementation, and hence calls for a new spec from
scratch as a long term fix for the Web. We prototyped the model in Chromium
behind the flag
The new model maintains a two-bit user activation state at every
in the frame hierarchy:
HasSeenUserActivation: This is a sticky bit for the APIs that only needs a
signal on historical user activation. The bit gets set on first user action,
and is never reset during the lifetime of the
window object. Example APIs:
HasConsumableUserActivation: This is a transient bit for the APIs that need
limited invocation per user interaction. The bit gets set on every user
interaction, and is reset either after an expiry time defined by the browser
or through a call to an activation-consuming API
Any user interaction in a
window object sets the activation bits in the
window objects of all ancestor frames (including the
interacted with). (See Related Links below for an API to modify this default
Any consumption of the transient bit resets the transient bits in the
objects of the whole frame tree.
In Chromium, the main change introduced by this model is replacing stack-allocated per-process gesture tokens with per-frame states as described above. This effectively:
removes the need for token storing/passing/syncing for every user API,
changes activation visibility from stack-scoped to frame-scoped, and
fuses multiple user interactions within the expiry time interval into a single activation.
For further details on the model and Chromium implementation, see:
Modern browsers already show different levels activation-dependence for activation-aware APIs, and the Web needs a spec for this behavior. The UAv2 model induces a classification of user APIs into three distinct levels, making it easy for any user API to spec its activation-dependence in a concise yet precise manner. The levels are as follows, sorted by their “strength of dependence” on user activation (from strongest to weakest):
Transient activation consuming APIs: These APIs require the transient bit, and
they consume the bit in each call to prevent multiple calls per user
is most (all?) browsers today.
Transient activation gated APIs: These APIs require the transient bit but
don’t consume it, so multiple calls are allowed per user activation until the
transient bit expires. E.g.
in Chromium and other many browsers.
Our prototype implementation preserved all the APIs’ past behavior in Chromium after a few (mostly minor) changes.
Compare these demos in Chrome 72+ vs. in all other browsers to see why UAv2 makes sense.
User activation propagation in the frame tree:
Test activation propagation with popups: Shows how UAv2 states change across the frame tree through user interaction and subsequent consumption through popups.
Consistent availability of user activation state through API chaining:
Activation Transfer through
API to allow developers transfer user activation state to any target
in the frame tree.
JS API for querying User Activation states: An API to determine the state of user activation. This is independent but somewhat related to UAv2.