Skip to content

Commit

Permalink
Define a permission store (closes #384) (#390)
Browse files Browse the repository at this point in the history
See #384 for more information.

Co-authored-by: Marcos Cáceres <[email protected]>
Co-authored-by: Anne van Kesteren <[email protected]>
Co-authored-by: Jeffrey Yasskin <[email protected]>
Co-authored-by: Mike Taylor <[email protected]>
  • Loading branch information
5 people authored Dec 9, 2022
1 parent 2bd53ac commit f3b9273
Showing 1 changed file with 145 additions and 9 deletions.
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>.
</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.
</li>
<li>
Return null.
</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.
</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 @@ -510,6 +578,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>:
</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 @@ -518,7 +638,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 @@ -637,9 +757,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 @@ -671,8 +793,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 @@ -681,6 +803,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 @@ -743,12 +875,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

0 comments on commit f3b9273

Please sign in to comment.