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

Define a permission store (closes #384) #390

Merged
merged 20 commits into from
Dec 9, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
154 changes: 145 additions & 9 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,74 @@ <h3>
reset because its [=permission/lifetime=] has expired.
</p>
</section>
<section>
<h3>
Permission Store
</h3>
<p>
The user agent maintains a single <dfn class="export">permission store</dfn> which is a [=/list=] of [=permission store entries=]. Each particular [=entry=] denoted by its [=permission store entry/descriptor=] and [=permission store entry/key=] can only appear at most once in this list.
</p>
<p>
The user agent MAY remove [=entries=] from the [=permission store=] when their respective [=permission=]'s [=permission/lifetime=] has expired.
</p>
<p>
A <dfn class="export" data-local-lt="entry">permission store entry</dfn> is a [=tuple=] of {{PermissionDescriptor}} <dfn class="export" data-dfn-for="permission store entry">descriptor</dfn>, [=permission key=] <dfn class="export" data-dfn-for="permission store entry">key</dfn>, and [=permission/state=] <dfn class="export" data-dfn-for="permission store entry">state</dfn>.
johannhof marked this conversation as resolved.
Show resolved Hide resolved
</p>
<p>
To <dfn class="export">get a permission store entry</dfn> given a {{PermissionDescriptor}} |descriptor| and [=permission key=] |key|:
<ol class="algorithm">
<li>
<!-- TODO: PermissionDescriptor equality is not defined (#396) -->
If the user agent's [=permission store=] [=list/contains=] an [=entry=] whose [=permission store entry/descriptor=] is |descriptor|, and whose [=permission store entry/key=] [=permission key/is equal to=] |key| given |descriptor|, return that entry.
johannhof marked this conversation as resolved.
Show resolved Hide resolved
</li>
<li>
Return null.
miketaylr marked this conversation as resolved.
Show resolved Hide resolved
</li>
</ol>
</p>
<p>
To <dfn class="export">set a permission store entry</dfn> given a {{PermissionDescriptor}} |descriptor|, a [=permission key=] |key|, and a [=permission/state=] |state|, run these steps:
<ol class="algorithm">
<li>
Let |newEntry| be a new [=permission store entry=] whose [=permission store entry/descriptor=] is |descriptor|, and whose [=permission store entry/key=] is |key|, and whose [=permission store entry/state=] is |state|.
</li>
<li>
If the user agent's [=permission store=] [=list/contains=] an [=entry=] whose [=permission store entry/descriptor=] is |descriptor|, and whose [=permission store entry/key=] [=permission key/is equal to=] |key| given |descriptor|, [=list/replace=] that entry with |newEntry| and abort these steps.
</li>
<li>
[=list/Append=] |newEntry| to the user agent's [=permission store=].
</li>
</ol>
</p>
<p>
To <dfn class="export">remove a permission store entry</dfn> given a {{PermissionDescriptor}} |descriptor| and [=permission key=] |key|, run these steps:
<ol class="algorithm">
<li>
[=list/Remove=] the [=entry=] whose [=permission store entry/descriptor=] is |descriptor|, and whose [=permission store entry/key=] [=permission key/is equal to=] |key| given |descriptor|, from the user agent's [=permission store=].
</li>
</ol>
</p>
<p>
A <dfn class="export">permission key</dfn> has its type defined by a feature's [=powerful feature/permission key type=].
<aside class="note">
The permission key defines the scope of a permission grant, which is usually per-origin.
Powerful features may override the [=powerful feature/permission key type=] to specify a custom permission key.
This is useful for features that want to change the granularity of permissions based on additional context,
such as double-keying on both an embedded origin and a top-level origin.
</aside>
</p>
<p>
To determine whether a [=permission key=] |key1| <dfn class="export" data-dfn-for="permission key">is equal to</dfn> a [=permission key=] |key2|, given a {{PermissionDescriptor}} |descriptor|, run the following steps:
<ol class="algorithm">
<li>
If |key1| is not of |descriptor|'s [=powerful feature/permission key type=] or |key2| is not of |descriptor|'s [=powerful feature/permission key type=], return false.
johannhof marked this conversation as resolved.
Show resolved Hide resolved
</li>
<li>
Return the result of running the [=powerful feature/permission key comparison algorithm=] for the feature named by |descriptor|'s {{PermissionDescriptor/name}}, passing |key1| and |key2|.
</li>
</ol>
</p>
</section>
<section>
<h2>
Powerful features
Expand Down Expand Up @@ -501,6 +569,58 @@ <h2>
</li>
</ol>
</dd>
<dt>
A <dfn data-dfn-for="powerful feature" class="export">permission key type</dfn>:
</dt>
<dd>
<p>
The type of [=permission key=] used by the feature. Defaults to [=origin=].
A feature that specifies a custom [=powerful feature/permission key type=] MUST also specify a
[=powerful feature/permission key generation algorithm=].
</p>
</dd>
<dt>
A <dfn data-dfn-for="powerful feature" class="export">permission key generation algorithm</dfn>:
johannhof marked this conversation as resolved.
Show resolved Hide resolved
</dt>
<dd>
<p>
Takes an [=environment settings object=], and returns a new [=permission key=].
If unspecified, this defaults to the <a>default permission key generation algorithm</a>.
A feature that specifies a custom [=powerful feature/permission key generation algorithm=] MUST also specify a
[=powerful feature/permission key comparison algorithm=].
</p>
<p>
The <dfn class="export">default permission key generation algorithm</dfn>,
given an [=environment settings object=] |settings|, runs the following steps:
</p>
<ol class="algorithm">
<li>
Return |settings|'s [=environment/top-level origin=].
</li>
</ol>
<aside class="note" title="Permission Delegation">
Most powerful features grant permission to the top-level origin and delegate access to the requesting document via [[[Permissions-Policy]]].
This is known as permission delegation.
</aside>
</dd>
<dt>
A <dfn data-dfn-for="powerful feature" class="export">permission key comparison algorithm</dfn>:
</dt>
<dd>
<p>
Takes two [=permission keys=] and returns a [=boolean=] that shows whether the two keys are equal.
If unspecified, this defaults to the <a>default permission key comparison algorithm</a>.
</p>
<p>
The <dfn class="export">default permission key comparison algorithm</dfn>,
given [=permission keys=] |key1| and |key2|, runs the following steps:
</p>
<ol class="algorithm">
<li>
Return |key1| is [=same origin=] with |key2|.
</li>
</ol>
</dd>
<dt>
A <dfn data-dfn-for="powerful feature" class="export">permission revocation
algorithm</dfn>:
Expand All @@ -509,7 +629,7 @@ <h2>
<p>
Takes no arguments. Updates any other parts of the implementation that need to be kept
in sync with changes in the results of <a>permission states</a> or [=powerful
feature/extra permission data=], and then [=react to the user revoking permission=].
feature/extra permission data=].
</p>
<p>
If unspecified, this defaults to running [=react to the user revoking permission=].
Expand Down Expand Up @@ -628,9 +748,11 @@ <h3 id="reading-current-states">
</li>
</ol>
</li>
<li>If there was a previous invocation of this algorithm with the same |descriptor| and
|settings|, returning |previousResult|, and the user agent has not received <a>new
information about the user's intent</a> since that invocation, return |previousResult|.
<li>Let |key| be the result of [=powerful feature/permission key generation algorithm|generating a permission key=] for |descriptor| with |settings|.
</li>
<li>Let |entry| be the result of [=get a permission store entry|getting a permission store entry=] with |descriptor| and |key|.
</li>
<li>If |entry| is not null, return a {{PermissionState}} enum value from |entry|'s [=permission store entry/state=].
</li>
<li>Return the {{PermissionState}} enum value that represents the permission state of
|feature|, taking into account any [=powerful feature/permission state constraints=] for
Expand Down Expand Up @@ -662,8 +784,8 @@ <h3 id="requesting-more-permission">
<li>Ask the user for <a>express permission</a> for the calling algorithm to use the
<a>powerful feature</a> described by |descriptor|.
</li>
<li>If the user gives [=express permission=] to use the powerful feature, return
{{PermissionState/"granted"}}; otherwise return {{PermissionState/"denied"}}. The user's
<li>If the user gives [=express permission=] to use the powerful feature, set |current state| to
{{PermissionState/"granted"}}; otherwise to {{PermissionState/"denied"}}. The user's
interaction may provide <a>new information about the user's intent</a> for the
[=origin=].
<p class="note">
Expand All @@ -672,6 +794,16 @@ <h3 id="requesting-more-permission">
this framework.
</p>
</li>
<li>
Let |key| be the result of [=powerful feature/permission key generation algorithm|generating a permission key=] with the [=current settings object=].
</li>
<li>
[=Queue a task=] on the [=current settings object=]'s [=environment settings
object/responsible event loop=] to [=set a permission store entry=] with |descriptor|, |key|, and |current state|.
</li>
<li>
Return |current state|.
</li>
</ol>
<p>
As a shorthand, <a>requesting permission to use</a> a {{DOMString}} |name|, is the same
Expand Down Expand Up @@ -734,12 +866,16 @@ <h3 id="reacting-to-revocation">
</h3>
<p>
When the user agent learns that the user no longer intends to grant permission to use a
<a>feature</a>, <dfn>react to the user revoking permission</dfn> by running these steps:
feature described by the {{PermissionDescriptor}} |descriptor| in the context
described by the [=permission key=] |key|, <dfn>react to the user revoking permission</dfn>
by running these steps:
</p>
<ol class="algorithm">
<li>
<a>Queue a global task</a> on the [=user interaction task source=] to run that
feature's [=powerful feature/permission revocation algorithm=].
Run |descriptor|'s {{PermissionDescriptor/name}}'s [=powerful feature/permission revocation algorithm=].
</li>
<li>
[=Remove a permission store entry=] with |descriptor| and |key|.
</li>
</ol>
</section>
Expand Down