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

User Activation: ability to transfer activation to another frame #4364

Closed
mustaqahmed opened this issue Feb 13, 2019 · 13 comments
Closed

User Activation: ability to transfer activation to another frame #4364

mustaqahmed opened this issue Feb 13, 2019 · 13 comments
Labels
addition/proposal New features or enhancements interop Implementations are not interoperable with each other needs implementer interest Moving the issue forward requires implementers to express interest topic: user activation

Comments

@mustaqahmed
Copy link
Contributor

mustaqahmed commented Feb 13, 2019

To prove that a simple user activation model works for the web (#1903), Chrome just shipped User Activation v2 in M72 (stable release started 2 weeks ago). We encountered some minor regressions so far, all around the common theme that an activated frame wants to delegate activation-dependent tasks to another frame.

This requirement was not relevant before UAv2 in Chrome, because of render-process-wide visibility of activation state. UAv2 defines the default visibility of a user activation to be all container frames, which exposed those use-cases as regressions.

We need to address this problem now: define a way to change the default visibility of user activation.

Here is our proposal: allow transfer of user activation to a target frame through postMessage() calls.

@mustaqahmed
Copy link
Contributor Author

Here is the design doc for our proposal.

@annevk
Copy link
Member

annevk commented Feb 14, 2019

So we'd end up with both a timeout and forwarding a bit? Seems a bit unfortunate.

cc @smaug----

@annevk annevk added addition/proposal New features or enhancements needs implementer interest Moving the issue forward requires implementers to express interest interop Implementations are not interoperable with each other labels Feb 14, 2019
@mustaqahmed
Copy link
Contributor Author

mustaqahmed commented Feb 14, 2019

Let me clarify the difference between the proposed "transfer" vs the "gesture token forwarding" we (conceptually) have without UAv2. I mentioned "conceptually" here because no browser fully supported it because of the complications involved.

  • This would be a dedicated API for activation. Only the postMessage() calls with a special option would perform the transfer. No other "chaining" (postMessage() without the option, promises, setTimeout(), whatever) would transfer the activation.

    Token forwarding is assumed implicit with any kind of chaining. This makes the outcome of any call to an activation-gated API dependent on the implementation details of the chaining involved in this call. E.g. in Chrome, we never logically supported token forwarding through promises (it just happened to work in same-process cases because of a renderer-wide shared state).

  • Transfer vs propagation differences. The sender (frame) loses activation state through a transfer, so can't call any activation gated API after a transfer. And only the remaining (delta) expiry time available at the sender is transferred to the receiver, making an arbitrary chain of transfers safe from abuse.

    This is not the case with token forwarding: it extends activation availability to the "chained task". This can be abused to multiply a user activation (possibly by a pair of rogue cross-origin subframes). Because of this, Chrome has been halting the forwarding after the first postMessage() call or (in most browsers) beyond a 'setTimeout()` call depth of one. This is not consistent.

  • Explicit for developers vs implicit in implementation details. If an event handler sends two cross-process messages, it would choose which of them (if at all) would cause the transfer. With token forwarding, Chrome has to pick one for propagation (for the reason mentioned above), even through the script may need activation only through the other.

Btw, it doesn't have to be postMessage(). Something like targetwindow.transferActivation() could be an option too, might be even better if we want/have to define it to be synchronous.

@annevk
Copy link
Member

annevk commented Feb 15, 2019

Thanks. FWIW, I don't think we want another synchronous communication channel between two places that could be in different processes.

@mustaqahmed
Copy link
Contributor Author

Sticking to postMessage() seems logical then, because:

  • it's a well-known asynchronous communication method, and
  • It already allows transfer of objects across processes, so adding "activation transfer" on top looks like a sensible extension.

@mustaqahmed
Copy link
Contributor Author

@mounirlamouri suggested window.transferUserActivation() instead, which I think can be asynchronous too.

@annevk, wdyt?

@smaug----: we would love to know your thoughts too.

@mounirlamouri
Copy link
Member

Something that was pointed out to me offline is that my proposal assumes that the user activation isn't linked to a scope which may be what Mozilla and Chrome are doing but not what Safari is. Do we see a path forward with some consistency here? Do we want to design an API based on a convergence towards a similar behaviour?

@mustaqahmed
Copy link
Contributor Author

@mounirlamouri: The transfer idea here could be applied to scoped user activation model too, primarily because the model never really worked consistently with postMessages, even for same-origin frames. If the convergence question here is about the underlying model for user activation, I would suggest #1903 for that discussion.

@mustaqahmed
Copy link
Contributor Author

I agree with @mounirlamouri that window.transferUserActivation() is a cleaner API, vs postMessage() transfer.

@travisleithead
Copy link
Member

So, since this transfer API (whether postMessage or transferUserActivation) requires developer to specificially make the transfer, won't they need an introspection API to know if the given window has activation state at the current moment? (Or are we expecting them to simply always attempt to transfer the activation whether or not they might have it?) Is there a place where the current activation state can be read? (e.g., window.hasActivation or window.hasTransientActivation / hasEverBeenActivated)?

@mustaqahmed
Copy link
Contributor Author

@travisleithead: we proposed a separate query API for that.
We have window.navigator.userActivation returning both sticky (.hasBeenActive) and transient (.isActive) bits (available in Chrome 72).

@travisleithead
Copy link
Member

Ah, makes sense. Thanks! https://github.com/dtapuska/useractivation

@mustaqahmed
Copy link
Contributor Author

Motivated by the feedback from TAG about this proposal, plus a new use-case we want to support, we have switched our focus to an alternate Capability Delegation API (WICG repo, design doc).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
addition/proposal New features or enhancements interop Implementations are not interoperable with each other needs implementer interest Moving the issue forward requires implementers to express interest topic: user activation
Development

Successfully merging a pull request may close this issue.

4 participants