Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Activation delegation through post messages #4369

Closed
wants to merge 4 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
185 changes: 129 additions & 56 deletions source
Original file line number Diff line number Diff line change
Expand Up @@ -30121,8 +30121,8 @@ interface <dfn>HTMLIFrameElement</dfn> : <span>HTMLElement</span> {
keyword allows the content to <span>navigate</span> its <span>top-level browsing context</span>;
the <code
data-x="attr-iframe-sandbox-allow-top-navigation-by-user-activation">allow-top-navigation-by-user-activation</code>
keyword behaves similarly but only allows such <span data-x="navigate">navigation</span> when
<span>triggered by user activation</span>; and the <code
keyword behaves similarly but allows such <span data-x="navigate">navigation</span> only when
<span>transient activation flag</span> is true; and the <code
data-x="attr-iframe-sandbox-allow-forms">allow-forms</code>, <code
data-x="attr-iframe-sandbox-allow-modals">allow-modals</code>, <code
data-x="attr-iframe-sandbox-allow-orientation-lock">allow-orientation-lock</code>, <code
Expand Down Expand Up @@ -34905,8 +34905,8 @@ interface <dfn>MediaError</dfn> {
<p>A <span>media element</span> is said to be <dfn>allowed to play</dfn> if the user agent and the
system allow media playback in the current context.</p>

<p class="note">For example, a user agent could require that playback is <span>triggered by user
activation</span>, but an exception could be made to allow playback while <span
<p class="note">For example, a user agent could allow playback only when <span>transient
activation flag</span> is true, but an exception could be made to allow playback while <span
data-x="concept-media-muted">muted</span>.</p>

<p>A <span>media element</span> is said to have <dfn>ended playback</dfn> when:</p>
Expand Down Expand Up @@ -47715,8 +47715,8 @@ ldh-str = &lt; as defined in <a href="https://tools.ietf.org/html/rfc1034#
<p>The element's <span>input activation behavior</span> is to run the following steps:</p>

<ol>
<li><p>If the algorithm is not <span>triggered by user activation</span>, then return
without doing anything else.</p></li>
<li><p>If the algorithm is invoked then <span>transient activation flag</span> is false, then
return without doing anything else.</p></li>

<li>
<p>Run these steps <span>in parallel</span>:</p>
Expand Down Expand Up @@ -72442,64 +72442,121 @@ END:VCARD</pre>
document</span>'s <span>top layer</span>.</p>


<!-- mDebug: new sections begin -->

<h3>Tracking user activation</h3>

<h3>Activation</h3>
<h4>Introduction</h4>

<p>Certain elements in HTML have an <span>activation behavior</span>, which means that the user
can activate them. This is always caused by a <code data-x="event-click">click</code> event.</p>
<!-- NON-NORMATIVE SECTION -->

<div w-nodev>
<p>To prevent abuse of certain APIs that could be annoying to users (e.g. opening popups or
vibrating phones), Web browsers allow the use of these APIs only when the user is actively
interacting with the web page or have interacted with the page at least once. This "active
interaction" state is maintained through the <span>user activation state</span> object in each
<code>Window</code>.</p>

<p>The user agent should allow the user to manually trigger elements that have an <span>activation
behavior</span>, for instance using keyboard or voice input, or through mouse clicks. When the
user triggers an element with a defined <span>activation behavior</span> in a manner other than
clicking it, the default action of the interaction event must be to <span>fire a <code
data-x="event-click">click</code> event</span> at the element.</p>
<!-- interaction event spec point -->
<h4>Processing model</h4>

<p id="allowed-to-show-a-popup">An algorithm is <dfn data-export="">triggered by user
activation</dfn> if any of the following conditions is true:</p>
<p>A user interaction <dfn data-x="activates-a-window">activates a <code>Window</code> object
<var>W</var></dfn> if either:</p>
<ul>
<li>input events from the user interaction is targetted to an element of <var>W</var>, or</li>

<li>the interaction <span data-x="activates-a-window">activates the <code>Window</code>
object</span> in a subframe of <var>W</var>.</li>
</ul>

<p>The <dfn>user activation state</dfn> of a <code>Window</code> object <var>W</var> consists of
two boolean flags, both of which are initially set to false:</p>
<ul>
<li><p>The <span data-x="concept-task">task</span> in which the algorithm is running is currently
processing an <span>activation behavior</span> whose <code data-x="event-click">click</code>
event's <code data-x="dom-Event-isTrusted">isTrusted</code> attribute is true.</li>
<li>The <dfn>sticky activation flag</dfn> indicates the historical activation state: whether the
user has ever interacted with <var>W</var> or its subframes. The flag is set when <var>W</var>
is <span data-x="activates-a-window">activated</span> for the very first time, and is never
reset during the lifetime of <var>W</var>.</li>

<li>The <dfn>transient activation flag</dfn> indicates the current activation state: whether the
user is currently interacting with <var>W</var> or its subframes. The flag is set every time
<var>W</var> is <span data-x="activates-a-window">activated</span>, and is reset either
<ul>
<li>after an expiry time defined by the browser, or</li>
<li>through a call to an <span data-x="">activation-consuming API</span> in the context of
any <code>Window</code> object of the page.</li>
</ul>
</li>
</ul>

<li>
<p>The <span data-x="concept-task">task</span> in which the algorithm is running is currently
running the event listener for an event whose <code
data-x="dom-Event-isTrusted">isTrusted</code> attribute is true and whose <code
data-x="dom-Event-type">type</code> is one of:</p>
<p class="note"> The propagation of the <span>transient activation flag</span> in the frame tree
is assymetric between setting vs resetting of the flag. A user interaction with a frame
<var>F</var> sets the flag in the <code>Window</code> object of each ancestor frame of
<var>F</var> (including <var>F</var> itself). However, an <span data-x="">activation-consuming
API</span> call in the context of the <code>Window</code> object of frame of <var>F</var> resets
the flag in <em>all</em> <code>Window</code> objects across the whole frame tree. This prevents
multiple calls to an <span data-x="">activation-consuming API</span> even when the frame hierarchy
is deep.</p>

<ul class="brief">
<li><code data-x="event-change">change</code></li>
<li><code data-x="event-click">click</code></li>
<li><code data-x="event-contextmenu">contextmenu</code></li>
<li><code data-x="event-dblclick">dblclick</code></li>
<li><code data-x="event-mouseup">mouseup</code></li>
<li><code data-x="event-pointerup">pointerup</code></li>
<li><code data-x="event-reset">reset</code></li>
<li><code data-x="event-submit">submit</code></li>
<li><code data-x="event-touchend">touchend</code></li>
</ul>
<h4>APIs gated by user activation</h4>

</li>
<p>APIs that are dependent on <span>user activation state</span> are classified into three
different levels. The levels are as follows, sorted by their "strength of dependence" on user
activation (from strongest to weakest):</p>
<ol>
<li><dfn>Transient activation consuming APIs</dfn>: These APIs require the transient bit, and
they consume the bit in each call to prevent multiple calls per user activation.</li>

<li>
<p>The <span data-x="concept-task">task</span> in which the algorithm is running was <span
data-x="queue a task">queued</span> by an algorithm that was <span>triggered by user
activation</span>, and the chain of such algorithms started within a user-agent defined
timeframe.</p>
<li><dfn>Transient activation gated APIs</dfn>: These APIs require the transient bit but don't
consume it, so multiple calls are allowed per user activation until the transient bit
expires.</li>

<p class="example">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.</p>
</li>
<li><dfn>Sticky activation gated APIs</dfn>: These APIs require the sticky activation bit, so
they are blocked until the very first user activation.</li>
</ol>


<h4>Events triggering user activation</h4>

<div w-nodev>

<!-- NON-NORMATIVE SECTION -->

<!-- The following comment/tag came from the old text. Not sure who/which-spec anchors here. -->
<!-- interaction event spec point -->

<p class="&#x0058;&#x0058;&#x0058;">The event set is inconsistent across major browsers. See <a
href="https://github.com/whatwg/html/issues/3849">issue #3849</a>.</p>

<p>A <code>Window</code> object <var>W</var> is considered activated when <var>W</var> or any
elements of <var>W</var> receives an event whose <code
data-x="dom-Event-isTrusted">isTrusted</code> attribute is true and whose <code
data-x="dom-Event-type">type</code> is one of:</p>
<ul class="brief">
<li><code data-x="event-change">change</code></li>
<li><code data-x="event-click">click</code></li>
<li><code data-x="event-contextmenu">contextmenu</code></li>
<li><code data-x="event-dblclick">dblclick</code></li>
<li><code data-x="event-mouseup">mouseup</code></li>
<li><code data-x="event-pointerup">pointerup</code></li>
<li><code data-x="event-reset">reset</code></li>
<li><code data-x="event-submit">submit</code></li>
<li><code data-x="event-touchend">touchend</code></li>
</ul>

</div>

<h3>Activation behavior of elements</h3>

<p>Certain elements in HTML have an <span>activation behavior</span>, which means that the user
can activate them. This is always caused by a <code data-x="event-click">click</code> event.</p>

<div w-nodev>

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

</div>

<!-- v2 idea: HTMLImageElement.click(x, y); or clickPoint(), if click() can't be done in IE; can
this be emulated in IE by posting a synthetic mouse click event with those X and Y coords?
Expand Down Expand Up @@ -72540,6 +72597,7 @@ END:VCARD</pre>

</div>

<!-- mDebug: new sections end -->


<h3>Focus</h3>
Expand Down Expand Up @@ -77660,12 +77718,12 @@ console.assert(iframeWindow.frameElement === null);
then:</p>

<ol>
<li><p>If this algorithm is <span>triggered by user activation</span> and <var>A</var>'s
<li><p>If <span>transient activation flag</span> is true and <var>A</var>'s
<span>active document</span>'s <span>active sandboxing flag set</span> has its <span>sandboxed
top-level navigation with user activation browsing context flag</span> set, then return
false.</p></li>

<li><p>Otherwise, if this algorithm is not <span>triggered by user activation</span> and
<li><p>Otherwise, if <span>transient activation flag</span> is false and
<var>A</var>'s <span>active document</span>'s <span>active sandboxing flag set</span> has its
<span>sandboxed top-level navigation without user activation browsing context flag</span> set,
then return false.</p></li>
Expand Down Expand Up @@ -77937,7 +77995,7 @@ console.assert(iframeWindow.frameElement === null);
applicable option from the following list:</p>

<dl class="switch">
<dt id="popup-blocker">If the algorithm is not <span>triggered by user activation</span> and
<dt id="popup-blocker">If <span>transient activation flag</span> is false and
the user agent has been configured to not show popups (i.e. the user agent has a "popup
blocker" enabled)</dt>

Expand Down Expand Up @@ -78391,6 +78449,7 @@ interface <dfn data-export="" data-dfn-type="interface">Window</dfn> : <span>Eve

dictionary <dfn>WindowPostMessageOptions</dfn> : <span>PostMessageOptions</span> {
USVString targetOrigin = "/";
boolean transferUserActivation = false;
};</code></pre>

<!-- for more features to add here, look here:
Expand Down Expand Up @@ -80124,8 +80183,8 @@ interface <dfn>BarProp</dfn> {

<p>This flag <a href="#sandboxLinks">prevents content from navigating their <span>top-level
browsing context</span></a> and <a href="#sandboxClose">prevents content from closing their
<span>top-level browsing context</span></a>. It is consulted only from algorithms that are
<em>not</em> <span>triggered by user activation</span>.</p>
<span>top-level browsing context</span></a>. It is consulted only when <span>transient
activation flag</span> is false.</p>

<p>When the <span>sandboxed top-level navigation without user activation browsing context
flag</span> is <em>not</em> set, content can navigate its <span>top-level browsing
Expand All @@ -80143,8 +80202,8 @@ interface <dfn>BarProp</dfn> {

<p>This flag <a href="#sandboxLinks">prevents content from navigating their <span>top-level
browsing context</span></a> and <a href="#sandboxClose">prevents content from closing their
<span>top-level browsing context</span></a>. It is consulted only from algorithms that
<em>are</em> <span>triggered by user activation</span>.</p>
<span>top-level browsing context</span></a>. It is consulted only when <span>transient
activation flag</span> is true.</p>

<p>As with the <span>sandboxed top-level navigation without user activation browsing context
flag</span>, this flag only affects the <span>top-level browsing context</span>; if it is not
Expand Down Expand Up @@ -82880,8 +82939,8 @@ interface <dfn>Location</dfn> { // but see also <a href="#the-location-interface
processor), user agents should attempt to mitigate the risk that this is an attempt to exploit the
target software, e.g. by prompting the user to confirm that the <span>source browsing
context</span>'s <span>active document</span>'s <span>origin</span> is to be allowed to invoke the
specified software. In particular, if the <span>navigate</span> algorithm, when it was invoked,
was not <span>triggered by user activation</span>, the user agent should not invoke the external
specified software. In particular, if the <span>navigate</span> algorithm was invoked when
<span>transient activation flag</span> was false, the user agent should not invoke the external
software package without prior user confirmation.</p>

<p class="example">For example, there could be a vulnerability in the target software's URL
Expand Down Expand Up @@ -96595,6 +96654,14 @@ function receiver(e) {
<li><p>Let <var>targetOrigin</var> be <var>options</var>["<code
data-x="">targetOrigin</code>"].</p></li>

<li><p>Let userActivationBits be null</p></li>

<li><p>If <var>options</var>'s <code data-x="">transferUserActivation</code> member is true, set
userActivationBits to be <var>window</var>'s <span>user activation state</span>.</p></li>

<li><p>Let <var>targetOrigin</var> be the value of <var>options</var>'s <code
data-x="">targetOrigin</code> member.</p></li>

<li><p>If <var>targetOrigin</var> is a single U+002F SOLIDUS character (/), then set
<var>targetOrigin</var> to <var>incumbentSettings</var>'s <span
data-x="concept-settings-object-origin">origin</span>.</p>
Expand All @@ -96621,6 +96688,9 @@ function receiver(e) {
<span>StructuredSerializeWithTransfer</span>(<var>message</var>, <var>transfer</var>). Rethrow
any exceptions.</p></li>

<li><p>If userActivationBits is not null, clear <var>window</var>'s <span>user activation
state</span>.</p></li>

<li>
<p><span>Queue a task</span> on the <span>posted message task source</span> to run the
following steps:</p>
Expand Down Expand Up @@ -96658,6 +96728,9 @@ function receiver(e) {
<code>MessagePort</code> objects in <var>deserializeRecord</var>.[[TransferredValues]], if any,
maintaining their relative order.</p></li>

<li><p>If userActivationBits is not null, assign userActivationBits to
<var>targetWindow</var>'s <span>user activation state</span>.</p></li>

<li><p><span data-x="concept-event-fire">Fire an event</span> named <code
data-x="event-message">message</code> at <var>targetWindow</var>, using
<code>MessageEvent</code>, with the <code data-x="dom-MessageEvent-origin">origin</code>
Expand Down