w3c / ambient-light

Ambient Light Sensor
https://www.w3.org/TR/ambient-light/
Other
26 stars 21 forks source link

Add camera permission requirement to spec? #79

Open rakuco opened 2 years ago

rakuco commented 2 years ago

See https://www.w3.org/2021/10/29-dap-minutes.html#t07:

RESOLUTION: Add camera permission requirement to ALS spec to help enable shipment of the API

If I've understood it correctly, the idea would be to add text to the spec that mandates that permission for accessing ALS would be granted only if access to ALS as well as camera is allowed (in a similar fashion to getUserMedia() and the microphone/camera permissions, for example).

I'd like to make sure that this is indeed the idea, especially in light of https://github.com/w3c/ambient-light/issues/64#issuecomment-954444294 (This will require continuous monitoring of the ALS and not make sense to bundle with a camera API (including permissions)).

I'm also wondering if this makes sense as a normative requirement or as an implementation detail. The DAS F2F discussion mentioned Chrome's position:

we'd be willing to enable the ALS API for websites that use camera already we could consider ALS augmenting the camera

in this case, isn't it up to the UA to do one of the following:

rakuco commented 2 years ago

cc @reillyeon

rakuco commented 2 years ago

@reillyeon I was wondering if you could chime in, I'm not sure how much of the above should be done here and how much should be taken care of in Chromium.

@engedy fyi

reillyeon commented 2 years ago

I think the resolution was to make requesting the "camera" permission a normative requirement.

From an implementation perspective however I'd be interested in @engedy's thoughts on how usage of the ALS (without camera) would be presented to the user. We've set up a reasonably good precedent for using tab indicators (and notifications on mobile) for this sort of thing.

rakuco commented 2 years ago

I think the resolution was to make requesting the "camera" permission a normative requirement.

If I've understood it correctly, the idea is to:

Consequently, from an UA perspective, calling AmbientLightSensor.start() would prompt for sensor and camera access (in whatever fashion the UA sees fit). If allowed by the user, this means that:

reillyeon commented 2 years ago

I would go so far as to remove the ambient-light-sensor permission and feature and only refer to camera in the specification.

rakuco commented 2 years ago

Hmm, interesting. I don't have strong objections to the idea, although I don't know if this will confuse users depending on how the UI is constructed (e.g. a website asks for camera access although the camera indicator does not get turned on and no camera access seems to be happening).

Let me try to summarize the new proposal:

I wonder if others would like to chime in before I work on a patch? @anssiko @kenchris @larsgk @marcoscaceres @willmorgan @engedy

willmorgan commented 2 years ago

Having the ALS work by relying on getUserMedia's side effects doesn't feel right to me, but maybe getUserMedia is actually a better API to use as developers can select the relevant sensor device. If this is for permission only, I'm tentatively OK with this, but I have some questions on how we might provide a more consistent API to developers.

Last year I looked into accessing the ALS via getUserMedia, and concluded that it would require some spec changes to provide a consistent API surface. To be clear, I'm actually more in favour of this method now I've had another look.

The main reasons were:

That being said, the existing non-GUM spec doesn't let developers specify which sensor to use. For my use case, this would be useful as we need to specify the front facing camera.

If the WebRTC WG (assuming this is the correct one?) would be interested in providing some guidance to reshape the API to make it more getUserMedia-y, that would be interesting.

If it took this route, I'd be interested in knowing:

rakuco commented 2 years ago

Interesting points. Last year's decision was about permissions only, but as you said it's not clear how this would work in terms of UI and integration with gUM permissions. Maybe @engedy can provide some insight here from a Chromium perspective.

From an ALS perspective device selection isn't a problem since the Generic Sensors APIs do not currently expose more than one sensor of a given type and devices usually ship with a single ALS. Would the API in its current form (i.e. with no integration with gUM) also work for your use case?

willmorgan commented 2 years ago

From an ALS perspective device selection isn't a problem since the Generic Sensors APIs do not currently expose more than one sensor of a given type and devices usually ship with a single ALS. Would the API in its current form (i.e. with no integration with gUM) also work for your use case?

Ultimately it would work in its current form, I'm just thinking about edge cases where we might take action based on the wrong input in the future.

As for https://github.com/w3c/ambient-light/issues/64#issuecomment-954444294, I'm not familiar with @larsgk's use case but I don't think car dashboards or ship bridges necessarily have cameras that are accessible.

In these scenarios where those devices don't have any video inputs, how should getUserMedia respond? Going by the current spec, it should fail before any permission prompt because video inputs aren't available.

reillyeon commented 2 years ago

I agree that relying on a side effect of getUserMedia() isn't the right design. The proposal here is to use the existing "camera" permission, not the getUserMedia() function. Both would, under the hood, request the "camera" permission but developers would not need to consider this when designing their sites and would call the appropriate method, AmbientLightSensor.start() or Navigator.getUserMedia(), for their application. The side-effect of this would be that a site which already had the "camera" permission because of a call to one of these functions would be able to call the other without re-prompting the user. The only downside as you mention is that devices with a dedicated camera notification LED would not illuminate this LED when only the ALS is in use. Browsers would have the choice of implementing their own notification UI for this case.

willmorgan commented 2 years ago

Sorry @reillyeon, I think I got the wrong end of the stick, so thanks for clarifying.

If the proposal is that AmbientLightSensor.start() grants the camera permission, would that mean that in theory you could call AmbientLightSensor.start(), obtain camera permission, and then call getUserMedia() without further permission checks?

rakuco commented 2 years ago

If the proposal is that AmbientLightSensor.start() grants the camera permission, would that mean that in theory you could call AmbientLightSensor.start(), obtain camera permission, and then call getUserMedia() without further permission checks?

I believe so. Do note that calling AmbientLightSensor.start() would still prompt the user rather than granting the "camera" permission directly (as would be the case now in Chromium if we used a regular sensors permission, although we also want to change that).

reillyeon commented 2 years ago

If the proposal is that AmbientLightSensor.start() grants the camera permission, would that mean that in theory you could call AmbientLightSensor.start(), obtain camera permission, and then call getUserMedia() without further permission checks?

Correct, and as @rakuco said, AmbientLightSensor.start() would show the user a prompt that says "camera" so this isn't a sneaky way to get the "camera" permission without asking for it.

lknik commented 2 years ago

Do you plan to allow access to ALS if access to camera is already granted?

Because providing access to the camera if ALS permission is given would grant access to, like, much more information than those from ALS sensor on their own?

Aside from the fact that it may be technically confusing to make a hard link between ALS and the webcam, as these are different sensors.

Why then, not rename AmbientLightSensor.start() to Camera.start()?

reillyeon commented 2 years ago

Because providing access to the camera if ALS permission is given would grant access to, like, much more information than those from ALS sensor on their own?

To reiterate: The proposal is that there will be no ALS permission. Accessing the ALS will require camera permission.

rakuco commented 2 years ago

A patch that basically does s/ambient-light/camera/ in a few places is pretty easy to write, but I'd like to try to hash out the integration between these changes and the Media Capture and Streams spec:

willmorgan commented 2 years ago

Reading back through the OP link to the minutes, I'm not sure I understand the rationale behind moving the permission to camera in order to move this API forward.

Looking at @rakuco's notes above it seems that using the same camera permission is going to cause more confusion and edge cases in the wild.

Would it be possible for getUserMedia to implicitly grant an ambient light sensor permission instead? Or does that take us back to square one?

reillyeon commented 2 years ago

Pardon my ignorance on the details of the Permissions API integration in the Media Capture and Streams spec. I wasn't aware of the deviceId detail because to my knowledge it isn't implemented in Chromium. Is it implemented in any other browser?

It does throw a wrench into the plan to simply treat the ALS like another camera if the spec is designed to allow users to grant access to individual cameras. We could define the integration between the two specifications such that ALS access is granted if access to any camera is granted, since the ALS is likely less directional than a front- or rear-facing camera. Or we could assume that the ALS is always front-facing and tie it to that camera is particular.

The rationale for this original proposal was that, on a device with a front-facing camera and ambient light sensor, like a phone or laptop, the information captured by these two sensors is equivalent from a privacy perspective as both measure light coming from roughly the same direction. The ALS is obviously a much lower-detail sensor but rather than explain to the user that the site is requesting something less powerful but still potentially concerning to their privacy we simply call them both a camera and leave it at that. It also helps that applications such as iProov are going to be requesting access to both the ALS and front-facing camera at the same time anyways.

lknik commented 2 years ago

I wouldn't say that information captured with a front-facing camera and ALS are equivalent (esp. not in context of privacy, as camera also offers, well, the full view), as they are very different. The issue is that if the permission is asked to in order to use ALS, it would then be possible to use it as a camera, which may be unexpected.

Unless the prompt would fully inform about access to camera, and all that mechanisms that exist today.

reillyeon commented 2 years ago

Unless the prompt would fully inform about access to camera, and all that mechanisms that exist today.

Yes, my proposal is to fully inform the user about access to the camera. I shouldn't have said that they were equivalent. What I said afterwards is the important part: Trying to explain to the user what an ALS is and how they should think about the privacy consequences is likely too complex. We should treat it as if it were as powerful as a real camera instead. We should call it a camera.

Ideally we could bundle it up with all the other cameras in the existing "camera" permission but as @rakuco pointed out, the Media Capture spec supports granting permission to individual cameras. I'm not sure how to resolve that.

Does this at least clarify the original rationale for this proposal?

willmorgan commented 2 years ago

@reillyeon That does clarify, thanks.

I do see the appeal of reusing the camera permission. On the other hand, I'd have thought that navigator.permissions.request() should be the API that solves this. As far as I can tell however, sentiment towards it is negative and there's a preference towards explicit methods. It's also worth noting that requesting camera permission in this way still wouldn't scope that permission to a given device.

As of today, Safari doesn't support the Permissions API at all; in Firefox while .query() is implemented, .request() is not.

If developers want to build a rich, interactive experience on the web platform, queueing prompt after prompt isn't a great user experience. To request motion data and camera on Safari on iOS, you have two separate, blocking prompts that the user needs to click. To make matters worse, the decision to deny permission is cached until you reload the page, which can break SPAS.

In my opinion, it's likely that developers are going to be requesting more than one permission for their experiences, so the navigator.permissions.request() API would make sense. However I appreciate the contention and good points in that area, and the motivation in why we're considering camera permissions instead.

The permission/privacy/query/request landscape is already quite fragmented, and I'm not sure if shoehorning in ALS permissions through the camera is going to make things better, even if I really, really want to use it in production today(!)

I can see parallels being drawn with accelerometer/magnetometer permissions, where DeviceMotionEvent.requestPermission() needs to be called to grant access in Safari, with Chrome to follow suit shortly (last checked 26th July 2022).

Would a more consistent way of doing this be to keep the ambient-light-sensor permission name, and expose AmbientLightSensor.requestPermission()? The wording for the request could be something like "Origin X requests permission to access information about the lighting conditions in your environment".

I feel like that approach at least has buy-in from WebKit and Chrome, with Mozilla's position tbc.

Btw, I see that permissions.request() and permissions.revoke() are now back in the WICG 😖

rakuco commented 2 years ago

I can see parallels being drawn with accelerometer/magnetometer permissions, where DeviceMotionEvent.requestPermission() needs to be called to grant access in Safari, with Chrome to follow suit shortly (last checked 26th July 2022).

Would a more consistent way of doing this be to keep the ambient-light-sensor permission name, and expose AmbientLightSensor.requestPermission()? The wording for the request could be something like "Origin X requests permission to access information about the lighting conditions in your environment".

DeviceMotionEvent.requestPermission() is quite different from a potential AmbientLightSensor.requestPermission() behind the scenes. Contrary to the Generic Sensors spec (and ALS), the Device Orientation spec did/does not integrate with the Permissions spec, so requestPermission() was added as a way of making it possible to require user consent without introducing a behavior change to what was already in the spec. The Generic Sensors API does integrate with the Permissions spec, and requesting permission is already part of Sensor.start(). ALS.requestPermission() would either be redundant or require changing the Generic Sensor behavior and adding the method to the base Sensor interface instead.

I feel like that approach at least has buy-in from WebKit and Chrome, with Mozilla's position tbc.

Per https://webkit.org/tracking-prevention/ (particularly the "Anti Fingerprinting" section) I wouldn't worry too much about WebKit in this context.

I do see the appeal of reusing the camera permission. On the other hand, I'd have thought that navigator.permissions.request() should be the API that solves this. As far as I can tell however, sentiment towards it is negative and there's a preference towards explicit methods. It's also worth noting that requesting camera permission in this way still wouldn't scope that permission to a given device.

As of today, Safari doesn't support the Permissions API at all; in Firefox while .query() is implemented, .request() is not.

Btw, I see that permissions.request() and permissions.revoke() are now back in the WICG confounded

Given WICG/permissions-request#5 and the level of activity in both WICG specs, I don't think these APIs will (re)appear any time soon and would not count on them. @engedy is an editor for both though, so he might have more information about this.

rakuco commented 2 years ago

Ideally we could bundle it up with all the other cameras in the existing "camera" permission but as @rakuco pointed out, the Media Capture spec supports granting permission to individual cameras. I'm not sure how to resolve that.

In addition to that, I feel it's hard to use the "camera" permission in a way that does not either break or weaken the requirements of the Media Capture spec. As mentioned in https://github.com/w3c/ambient-light/issues/79#issuecomment-1180571834 I think we'd need to think of the enumerability of ambient light sensors, how they integrate into Media Capture's Privacy Indicator Requirements, the DevicePermissionDescriptor and CameraDevicePermissionDescriptor dictionaries and the internal slots used in the spec, for example.

If we were not to use the "camera" permission, I think we'd have to deal with two problems:

  1. Possibly showing multiple permission prompts to users coming from multiple APIs/specs.
  2. Communicating what permission is required in a way that users can understand.

Aren't they both user agent concerns more than spec ones though? A UA could choose not to show a prompt, or delay showing it to bundle it with others based on whatever heuristics or data it chooses (1), and a UA could also choose to implement some UI for ALS requests similar to what it shows for media capture (2).

Based on the concerns and possible issues with using the "camera" permission, maybe abandoning this idea would lead to less work and confusion?

rakuco commented 2 years ago

@reillyeon @engedy I was wondering if you had time to look at the comments above?

lknik commented 2 years ago

@reillyeon I see, so you treat ALS as potentially being even more invasive than it may be (i.e. as if a full camera was used), if so then it does clarify the case here

rakuco commented 2 years ago

One extra option that @mikewest mentioned when we talked about this today: experiment with handling it as a camera in the implementation side and, if that makes sense, incorporate the idea into the spec. As such, I'd appreciate some input here too.

In other words, since the original idea is requiring the "camera" permission and some of the use cases listed in https://w3c.github.io/ambient-light/#usecases-requirements are already tied to camera use, we could require the "camera" permission without requesting it -- if AmbientLightSensor.start() is called without camera access (via a previous call to getUserMedia(), for example), it would fail instead of prompting for access.

A few opens:

rakuco commented 2 years ago

This was discussed at the 2022 TPAC: https://www.w3.org/2022/09/15-dap-minutes.html#t18

The specifics of how this would work have varied over time, so let me try to see if I've captured the latest proposal correctly.

The idea is to tie ALS and video capture (via navigator.mediaDevices.getUserMedia()) together, so that an ALS is active if and only if there is at least one "live" MediaStreamTrack whose source is a local video capture device (regardless of whether it's a front-facing camera, a virtual device or something else).

We'd have an "ALS readings can be exposed" algorithm like this for an AmbientLightSensor object sensor:

It's similar to https://w3c.github.io/mediacapture-main/#context-capturing-state, and it would be run whenever the [[devicesLiveMap]] internal slot changes. In practice, it's similar to what https://w3c.github.io/mediacapture-main/#privacy-indicator-requirements mandates for the indicators in the UI.

The Media Capture spec is a bit hand-wavy when it comes to the concepts of sources and devices, and I think we'd be the first to have this sort of integration, so I'd like to double check that this is the right direction.

Opens:

reillyeon commented 2 years ago

Do we still need the "ambient-light-sensor" powerful feature if the idea is for implementations not to prompt for it explicitly?

I think we should remove it because it's not something that it would make sense for a developer to request or query the state of.

Does a lack of active video sources cause an ALS to stop or just stop provide readings?

I think firing an error event with something like "No active video track." would provide a better developer experience.

Similarly, does ALS.start() fail if there are no active video sources or should the sensor just not provide readings?

Same as above.

If the idea is to tie an ALS to an active track, maybe we do not even need to worry about the "camera" permission name or permission policy name at all?

Just requiring an active video track does seem like it simplifies the model significantly.

Maybe it makes sense to explicitly take a MediaStreamTrack instance in the constructor and tie an ALS to a specific track's lifetime?

I'm not sure that it provides value and just makes the API harder to call.