w3c / permissions

Permissions API
https://www.w3.org/TR/permissions/
Other
107 stars 51 forks source link

"Requesting more permission" algorithms are tightly coupled to prompts #153

Open jugglinmike opened 7 years ago

jugglinmike commented 7 years ago

Currently, the "request permission to use" and "prompt the user to choose," algorithms are specified to request input from the user and block until the user responds to that specific request. If the UA receives new information about the user's intent through some other mechanism than that request, the algorithm continues to block.

This allows the following user flow:

  1. Visit a site that prompts for permission to use geolocation data
  2. Receive a prompt to allow access
  3. Ignore prompt, but allow Geolocation access through some other means
  4. Note that the prompt is still active

This seems like a potential oversight. At this point in the interaction, the user's intent is clear, and the prompt is arguably superfluous. While the prompt itself is largely inconsequential, it reflects the control flow through application code (via the request method). This means applications themselves would exhibit the same behavior under these circumstances.

I'm wondering if it makes more sense for the "requesting more permissions" algorithms to prompt the user, but to then block on the receipt of new information about the user's intent (regardless of the source).

raymeskhoury commented 7 years ago

If the UA returns "prompt" from permission state then I think it's reasonable to expect that the UA will show some type of UI that elicits some kind of information from the user which is fed back into the decision (which I would describe as a prompt :).

However, that doesn't stop the UA from determining the decision through other means. What I mean is that the UA is never obliged to return "prompt". For example, UAs would be free to block a permission to a website that is on a malware blacklist. In this case, the UA would return "denied" as the value for permission state and a prompt would never be shown. Likewise, they could decide, based on prior user behavior, that it is a good choice to allow a permission for a particular website and they could return "granted" here.

So I guess it feels relatively consistent in my mind. Note that exposing the notion of "prompt" in the platform was an explicit choice. It does imply something about what the UA will do (although it's only vaguely defined what a prompt will do). But it's also practically important because websites need to know if they user will expect some type of UI to be shown in order to give them appropriate warning.

Does that make sense? What are your thoughts?

jugglinmike commented 7 years ago

That all makes sense to me! I may not have explained myself well enough, though, because I'm still unsure about the behavior I had in mind when I submitted this issue. A more concrete example may be in order.

Given the following application code:

navigator.permissions.request({ name: 'geolocation' })
  .then((result) => {
      if (result.state === 'granted') {
        myApp.updateLocation();
      }
    });

As you explained in your response, a user may run this code, and the UA may immediately return a permission state of "denied" or "granted". In this case, no prompt would be displayed at all.

However, the issue I have in mind concerns only those cases where the descriptor's permission state is "prompt". Taking this for granted, we can expect a prompt to be displayed and the promise returned by request to wait in the "pending" state. At this point, if the user ignores the prompt but instead enables Geolocation through other means (e.g. in Firefox: right click, "View Page Info", "Permissions", "Access Your Location", "Allow" checkbox), then:

  1. the prompt will continue to be displayed
  2. (more importantly) the promise will not be resolved

This is surprising to me because at this point in the hypothetical, the user's intent seems clear.

One way of looking at this is asking, "is the purpose of the prompt to receive input from the user, or is the purpose of the prompt to elicit new information about the user's intent?" If the answer is "the former," then the current text is appropriate. But I believe it's the latter, and that the text should actually wait on new information about the user's intent, regardless of the prompt.

jyasskin commented 7 years ago

I think the current text allows the browser to Do The Right Thing, although it doesn't mandate The Right Thing, which is probably correct for permissions. Specifically, https://w3c.github.io/permissions/#request-permission-to-use says:

  1. Ask the user’s permission for the calling algorithm to use the powerful feature described by descriptor.
  2. If the user grants permission, return "granted"; otherwise return "denied". The user’s interaction may provide new information about the user’s intent for this realm and other realms with the same origin.

"the user grants permission" could happen via the prompt or out of line, as you're worried about, and I think the wording says the browser can continue.

"prompt the user to choose" actually wants one of several choices, and it's reasonable to keep waiting for that particular prompt, even if the user grants access via another route. Even then, the UA could interpret that other route as "the user chose an option".

Does that make sense?

jugglinmike commented 7 years ago

Ah, I didn't consider that interpretation (clearly). Thanks for helping me understand!

Have you been following the review for a new "Automation" section? For context: we discussed the difference between a "reactive" API (i.e. an API for responding to active prompts) and a "proactive" API (i.e. an API for setting internal permission state before prompts are even issued). Although I initially proposed a "reactive" API, @raymeskhoury pushed for a "reactive" "proactive" API instead.

I assumed the two API styles were mutually exclusive, but it looks like that may be incorrect. Under this interpretation, if a promise for a given permission request is pending, and the relevant permission descriptor's state is set via WebDriver, then we should expect the promise to be resolved with the new value. In other words, the "proactive" API can be used to react to previously-issued prompts.

@jyasskin Does that sound right to you? @raymeskhoury do you know if Chrome's implementation is well-suited to this behavior?

raymeskhoury commented 7 years ago

@raymeskhoury pushed for a "reactive" API instead.

I think you mean proactive API here?

I assumed the two API styles were mutually exclusive

I think it's a bit fuzzy but I think if I squint I can see additional coverage we might get by simulating some kind of prompting behavior in the UA. However, in practice I don't see a reactive API being very valuable to test writers in the presence of a proactive one and potentially just causing confusion. My thought is that we shouldn't spend the time specifying/implementing that behavior for now. If a clear need comes along we can dig deeper. WDYT?

jugglinmike commented 7 years ago

I think you mean proactive API here?

Yes, I do. I really need to be more careful. Sorry for the confusion!

My thought is that we shouldn't spend the time specifying/implementing that behavior for now. If a clear need comes along we can dig deeper. WDYT?

I support your suggestion to dig deeper if a clear need comes along. It's just that I don't think this will be necessary, after all.

My interpretation of @jyasskin's input is that a "proactive" API can actually be used "reactively." In more concrete terms: directly setting the state of a permission descriptor after a request has been made will be interpreted as "the user grant[ing] permission", and that the pending promise will be fulfilled.

I don't mean to belabor this detail, but because the distinction will be observable from WebDriver scripts, I want to be sure I understand what the expected behavior is. It took me some time to come to this interpretation. It may be due to carelessness on my part, but I'm starting to think that this spec language is a little too loose about this. I'd be interested in tightening it up a but, but first: do you agree with the interpretation I shared above?

jyasskin commented 7 years ago

I think you're right that if the WebDriver script notices that it has a request sitting behind a prompt, and it then sets the permission state to "granted" or "denied", then that should cause the prompt to return. We don't say that clearly, even after my suggested change to your patch, but I'm not sure how to make it better without limiting the ways UAs can return the user's intended permission state. Suggestions are welcome.

jan-ivar commented 7 years ago

I think the important guarantee in this algorithm is that other specs rely on it to mandate that UAs don't let web pages use powerful features without having to "Ask the user’s permission". I think it's purposely stronger than "obtain user consent", yet vague enough to let UAs implement policies for repeat permissions. So I'm very happy with the difficult line the current text draws.