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

Make requestPermission()'s behavior more backwards-compatible #129

Merged
merged 1 commit into from
Jan 22, 2024

Conversation

rakuco
Copy link
Member

@rakuco rakuco commented Jan 10, 2024

The changes added in #123 have introduced some behavior changes to the two
requestPermission() operations that were not originally intended.

Although the original steps were heavily modeled after the WebKit
implementation and do not follow what other specifications normally do, some
behavior changes from #123 have not been discussed and have been made more
backwards-compatible:

  • Calls to "request permission to use" may return "prompt", while the
    previous version implicitly converted anything that was not "granted" to
    "denied" (possibly because the current Safari implementation shows a modal
    dialog asking for access, so users can only allow or deny the permission
    request, so remaining at the "prompt" state is not possible).
    From a specification perspective, if a user has not explicitly granted the
    permission request, "prompt" is essentially the same as "denied" anyway,
    so we now explicitly set anything that is not "granted" to "denied" again.
  • The previous steps only checked for transient activation if users had not
    made an explicit permission choice yet, which basically means that the
    permission state is set to "prompt".
    This change restores this behavior by first checking the current
    permission states for all required permission names and only throwing a
    NotAllowed exception if one of them is "prompt" and there is no transient
    activation. In other words, if a permission is either "granted" or
    "denied" then requestPermission() will resolve to one of the values
    without requiring transient activation.

While here, refer to the right definitions of "granted" and "denied": use
the PermissionState enum definitions, which is what the Permissions API
algorithms we invoke return, rather than the non-Web IDL definitions that
these enum values correspond to.


Preview | Diff

The changes added in #123 have introduced some behavior changes to the two
requestPermission() operations that were not originally intended.

Although the original steps were heavily modeled after the WebKit
implementation and do not follow what other specifications normally do, some
behavior changes from #123 have not been discussed and have been made more
backwards-compatible:

- Calls to "request permission to use" may return "prompt", while the
  previous version implicitly converted anything that was not "granted" to
  "denied" (possibly because the current Safari implementation shows a modal
  dialog asking for access, so users can only allow or deny the permission
  request, so remaining at the "prompt" state is not possible).
  From a specification perspective, if a user has not explicitly granted the
  permission request, "prompt" is essentially the same as "denied" anyway,
  so we now explicitly set anything that is not "granted" to "denied" again.
- The previous steps only checked for transient activation if users had not
  made an explicit permission choice yet, which basically means that the
  permission state is set to "prompt".
  This change restores this behavior by first checking the current
  permission states for all required permission names and only throwing a
  NotAllowed exception if one of them is "prompt" and there is no transient
  activation. In other words, if a permission is either "granted" or
  "denied" then requestPermission() will resolve to one of the values
  without requiring transient activation.

While here, refer to the right definitions of "granted" and "denied": use
the PermissionState enum definitions, which is what the Permissions API
algorithms we invoke return, rather than the non-Web IDL definitions that
these enum values correspond to.
@rakuco rakuco requested a review from reillyeon January 10, 2024 15:36
@@ -306,20 +306,24 @@ The <dfn attribute for="DeviceOrientationEvent">absolute</dfn> attribute must re
The <dfn method for="DeviceOrientationEvent">requestPermission(<var>absolute</var>)</dfn> method steps are:

1. Let <var>global</var> be the <a>current global object</a>.
1. If <a>this</a>'s <a>relevant global object</a> does not have <a>transient activation</a>, return <a>a promise rejected with</a> a "{{NotAllowedError}}" {{DOMException}}.
1. Let <var>hasTransientActivation</var> be true if <a>this</a>'s <a>relevant global object</a> has <a>transient activation</a>, and false otherwise.

Choose a reason for hiding this comment

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

shouldn't it be "or false, otherwise" ? or "or else false"

Copy link
Member Author

Choose a reason for hiding this comment

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

The "[...], and/or $SOMETHING otherwise" idiom is used in several specs, they just don't agree on whether to use "and" or "or".

1. Let <var>result</var> be <a>a new promise</a> in <a>this</a>'s <a>relevant Realm</a>.
1. Run these steps <a>in parallel</a>:
1. If <var>absolute</var> is true:
1. Let <var>permissions</var> be « "<a permission>accelerometer</a>", "<a permission>gyroscope</a>", "<a permission>magnetometer</a>" ».
1. Otherwise:
1. Let <var>permissions</var> be « "<a permission>accelerometer</a>", "<a permission>gyroscope</a>" ».
1. Let <var>permissionState</var> be "<a for="permission">granted</a>".
1. <a for="list">For each</a> <var>name</var> of <var>permissions</var>:
1. If <var>name</var>'s <a>permission state</a> is "{{PermissionState/prompt}}" and <var>hasTransientActivation</var> is false:

Choose a reason for hiding this comment

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

if you check hasTransientActivation here in each iteration and that value never changes, why not move that check outside?

Copy link
Member Author

Choose a reason for hiding this comment

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

Not sure I understood the suggestion. The check here is basically "if the user needs to be prompted but there's no transient activation, reject the promise and stop", so I can't just check for transient activation separately.

1. Let <var>permissionState</var> be "<a for="permission">granted</a>".
1. <a for="list">For each</a> <var>name</var> of <var>permissions</var>:
1. If <var>name</var>'s <a>permission state</a> is "{{PermissionState/prompt}}" and <var>hasTransientActivation</var> is false:
1. <a>Queue a global task</a> on the <a>device motion and orientation task source</a> given <var>global</var> to <a>reject</a> <var>result</var> with a "{{NotAllowedError}}" {{DOMException}}.

Choose a reason for hiding this comment

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

I would probably add a comma before "to reject"

Copy link
Member Author

Choose a reason for hiding this comment

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

Do you mean "Queue a global task, to [...]"? Isn't it usual to just say "queue a task to xyz"?

@rakuco rakuco merged commit 0b538e9 into main Jan 22, 2024
2 checks passed
@rakuco rakuco deleted the post-permission-api-integration-fixes branch January 22, 2024 17:57
github-actions bot added a commit that referenced this pull request Jan 22, 2024
SHA: 0b538e9
Reason: push, by rakuco

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants