├── .pr-preview.json ├── tidyconfig.txt ├── docs └── assets │ └── images │ ├── sample-prompts.png │ └── permission-settings.png ├── w3c.json ├── LICENSE.md ├── .github ├── CODE_OF_CONDUCT.md ├── PULL_REQUEST_TEMPLATE.md ├── workflows │ ├── tidy.yml │ └── auto-publish.yml └── CONTRIBUTING.md ├── README.md ├── extensibility.md └── index.html /.pr-preview.json: -------------------------------------------------------------------------------- 1 | { 2 | "src_file": "index.html", 3 | "type": "respec" 4 | } 5 | -------------------------------------------------------------------------------- /tidyconfig.txt: -------------------------------------------------------------------------------- 1 | char-encoding: utf8 2 | indent: yes 3 | wrap: 100 4 | tidy-mark: no 5 | newline: LF 6 | custom-tags: yes 7 | -------------------------------------------------------------------------------- /docs/assets/images/sample-prompts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/w3c/permissions/HEAD/docs/assets/images/sample-prompts.png -------------------------------------------------------------------------------- /docs/assets/images/permission-settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/w3c/permissions/HEAD/docs/assets/images/permission-settings.png -------------------------------------------------------------------------------- /w3c.json: -------------------------------------------------------------------------------- 1 | { 2 | "group": [ 3 | "49309" 4 | ], 5 | "contacts": [ 6 | "samuelweiler", "wseltzer", "sideshowbarker" 7 | ], 8 | "repo-type": "rec-track" 9 | } 10 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | All documents in this Repository are licensed by contributors 2 | under the 3 | [W3C Software and Document License](https://www.w3.org/Consortium/Legal/copyright-software). 4 | 5 | -------------------------------------------------------------------------------- /.github/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | 3 | All documentation, code and communication under this repository are covered by the [W3C Code of Ethics and Professional Conduct](https://www.w3.org/Consortium/cepc/). 4 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | closes #??? 2 | 3 | The following tasks have been completed: 4 | 5 | * [ ] Modified Web platform tests (link) 6 | 7 | Implementation commitment: 8 | 9 | * [ ] WebKit (link to issue) 10 | * [ ] Blink (link to issue) 11 | * [ ] Gecko (link to issue) 12 | 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # About 2 | This repo holds some of the sources for the Permissions API, an interface for Web applications to be able to manage permissions. 3 | 4 | The latest editor’s draft is at https://w3c.github.io/permissions/ 5 | 6 | # Contributing 7 | We welcome contributions to this repo. For more info, please see [CONTRIBUTING](https://github.com/w3c/permissions/blob/main/.github/CONTRIBUTING.md). 8 | 9 | # License 10 | Please refer to [W3C Software and Document License](https://www.w3.org/Consortium/Legal/copyright-software). 11 | -------------------------------------------------------------------------------- /.github/workflows/tidy.yml: -------------------------------------------------------------------------------- 1 | name: Tidy document 2 | on: 3 | workflow_dispatch: {} 4 | push: 5 | branches: 6 | - main 7 | 8 | jobs: 9 | tidy: 10 | name: Tidy up 11 | runs-on: macos-latest 12 | steps: 13 | - uses: actions/checkout@v2 14 | - run: brew install tidy-html5 15 | - run: tidy -config tidyconfig.txt -o index.html index.html 16 | - uses: peter-evans/create-pull-request@v3 17 | with: 18 | title: "Tidied up document using tidy-html5" 19 | commit-message: "chore(tidy): tidy up document" 20 | branch: html-tidy 21 | -------------------------------------------------------------------------------- /.github/workflows/auto-publish.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: 3 | pull_request: {} 4 | push: 5 | branches: [main] 6 | jobs: 7 | main: 8 | name: Build, Validate, Deploy 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v2 12 | - uses: w3c/spec-prod@v2 13 | with: 14 | GH_PAGES_BRANCH: gh-pages 15 | TOOLCHAIN: respec 16 | W3C_NOTIFICATIONS_CC: ${{ secrets.CC }} 17 | W3C_ECHIDNA_TOKEN: ${{ secrets.ECHIDNA_TOKEN }} 18 | W3C_WG_DECISION_URL: https://lists.w3.org/Archives/Public/public-webappsec/2015Mar/0170.html 19 | W3C_BUILD_OVERRIDE: | 20 | specStatus: WD 21 | -------------------------------------------------------------------------------- /extensibility.md: -------------------------------------------------------------------------------- 1 | # Extensibility 2 | 3 | This document describes how the Permissions API can be used to express more complex permissions than the one currently 4 | specified and how it should be used by other specifications. 5 | 6 | ## Permission description 7 | 8 | ```js 9 | dictionary PermissionDescriptor { 10 | required PermissionName name; 11 | }; 12 | ``` 13 | ```PermissionDescriptor``` is a dictionary that describes a permission. Its minimal content is a permission name but complex permissions can be described by more than a name. Such permissions should inherit from it and extend it. 14 | 15 | ## Simple permissions 16 | 17 | ```geolocation``` and ```notifications``` do not require more options for now. So their usage only require passing a ```PermissionDescriptor``` with a ```name```. 18 | 19 | ## Quota API 20 | 21 | Quota API will need options because it is more granular than accepted/denied: 22 | ```js 23 | dictionary QuotaPermissionDescriptor : PermissionDescriptor { 24 | required unsigned long long quota; 25 | StorageType type; 26 | }; 27 | ``` 28 | 29 | Checking ```quota``` permission would look like: 30 | ```js 31 | navigator.permissions.query({name: 'quota', quota: '1024', type: 'persistent' }).then(function(status) { 32 | if (status.status == 'denied') { 33 | navigator.permissions.query({name:'quotar', quota: '512', type: 'persistent' }).then(ellipsis); 34 | } 35 | }); 36 | ``` 37 | 38 | ## GetUserMedia 39 | 40 | Capture has basically two permissions: audio and video. There are a couple of ways to design this. 41 | 42 | ### Have one permission with two booleans 43 | 44 | ```js 45 | dictionary CapturePermissionDescriptor : PermissionDescriptor { 46 | required boolean audio; 47 | required boolean video; 48 | }; 49 | ``` 50 | But it might be odd if ```audio``` and ```video``` are both set to ```false```. Though, technically, the permission 51 | should definitely be granted. 52 | 53 | ### Have an enum for the tri-state 54 | 55 | ```js 56 | enum CapturePermissionType { 57 | "audio", 58 | "video", 59 | "audio-video" 60 | } 61 | dictionary CapturePermissionDescriptor : PermissionDescriptor { 62 | required CapturePermissionType type; 63 | }; 64 | ``` 65 | 66 | ### Have two permissions 67 | 68 | Simply ```capture-video``` and ```capture-audio```. 69 | 70 | ## Geolocation extended 71 | 72 | The Geolocation specification defines a boolean called ```enableHighAccuracy```. Some user agents could have a 73 | permissions behaviour depending on that value. We could imagine that the ```geolocation``` permission could be 74 | extended to include this boolean in the future: 75 | ```js 76 | dictionary GeolocationPermissionDescriptor : PermissionDescriptor { 77 | boolean enableHighAccurary = true; 78 | }; 79 | ``` 80 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Everyone is welcome to contribute to this specification. 4 | 5 | Any simple editorial contribution can simply be done with a GitHub Pull Request. 6 | You can even do an inline edit of the file on GitHub. 7 | 8 | Note: Contributions to this repository are intended to become part of Recommendation-track documents governed by the 9 | [W3C Patent Policy](https://www.w3.org/Consortium/Patent-Policy-20040205/) and 10 | [Software and Document License](https://www.w3.org/Consortium/Legal/copyright-software). To make substantive contributions to specifications, you must either participate 11 | in the relevant W3C Working Group or make a non-member patent licensing commitment. 12 | 13 | ## Style guide to contributors 14 | 15 | - the spec uses [ReSpec](https://www.w3.org/respec/) 16 | - the spec is tidied using [HTML5 Tidy](https://github.com/w3c/tidy-html5). For 17 | instructions on running HTML5 tidy, see below. 18 | - Running tidy is optional. We run tidy on the server after every commit. 19 | - Put comments in front of sections, for better readability with 20 | syntax coloring editors. 21 | 22 | ## Commit message guidelines 23 | 24 | - When relevant, include `closes #` and the issue number. 25 | - The commit message should be short and concise. 26 | - Prefix the commit message with one of the following: 27 | - `Editorial:` -for editorial/non-normative change to the specification. 28 | - `Chore:` - when fixing ReSpec stuff or other non-spec related stuff (e.g., CI). 29 | - Normative changes should not be prefixed with anything. These go into the changelog. 30 | 31 | ## Optional - Running HTML5 Tidy 32 | 33 | We run HTML5 tidy on the server after every commit. 34 | 35 | But, if you are planning to make a lot of edits, please make sure you 36 | have [HTML5 Tidy](https://github.com/w3c/tidy-html5) installed. 37 | 38 | On MacOS: 39 | 40 | ``` 41 | brew install tidy-html5 42 | ``` 43 | 44 | Don't use the the one that ships with \*nix systems. 45 | 46 | You can confirm check the version by running the following. 47 | 48 | ```bash 49 | tidy --version 50 | ``` 51 | 52 | It should say "HTML Tidy for Apple macOS version 5.8.0" or something similar for your OS. 53 | 54 | Once you have confirmed (make sure you have committed your changes before 55 | running tidy, as the changes are destructive ... in a good way:)): 56 | 57 | ```bash 58 | tidy -config tidyconfig.txt -o index.html index.html 59 | ``` 60 | 61 | If you are not the sole contributor to a contribution (pull request), please identify all 62 | contributors in the pull request comment. 63 | 64 | ## Contributing for other people 65 | 66 | To add a contributor (other than yourself, that's automatic), mark them one per line as follows: 67 | 68 | ```text 69 | +@github_username 70 | ``` 71 | 72 | If you added a contributor by mistake, you can remove them in a comment with: 73 | 74 | ```text 75 | -@github_username 76 | ``` 77 | 78 | If you are making a pull request on behalf of someone else but you had no part in designing the 79 | feature, you can remove yourself with the above syntax. 80 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 |68 | This specification defines common infrastructure that other specifications can use to 69 | interact with browser permissions. These permissions represent a user's choice to allow or 70 | deny access to "powerful features" of the platform. For developers, the specification 71 | standardizes an API to query the permission state of a powerful feature, and be notified if 72 | a permission to use a powerful feature changes state. 73 |
74 |77 | This is a work in progress. 78 |
79 |85 | Specifications can define features that are explicitly identified as a [=powerful 86 | feature=]. These features are said to be "powerful" in that they can have significant 87 | privacy, security, and performance implications. As such, users rely on user agents to deny 88 | sites the ability to use these features until they have given express permission, and 89 | usually only granting this ability for a limited amount of time. Express permission to 90 | allow a site to use a powerful feature is generally given and controlled through browser 91 | UI, as illustrated below. 92 |
93 |
96 | 101 | In this sense, a permission represents the current state of user consent for certain types 102 | of features, and particularly "powerful features". Ultimately the user retains control of 103 | these permissions and have the ability to manually grant or deny permissions through user 104 | preferences. Further, user agents assist users in managing permissions by, for example, 105 | hiding and automatically denying certain permission prompts that would otherwise be a 106 | nuisance, and automatically expiring granted permissions if a user doesn't visit a website 107 | for some time. 108 |
109 |
113 | 122 | This example uses the Permissions API to decide whether local news should be shown using 123 | the Geolocation API or with a button offering to add the feature. 124 |
125 |
126 | const { state } = await navigator.permissions.query({
127 | name: "geolocation"
128 | });
129 | switch (state) {
130 | case "granted":
131 | showLocalNewsWithGeolocation();
132 | break;
133 | case "prompt":
134 | showButtonToEnableLocalNews();
135 | break;
136 | case "denied":
137 | showNationalNews();
138 | break;
139 | }
140 |
141 | 142 | This example simultaneously checks the state of the `"geolocation"` and `"notifications"` 143 | [=powerful features=]: 144 |
145 |
146 | const queryPromises = ["geolocation", "notifications"].map(
147 | name => navigator.permissions.query({ name })
148 | );
149 | for await (const status of queryPromises) {
150 | console.log(`${status.name}: ${status.state}`);
151 | }
152 |
153 | 154 | This example is checking the permission state of the available cameras. 155 |
156 |
157 | const devices = await navigator.mediaDevices.enumerateDevices();
158 |
159 | // filter on video inputs, and map to query object
160 | const queries = devices
161 | .filter(({ kind }) => kind === "videoinput")
162 | .map(({ deviceId }) => ({ name: "camera", deviceId }));
163 |
164 | const promises = queries.map((queryObj) =>
165 | navigator.permissions.query(queryObj)
166 | );
167 |
168 | try {
169 | const results = await Promise.all(promises);
170 | // log the state of each camera
171 | results.forEach(({ state }, i) => console.log("Camera", i, state));
172 | } catch (error) {
173 | console.error(error);
174 | }
175 |
176 | 182 | This section specifies a model for [=permissions=] to use [=powerful features=] on the Web 183 | platform. 184 |
185 |190 | A permission represents a user's decision to allow a web 191 | application to use a [=powerful feature=]. This decision is represented as a permission 192 | [=permission/state=]. 193 |
194 |195 | Express permission refers to the user 196 | [=permission/grants|granting=] the web application the ability to use a [=powerful 197 | feature=]. 198 |
199 | 215 |216 | Conceptually, a [=permission=] for a [=powerful feature=] can be in one of the following 217 | states: 218 |
219 |247 | To ascertain new information about the user's intent, a user 248 | agent MAY collect and interpret information about a user's intentions. This information 249 | can come from explicit user action, aggregate behavior of both the relevant user and 250 | other users, or implicit signals this specification hasn't anticipated. 251 |
252 | 261 |262 | Every [=permission=] has a lifetime, 263 | which is the duration for which a particular permission remains [=permission/"granted"=] 264 | before it reverts back to its [=permission/default state=]. A [=permission/lifetime=] 265 | could be until a particular [=ECMAScript/Realm=] is destroyed, until a particular 266 | [=top-level browsing context=] is destroyed, a particular amount of time, or be infinite. 267 | The lifetime is negotiated between the end-user and the [=user agent=] when the user 268 | gives [=express permission=] to use a [=feature=]—usually via some permission UI or 269 | user-agent defined policy. 270 |
271 |272 | Every permission has a default state (usually 273 | [=permission/"prompt"=]), which is the [=permission/state=] that the permission is in 274 | when the user has not yet given [=express permission=] to use the [=feature=] or it has 275 | been reset because its [=permission/lifetime=] has expired. 276 |
277 |283 | The user agent maintains a single permission store which is a 284 | [=/list=] of [=permission store entries=]. Each particular [=entry=] denoted by its 285 | [=permission store entry/descriptor=] and [=permission store entry/key=] can only appear 286 | at most once in this list. 287 |
288 |289 | The user agent MAY remove [=entries=] from the [=permission store=] when their respective 290 | [=permission=]'s [=permission/lifetime=] has expired. 291 |
292 |293 | A permission store entry is a [=tuple=] 294 | of {{PermissionDescriptor}} descriptor, [=permission key=] key, and [=permission/state=] state. 298 |
299 |301 | To get a permission store entry given a 302 | {{PermissionDescriptor}} |descriptor:PermissionDescriptor| and [=permission key=] 303 | |key|: 304 |
305 |319 | To set a permission store entry given a 320 | {{PermissionDescriptor}} |descriptor:PermissionDescriptor|, a [=permission key=] |key|, 321 | and a [=permission/state=] |state|, run these steps: 322 |
323 |339 | To remove a permission store entry given a 340 | {{PermissionDescriptor}} |descriptor:PermissionDescriptor| and [=permission key=] 341 | |key|, run these steps: 342 |
343 |351 | A permission key has its type defined by a feature's [=powerful 352 | feature/permission key type=]. 353 |
354 | 361 |363 | To determine whether a [=permission key=] |key1| is equal to a [=permission key=] |key2|, given a 365 | {{PermissionDescriptor}} |descriptor|, run the following steps: 366 |
367 |383 | A powerful feature is a web platform 384 | feature (usually an API) for which a user gives [=express permission=] before the feature 385 | can be used. Except for a few notable exceptions (e.g., the [[[Notifications]]]), most 386 | powerful features are also [=policy-controlled features=]. For powerful features that are 387 | also [=policy-controlled features=], [[Permissions-Policy]] controls whether a 388 | [=document=] is [=allowed to use=] a given feature. That is, a powerful feature can only 389 | request [=express permission=] from a user if the [=document=] has permission delegated 390 | to it via the corresponding [=policy-controlled feature=] (see example below). Subsequent 391 | access to the feature is determined by the user having [=permission/"granted"=] 392 | permission, or by satisfying some criteria that is equivalent to a permission 393 | [=permission/grant=]. 394 |
395 | 413 |414 | A [=powerful feature=] is identified by its name, which is a string literal (e.g., "geolocation"). 416 |
417 |418 | The user agent tracks which [=powerful features=] the user has [=permission=] to use via 419 | the [=environment settings object=]. 420 |
421 |426 | Each [=powerful feature=] can define zero or more additional aspects. An aspect is defined as WebIDL [=dictionary=] that 428 | [=dictionary/inherits=] from {{PermissionDescriptor}} and serves as a WebIDL 429 | interface's [=powerful feature/permission descriptor type=]. 430 |
431 | 460 |467 | The permissions task source is a [=task source=] used to perform 468 | permissions-related [=tasks=] in this specification. 469 |
470 |477 | When a conforming [=specification=] specifies a powerful feature 478 | it: 479 |
480 |496 | Registering the newly specified [=powerful features=] in the [[[permissions-registry]]] 497 | gives this Working Group an opportunity to provide feedback and check that integration with 498 | this specification is done effectively. 499 |
500 |506 | {{PermissionDescriptor}} or one of its subtypes. If unspecified, this defaults to 507 | {{PermissionDescriptor}}. 508 |
509 |510 | The feature can define a partial order on descriptor 512 | instances. If |descriptorA| is stronger than |descriptorB|, then if |descriptorA|'s 514 | [=permission state=] is {{PermissionState/"granted"}}, |descriptorB|'s [=permission 515 | state=] must also be {{PermissionState/"granted"}}, and if |descriptorB|'s [=permission 516 | state=] is {{PermissionState/"denied"}}, |descriptorA|'s [=permission state=] must also 517 | be {{PermissionState/"denied"}}. 518 |
519 | 529 |542 | Some [=powerful features=] have more information associated with them than just a 543 | {{PermissionState}}. Each of these features defines an [=powerful feature/extra 544 | permission data type=]. 545 |
546 |547 | For example, {{MediaDevices/getUserMedia()}} needs to determine which cameras 548 | the user has granted permission to access. 549 |
550 |552 | If a {{DOMString}} |name| names one of these features, then |name|'s 553 | extra permission data for 554 | an optional environment settings object |settings| is the result of the 555 | following algorithm: 556 |
557 |572 | If specified, the [=powerful feature/extra permission data=] algorithm is usable for 573 | this feature. 574 |
575 |597 | Takes an instance of the [=powerful feature/permission descriptor type=] and a new or 598 | existing instance of the [=powerful feature/permission result type=], and updates the 599 | [=powerful feature/permission result type=] instance with the query result. Used by 600 | {{Permissions}}' {{Permissions/query(permissionDesc)}} method and the 601 | [=`PermissionStatus` update steps=]. If unspecified, this defaults to the [=default 602 | permission query algorithm=]. 603 |
604 |606 | The default permission query algorithm, given a 607 | {{PermissionDescriptor}} permissionDesc and a {{PermissionStatus}} 608 | |status|, runs the following steps: 609 |
610 ||status|'s {{PermissionStatus/state}} to |permissionDesc|'s
612 | permission state.
613 | 622 | The type of [=permission key=] used by the feature. Defaults to [=origin=]. A feature 623 | that specifies a custom [=powerful feature/permission key type=] MUST also specify a 624 | [=powerful feature/permission key generation algorithm=]. 625 |
626 |633 | Takes an [=origin=] |origin| and an [=origin=] |embedded origin|, and returns a new 634 | [=permission key=]. If unspecified, this defaults to the [=default permission key 635 | generation algorithm=]. A feature that specifies a custom [=powerful feature/permission 636 | key generation algorithm=] MUST also specify a [=powerful feature/permission key 637 | comparison algorithm=]. 638 |
639 |641 | The default permission key generation algorithm, given an 642 | [=origin=] |origin| and an [=origin=] |embedded origin|, runs the following steps: 643 |
644 |661 | Takes two [=permission keys=] and returns a [=boolean=] that shows whether the two keys 662 | are equal. If unspecified, this defaults to the [=default permission key comparison 663 | algorithm=]. 664 |
665 |667 | The default permission key comparison algorithm, given 668 | [=permission keys=] |key1| and |key2|, runs the following steps: 669 |
670 |682 | Takes no arguments. Updates any other parts of the implementation that need to be kept 683 | in sync with changes in the results of [=permission states=] or [=powerful 684 | feature/extra permission data=]. 685 |
686 |687 | If unspecified, this defaults to running [=react to the user revoking permission=]. 688 |
689 |695 | Specifications that define one or more [=powerful features=] SHOULD suggest a 696 | [=permission=] [=permission/lifetime=] that is best suited for the particular feature. 697 | Some guidance on determining the lifetime of a permission is noted below, with a strong 698 | emphasis on user privacy. If no [=permission/lifetime=] is specified, the user agent 699 | provides one. 700 |
701 |702 | When the permission [=permission/lifetime=] expires for an origin: 703 |
704 |745 | An {{PermissionState}} value that serves as a [=permission=]'s [=permission/default 746 | state=] of a [=powerful feature=]. 747 |
748 |749 | If not specified, the [=permission=]'s [=permission/default state=] is 750 | {{PermissionState/"prompt"}}. 751 |
752 |755 | A default powerful feature is a [=powerful feature=] with all of 756 | the above types and algorithms defaulted. 757 |
758 |769 | To get the current 770 | permission state, given a [=powerful feature/name=] |name| and an optional 771 | [=environment settings object=] |settings|, run the following steps. This algorithm 772 | returns a {{PermissionState}} enum value. 773 |
774 |784 | A |descriptor|'s permission state, given an optional 785 | environment settings object |settings| is the result of the following algorithm. 786 | It returns a {{PermissionState}} enum value: 787 |
788 |825 | As a shorthand, a {{DOMString}} |name|'s [=permission state=] is the [=permission state=] 826 | of a {{PermissionDescriptor}} with its {{PermissionDescriptor/name}} member set to 827 | |name|. 828 |
829 |836 | To request permission to use a |descriptor:PermissionDescriptor|, the user 838 | agent must perform the following steps. This algorithm returns either 839 | {{PermissionState/"granted"}} or {{PermissionState/"denied"}}. 840 |
841 |855 | This is intentionally vague about the details of the permission UI and how the user 856 | agent infers user intent. User agents should be able to explore lots of UI within 857 | this framework. 858 |
859 |876 | As a shorthand, [=requesting permission to use=] a {{DOMString}} |name|, is the same as 877 | [=requesting permission to use=] a {{PermissionDescriptor}} with its 878 | {{PermissionDescriptor/name}} member set to |name|. 879 |
880 |887 | To prompt the user to choose one or more |options| associated with a given 889 | |descriptor:PermissionDescriptor| and an optional boolean 890 | |allowMultiple:boolean| (default false), the user agent must perform the following 891 | steps. This algorithm returns either {{PermissionState/"denied"}} or the user's 892 | selection. 893 |
894 |919 | This is intentionally vague about the details of the permission UI and how the user 920 | agent infers user intent. User agents should be able to explore lots of UI within 921 | this framework (e.g., a permission prompt could time out and automatically return 922 | "denied" without the user making an explicit selection). 923 |
924 |928 | As a shorthand, [=prompting the user to choose=] from options associated with a 929 | {{DOMString}} |name|, is the same as [=prompting the user to choose=] from those options 930 | associated with a {{PermissionDescriptor}} with its {{PermissionDescriptor/name}} member 931 | set to |name|. 932 |
933 |940 | When the user agent learns that the user no longer intends to grant permission to use a 941 | feature described by the {{PermissionDescriptor}} |descriptor| in the context described 942 | by the [=permission key=] |key|, react to the user revoking permission by 943 | running these steps: 944 |
945 |
964 | [Exposed=(Window)]
965 | partial interface Navigator {
966 | [SameObject] readonly attribute Permissions permissions;
967 | };
968 |
969 | [Exposed=(Worker)]
970 | partial interface WorkerNavigator {
971 | [SameObject] readonly attribute Permissions permissions;
972 | };
973 |
974 |
980 | [Exposed=(Window,Worker)]
981 | interface Permissions {
982 | Promise<PermissionStatus> query(object permissionDesc);
983 | };
984 |
985 | dictionary PermissionDescriptor {
986 | required DOMString name;
987 | };
988 |
989 | 995 | When the query() method is invoked, the user agent MUST run the 996 | following query a permission algorithm, passing the 997 | parameter permissionDesc: 998 |
999 |
1060 | [Exposed=(Window,Worker)]
1061 | interface PermissionStatus : EventTarget {
1062 | readonly attribute PermissionState state;
1063 | readonly attribute DOMString name;
1064 | attribute EventHandler onchange;
1065 | };
1066 |
1067 | enum PermissionState {
1068 | "granted",
1069 | "denied",
1070 | "prompt",
1071 | };
1072 |
1073 | 1074 | {{PermissionStatus}} instances are created with a [[\query]] internal slot, 1075 | which is an instance of a feature's [=powerful feature/permission descriptor type=]. 1076 |
1077 |1078 | The "granted", "denied", and "prompt" enum values 1079 | represent the concepts of [=permission/"granted"=], [=permission/"denied"=], and 1080 | [=permission/"prompt"=] respectively. 1081 |
1082 |1088 | To create a `PermissionStatus` for a given 1089 | {{PermissionDescriptor}} |permissionDesc:PermissionDescriptor|: 1090 |
1091 |1116 | The name attribute returns the value it was initialized to. 1117 |
1118 |1124 | The state attribute returns the latest value that was set on the current 1125 | instance. 1126 |
1127 |
1133 | The onchange attribute is an [=event handler=] whose corresponding [=event
1134 | handler event type=] is change.
1135 |
1138 | Whenever the [=user agent=] is aware that the state of a {{PermissionStatus}} 1139 | instance |status| has changed, it asynchronously runs the `PermissionStatus` 1140 | update steps: 1141 |
1142 |change at |status|.
1161 | 1170 | A {{PermissionStatus}} object MUST NOT be garbage collected if it has an [=event 1171 | listener=] whose type is `change`. 1172 |
1173 |1178 | Two classes of product can claim conformance to this specification: [=user agents=] and 1179 | other specifications (i.e., a technical report that [=specifies a powerful 1180 | feature=] in a manner that conforms to the requirements of this specification). 1181 |
1182 |1188 | Although both this specification and the [[[Permissions-Policy]]] specification deal with 1189 | "permissions", each specification serves a distinct purpose in the platform. Nevertheless, 1190 | the two specifications do explicitly overlap. 1191 |
1192 |1193 | On the one hand, this specification exclusively concerns itself with [=powerful features=] 1194 | whose access is managed through a user-agent mediated permissions UI (i.e., permissions 1195 | where the user gives express consent before that feature can be used, and where the user 1196 | retains the ability to deny that permission at any time for any reason). These powerful 1197 | features are registered in the [[[permissions-registry]]]. 1198 |
1199 |1200 | On the other hand, the [[[Permissions-Policy]]] specification allows developers to 1201 | selectively enable and disable policy-controlled features through a "[=Document/permissions 1202 | policy=]" (be it a HTTP header or the [^iframe/allow^] attribute). In that sense, the 1203 | Permissions Policy subsumes this specification in that [[[Permissions-Policy]]] governs 1204 | whether a feature is available at all, independently of this specification. These 1205 | policy-controlled features are also registered in the [[[permissions-registry]]]. 1206 |
1207 |1208 | A powerful feature that has been disabled by the [[[Permissions-Policy]]] specification 1209 | always has its [=permission state=] reflected as "denied" by this specification. This 1210 | occurs because [=getting the current permission state|reading the current permission=] 1211 | relies on [[HTML]]'s "[=allowed to use=]" check, which itself calls into the 1212 | [[[Permissions-Policy]]] specification. Important to note here is the sharing of permission 1213 | names across both specifications. Both this specification and the [[[Permissions-Policy]]] 1214 | specification rely on other specifications defining the names of the permission and 1215 | [=powerful feature/name=], and they are usually named the same thing (e.g., "geolocation" 1216 | of the [[[Geolocation]]], and so on). 1217 |
1218 |1219 | Finally, it's not possible for a powerful feature to ever become "granted" through any 1220 | means provided by the [[[Permissions-Policy]]] specification. The only way that a 1221 | [=powerful feature=] can be [=permission/"granted"=] is by the user giving [=express 1222 | permission=] or by some user agent policy. 1223 |
1224 |1230 | For the purposes of user-agent automation and application testing, this document defines 1231 | extensions to the [[WebDriver]] and [[WebDriver-BiDi]] specifications. It is OPTIONAL for a 1232 | user agent to support them. 1233 |
1234 |
1235 | dictionary PermissionSetParameters {
1236 | required object descriptor;
1237 | required PermissionState state;
1238 | };
1239 |
1240 | 1242 | To set a permission given a {{PermissionDescriptor}} 1243 | |descriptor:PermissionDescriptor|, a {{PermissionState}} |state:PermissionState|, an 1244 | optional [=permission key=] |key|, and an optional |user agent|: 1245 |
1246 |1297 | This document defines the following extension commands for the [[WebDriver]] 1298 | specification. 1299 |
1300 || 1308 | HTTP Method 1309 | | 1310 |1311 | [=extension command URI template|URI Template=] 1312 | | 1313 |
|---|---|
| 1316 | POST 1317 | | 1318 |1319 | /session/{session id}/permissions 1320 | | 1321 |
1325 | The Set Permission 1326 | extension command simulates user modification of a {{PermissionDescriptor}}'s 1327 | [=permission state=]. 1328 |
1329 |1330 | The remote end steps are: 1331 |
1332 |1341 | For example, user agents that define the "midi" powerful feature as 1342 | "always on" can choose to reject a command to set the [=permission state=] to 1343 | {{PermissionState/"denied"}} at this step. 1344 |
1345 |1383 | This document defines the following [=extension modules=] for the [[WebDriver-BiDi]] 1384 | specification. 1385 |
1386 |1391 | The permissions module contains commands for managing the remote end browser 1392 | permissions. 1393 |
1394 |1399 | {^remote end definition^} 1400 |
1401 |1402 | PermissionsCommand = ( 1403 | permissions.setPermission 1404 | ) 1405 |1406 |
1416 | permissions.PermissionDescriptor = {
1417 | name: text,
1418 | }
1419 |
1420 | 1421 | The `permissions.PermissionDescriptor` type represents a {{PermissionDescriptor}}. 1422 |
1423 |1429 | permissions.PermissionState = "granted" / "denied" / "prompt" 1430 |1431 |
1432 | The `permissions.PermissionState` type represents a {{PermissionState}}. 1433 |
1434 |1445 | The Set Permission [=command=] simulates user 1446 | modification of a {{PermissionDescriptor}}'s [=permission state=]. 1447 |
1448 |
1454 | permissions.setPermission = (
1455 | method: "permissions.setPermission",
1456 | params: permissions.SetPermissionParameters
1457 | )
1458 |
1459 | permissions.SetPermissionParameters = {
1460 | descriptor: permissions.PermissionDescriptor,
1461 | state: permissions.PermissionState,
1462 | origin: text,
1463 | ? embeddedOrigin: text,
1464 | ? userContext: text,
1465 | }
1466 |
1467 | EmptyResult
1473 | 1478 | The [=remote end steps=] with |session| and |command parameters| are: 1479 |
1480 |1534 | This [=W3C Registry=] provides a centralized place to find the [=policy-controlled 1535 | features=] and/or [=powerful features=] of the web platform. Through the [=change 1536 | process=] it also helps assure permissions in the platform are consistently specified 1537 | across various specifications. 1538 |
1539 |1540 | By splitting the registry into standardized permissions and provisional permissions, the 1541 | registry also provides a way to track the status of these features. 1542 |
1543 |1549 | The change process for adding and/or updating this registry is as follows: 1550 |
1551 |1595 | For a permission to appear in the table of standardized permissions, and thus be 1596 | considered a standardized permission, it needs to meet the following criteria: 1597 |
1598 |1608 | Each [=permission=] is identified by a unique literal string. In the case of 1609 | [[[Permissions-Policy]]], the string identifies a [=policy-controlled features=]. 1610 | Similarly, in the [[[Permissions]]] specification the string identifies a [=powerful 1611 | feature=]. 1612 |
1613 | 1625 || 1632 | Identifying string 1633 | | 1634 |1635 | Is [=policy-controlled feature=]? 1636 | | 1637 |1638 | Is [=powerful feature=]? 1639 | | 1640 |1641 | Specification 1642 | | 1643 |1644 | Implementations 1645 | | 1646 |||
|---|---|---|---|---|---|---|
| 1649 | Chromium 1650 | | 1651 |1652 | Gecko 1653 | | 1654 |1655 | WebKit 1656 | | 1657 |||||
| 1660 | "geolocation" 1661 | | 1662 |1663 | YES 1664 | | 1665 |1666 | YES 1667 | | 1668 |1669 | [[[geolocation]]] 1670 | | 1671 |1672 | YES 1673 | | 1674 |1675 | YES 1676 | | 1677 |1678 | YES 1679 | | 1680 |
| 1683 | "[=notifications=]" 1684 | | 1685 |1686 | NO 1687 | | 1688 |1689 | YES 1690 | | 1691 |1692 | [[[NOTIFICATIONS]]] 1693 | | 1694 |1695 | YES 1696 | | 1697 |1698 | YES 1699 | | 1700 |1701 | YES 1702 | | 1703 |
| 1706 | [="push"=] 1707 | | 1708 |1709 | NO 1710 | | 1711 |1712 | YES 1713 | | 1714 |1715 | [[[push-api]]] 1716 | | 1717 |1718 | YES 1719 | | 1720 |1721 | YES 1722 | | 1723 |1724 | YES 1725 | | 1726 |
| 1729 | "web-share" 1730 | | 1731 |1732 | YES 1733 | | 1734 |1735 | NO 1736 | | 1737 |1738 | [[[Web-Share]]] 1739 | | 1740 |1741 | YES 1742 | | 1743 |1744 | YES 1745 | | 1746 |1747 | YES 1748 | | 1749 |
1782 | Provisional permissions are permissions that are not yet [=standardized 1783 | permission|standardized=] (i.e., they are either experimental, still in the incubation 1784 | phase, or are only implemented in a single browser engine). 1785 |
1786 || 1792 | Identifying string 1793 | | 1794 |1795 | Is [=policy-controlled feature=]? 1796 | | 1797 |1798 | Is [=powerful feature=]? 1799 | | 1800 |1801 | Specification 1802 | | 1803 |1804 | Implementations 1805 | | 1806 |||
|---|---|---|---|---|---|---|
| 1809 | Chromium 1810 | | 1811 |1812 | Gecko 1813 | | 1814 |1815 | WebKit 1816 | | 1817 |||||
| 1820 | [="accelerometer"=] 1821 | | 1822 |1823 | YES 1824 | | 1825 |1826 | YES 1827 | | 1828 |1829 | [[[orientation-event]]] 1830 | | 1831 |1832 | YES 1833 | | 1834 |1835 | NO 1836 | | 1837 |1838 | NO 1839 | | 1840 |
| 1843 | "[=window-management=]" 1844 | | 1845 |1846 | YES 1847 | | 1848 |1849 | YES 1850 | | 1851 |1852 | [[[window-management]]] 1853 | | 1854 |1855 | YES 1856 | | 1857 |1858 | NO 1859 | | 1860 |1861 | NO 1862 | | 1863 |
| 1866 | "[=local-fonts=]" 1867 | | 1868 |1869 | YES 1870 | | 1871 |1872 | YES 1873 | | 1874 |1875 | [[[local-font-access]]] 1876 | | 1877 |1878 | YES 1879 | | 1880 |1881 | NO 1882 | | 1883 |1884 | NO 1885 | | 1886 |
1920 | An adversary could use a [=permission state=] as an element in creating a "fingerprint" 1921 | corresponding to an end-user. Although an adversary can already determine the state of a 1922 | permission by actually using the API, that often leads to a UI prompt being presented to 1923 | the end-user (if the permission was not already [=permission/"granted"=]). Even though this 1924 | API doesn't expose new fingerprinting information to websites, it makes it easier for an 1925 | adversary to have discreet access to this information. 1926 |
1927 |1928 | A user agent SHOULD provide a means for the user to review, update, and reset the 1929 | [=permission=] [=permission/state=] of [=powerful features=] associated with an [=origin=]. 1930 |
1931 |1937 | There are no documented security considerations at this time. Readers are instead 1938 | encouraged to read section [[[#privacy-considerations]]]. 1939 |
1940 |1947 | The editors would like to thank Adrienne Porter Felt, Anne van Kesteren, Domenic Denicola, 1948 | Jake Archibald and Wendy Seltzer for their help with the API design and editorial work. 1949 |
1950 |