This proposal is deprecated, replaced by WICG/capability-delegation
An API to allow developers transfer user activation state to any target window
in the frame tree.
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. Browsers control access to “abusable” of APIs through user activation, e.g., popups are usually blocked unless the user is actively interacting with the page.
Chrome shipped User Activation
v2 in version 72, before
which the concept of user activation visibility was not defined. With UAv2, a
user activation in a window
object makes the activation state visible by
default to all container window
objects (that is, those in the ancestor frames
in the frame tree, including the frame being interacted with). We encountered a
few regressions where the developers would like to override this default
visibility. To support such use-cases, we are proposing here an API that allows
passing on the activation state to any window
in the frame tree.
Note, however, that our proposed API makes sense without User Activation v2 too, even though we have spec limitations with the notion of user activation.
Here is the initial pull request for whatwg/html.
Suppose a page has a button on the top frame, and it has a subframe that wants to open a popup when that button on the top frame is clicked. The default visibility rule in UAv2 means that the subframe would be unable to open a popup because it cannot see the user activation in its parent frame. To let the subframe open a popup, the top frame will transfer its own user activation to the subframe after a click, as follows:
// Script for top frame
function clickHandler() {
let targetWindow = frames[0];
targetWindow.postMessage("handle_click", {transferUserActivation: true});
}
let elem = document.getElementById("button");
elem.addEventListener("click", clickHandler);
// Script for subframe
function messageReceiver(e) {
if (e.source === window.parent && e.data === "handle_click")
window.open("about:blank");
}
window.addEventListener("message", messageReceiver);
After a transfer, the sender window
loses the activation state, so can’t
call any activation-gated API until it sees another user activation. This is
done to discourage abusive propagation of activation.
window
gets the activation state the sender
had before. If the receiver already had activation at the time of transfer,
its new activation state will effectively be the union of its old state and
the transferred-in state. To be precise:
The changes below are on top of WindowPostMessateOptions
added through JS API
for querying User Activation states.
partial dictionary WindowPostMessageOptions {
boolean transferUserActivation = false;
};
Main design with security considerations.
We also explored the possibility of adding an <iframe>
attribute to allow
activation visibility in selected subframes. This API won’t be useful when the
receiver frame is not a descendant subframe (e.g. a sibling frame in the frame
tree), or when the sender frame would transfer dynamically (e.g. only certain
clicks would be delegated instead of all).
Work in progress. First need to complete an implementation behind a flag in Chrome. Note that the API can’t be done through a polyfill.
User Activation v2: The spec explainer for UAv2.
JS API for querying User Activation states: An this is independent but somewhat related to UAv2.