w3c / permissions

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

Drop .request() #83

Closed martinthomson closed 6 years ago

martinthomson commented 8 years ago

I realize that this might be a minority opinion here, but I think that .request() stands to undermine a lot of the work that we've done to make permissions on the web meaningful and relevant to users. The most important aspect of that being that permissions requests are made in context.

You have probably all read this before, but it's worth a refresher. That summarizes where this is coming from. I will note that model has been vindicated in that Android has moved to making requests in context also.

What I want to focus on here, something I consider more important than speculation about how applications might actually use .request(), is the consequence aspect of making individual APIs trigger use consent interactions.

When an application calls getUserMedia() (for the first time), it causes two things to happen: a user consent interaction, and acquisition of a resource. The same for geolocation. As a consequence, the users sees that the application is then recording media or accessing their GPS (both of which usually have indicators in chrome that the user has already learned to recognize).

I believe that coupling of request and consequence to be important. It provides applications with an incentive to defer requests until the point where the capability provided by the API is needed. More so in browsers that don't implement persistent-by-default permissions. That preserves the contextual relationship between asking and using.

An API like .request() undermines this model. We already have ways to request permission from users, and I don't see any suggestion that we're going to change that. That means that this API only serves to endorse modes where asking is decoupled from consequence.

There might be exceptions to this, and here I note that we don't appear to have a good substitute for just asking ahead of time when it comes to push notifications. The Notifications API has its own analogue of .request() for that purpose, which turns out to be bad UX, but the best we've been able to come up with thus far. That doesn't justify the creation of a generic permission request capability.

jimmywarting commented 8 years ago

I like request method because how it unifies the API on how you request permissions. Read #48 as to why I hate the existing individual request permission model. Each one of them have there own syntax and some of them are "broken" or lacks useful informations as "was the permission rejected?"

Asking ahead of time will be entirely up to the developers. I think most developers has a common sense and would only disturb the user with a prompt when needed

jan-ivar commented 8 years ago

Asking ahead of time will be entirely up to the developers. I think most developers has a common sense and would only disturb the user with a prompt when needed

@jimmywarting why do common sense developers need .request then?

jyasskin commented 8 years ago

Thanks for filing this issue @martinthomson. I don't have a preference either way, but I wanted to be more precise about the Android model: Android M moved from request-at-install-time to an explicit request function that looks a lot like Permissions.request(): Activity.requestPermissions().

I'll try to get some more folks with opinions to comment.

jimmywarting commented 8 years ago

@jan-ivar To get a unified API that works the same way for all permissions and isen't broken ofc

jan-ivar commented 8 years ago

@jimmywarting thanks for clarifying. Unfortunately, as @martinthomson points out .request is different in significant and problematic ways from existing _access_ APIs, yet your use-case doesn't seem to need these differences. Ergonomics aside, I'm confident we can fix existing problems without requiring new APIs.

slightlyoff commented 8 years ago

Hey @martinthomson, @jan-ivar:

I'm not sure I actually understand the concerns being raised. Requesting a geolocation permission via Permission.request() will have exactly the same side-effect (UI being shown) as navigator.geolocation.getCurrentPosition() or navigator.geolocation.watchPosition() and conceptually can also do acquisition (use) by providing the resource in the per-API subclass of PermissionStatus. The separation of "acquisition" in the case of geolocation is down to legacy API design.

In a future where all API designers can rely on browsers to have implemented Permission.request(), it will be possible for them to avoid doubling up API or separating these. In the interim period where Mozilla (and others) have failed to implement the full API, it's harder to give advice to API authors that they should not also provide their own API. That said, the TAG is working toward that future by making sure that all APIs which can have a permission are at least designed with the Permissions API in mind.

Next, as @jyasskin points out, we don't have data to confirm your fear despite have quite a lot of use of similar APIs in Android M. The risk of showing UI is itself the primary consequence that developers seek to avoid (and why the reflection side of the Permission API is so powerful) and that is what creates incentive to put use in-context.

Lastly, as a matter of platform consistency, you should think of the Permission API similarly to the Promises API: it's a new primitive that we need to work to expand integration and use of and is a project we're actively working on as new APIs come across the transom. Pointing to the fact tha some legacy APIs already have their own (inconsistent, frequently broken, badly designed) request* methods doesn't say anything about how we should improve the situation. With that perspective, I hope you'll come to view the Permissions API as the solution and not the problem. Having personally done the (relatively brutal) TAG review of the API, I certainly came to that conclusion.

Regards

jan-ivar commented 8 years ago

@slightlyoff promises solved real problems like error propagation in asynchronous flow. What problem does .request solve?

slightlyoff commented 8 years ago

Promises helped resolve some of the nasty timing and API inconsistency issues we experience across the platform. As I said over and over again in the Promises standards effort "the single biggest thing Promises give us is one way to do it". The same is true of Promise.request() (and friends). Today there's no uniform way of packing arguments, registering callbacks, dealing with return values for permission states, or any of the rest.

The Permissions API, like Promises before it, open up the ability to heal that rift across the platform, both for legacy APIs like geolocation and (more excitingly) for new APIs that will be discouraged from (badly) re-inventing such APIs each time they need to expose this sort of thing.

jyasskin commented 8 years ago

With Promises, we can take advantage of the uniform API to write libraries or even language features that treat a bunch of kinds of Promises generically. With Permissions.request(), I don't immediately see that opportunity, especially since different permissions need different extra data in their request() calls. Do we have any examples of web developers out in the wild building libraries that abstract permission calls like this?

I do see the benefit of establishing a pattern for request calls to follow. That could be done simply as TAG guidance for new APIs, plus an attempt to retrofit it onto older APIs like geolocation and notifications. It sounds like that's the path @jan-ivar and @martinthomson want to take. However, a new API gives an easier place to do that retrofit and makes it harder to miss the TAG guidance in the spec for a new permission.

martinthomson commented 8 years ago

Yes, promises are great. And I get that our primitive engineer brains love to seek out patterns and try to tame them.

Where promises serve to replace an existing feature in a superior way, .request() cannot ever serve as a replacement. The API that does something still has to exist.

Many of the benefits you claim to gain from .request() are actually realized by defining .query(). I'm not arguing against that, it's a good idea. Indeed, I see much of those benefits being realized in terms of codifying what permissions an API might require. Those have a clarifying effect on the APIs themselves for the reasons @jyasskin describes. We're learning a lot about the assumptions we've made and we don't need .request() for that.

If unification is your goal here (and leaving aside for the moment that we're not really talking about unification), we have to establish that a unified API has marginal utility that outweighs the negatives. You are right to ask what the actual negative impact of decoupling is. I've already seen some indication that these negatives are present with notifications, where a decoupled request is all we currently have. A large site conducted an experiment on what style of prompting for push notifications got the best conversion rate. Asking at page load time turned out to be best for their metrics.

I know that there is a desire to do the same for getUserMedia(). I believe that there are a sizeable number of web developers who find the whole consent experience very frustrating and who would rather have it out of the way.

Install Skype on Android and witness what it does to destroy the contextual permissions thing when you start it up.

jyasskin commented 8 years ago

Let me belatedly summarize the pros and cons I see for permissions.request(), and the pros and cons I'm skeptical of so far:

Pro

  1. Provides a new spelling for several old APIs where we can get their interfaces right.
  2. Provides a uniform spelling for requesting a permission so developers don't have to learn the intricacies of each capability's request function. (This is tempered by each capability getting to refine its PermissionDescriptor, probably in non-uniform ways.)

Con

  1. Redundant with other, more tuned spellings of particular APIs. For example, getUserMedia() might have a way to express interacting constraints on the camera and microphone, which we wouldn't be able to express in the generic request() interface.
  2. Might cause extra permission prompts. In Firefox's model, even if you request and get permission for something like geolocation, you probably can't call getCurrentPosition() without another prompt. If folks call request() thinking it'll get them access to use location wherever, they'll wind up spamming the user.

Unconvincing Pro

  1. "request() is like Promises in that it'll help devs build libraries to treat a bunch of different permission requests uniformly." I think each capability is different enough that it'll be hard to do things like make arrays of PermissionDescriptors, and because we want devs to ask for permissions in context, that wouldn't even necessarily be a good thing.

Unconvincing Con

  1. "request() makes developers more likely to ask for permissions on startup." If devs find that prompting on startup gets them "the best conversion rate", they can do that with the existing functions. Just call watchLocation() on startup to get the prompt early, and then save the stream of values so you never have to ask again. We even have an extra lever with request() to inhibit asking on startup: it'll be web-compatible to require a user gesture for a call to request(), but it's less so to require it for watchLocation().

Did I catch everything?

jan-ivar commented 8 years ago

Provides a uniform spelling for requesting a permission so developers don't have to learn the intricacies of each capability's request function.

Apples and oranges.

If "permissions" are mere elevation-level badges (prompt, grant, or deny), then sure, all permissions are the same, and a uniform API makes sense (unless you hate Android's challenge model).

But overload access onto this API, and similarities end. Why would accessing geo-location work anything like accessing the camera? They take totally different arguments and return totally different things! No developer thinks they can ignore these domains differences.

In Firefox's model, even if you request and get permission for something like geolocation, you probably can't call getCurrentPosition() without another prompt.

Right, mandating the Chrome permission model (implicit persistent permission on access) is a non-starter.

martinthomson commented 8 years ago

Provides a new spelling for several old APIs where we can get their interfaces right.

I don't find this convincing myself. Old APIs are getting new spellings as we speak. The poster child here, geolocation, has been talking about a new promise-based API. But the problem there is that there is nothing functionally wrong with their API, it's just disgusting when viewed with 2016 eyes.

Provides a uniform spelling for requesting a permission so developers don't have to learn the intricacies of each capability's request function.

I very much agree with the point on tempering here. The complexity here is not in the high level "ask for X", it's in the nuance involved with the descriptor. Of course, we all emphasize the importance of that point that differently.

@jan-ivar's concern is related to this I think. We aren't dealing well with the different ways that browsers might choose to implement access control. If all we ever do is vend season passes for sites, then this API is a fine one, but we don't do that for "filesystem" (i.e., <input type="file">).

At some level, I think that we do need to dumb down the interaction across the different APIs, but thus far it's been a little slap-dash.

alvestrand commented 8 years ago

Note: I am in favor of two things, for different reasons:

I have a strong opinion / care a lot on the first and a weak opinion / don't care as much on the second, which is why I filed #94.

jan-ivar commented 8 years ago

In the interest of separating discussion, I think we're only talking about the .request method here.

jyasskin commented 8 years ago

Coming back to this issue, we've talked over the pros and cons within Google a bit, and we still think permissions.request() is the right thing to do:

  1. It will let us stop building request() functions in future interfaces. They'll still need to define their descriptors and result types, but the TAG won't have to double-check that the overall shape is right.
  2. A new polyfill shows that if folks want the request() shape today, they can get it, so the new API won't do any more to let sites ask for permissions out of context. Along with permissions.query(), we think it'll actually help sites ask in context, since it helps authors think about exactly when they're showing prompts to their users.
  3. If we keep request(), we'd like to add guidance that new specs should avoid showing permission prompts from any function other than permissions.request(). To accomplish this, permissions.request() could always include an object in its result that would be used to access the requested API, and request() would probably be the only way to get that object. In the very long run, we can think about deprecating the old spellings of functions like Notifications.requestPermission() and getUserMedia() in favor of permissions.request(), in order to remove the redundancy, but of course we wouldn't do that until usage fell low enough.
annevk commented 8 years ago

I think the main problem with request() (and also query() really) is that the answer is not uniform. Depending on the permission you request, the answer you get has vastly different implications with regards to scope. So unlike with promises, you cannot actually write generic code on top (e.g., using BroadcastChannel to share the answer with other globals will only work as expected for some permissions).

I think I would be much more comfortable with this API if we actually defined the underlying "request access" primitive in sufficient detail for the answer to be uniform and provide guarantees to developers.

jan-ivar commented 8 years ago

@jyasskin Thanks for the polyfill. Hopefully it clarifies for everyone that .request() as proposed would be an API for requesting _functionality_, not for requesting permission for said functionality.

Historically, specs draft APIs around functionality, not externalities of functionality such as whether something is allowed or not. We have web developers ask for the camera, not ask for elevation of camera permissions in order to get a camera stream as an aside.

This PR violates that, and is stealing the API surface of any spec that has a powerful feature. Hopefully, there won't be a future API corralled around some other externality, like the configuration or storage needs of a feature, or we'll have three or four ways to do the same thing.

I understand the impulse that when we can query something, we want to set and clear those things as well. However, setting and clearing of permissions is expressly implicit in using functionality on the web, by design, for the good reasons outlined in roc's blog (to prevent the permission bundle problem).

About bundling, @alvestrand said:

... the "request by using" paradigm, while applicable to a lot of cases, has the nasty side effect that applications whose logic really lend themselves to request() will try to acquire sources they don't need in order to make sure they have already done the dialogs if they need them later.

Not all browsers auto-persist permissions, so the payout of such arm-twisting is more rewarding in Chrome. Roc calls those "Greedy Applications". He says: "One wrinkle is that lazy app developers can turn the "permissions in context" model back into the "bundled permissions" model by activating APIs up-front and refusing to let the application proceed until all requests are granted. My hope is that if most apps don't behave that way, users will develop higher expectations and be distrustful of lazy apps."

This has mostly held (he said that in 2011). In any case, the way around that problem is not to piggyback said functionality onto the setting of permissions. That's awkwardly backwards, an attempt at a cross-domain (lateral) API. Even WebIDL is screaming.

Asking web developers to pivot to "permissions" as a concept to access functionality seems to encourage bundling, if not in function then in form. It will make them "lazy".

Now, looking at the two lone pros that have been mentioned for this PR:

  1. Provides a new spelling for several old APIs where we can get their interfaces right.
  2. Provides a uniform spelling for requesting a permission so developers don't have to learn the intricacies of each capability's request function. (This is tempered by each capability getting to refine its PermissionDescriptor, probably in non-uniform ways.)

These both seem aimed at lazy developers who don't want "to learn". That's a con in my book.

For instance, did you know that to immediately relinquish a hardware device you've obtained with getUserMedia, you must call stream.getTracks().forEach(track => track.stop()) ?

We want people to learn the intricacies of each capability's request function. One is not like the other.

alvestrand commented 8 years ago

It almost goes without saying, but I concluded some time ago that I think Roc was wrong in his arguments against requesting permissions. The inability to "ask first, open later" is making applications more convoluted, not less.

Jan-Ivar also misinterprets what I meant with the comment about "acquire sources they don't need" - if permission is lost when relinquishing them, the applications that fall into this trap will hang on to the devices (which will work both in Chrome and Firefox). This consumes system resources for no better reason than working around a mildly inconvenient API.

I also think that the idea of returning a capability from requestPermission() has merit, but the polyfill illustrates that it's not the same thing as opening the device - when we're dealing with real hardware like a camera that has lots of configuration settings on its own, opening it has side effects and takes time. Checking whether or not you have permission to open it should be fast and have no side effects; requesting permission is likely to involve human interaction, so isn't fast - but it should not have side effects.

Developers are not lazy, but they have priorities; the greatest praise I've had for the WebRTC API was a developer who said "the WebRTC part of my app took 5 minutes, which meant I could spend my time on working on the other aspects instead".

jan-ivar commented 8 years ago

@alvestrand One of us must have misunderstood the polyfill. .request seems identical to opening the device. @jyasskin Is the goal to support "request-before-use" as well as "request-on-use"?

Unless it is, I see no reason to argue roc's well-established principle behind web permissions today.

When apps bully users into giving permissions without any obvious benefit, we should protect the users' right to say no, not the users' right to say yes with less use of system resources.

I dare a greedy application to grab the user's camera and keep it on for the duration of their visit, with recording-indicator and hardware light on. That'd drive away users fast. As roc says, I hope "users will develop higher expectations and be distrustful of" such apps.

jyasskin commented 8 years ago

When writing the polyfill, I assumed that if you drop the handle, you might have to re-prompt in order to get it back. My geolocation implementation is knowingly a bit wrong in that regard, since it only uses getCurrentPosition() instead of watchPosition(), but with enough time, I'd have it emulate a multiply-callable getCurrentPosition() by just keeping the watchPosition() stream open. I think we can probably improve on the polyfill's detailed behavior with a native API, and I think we'll still have to discuss those detailed improvements after the overall outline is figured out. For example, I know of some differences between what @alvestrand and I are imagining.

@marcoscaceres, were you saying that Firefox's reprompting within the same realm is probably a bug? That seems inconsistent with @jan-ivar's position that reprompting is desirable. What are Mozilla's goals here, as distinct from a bunch of individuals who work at Mozilla?

jan-ivar commented 8 years ago

@jyasskin Can we get a clear answer on whether the goal is to support "request-before-use" as well as "request-on-use"? This is really confusing.

jyasskin commented 8 years ago

Yes, the folks who want a .request() function want sites to be able to request permission to use a feature, wait a bit, and then use the feature.

jan-ivar commented 8 years ago

@jyasskin I think that's pretty much a non-starter for Mozilla.

jan-ivar commented 8 years ago

@jyasskin To answer your question, if you drop the last handle (stream) then you have to re-prompt, unless you have persistent permission, so says the spec (From February before the still-confusing permissions spec integration).

@marcoscaceres may have been thinking of bug 1270572 which is different.

jyasskin commented 8 years ago

The polyfill demonstrates that request-before-use works with no changes to the web platform. It's not perfect -- on Firefox it takes more resources for several features and leaves the camera light on for "camera" -- but permissions.request() isn't needed for websites to adopt the model.

jan-ivar commented 8 years ago

Unless you assign the returned stream somewhere, you have about 10 seconds before garbage collection kicks in and turns off the camera (and your access), causing a re-prompt on subsequent access.

I agree permissions.request() isn't needed. permissions.query() has the same value without it.

slightlyoff commented 8 years ago

Jan: while you assert that request isn't needed, you haven't addressed the concerns about commonality across APIs. In my view, your statement-without-evidence can be dismissed similarly.

jan-ivar commented 8 years ago

@slightlyoff I was merely agreeing with @jyasskin. As to concerns about commonality, I see no evidence. In contrast, I see plenty of evidence that "request-on-use" has served the web well. Sadly, our concerns seem diametrically opposed on this issue.

jan-ivar commented 8 years ago

Users are higher in the order of constituencies, so asking them to give up knowing what permissions are for, so developers can have more commonality across APIs, seems like a poor tradeoff.

jyasskin commented 8 years ago

@jan-ivar, you linked to https://github.com/chromium/permissions.request/blob/master/permissions.request.ts#L268 which stores the returned stream somewhere, and then 6 hours later, you talked about not assigning it. I'm coming to the conclusion that you're filibustering, so I'm going to wait for another Mozillan to come talk about Mozilla's position.

jan-ivar commented 8 years ago

@jyasskin It stores it in the returned result object, so someone calling this just to elevate permission and not caring about the stream (e.g. the touted "request-before-use" case) will be sorely surprised after 10 seconds in Firefox. Asking the user to store stream is "use".

jan-ivar commented 8 years ago

Is the user always expected to either hold on to the returned status object or register a listener on it?

jan-ivar commented 8 years ago

@ShijunS Edge and Firefox have similar permission models, what do you think of this?

ShijunS commented 8 years ago

It looks like the request() method is largely based on a 'request-before-use' model, hence requires a stored permission (either granted or denied). This could lead to potential conflict with per-use permission options for some functionality currently supported in the Firefox and Edge permission models.

BTW, when users 'dismiss' a user permission ask, it typically means a one-time 'denied'. It's not clear how that would be reflected in the 'request-before-use' model. I assume the permission state would stay as 'prompt', although user doesn't really want to be asked again right away.

jyasskin commented 8 years ago

@ShijunS Thanks for chiming in from the Edge position! From a quick test with 'microphone', it looks like Edge does store a permission grant for the life of the realm (~tab). It's only Firefox's default grant that seems to have no storage at all. Edge's behavior makes the request() function work fine. Is 'camera' different?

If the page requests permission to use the same feature immediately after the user dismisses a prompt, does Edge prompt again or immediately deny? If it prompts again, then permissions.query() should return prompt. I think the result of request() is still up in the air. It's currently specified to return prompt too, with no capability object, I can imagine it returning denied instead. That's probably a different issue than this one, but do you have a preference?

ShijunS commented 8 years ago

@jyasskin, if a capture device is in use already, we don't prompt again for the same device. There is no difference for the app to call clone() or call GUM() again in that case. If you reload your test page on the same tab in Edge, I'm sure you will get a new user permission prompt.

It seems for the per-use model, if request() returns either a "granted" or a "denied" state, I expect there will have to a 'lifetime' associated with that state. It could potentially be more complicated if the 'lifetime' has a device dependency. BTW, I don't see any clean solution personally, so can't really pick what I'd prefer at this point.

jyasskin commented 8 years ago

@ShijunS It looks like Edge doesn't prompt within the same realm even if the capture device has stopped being used. Specifically, visit https://jyasskin.github.io/sandbox/camera-pause/, click 'Replace stream', grant permission, then hit 'Stop stream'. The hardware light should go out. Then, without reloading the page, click 'replace stream' again. In my test, there was no extra permission prompt, and the hardware light turned on again, and the <video> element resumed playing from my camera. This demonstrates that a 'mute video' button will work in a video-chat app. Then, reload the page (to create a new realm), and clicking 'replace stream' should ask for permission again. That demonstrates that you're not storing permission persistently.

I think that's a reasonable behavior for Edge, and although the request() polyfill doesn't behave well right now (it leaves the camera light on), it looks straightforward to make it behave well in Edge.

ShijunS commented 8 years ago

@jyasskin, Edge's permission model has dependency on device type, deviceId, and the type of origins (http vs. https). The model is also evolving as well. In addition, when user pauses the preview video tag, the camera light is off as well. I'm still thinking how to make the query() fit in without confusing apps and users. It'd be a challenge to have a new request() on top of that.

jyasskin commented 8 years ago

@ShijunS If you can describe the dependency precisely, probably in a new issue, I'm happy to help figure out how to make query() fit in.

ShijunS commented 8 years ago

@jyasskin, will do. Let's keep discussion here for request().

martinthomson commented 8 years ago

Coming in to this after a break (hello from Almaty!).

The problem I have with this discussion so far is the presumption (in various posts) that a particular model is somehow wrong, or that this is something where a compromise is necessary.

I see us wasting a lot of time on this, and not actually making any progress. That is because we disagree. I was given the impression that variations in how browsers interact with users was an important property to preserve.

That means that disagreement isn't a real problem. Well, it is as long as .request() continues to exist because I think we've proven that it can't be implemented consistently without forcing changes on browsers that they don't want (granted, it's clear that Mozilla aren't in agreement on this point, though that's not news).

I don't find the polyfill convincing either way here. It merely takes the current APIs and switches direct effects with secondary effects.

So let's talk about effects on implementations: say that the purpose of .request() is to produce whatever UX will turn a call to .query() from "prompt" to "granted" (assuming that they are made within the same scope, and that the user doesn't change their mind, blah, blah, ...). In implementations that have a "remember this choice" option (as Firefox does): are they forced to fix that toggle in the "remember" position?

I haven't seen a satisfactory answer to that; as I see it, this would force Firefox to do that, which I don't think we're prepared to do. Also, implementations that present a choice (as with getUserMedia()), but associate persistent permission with all devices (again, Firefox), are they obligated to remove the choice so that the intent of the prompt is properly clear?

It's clear that if there is no possibility of persisting permissions, then .request() will always fail, but if a persistent grant is ever conditional, this API produces some surprising effects.

jyasskin commented 8 years ago

@martinthomson I completely agree that "variations in how browsers interact with users [are] an important property to preserve."

I don't think the purpose of .request() should be to cause .query() to return a different value. It should be to ask the user for permission to use a feature. Once permission is granted, you should get a capability object that lets you use the feature without further prompts (unless the user takes action to revoke permission), but having that capability object shouldn't imply that a subsequent .request() call won't show a prompt.

The only objections to the polyfill's behavior were that it would cost resources/time to open the camera and would leave the camera light on. Resource optimization isn't restricted by specs, and Jan-ivar thinks the camera light is a bug in Firefox. So adding .request() definitely wouldn't "[force] [permission model] changes on browsers that they don't want".

jan-ivar commented 8 years ago

@jyasskin Even if you modify the polyfill to set track.enabled = false the instant you've obtained the camera, the camera light would likely still come on for a second or two (to combat the turning-on-and-off-quickly exploit @alvestrand mentions), and the browser's device indicators would likely still blare red for the duration as before (with a slightly modified skin), which seems undesirable.

Since it encourages Android-style permission bundling, we may also want to actively discourage it working.

jyasskin commented 8 years ago

@jan-ivar Having the camera light come on temporarily when you grant camera permission is totally in line with browsers varying in how they interact with their users. If that's the behavior Firefox decides .request() should have, I don't see any problem with it.

alvestrand commented 8 years ago

@jyasskin the idea of ".request() returns an object that can be used to gather permissions" is almost identical to the idea I had on the first attempt at merging permissions with getusermedia, where there would be a temporary permission that was automatically dropped at device close. This proved to be highly confusing, and we went for another solution where getusermedia was the one that checked for open devices before bothering to ask about permissions.

@jan-ivar seeing you argue in one paragraph that we shouldn't do .request because it restricts browser UI choice for permission handling and in the next paragraph that we shouldn't make .request() work because it discourages one particular choice of UI for permissions (Android bundling) is confusing to me.

jyasskin commented 8 years ago

@alvestrand (I'm probably just restating what you actually meant, but in the interest of being painfully precise,) I think ".request() returns an object that can be used to gather permissions" isn't quite right. request() gathers the permissions, and then it returns an object that can be used to use the feature. If open devices imply that permission has already been granted, then request() would check for open devices before bothering to ask about permissions. Then it would return an object (maybe a disabled MediaStream, maybe something more tailored for the purpose) that allows use of the feature. If that's actually what you tried, then the information that it was confusing is really helpful.

jan-ivar commented 8 years ago

I don't think the purpose of .request() should be to cause .query() to return a different value.

@jyasskin So it's not a simple permission-elevation API anymore like it used to be. And if you return a stream with disabled tracks then it's no longer a straightforward request-functionality API either...

Is your idea that developers must first ask permission with permission.request({name: "camera"}), hold onto the object it resolves with, and then call getUserMedia(constraints)?

@alvestrand I’m all for individual browsers innovating, but you’re asking to change how the web works to do it, which is different. From where I'm sitting there's no problem today, and I haven't read a compelling blog on why we should steer developers toward permission bundling.

alvestrand commented 8 years ago

@jyasskin I think I prefer the model where .request is a tool for gathering information about the user's intent, and thus may modify what .query() returns.

Capability models sound real nice, but I haven't seen many cases where generic models have proved successful (we use scope-limited ones every time we have "file open" return a file descriptor.)

jyasskin commented 8 years ago

@alvestrand, what do you mean by "gathering information about the user's intent"? Would .request() always show a prompt? If the user chooses to grant permission but not to save that decision for later, would the subsequent attempt to use the API show a second prompt?

Clearly .request() can modify what .query() returns, but Firefox's model would have to change to let us require .request() to modify .query()'s result, and I don't think we can change their model for them.