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

Ephemeral navigation portals #192

Open
jeremyroman opened this issue May 6, 2020 · 8 comments
Open

Ephemeral navigation portals #192

jeremyroman opened this issue May 6, 2020 · 8 comments
Labels
design work needed An acknowledged gap in the proposal that needs design work to resolve

Comments

@jeremyroman
Copy link
Collaborator

@jakearchibald has previously proposed in a few places that it be possible to load a portal which would have immediate access to its first-party storage in exchange for a UA-enforced guarantee that it will be activated within some fixed timeframe (say, five seconds). This could be hooked onto existing content-initiated navigations (e.g. links, form submissions) through a hypothetical navigate event, which would look something like:

partial interface NavigateEvent {
  HTMLPortalElement createPortal();
};

I suspect we'd need a few more features if we took such a direction, like telling the author what the deadline is and letting them observe the result of an implicit activation (esp. if it can be rejected).

dictionary EphemeralNavigationPortalInfo {
  HTMLPortalElement portalElement;
  DOMHighResTimeStamp deadline;
  Promise<void> activated;
};

// or a similar exposure on NavigateEvent, if we're willing to also commit to figuring out the implications of intercepting navigations (e.g. what happens to ones initiated from other frames)
partial interface Window {
  EphemeralNavigationPortalInfo createPortalForNavigation(RequestInfo navigationRequest);
};

Either way, I think there are some open questions, especially since we can't actually guarantee that the forced activation will actually be possible. For instance, the request could result in a 204 No Content response, a network or TLS error, abort (including via AbortController if we allow that to be configured on the request), etc. after a credentialed request has already been sent, and of course we could need to cancel due to a concurrent navigation being initiated.

If the conditions for doing this are similar to initiating a navigation that might result in a 204 response, then we may be okay but I think there are details that merit investigation if we want to pursue something along these lines.

@jakearchibald
Copy link
Collaborator

Ohhh I hadn't considered something like createPortalForNavigation. It removes (or decouples) the need for the navigate event. I still think we want a navigate event on the platform at some point, but I guess we can think about that later, or leave it to someone else 😄.

For instance, the request could result in a 204 No Content response,

I think the "risky time" for a portal like is, is when it can run script, and it isn't top level. So, createPortalForNavigation could return a promise that fulfills once we have a response we can work with. Is the result of a normal navigation would be a no-op (due to CSP, Content-Disposition, or 204 (do we no-op in that case?)), the promise could reject.

The promise would reject with an abort error if the navigation is stopped or cancelled somehow, like the user hitting the stop button, or another navigation taking priority.

EphemeralNavigationPortalInfo could also include an AbortSignal, which triggers if the navigation is aborted after the portal has been vended.

+1 to deadline.

I'm less sure about activated, since you wouldn't expect this page to be running script at that point anyway.

Need to think of how this would fit in with the restore callback and other activate options. Maybe they need to be given to createPortalForNavigation.

@jeremyroman
Copy link
Collaborator Author

If activation can fail in a way that keeps the page presented, I think activated is necessary to observe the reason for that. Even in the success case, you could later be pulled from bfcache, so even though you could add a once listener to pagehide/pageshow to observe that, it seems less ergonomic.

The idea of having the result not resolve until a document commits is interesting, though it is kinda equivalent to having the portal element have a promise that resolves when a document commits (which is similar to the contentPainted promise discussed on another issue).

@domenic domenic added the design work needed An acknowledged gap in the proposal that needs design work to resolve label May 8, 2020
@jakearchibald
Copy link
Collaborator

so even though you could add a once listener to pagehide/pageshow to observe that, it seems less ergonomic.

The restore callback would provide the ergonomic way to detect that, no?

The idea of having the result not resolve until a document commits is interesting, though it is kinda equivalent to having the portal element have a promise that resolves when a document commits

Yeah, a value on the portal is probably better. It's ok to add it to third party portals, because you can already access this timing with iframes. It's ok to add it to createPortalForNavigation first-party portals because you can already access this timing with pagehide on navigation.

@jyasskin
Copy link
Member

This interacts with the mitigations identified in #208 as "Blocked by preventing fetches within portals from using credentials until they're activated". That needs at least one extra mitigation here:

@jakearchibald
Copy link
Collaborator

Is it feasible to say that a page can only call this function once in its lifetime?

Can we do whatever we do for repeated assignments to window.location.href?

@jeremyroman
Copy link
Collaborator Author

The mitigations that had previously been proposed were to require a user gesture and for the UA to activate such a portal if the document doesn't do so within some window (and it isn't cancelled by some other navigation -- I haven't given window.stop much thought).

Saying you can only do so once for a page's lifetime seems infeasible -- because it would preclude any further outgoing navigations after restoring from bfcache or similar.

What about, as @jakearchibald says, whatever mitigation is appropriate for the page navigating itself to URLs that serve 204 responses?

@jakearchibald
Copy link
Collaborator

Not just 204 responses, it could be a never-response, which the browser can't really distinguish from a slow response, except via timeouts.

@jyasskin
Copy link
Member

It makes sense to plan to match whatever we wind up doing for assignments to window.location.href. I've asked the anti-tracking folks to come up with a plan for that, and I don't think it needs to block Portals.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
design work needed An acknowledged gap in the proposal that needs design work to resolve
Projects
None yet
Development

No branches or pull requests

4 participants