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

Define the activation behavior of a <portal> element. #223

Merged
merged 6 commits into from
Jul 7, 2020
Merged
Show file tree
Hide file tree
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
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ In exchange for these restrictions, portals gain an additional capability that i
myPortal.activate();
```

_Note: [issue #174](https://github.com/WICG/portals/issues/174) discusses making this the default behavior when clicking on a portal, similar to a link._
Unless prevented by the author, clicking a portal activates it as well, similarly to a link.

At this point, the user will observe that their browser has navigated to `https://www.example.com/` (e.g., via changes to the URL bar contents and back/forward UI). Since `https://example.com/` was already loaded in the portal context, this navigation will occur seamlessly and instantly, without a network round-trip or document re-initialization.

Expand Down Expand Up @@ -167,11 +167,10 @@ TODO:

Portals enable preloading, previewing and seamless transitions to another web page. They are expected to often be partially or fully offscreen, scaled, faded or otherwise styled in a way that makes them unnatural to interact with directly. Additionally, we expect many web pages to allow themselves to be loaded in a portal for the purposes of facilitating a seamless transition, but wish to mitigate certain kinds of threat (e.g. some forms of clickjacking) from an embedder who may not be fully trusted.

Therefore the portal content cannot be focused and does not receive input events. Instead, the `<portal>` element itself is focusable (similar to a button or link) and eligible to receive input events (such as clicks) in the host document. For instance, the host document may handle this click event to animate and activate the `<portal>` element and navigate to the target document.
Therefore the portal content cannot be focused and does not receive input events. Instead, the `<portal>` element itself is focusable (similar to a button or link) and eligible to receive input events (such as clicks) in the host document. For instance, the host document may handle this click event to animate and activate the `<portal>` element and navigate to the target document. If not handled, clicking will activate the `<portal>` immediately.

TODO:

- Did we end up adding a default click behavior like links?
- Discuss scrolling, including the problem of scroll handoff and its importance. Note that scroll handoff is a ??? in spec terms but we promise to spec something interoperably implementable, somehow.
- When/if we update this explainer to discuss resize limitations, comment on how that affects interactivity.
- Consider discussing how storage access limitations interact with interactivity.
Expand Down
46 changes: 36 additions & 10 deletions index.bs
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,8 @@ spec:url; type:dfn; text:scheme

<section algorithm="portal-browsing-context-activate">
To <dfn>activate a portal browsing context</dfn> |successorBrowsingContext| in
place of |predecessorBrowsingContext| with [=origin=] |sourceOrigin|, data
|serializeWithTransferResult|, and promise |promise|, run the following steps [=in parallel=]:
place of |predecessorBrowsingContext| with [=origin=] |sourceOrigin|, optional data
|serializeWithTransferResult|, and optional promise |promise|, run the following steps [=in parallel=]:

1. [=Assert=]: The [=portal state=] of |predecessorBrowsingContext| is "`none`".

Expand Down Expand Up @@ -167,8 +167,8 @@ spec:url; type:dfn; text:scheme

1. Let |dataClone| be null.

1. If |successorBrowsingContext|'s [=active document=]'s [=Document/origin=] is
[=same origin=] with |sourceOrigin|, then:
1. If |serializeWithTransferResult| is given and |successorBrowsingContext|'s [=active document=]'s
[=Document/origin=] is [=same origin=] with |sourceOrigin|, then:

1. Let |deserializeRecord| be
[$StructuredDeserializeWithTransfer$](|serializeWithTransferResult|, |targetRealm|),
Expand All @@ -186,7 +186,7 @@ spec:url; type:dfn; text:scheme

1. Set |event|'s [=PortalActivateEvent/successor window=] to |successorWindow|.

1. Set |event|'s [=PortalActivateEvent/activation promise=] to |promise|.
1. Set |event|'s [=PortalActivateEvent/activation promise=] to |promise|, if it is given, and null otherwise.

1. [=Dispatch=] |event| to |successorWindow|.

Expand Down Expand Up @@ -217,7 +217,7 @@ spec:url; type:dfn; text:scheme

1. Otherwise:

1. [=Queue a global task=] on the [=portal task source=] given
1. If |promise| is given, [=queue a global task=] on the [=portal task source=] given
|predecessorBrowsingContext|'s [=browsing context/active window=] to resolve
|promise| with undefined.

Expand Down Expand Up @@ -630,6 +630,33 @@ spec:url; type:dfn; text:scheme
portals-cross-origin-load.sub.html
</wpt>

<section algorithm="htmlportalelement-activation-behavior">
A <{portal}> element |el|'s [=activation behavior=] is to run the following steps:

1. Let |portalBrowsingContext| be the [=guest browsing context=] of |el|.

1. If |portalBrowsingContext| is null, return.

1. Let |predecessorBrowsingContext| be the [=document browsing context|browsing context=] of
|el|'s [=node document=].

1. If |predecessorBrowsingContext| is null, return.

1. If the [=portal state=] of |predecessorBrowsingContext| is not "`none`", return.

1. Let |sourceOrigin| be |el|'s [=relevant settings object=]'s
[=environment settings object/origin=].

1. Run the steps to [=activate a portal browsing context|activate=] |portalBrowsingContext|
in place of |predecessorBrowsingContext| with |sourceOrigin|.

<div class="note">
This is substantially similar to the steps in {{activate(options)}}, with default options.
User agents might wish to display suitable console messages under the same conditions that would
result in promise rejection in those steps.
</div>
</section>

The following events are dispatched on {{HTMLPortalElement}} objects:

<table class="data" dfn-for="HTMLPortalElement">
Expand Down Expand Up @@ -816,7 +843,7 @@ spec:url; type:dfn; text:scheme

A {{PortalActivateEvent}} has an associated <dfn for="PortalActivateEvent">predecessor browsing context</dfn>,
which is a [=top-level browsing context=] or null, a <dfn for="PortalActivateEvent">successor window</dfn>, which is
a {{Window}}, an <dfn for="PortalActivateEvent">activation promise</dfn>, which is a [=promise=], and a
a {{Window}}, an <dfn for="PortalActivateEvent">activation promise</dfn>, which is a [=promise=] or null, and a
<dfn for="PortalActivateEvent">adopted predecessor element</dfn>, which is a <{portal}> element or null.

<section algorithm="portalactivateevent-event-constructing-steps">
Expand Down Expand Up @@ -847,9 +874,8 @@ spec:url; type:dfn; text:scheme

1. Set [=this=]'s [=PortalActivateEvent/adopted predecessor element=] to |adoptedPredecessorElement|.

1. [=Queue a global task=] on the [=portal task source=] given |predecessorBrowsingContext|'s
[=browsing context/active window=] to resolve [=this=]'s [=activation promise=] with
undefined.
1. If [=this=]'s [=activation promise=] is not null, [=queue a global task=] on the [=portal task source=]
given |predecessorBrowsingContext|'s [=browsing context/active window=] to resolve it with undefined.

Note: Queuing this immediately makes it possible to send messages to the adopted
portal during dispatch of the {{Window/portalactivate!!event}} event without
Expand Down