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

Determine how PTZ permission prompts are supposed to work #243

Open
youennf opened this issue Aug 6, 2020 · 17 comments
Open

Determine how PTZ permission prompts are supposed to work #243

youennf opened this issue Aug 6, 2020 · 17 comments
Labels

Comments

@youennf
Copy link
Contributor

youennf commented Aug 6, 2020

The spec is not very clear about how PTZ permission is asked as part of the getUserMedia call.
It would be good to identify how this is supposed to work and specify it as precisely as possible.
This might require defining potential hooks from mediacapture-main spec and help clearing potential fingerprinting issues.

Also, from what I understood, the goal of the proposal is that a single prompt may be implemented to allow the user to either:

  • deny camera and PTZ
  • deny PTZ but allow camera
  • allow camera and PTZ
    Is that correct?
    This is somehow new to getUserMedia related prompts, which are currently mostly boolean.
    If you add audio to the mix, this makes the prompt request to the user potentially complex.

To be noted also that there is a desire to move to in-chome device picker for getUserMedia.
It would be good to validate that the PTZ proposed approach can be adequately implemented in that scenario.
The closest example I can think of might be screen sharing, user being able to optionally select output audio.

To help driving the discussion, it would be good to document other possibilities, with pros and cons, or at least why these alternatives were discarded. I am for instance thinking of:

  • A separate API dedicated to get PTZ camera access
  • getUserMedia to get camera (with ability to favour PTZ device if any is available) and applyConstraints to start using PTZ, the latter gated by a PTZ specific permission (with a prompt at applyConstraints time or pre-granting at getUserMedia time).
@riju riju added the PTZ Pan-Tilt-Zoom label Aug 6, 2020
@riju
Copy link
Collaborator

riju commented Aug 7, 2020

The spec is not very clear about how PTZ permission is asked as part of the getUserMedia call.

Maybe we need to be more verbose in the spec, but there's an example in the spec to show how PTZ works with gUM().

Also, from the ptz-explainer

const panTiltZoomPermissionStatus = await navigator.permissions.query({
  name: "camera",
  panTiltZoom: true,
});

if (panTiltZoomPermissionStatus.state == "granted") {
  // User has granted access to this website to control camera PTZ.
}

A separate API dedicated to get PTZ camera access

We touched upon this in the ptz-explainer. From a Privacy and Security angle, having 2 separate permissions (camera and ptz) makes sense, where {name: "camera", panTiltZoom: true} is stronger than {name: "camera", panTiltZoom: false}.

From UX perspective, we thought it's better to combine both camera and PTZ permission in a single prompt (avoid prompt fatigue).

If the selected/connected camera does not support PTZ though or user blocks solely the PTZ permission, the UA will either reject the getUserMedia() call if PTZ constraints are required, or fall back to the camera permission if PTZ constraints are defined as advanced constraints.

@beaufortfrancois
Copy link
Contributor

Spec says for tilt for instance:

Any algorithm which uses a MediaTrackConstraintSet object and its tilt dictionary member which exists after a possible normalization MUST request permission to use (as defined in [permissions]) a PermissionDescriptor with its name member set to camera and its panTiltZoom member set to true, and, optionally, consider its deviceId member set to any appropriate device’s deviceId."

Would it help if we were indicating that if gUM requests ptz capability, and a device with the capability is selected, it should prompt for that permission?
Or maybe instead of saying "any algorithm", we could link to a specific section about gUM.

@riju
Copy link
Collaborator

riju commented Aug 14, 2020

@youennf : gentle ping.

@youennf
Copy link
Contributor Author

youennf commented Aug 14, 2020

maybe instead of saying "any algorithm", we could link to a specific section about gUM.

Yes, I would think it helps.

there's an example in the spec

I am not clear on whether it is possible for a browser to allow a user to say: yes for camera but no for PTZ in case of getUserMedia({ video : { pan : true })?
If it is possible, is it mandatory for a user agent to support that or is it UX territory?
If it is possible, how is the web page notified of the user decision (getCapabilities, navigator.permissions.query).
If it is possible, browser A supports it but browser B does not, web pages might be coded so that getUserMedia promise fulfilment means PTZ is granted for instance while this might not be true on all browsers, hence compat issues.
If it is possible, we enter in UX that might ask variable questions like : camera-only, microphone-only, camera+microphone, cameraPTZ-only, cameraPTZ+microphone... This adds a lot of variability to the question asked to the user.

Another related question (maybe this is already clear in the spec). If PTZ is supported by the camera and page has a MediaStreamTrack, what would return capabilities.pan and applyConstraints({pan: xxx}) in the following cases:

  • page did not ask for { pan : true } in getUserMedia
  • page asked for { pan : true } but user decided to only grant camera, not PTZ.

The primer also says: "It will also be possible for users to revoke the PTZ permission by itself, while keeping the camera permission". Is there anything the spec should say about this case? For instance, in terms of what happens to live cameraPTZ track(s)? media capture main indicates (not very strongly though) that the live tracks get ended if permission is revoked.

@beaufortfrancois
Copy link
Contributor

maybe instead of saying "any algorithm", we could link to a specific section about gUM.

Yes, I would think it helps.

I'll work on this.

there's an example in the spec

I am not clear on whether it is possible for a browser to allow a user to say: yes for camera but no for PTZ in case of getUserMedia({ video : { pan : true }})?

Nope. With getUserMedia({ video : { pan : true }}), the website requests a camera PTZ. If there's none, it will fail.
However with getUserMedia({ video: { advanced: [{ pan: true }] } }), the website asks to prefer a PTZ camera during camera selection process.

If it is possible, is it mandatory for a user agent to support that or is it UX territory?
If it is possible, how is the web page notified of the user decision (getCapabilities, navigator.permissions.query).

It could use the permissions API indeed. See below

const panTiltZoomPermissionStatus = await navigator.permissions.query({
  name: "camera",
  panTiltZoom: true,
});
panTiltZoomPermissionStatus.onchange = () => {
  // User has changed PTZ permission status.
}

Using "pan" in videoTrack.getCapabilities() is also a reliable way to know if selected camera supports pan for instance.

If it is possible, browser A supports it but browser B does not, web pages might be coded so that getUserMedia promise fulfilment means PTZ is granted for instance while this might not be true on all browsers, hence compat issues.

You would still use getCapabilities() and getSettings() to retrieve pan, tilt, and zoom values and display them in the UI.
This is why you should use if ("pan" in navigator.mediaDevices.getSupportedConstraints()) to know if PTZ is supported by the browser first.

If it is possible, we enter in UX that might ask variable questions like : camera-only, microphone-only, camera+microphone, cameraPTZ-only, cameraPTZ+microphone... This adds a lot of variability to the question asked to the user.

You can give a try to the Chromium implementation by running Chrome 86 with --use-fake-device-for-media-stream and play with https://ptz.glitch.me.

Another related question (maybe this is already clear in the spec). If PTZ is supported by the camera and page has a MediaStreamTrack, what would return capabilities.pan and applyConstraints({pan: xxx}) in the following cases:

  • page did not ask for { pan : true } in getUserMedia
  • page asked for { pan : true } but user decided to only grant camera, not PTZ.

In both cases, capabilities.pan is undefined and applyConstraints({pan: xxx}) rejects.

The primer also says: "It will also be possible for users to revoke the PTZ permission by itself, while keeping the camera permission". Is there anything the spec should say about this case? For instance, in terms of what happens to live cameraPTZ track(s)? media capture main indicates (not very strongly though) that the live tracks get ended if permission is revoked.

We don't end live tracks for now, but that's something we could do indeed.
Where is it in the media capture main spec?

@youennf
Copy link
Contributor Author

youennf commented Aug 14, 2020

In both cases, capabilities.pan is undefined and applyConstraints({pan: xxx}) rejects.

I think I saw these checks for applyConstraints in the spec.
Where is it specified in the spec for capabilities?
Will the capabilities change if permission is revoked?
Should the spec say anything about getSettings result sanitisation based on PTZ permission?

Nope. With getUserMedia({ video : { pan : true }}), the website requests a camera PTZ. If there's none, it will fail.
However with getUserMedia({ video: { advanced: [{ pan: true }] } }), the website asks to prefer a PTZ camera during camera selection process.

AIUI, for both queries, getUserMedia will do the same permission request made with: { name: "camera", panTiltZoom: true } and the result of the request is either denied or granted.
I do not see a way for the browser to grant camera but not PTZ for the second query.
If user persistently denied PTZ, it seems to me that both requests will be rejected.

This does seem to contradict what the primer says:

If the selected/connected camera does not support PTZ though or user blocks solely the PTZ permission, the UA will either reject the getUserMedia() call if PTZ constraints are required, or fall back to the camera permission if PTZ constraints are defined as advanced constraints.

@beaufortfrancois
Copy link
Contributor

In both cases, capabilities.pan is undefined and applyConstraints({pan: xxx}) rejects.

I think I saw these checks for applyConstraints in the spec.
Where is it specified in the spec for capabilities?
Will the capabilities change if permission is revoked?
Should the spec say anything about getSettings result sanitisation based on PTZ permission?

You're absolutely right. I've filed #245

Nope. With getUserMedia({ video : { pan : true }}), the website requests a camera PTZ. If there's none, it will fail.
However with getUserMedia({ video: { advanced: [{ pan: true }] } }), the website asks to prefer a PTZ camera during camera selection process.

AIUI, for both queries, getUserMedia will do the same permission request made with: { name: "camera", panTiltZoom: true } and the result of the request is either denied or granted.
I do not see a way for the browser to grant camera but not PTZ for the second query.
If user persistently denied PTZ, it seems to me that both requests will be rejected.

In the second query, if there are no cameras with PTZ capabilities, the PTZ request will be ignored and it will be treated like a regular camera request.

This does seem to contradict what the primer says:

If the selected/connected camera does not support PTZ though or user blocks solely the PTZ permission, the UA will either reject the getUserMedia() call if PTZ constraints are required, or fall back to the camera permission if PTZ constraints are defined as advanced constraints.

@youennf
Copy link
Contributor Author

youennf commented Aug 14, 2020

In the second query, if there are no cameras with PTZ capabilities, the PTZ request will be ignored and it will be treated like a regular camera request.

It seems you say that, if there is no PTZ camera, the permission request will be { name: "camera", panTiltZoom: false }.
Where is this algorithm defined?
The spec says

Any algorithm which uses a MediaTrackConstraintSet object and its pan dictionary member which exists after a possible normalization MUST request permission to use (as defined in [permissions]) a PermissionDescriptor with its name member set to camera and its panTiltZoom member set to true, and, optionally, consider its deviceId member set to any appropriate device’s deviceId.
My interpretation of this wording is that the permission request will always be { name: "camera", panTiltZoom: true }.
It would be good to clarify this.

Now, let's take the case of a setup with a PTZ camera but user persistently denied PTZ permission. getUserMedia({ video: { advanced: [{ pan: true }] } }) will trigger a permission request of { name: "camera", panTiltZoom: true }. The result of the permission request will be 'denied' since PTZ permission is denied. getUserMedia will then always reject.
I might me misunderstanding things. In any case, more precisely defining the algorithms will help potential implementer understanding.

@beaufortfrancois
Copy link
Contributor

In the second query, if there are no cameras with PTZ capabilities, the PTZ request will be ignored and it will be treated like a regular camera request.

It seems you say that, if there is no PTZ camera, the permission request will be { name: "camera", panTiltZoom: false }.
Where is this algorithm defined?

It's not and it should be fixed in the spec. Thanks for raising this issue.
I've filed at #246

Now, let's take the case of a setup with a PTZ camera but user persistently denied PTZ permission. getUserMedia({ video: { advanced: [{ pan: true }] } }) will trigger a permission request of { name: "camera", panTiltZoom: true }. The result of the permission request will be 'denied' since PTZ permission is denied. getUserMedia will then always reject.
I might me misunderstanding things. In any case, more precisely defining the algorithms will help potential implementer understanding.

With getUserMedia({ video: { advanced: [{ pan: true }] } }), it will not reject as we're using advanced constraints here (optional then). It will be "downgraded" to a regular camera request.
However with getUserMedia({ video: { pan: true } }), the promise will always reject if user persistently denied PTZ permission.

@youennf
Copy link
Contributor Author

youennf commented Aug 18, 2020

With getUserMedia({ video: { advanced: [{ pan: true }] } }), it will not reject as we're using advanced constraints here (optional then). It will be "downgraded" to a regular camera request.

Where is this algorithm specified?
I understand this is the intent of the spec but that is not what I understand when reading it.

@beaufortfrancois
Copy link
Contributor

Advanced constraints are a concept of the mediacapture-main spec, so it should automatically apply to the mediacapture-image spec. I guess our spec should say that processing of the PTZ constraints follows the same rules as in the SelectSettings algorithm of mediacapture-main, except where explicitly noted (e.g., the boolean syntactic sugar). Would this help?

@youennf
Copy link
Contributor Author

youennf commented Aug 18, 2020

Constraints are validated/selected against what the devices can do, not what user allowed or denied.
SelectSettings can 'remove' the PTZ constraints if the PTZ constraints are advanced and there is no PTZ camera available.
SelectSettings cannot 'remove' the PTZ constraints if there is a PTZ camera, even if constraints are advanced and PTZ permission is denied.

@guidou
Copy link

guidou commented Aug 18, 2020

It is clear to me that this spec has the goal of having separate permissions for generic camera and PTZ. However, I'm not sure it is a goal of the spec is to mandate that browsers need to provide a prompt that allows to simultaneously grant the camera permission and denies the PTZ one in case none of the permissions have been persisted. Can anyone confirm?

I believe the current Chromium prototype implementation works with more traditional binary prompts that accept/reject everything that is requested. It is possible that the prompt only includes only camera, or only PTZ, or both, depending on the request and the persistent status of permissions.

In my opinion, implementations should have flexibility wrt to how they want to implement the prompts.

@youennf
Copy link
Contributor Author

youennf commented Aug 18, 2020

to mandate that browsers need to provide a prompt that allows to simultaneously grant the camera permission and denies the PTZ one in case none of the permissions have been persisted. Can anyone confirm?

Agreed with @guidou that we need to understand precisely what are the user agent (UI/prompt) requirements this spec mandates.
Also agreed that this particular requirement (granting both at the same time) might not suite WebKit/Safari needs.

In my opinion, implementations should have flexibility wrt to how they want to implement the prompts.

Agreed again.
We are far on our side from a concrete plan, but I could for instance see scenarios like:

  • getUserMedia is used to select a camera, if possible PTZ. At that point, PTZ permission decision is not presented to user.
  • Once camera permission is granted and device is in use, web site can see that camera is PTZ.
  • Web site tries to use PTZ (get values/apply constraints). At that point, PTZ permission is presented to user (with a persistency choice).

That said, it would be interesting to get input from potential customers of this API.
In general, user agent developers like getting flexibility while web developers prefer dealing with a single model for all user agents. If all user agents agree on a given model, it might be fine for the spec to engrave it.

@reillyeon
Copy link
Member

When building the PTZ permission prompt in Chromium we considered prompting on applyConstraints() in addition to getUserMedia(). The reason we chose not to is that as you say it would require a PTZ-specific permission prompt to "upgrade" the existing permission to access the camera. We wanted to ensure that all camera-related permission requests were made upfront and with full context for the user rather than piecemeal.

Do you think this is a place where implementations could reasonably disagree or should the specification mandate or forbid supporting a permission request as part of applyConstaints()?

@beaufortfrancois
Copy link
Contributor

For info, here's where we've talked about PTZ permission request in applyConstraints(): #223 (comment)

@beaufortfrancois
Copy link
Contributor

  • Once camera permission is granted and device is in use, web site can see that camera is PTZ.

@youennf How would you be able to detect camera is PTZ when capabilities and settings are not exposed when the PTZ permission has not been granted?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

6 participants