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 fixes #100

Merged
merged 9 commits into from
Jul 26, 2016
199 changes: 116 additions & 83 deletions index.bs
Original file line number Diff line number Diff line change
Expand Up @@ -73,31 +73,25 @@ spec: webidl
</h2>
<p><em>This section is non-normative.</em></p>
<p>
This document's goal is to specify an API that will help developers to
handle permissions on the Web platform. Web APIs have different ways to
This document specifies a model and an API to query and request permissions
to powerful features on the Web platform. Web APIs have different ways to
deal with permissions. The [[notifications]] API allows developers to
request a permission and check the permission status explicitly. Others
might only expose the status to web pages when they try to use the API,
request a permission and check the permission status explicitly.
Others expose the status to web pages when they try to use the API,
like the [[geolocation-API]] which fails if the permission was not
granted without allowing the developer to check beforehand.
</p>
<p>
Being able to know whether an API call is going to prompt is useful in
order to provide a good user experience. Unfortunately, more often than
not, those prompts can't be controlled by developers.
The Permissions API provides tools for developers to control when permission
prompts are shown and to relinquish permissions that are no longer needed.
</p>
<p>
The API specified in this document is meant to provide the tools so
that web applications can improve their user experience when
permissions are involved.
</p>
<p>
The solution described in this document is meant to be extensible but
isn't meant to be applicable to all the current and future permissions
available in the web platform. If you are working on a specification
that has a permission model that wouldn't fit in the model described in
this document, please contact the editors or file an issue. We would
love to hear about it.
The solution described in this document is meant to be extensible, but isn't
meant to be applicable to all the current and future permissions
available in the web platform. Working Groups that are creating specifications
whose permission model doesn't fit in the model described in this document
should contact the editors by
<a href="https://github.com/w3c/permissions/issues">filing an issue</a>.
</p>
</section>
<section class='non-normative'>
Expand All @@ -106,14 +100,15 @@ spec: webidl
</h2>
<p><em>This section is non-normative.</em></p>
<p>
Permission states can be used as an element of fingerprinting by
websites. Usually websites could already have access to the information
but often through actually using the API which could lead to a
permission request UI if the permission was not already granted. Thus,
even though this API doesn't expose new fingerprinting data to
websites, it makes it easier for them to have discreet access to it.
Therefore, implementations are encouraged to have an option for users
to block (globally or selectively) the querying of permission states.
An adversary could use a <a>permission state</a> as an element in creating a
"fingerprint" corresponding to an end-user. Although an adversary can
already determine the state of a permission by actually using the API, that
often leads to a permission request UI being presented to the end-user (if
the permission was not already {{"granted"}}). Thus, even though this API
doesn't expose new fingerprinting information to websites, it makes it
easier for an adversary to have discreet access to this information. Thus,
implementations are encouraged to have an option for users to block
(globally or selectively) the querying of <a>permission states</a>.
</p>
</section>
<section>
Expand All @@ -128,7 +123,7 @@ spec: webidl
or other sources this specification hasn't anticipated.
</dd>

<dt><dfn export>Powerful feature</dfn></dt>
<dt><dfn export local-lt="feature">Powerful feature</dfn></dt>
<dd>
A feature of a UA that some code might not be allowed to access, for
example because its <a>environment settings object</a> doesn't satisfy
Expand All @@ -146,16 +141,15 @@ spec: webidl
};
</pre>
<p>
Each <a>powerful feature</a> has one or more aspects that websites can
request permission to access. To describe these requests, each feature
defines a subtype of {{PermissionDescriptor}} to be its <a>permission
descriptor type</a>.
Each <a>powerful feature</a> has one or more <dfn>aspects</dfn> that
websites can request permission to access. To describe these aspects,
each feature defines a subtype of {{PermissionDescriptor}} to be its
<a>permission descriptor type</a>.
</p>

<div class="example" id="example-descriptors">
<p>
The {{"midi"}} feature has two aspects: access to normal messages, and
access to system exclusive messages. Thus, its permission descriptor type
The {{"midi"}} <a>feature</a> has two <a>aspects</a>: access to normal messages, and
access to system exclusive messages. Thus, its <a>permission descriptor type</a>
is:
</p>
<pre>
Expand All @@ -165,8 +159,8 @@ spec: webidl
</pre>
<p>
The {{"bluetooth"}} feature lets sites request to access whatever
Bluetooth devices are close to to the user's device. Thus, its descriptor
type is:
Bluetooth devices are close to to the user's device. Thus, its
<a>permission descriptor type</a> is:
</p>
<pre>
dictionary BluetoothPermissionDescriptor : PermissionDescriptor {
Expand Down Expand Up @@ -207,48 +201,81 @@ spec: webidl

<section>
<h3 id="reading-current-states">Reading the current permission state</h3>
<p>
|descriptor|'s <dfn export>permission state</dfn> is one of {{"granted"}},
{{"prompt"}}, or {{"denied"}}, indicating respectively if the calling
algorithm should succeed without prompting the user, show the user a
prompt to decide whether to succeed, or fail without prompting the user.
The UA must return whichever of these values most accurately reflects the
user's intent, except that if the <a>current settings object</a> is a
<a>non-secure context</a> and
<code>|descriptor|.{{PermissionDescriptor/name}}</code> isn't <a>allowed
in non-secure contexts</a>, then the UA must return {{"denied"}}.
Subsequent uses of |descriptor|'s <a>permission state</a> with the same
<a>current settings object</a> must return the same value, unless the UA
receives <a>new information about the user's intent</a>.
</p>
<div algorithm>
<p>
A |descriptor|'s <dfn export local-lt="state">permission state</dfn> is
the result of the following algorithm, which returns one of
{{"granted"}}, {{"prompt"}}, or {{"denied"}}:
</p>
<ol class="algorithm">
<li>
If the <a>current settings object</a> is a <a>non-secure context</a>
and <code>|descriptor|.{{PermissionDescriptor/name}}</code> isn't
<a>allowed in non-secure contexts</a>, then return {{"denied"}}.
</li>
<li>
If there was a previous invocation of this algorithm with the same
|descriptor| and <a>current settings object</a>, returning
|previousResult|, and the UA has not received <a>new information about
the user's intent</a> since that invocation, return |previousResult|.
</li>
<li>
Return whichever of the following options most accurately reflects the user's
intent for the calling algorithm:
<dl class="switch">
<dt>succeed without prompting the user</dt>
<dd>{{"granted"}}</dd>

<p class="issue" id="issue-current-entry-incumbent-or-relevant">
Safari is the only known UA that returns different results from this
algorithm for different settings objects with the same origin. We should
test which of the <a
href="https://html.spec.whatwg.org/multipage/webappapis.html#realms-settings-objects-global-objects">several
possible settings objects</a> it uses.
</p>
<dt>show the user a prompt to decide whether to succeed</dt>
<dd>{{"prompt"}}</dd>

<p>
Some <a>powerful features</a> have more information associated with them
than just a {{PermissionState}}. For example,
{{MediaDevices/getUserMedia()}} needs to determine <em>which</em> cameras
the user has granted the <a>current realm</a> permission to access. Each
of these features defines an <a>extra permission data type</a>, and then a
{{PermissionName}} |name|'s <dfn export>extra permission data</dfn> is the
instance of that type matching the UA's impression of the user's intent.
Subsequent uses of |name|'s <a>extra permission data</a> must return the
same value, unless the UA receives <a>new information about the user's
intent</a>.
</p>
<dt>fail without prompting the user</dt>
<dd>{{"denied"}}</dd>
</dl>
</li>
</ol>

<p class="issue" id="issue-current-entry-incumbent-or-relevant">
Safari is the only known UA that returns different results from this
algorithm for different settings objects with the same origin. We should
test which of the <a
href="https://html.spec.whatwg.org/multipage/webappapis.html#realms-settings-objects-global-objects">several
possible settings objects</a> it uses.
</p>
</div>

<div algorithm>
<p>
Copy link
Member

Choose a reason for hiding this comment

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

This is a different algorithm, defining the result of

"permission-name"'s extra permission data

Copy link
Member Author

Choose a reason for hiding this comment

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

Sorry, I don't understand this comment :(

In case I don't hear back from you in the next few hours; I'm about to shift focus to another project for 2 weeks, so could I kindly request that you fix this for me in the editorial_fixes branch? I've already fixed the <var>s (there are ~30 vars that could maybe be converted also, but I guess we should do that in a new PR).

Copy link
Member

Choose a reason for hiding this comment

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

Oh yeah, totally. I'd forgotten that this branch was in the main repo rather than a personal fork. I'll take it over.

Some <a>powerful features</a> have more information associated with them
than just a {{PermissionState}}. For example,
{{MediaDevices/getUserMedia()}} needs to determine <em>which</em> cameras
the user has granted the <a>current realm</a> permission to access. Each
of these features defines an <a>extra permission data type</a>. If a
{{PermissionName}} |name| names one of these features, then |name|'s
<dfn export>extra permission data</dfn> is the result of the following
algorithm:
</p>
<ol class="algorithm">
<li>
If there was a previous invocation of this algorithm with the same
|name| and <a>current settings object</a>, returning
|previousResult|, and the UA has not received <a>new information about
the user's intent</a> since that invocation, return |previousResult|.
</li>
<li>
Return the instance of |name|'s <a>extra permission data type</a> that
matches the UA's impression of the user's intent.
</li>
</ol>
</div>
</section>
<section>
<h3 id="requesting-more-permission">Requesting more permission</h3>

<p class="note">
The algorithms in this section may wait for user input, so they should not
be used from other algorithms running on the main thread.
Spec authors, please note that algorithms in this section can wait for
user input; so they shouldn't be used from other algorithms running on
the main thread.
</p>

<div algorithm="request-permission-to-use">
Expand All @@ -259,18 +286,23 @@ spec: webidl
</p>
<ol>
<li>
If |descriptor|'s <a>permission state</a> is not {{"prompt"}}, return
that value and abort these steps.
Let <var>current state</var> be the |descriptor|'s <a>permission
Copy link
Member

Choose a reason for hiding this comment

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

FYI, you can replace <var>foo</var> with |foo|.

state</a>.
</li>
<li>
If <var>current state</var> is not {{"prompt"}}, return
<var>current state</var> and abort these steps.
</li>
<li>
Ask the user's permission for the calling algorithm to use the
<a>powerful feature</a> described by |descriptor|.
</li>
<li>
If the user grants permission, return {{"granted"}}; otherwise return
{{"denied"}}. Depending on the details of the user's interaction, the
UA may also treat this as <a>new information about the user's
intent</a> for other <a>realms</a> with the <a>same origin</a>.
{{"denied"}}. If the user's interaction indicates they intend this
choice to apply to other realms, then treat this as <a>new information
about the user's intent</a> for other <a>realms</a> with the <a>same
origin</a>.

<p class="note">
This is intentionally vague about the details of the permission UI
Expand Down Expand Up @@ -307,9 +339,10 @@ spec: webidl
</li>
<li>
If the user chose an option, return it; otherwise return {{"denied"}}.
Depending on the details of the user's interaction, the UA may also
treat this as <a>new information about the user's intent</a> for other
<a>realms</a> with the <a>same origin</a>.
If the user's interaction indicates they intend this choice to apply
to other realms, then treat this this as <a>new information about
the user's intent</a> for other <a>realms</a> with the <a>same
origin</a>.

<p class="note">
This is intentionally vague about the details of the permission UI
Expand All @@ -324,10 +357,10 @@ spec: webidl
<h3 id="reacting-to-revocation">Reacting to users revoking permission</h3>

<p>
When the UA learns that the user no longer intends to grant permission for
a <a>realm</a> to use a feature, it must <a>queue a task</a> on <a>the
Realm's settings object</a>'s <a>responsible event loop</a> to run that
feature's <a>permission revocation algorithm</a>.
When the UA learns that the user no longer intends to grant permission
for a <a>realm</a> to use a <a>feature</a>, it must <a>queue a task</a>
on <a>the Realm's settings object</a>'s <a>responsible event loop</a> to
run that feature's <a>permission revocation algorithm</a>.
</p>
</section>
</section>
Expand Down