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

editorial: Remove the "obtain a permission" algorithm. #298

Merged
merged 1 commit into from
Jun 7, 2021

Conversation

rakuco
Copy link
Member

@rakuco rakuco commented Feb 4, 2021

This may have made more sense back when we had a custom
WakeLockPermissionDescriptor, but even then this felt like implementing a
custom permission model for no reason.

We are just interested in knowing whether we have permission to request a
wake lock from the platform, and we can use the Permission spec's "request
permission to use" algorithm for that just fine.

One important change is related to checking transient activation: the
"obtain a permission" algorithm essentially denied requests when
"screen-wake-lock"'s permission state was set to "prompt" AND there was no
transient user activation. In general, an API should either always or never
be user-activation gated. Given Blink is the only current implementation of
this spec and it does not currently gate this API on user activation, the
transient user activation check was removed altogether for now.

Together with #297, this fixes #187 and fixes #198.


Preview | Diff

@@ -215,40 +215,6 @@ <h2>
</ol>
</li>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure we want to show any permission prompt without user activation @reillyeon ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But actually raphael, I am not sure it always have to be gates behind a user activation. It the user accepted it on a previous visit, it is auto granted and thus no user activation is needed. But if we want to show the prompt ("prompt" state) well then we probably need a user activation to do so

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the WebNFC API we use custom logic to use the "query" permission algorithm when there isn't user activation and the "request" algorithm when there is. In contrast in the Idle Detection API we always use the "query" algorithm and provide a separate method which only requests permission and thus requires user activation.

Either approach is fine by me though the whole discussion is somewhat moot because Chromium doesn't implement the "screen-wake-lock" permission. It is always granted.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the WebNFC API we use custom logic to use the "query" permission algorithm when there isn't user activation and the "request" algorithm when there is.

From a quick look, the spec has a custom "obtain permission" algorithm that mimics "request permission" fairly closely and does not mention user activation anywhere, while the Chromium implementation always just calls its "request permission" equivalent and always blocks requests that were not user-activated. w3c/web-nfc#482 then references the explainer, which says users should query the current permission state and trigger "obtain permission" via a user-activated action. This mismatch sounds confusing to me.

In contrast in the Idle Detection API we always use the "query" algorithm and provide a separate method which only requests permission and thus requires user activation.

We used to do that, but decided to remove requestPermission() in #237.

Having said that, I guess the question is whether it is worth implementing a custom "request permission" algorithm that checks for user-activation somewhere in the steps (be it to always check for it upfront or only when the permission state is "prompt"), or to hope w3c/permissions#189 and/or w3c/permissions#194 are solved at some point so we can rely on the Permissions spec to take care of it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the absence of support from the Permissions API specification I think we should define custom algorithms but try to make sure they are consistent between specifications that the desire the "request permission if there is user activation" behavior. This can form the draft of the language that will hopefully be upstreamed at some point.

At its core the WebNFC issue seems to highlight the concern that requiring user activation should not be specified normatively and browsers can make that determination on their own, citing differences between Chrome and Firefox. In that case it would seem that always using the default "request" algorithm is fine and the user activation requirement is an optional intervention that implementations may choose to implement for some or all permissions.

I personally feel that requiring user activation for permission prompts should be normatively specified so I support adding the necessary custom steps here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If asking for permission requires user activation then, whether there is a separate requestPermission() method or not, for developers the process of requesting a wake lock requires a user gesture if they can't assume they have permission. That seems to be working as intended. Applications which know they already have permission (perhaps because they asked for permission in the past) don't need a user gesture.

For example, a site might add a button to enable the wake lock (and thus have activation while making the initial request) but call request() without a user gesture in the visibilitychanged handler to reacquire the lock later.

I'd like to see a resolution to the issues raised on the WebNFC and Permissions APIs but I don't think that should block this change.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(for the record, while we discuss this I've submitted #303 anyway to clean up the algorithm we currently have)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will you file issues in Web NFC and permission repos ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Who's "you" in this case and what issues are you referring to? :-) I've mentioned 2 issues in the Permissions spec and 1 in the Web-NFC spec, so it's not clear what other issues still need to be filed.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, I see now. Sorry have only half been following this discussion from the side lines :)

rakuco pushed a commit to rakuco/wake-lock that referenced this pull request Feb 5, 2021
Steps that run "in parallel" need to take several extra restrictions into
account: we do not have access to documents or global objects, cannot create
IDL interfaces or manipulate promises, for example, all of which we had been
doing, along with needlessly running nested "in parallel" steps.

This change attempts to rectify the situation by only running things in
parallel when absolutely necessary (i.e. when reaching out to the OS), and
queueing tasks from there when we need to manipulate promises or create
objects (changes to the "obtain permission" algorithm, which also runs in
parallel, are being tracked separately in w3c#298).

`WakeLock.request()`:
* Queue a task to reject `|promise|` when the permission request run in
parallel is denied.
* Manipulate the [[ActiveLocks]] internal slot, create a new
WakeLockSentinel and resolve the returned promise in a queued task.

`WakeLockSentinel.release()`:
* Do not run the "release a wake lock" algorithm in parallel (see changes to
the algorithm itself below).
* Just return a resolved promise once the rest of the steps run. The
returned promise does not have much use, but has been kept to avoid breaking
API compatibility.

"Acquire wake lock" algorithm:
* Stop running everything in parallel.
* Move all [[ActiveLocks]] manipulation to `WakeLock.request()` itself, and
make the algorithm just ask the platform for a wake lock.

"Release wake lock" algorithm:
* Stop running everything in parallel. The only steps that still need to run
in parallel are the ones asking the platform to release the wake lock.
* Consequently, stop queueing a task to change [[Released]] and fire the
"release" event and do it directly in the algorithm.

Fixes w3c#293.
rakuco pushed a commit to rakuco/wake-lock that referenced this pull request Feb 10, 2021
Conceptually, the steps remain the same:
1. Return "granted" or "denied" if the permission state is set to either
   value.
2. Otherwise, return "denied" if there is no user activation.
3. Call the "request permission to use" algorithm from the Permissions spec
   in case there is user activation.

The difference is that we now do it in 4 steps rather than 10 by 1) using
the shorthands provided by the Permissions spec that allow us to use a
PermissionName rather than having to create a PermissionDescriptor in the
algorithms and 2) checking the "permission state" directly rather than
invoking Permissions.query() and manipulating a promise.

Ideally, we would remove this algorithm altogether in favor of the "request
permission to use" algorithm from the Permissions spec, but we need to keep
it in order to check for user activation in case we are in a "prompt"
state (see the discussion in w3c#298).

By not manipulating promises anymore, this incidentally fixes w3c#187.
rakuco pushed a commit that referenced this pull request Feb 11, 2021
Conceptually, the steps remain the same:
1. Return "granted" or "denied" if the permission state is set to either
   value.
2. Otherwise, return "denied" if there is no user activation.
3. Call the "request permission to use" algorithm from the Permissions spec
   in case there is user activation.

The difference is that we now do it in 4 steps rather than 10 by 1) using
the shorthands provided by the Permissions spec that allow us to use a
PermissionName rather than having to create a PermissionDescriptor in the
algorithms and 2) checking the "permission state" directly rather than
invoking Permissions.query() and manipulating a promise.

Ideally, we would remove this algorithm altogether in favor of the "request
permission to use" algorithm from the Permissions spec, but we need to keep
it in order to check for user activation in case we are in a "prompt"
state (see the discussion in #298).

By not manipulating promises anymore, this incidentally fixes #187.
rakuco pushed a commit to rakuco/wake-lock that referenced this pull request Feb 11, 2021
Steps that run "in parallel" need to take several extra restrictions into
account: we do not have access to documents or global objects, cannot create
IDL interfaces or manipulate promises, for example, all of which we had been
doing, along with needlessly running nested "in parallel" steps.

This change attempts to rectify the situation by only running things in
parallel when absolutely necessary (i.e. when reaching out to the OS), and
queueing tasks from there when we need to manipulate promises or create
objects (changes to the "obtain permission" algorithm, which also runs in
parallel, are being tracked separately in w3c#298).

`WakeLock.request()`:
* Queue a task to reject `|promise|` when the permission request run in
parallel is denied.
* Manipulate the [[ActiveLocks]] internal slot, create a new
WakeLockSentinel and resolve the returned promise in a queued task.

`WakeLockSentinel.release()`:
* Do not run the "release a wake lock" algorithm in parallel (see changes to
the algorithm itself below).
* Just return a resolved promise once the rest of the steps run. The
returned promise does not have much use, but has been kept to avoid breaking
API compatibility.

"Acquire wake lock" algorithm:
* Stop running everything in parallel.
* Move all [[ActiveLocks]] manipulation to `WakeLock.request()` itself, and
make the algorithm just ask the platform for a wake lock.

"Release wake lock" algorithm:
* Stop running everything in parallel. The only steps that still need to run
in parallel are the ones asking the platform to release the wake lock.
* Consequently, stop queueing a task to change [[Released]] and fire the
"release" event and do it directly in the algorithm.

Fixes w3c#293.
rakuco pushed a commit to rakuco/wake-lock that referenced this pull request Feb 11, 2021
I thought w3c#298 would have landed by now. This is not the case, so adjust the
algorithm we currently have.
rakuco pushed a commit to rakuco/wake-lock that referenced this pull request Feb 15, 2021
Steps that run "in parallel" need to take several extra restrictions into
account: we do not have access to documents or global objects, cannot create
IDL interfaces or manipulate promises, for example, all of which we had been
doing, along with needlessly running nested "in parallel" steps.

This change attempts to rectify the situation by only running things in
parallel when absolutely necessary (i.e. when reaching out to the OS), and
queueing tasks from there when we need to manipulate promises or create
objects (changes to the "obtain permission" algorithm, which also runs in
parallel, are being tracked separately in w3c#298).

`WakeLock.request()`:
* Queue a task to reject `|promise|` when the permission request run in
parallel is denied.
* Manipulate the [[ActiveLocks]] internal slot, create a new
WakeLockSentinel and resolve the returned promise in a queued task.

`WakeLockSentinel.release()`:
* Do not run the "release a wake lock" algorithm in parallel (see changes to
the algorithm itself below).
* Just return a resolved promise once the rest of the steps run. The
returned promise does not have much use, but has been kept to avoid breaking
API compatibility.

"Acquire wake lock" algorithm:
* Stop running everything in parallel.
* Move all [[ActiveLocks]] manipulation to `WakeLock.request()` itself, and
make the algorithm just ask the platform for a wake lock.

"Release wake lock" algorithm:
* Stop running everything in parallel. The only steps that still need to run
in parallel are the ones asking the platform to release the wake lock.
* Consequently, stop queueing a task to change [[Released]] and fire the
"release" event and do it directly in the algorithm.

Fixes w3c#293.
rakuco pushed a commit to rakuco/wake-lock that referenced this pull request Feb 15, 2021
I thought w3c#298 would have landed by now. This is not the case, so adjust the
algorithm we currently have.
@marcoscaceres
Copy link
Member

Seems like we should just assume Permissions spec will eventually do the right thing and add a note pointing the related issue over on the other repo.

rakuco pushed a commit to rakuco/wake-lock that referenced this pull request Feb 25, 2021
Steps that run "in parallel" need to take several extra restrictions into
account: we do not have access to documents or global objects, cannot create
IDL interfaces or manipulate promises, for example, all of which we had been
doing, along with needlessly running nested "in parallel" steps.

This change attempts to rectify the situation by only running things in
parallel when absolutely necessary (i.e. when reaching out to the OS), and
queueing tasks from there when we need to manipulate promises or create
objects (changes to the "obtain permission" algorithm, which also runs in
parallel, are being tracked separately in w3c#298).

`WakeLock.request()`:
* Queue a task to reject `|promise|` when the permission request run in
parallel is denied.
* Manipulate the [[ActiveLocks]] internal slot, create a new
WakeLockSentinel and resolve the returned promise in a queued task.

`WakeLockSentinel.release()`:
* Do not run the "release a wake lock" algorithm in parallel (see changes to
the algorithm itself below).
* Just return a resolved promise once the rest of the steps run. The
returned promise does not have much use, but has been kept to avoid breaking
API compatibility.

"Acquire wake lock" algorithm:
* Stop running everything in parallel.
* Move all [[ActiveLocks]] manipulation to `WakeLock.request()` itself, and
make the algorithm just ask the platform for a wake lock.

"Release wake lock" algorithm:
* Stop running everything in parallel. The only steps that still need to run
in parallel are the ones asking the platform to release the wake lock.
* Consequently, stop queueing a task to change [[Released]] and fire the
"release" event and do it directly in the algorithm.

Fixes w3c#293.
rakuco pushed a commit to rakuco/wake-lock that referenced this pull request Feb 25, 2021
I thought w3c#298 would have landed by now. This is not the case, so adjust the
algorithm we currently have.
rakuco pushed a commit to rakuco/wake-lock that referenced this pull request Feb 28, 2021
Steps that run "in parallel" need to take several extra restrictions into
account: we do not have access to documents or global objects, cannot create
IDL interfaces or manipulate promises, for example, all of which we had been
doing, along with needlessly running nested "in parallel" steps.

This change attempts to rectify the situation by only running things in
parallel when absolutely necessary (i.e. when reaching out to the OS), and
queueing tasks from there when we need to manipulate promises or create
objects (changes to the "obtain permission" algorithm, which also runs in
parallel, are being tracked separately in w3c#298).

`WakeLock.request()`:
* Queue a task to reject `|promise|` when the permission request run in
parallel is denied.
* Manipulate the [[ActiveLocks]] internal slot, create a new
WakeLockSentinel and resolve the returned promise in a queued task.

`WakeLockSentinel.release()`:
* Do not run the "release a wake lock" algorithm in parallel (see changes to
the algorithm itself below).
* Just return a resolved promise once the rest of the steps run. The
returned promise does not have much use, but has been kept to avoid breaking
API compatibility.

"Acquire wake lock" algorithm:
* Stop running everything in parallel.
* Move all [[ActiveLocks]] manipulation to `WakeLock.request()` itself, and
make the algorithm just ask the platform for a wake lock.

"Release wake lock" algorithm:
* Stop running everything in parallel. The only steps that still need to run
in parallel are the ones asking the platform to release the wake lock.
* Consequently, stop queueing a task to change [[Released]] and fire the
"release" event and do it directly in the algorithm.

Fixes w3c#293.
rakuco pushed a commit to rakuco/wake-lock that referenced this pull request Feb 28, 2021
I thought w3c#298 would have landed by now. This is not the case, so adjust the
algorithm we currently have.
@rakuco rakuco force-pushed the remove-obtain-permission-algorithm branch from 0ac1555 to dcf96b1 Compare March 2, 2021 14:06
@rakuco
Copy link
Member Author

rakuco commented Mar 2, 2021

I've rebased the PR to resolve the conflicts, but it's still unclear how to proceed, as there are different schools of thought here: it'd be great to have this solved in the Permissions spec, but I don't see a lot of activity there and don't know if anyone's working on those items; OTOH, defining a custom permission model here that only checks for user activation under some circumstances sounds... unconventional?

@marcoscaceres
Copy link
Member

My position remains that we make it the permission spec's responsibility.

Copy link
Member

@reillyeon reillyeon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that for the implementation I represent there is no difference between the two options I am okay delegating responsibility to the Permissions API specification.

Copy link
Member

@marcoscaceres marcoscaceres left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Following suit with what @reillyeon said :)

@marcoscaceres
Copy link
Member

@rakuco, any chance of a rebase?

This may have made more sense back when we had a custom
`WakeLockPermissionDescriptor`, but even then this felt like implementing a
custom permission model for no reason.

We are just interested in knowing whether we have permission to request a
wake lock from the platform, and we can use the Permission spec's "request
permission to use" algorithm for that just fine.

One important change is related to checking transient activation: the
"obtain a permission" algorithm essentially denied requests when
"screen-wake-lock"'s permission state was set to "prompt" AND there was no
transient user activation. In general, an API should either always or never
be user-activation gated. Given Blink is the only current implementation of
this spec and it does not currently gate this API on user activation, the
transient user activation check was removed altogether for now.

Together with w3c#297, this fixes w3c#187 and fixes w3c#198.
@rakuco rakuco force-pushed the remove-obtain-permission-algorithm branch from dcf96b1 to 0221e02 Compare June 2, 2021 11:22
@rakuco
Copy link
Member Author

rakuco commented Jun 2, 2021

@rakuco, any chance of a rebase?

Done. A while ago you mentioned adding a note to reference w3c/permissions#194; do you still think it makes sense?

@rakuco
Copy link
Member Author

rakuco commented Jun 2, 2021

@marcoscaceres @xfq the checks are failing with

  Error: ROR] Document on track but no previous version.
        Plugin: w3c/headers
          Hint: Add [previousMaturity](https://respec.org/docs/#previousMaturity) and [previousPublishDate](https://respec.org/docs/#previousPublishDate) to ReSpec’s config.

do you know if this needs to be fixed in the spec or in the GitHub action?

@marcoscaceres
Copy link
Member

Temporary hiccup, @rakuco. If it happens again, just rerun the action (usually fixes it).

@marcoscaceres
Copy link
Member

A while ago you mentioned adding a note to reference w3c/permissions#194; do you still think it makes sense?

I don't think it's necessary, tbh. We will take that up in w3c/permissions#194.

@rakuco rakuco merged commit 4e8f885 into w3c:gh-pages Jun 7, 2021
@rakuco rakuco deleted the remove-obtain-permission-algorithm branch June 7, 2021 15:36
blueboxd pushed a commit to blueboxd/chromium-legacy that referenced this pull request Jun 30, 2021
With w3c/screen-wake-lock#298 the spec was
changed and matches what we'd already been doing in the Blink
implementation: instead of calling a custom "obtain permission"
algorithm, we just delegate everything to the standard "request a
permission" algorithm implemented elsewhere.

Update the comment and, while at it, fold WakeLock::ObtainPermission()
into WakeLock::DoRequest().

There should be no user-visible changes.

Change-Id: Iabf981df5cdbe04d0b4e67f0980a933c5167a3d0
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2988046
Reviewed-by: Reilly Grant <[email protected]>
Commit-Queue: Reilly Grant <[email protected]>
Commit-Queue: Raphael Kubo da Costa <[email protected]>
Auto-Submit: Raphael Kubo da Costa <[email protected]>
Cr-Commit-Position: refs/heads/master@{#897071}
mjfroman pushed a commit to mjfroman/moz-libwebrtc-third-party that referenced this pull request Oct 14, 2022
With w3c/screen-wake-lock#298 the spec was
changed and matches what we'd already been doing in the Blink
implementation: instead of calling a custom "obtain permission"
algorithm, we just delegate everything to the standard "request a
permission" algorithm implemented elsewhere.

Update the comment and, while at it, fold WakeLock::ObtainPermission()
into WakeLock::DoRequest().

There should be no user-visible changes.

Change-Id: Iabf981df5cdbe04d0b4e67f0980a933c5167a3d0
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2988046
Reviewed-by: Reilly Grant <[email protected]>
Commit-Queue: Reilly Grant <[email protected]>
Commit-Queue: Raphael Kubo da Costa <[email protected]>
Auto-Submit: Raphael Kubo da Costa <[email protected]>
Cr-Commit-Position: refs/heads/master@{#897071}
NOKEYCHECK=True
GitOrigin-RevId: 0e90f4e8c702fd782337f26c93221e6eeca26eaf
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
4 participants