Andy Paicu | 8b83ebd | 2020-02-21 11:19:36 | [diff] [blame] | 1 | # Permission Checks and Requests |
| 2 | |
| 3 | [TOC] |
| 4 | |
| 5 | ## PermissionManager and PermissionContextBase |
| 6 | |
| 7 | The |
Clark DuVall | 6b73c74 | 2020-03-11 19:00:15 | [diff] [blame] | 8 | [PermissionManager](https://cs.chromium.org/chromium/src/components/permissions/permission_manager.h) |
Andy Paicu | 8b83ebd | 2020-02-21 11:19:36 | [diff] [blame] | 9 | is the entry point for clients of the permissions infrastructure. |
Clark DuVall | 6b73c74 | 2020-03-11 19:00:15 | [diff] [blame] | 10 | [PermissionManager](https://cs.chromium.org/chromium/src/components/permissions/permission_manager.h) |
Andy Paicu | 8b83ebd | 2020-02-21 11:19:36 | [diff] [blame] | 11 | is a |
| 12 | [KeyedService](https://cs.chromium.org/chromium/src/components/keyed_service/core/keyed_service.h) |
| 13 | which means it is attached to a |
| 14 | [BrowserContext](https://cs.chromium.org/chromium/src/content/public/browser/browser_context.h). |
| 15 | Clients can perform various operations such as: |
| 16 | |
| 17 | * Query the status of a permission |
| 18 | * Request a permission from the user |
| 19 | * Reset a permission's state to the default |
| 20 | * Observe permissions changes |
| 21 | |
| 22 | Internally, |
Clark DuVall | 6b73c74 | 2020-03-11 19:00:15 | [diff] [blame] | 23 | [PermissionManager](https://cs.chromium.org/chromium/src/components/permissions/permission_manager.h) |
Andy Paicu | 8b83ebd | 2020-02-21 11:19:36 | [diff] [blame] | 24 | holds a list of PermissionsContexts, one per |
| 25 | [ContentSettingType](https://cs.chromium.org/chromium/src/components/content_settings/core/common/content_settings_types.h?l=17). |
| 26 | [PermissionContextBase](https://cs.chromium.org/chromium/src/components/permissions/permission_context_base.h) |
| 27 | is the base class for these contexts, and for every |
| 28 | [ContentSettingsType](https://cs.chromium.org/chromium/src/components/content_settings/core/common/content_settings_types.h) |
| 29 | there is a specific `...PermissionsContext` subclass. |
| 30 | |
| 31 | > EXAMPLE: |
| 32 | > [NotificationPermissionContext](https://cs.chromium.org/chromium/src/chrome/browser/notifications/notification_permission_context.h) |
| 33 | > handles the |
| 34 | > "[NOTIFICATIONS](https://cs.chromium.org/chromium/src/components/content_settings/core/common/content_settings_types.h?l=33)" |
| 35 | > content setting. |
| 36 | |
| 37 | In order to query, set, and reset the state of a permission, the |
| 38 | [HostContentSettingsMap](#HostContentSettingsMap) KeyedService is used, which |
| 39 | internally handles the more complicated things related to Content Settings. |
| 40 | |
| 41 | In order to present the user with a permission prompt when a permission is |
| 42 | requested, [PermissionRequestManager](#PermissionRequestManager) is used. |
| 43 | |
| 44 | ## [HostContentSettingsMap](https://cs.chromium.org/chromium/src/components/content_settings/core/browser/host_content_settings_map.h) |
| 45 | |
| 46 | ### Patterns |
| 47 | |
| 48 | In order to determine whether a permission is granted, blocked, needs a user |
| 49 | decision, etc, the appropriate content setting is checked. Content settings are |
| 50 | saved and retrieved using a key consisting of a 3-tuple of values: |
| 51 | |
| 52 | * Primary pattern: this is a |
| 53 | [ContentSettingsPattern](https://cs.chromium.org/chromium/src/components/content_settings/core/common/content_settings_pattern.h) |
| 54 | that represents the primary resource's URL. For permissions this refers to |
| 55 | the URL of the document requesting/using the permission. |
| 56 | * Secondary pattern: this is a |
| 57 | [ContentSettingsPattern](https://cs.chromium.org/chromium/src/components/content_settings/core/common/content_settings_pattern.h) |
| 58 | that is used for some types to provide some context around the primary |
| 59 | resource. For permissions this refers to the URL of the top-level document |
| 60 | of the page (except for "NOTIFICATIONS" in which case it's unused). |
| 61 | * Content type: this is a |
| 62 | [ContentSettingsType](https://cs.chromium.org/chromium/src/components/content_settings/core/common/content_settings_types.h) |
| 63 | that specifies which setting this operation refers to. |
| 64 | |
| 65 | > NOTE: While the code contains a `ResourceIdentifier` this is deprecated and |
| 66 | > should never be used. |
| 67 | |
| 68 | See [go/otjvl](go/otjvl) for a breakdown of primary/secondary pattern meanings |
| 69 | based on |
| 70 | [ContentSettingsType](https://cs.chromium.org/chromium/src/components/content_settings/core/common/content_settings_types.h) |
| 71 | |
| 72 | A |
| 73 | [ContentSettingsPattern](https://cs.chromium.org/chromium/src/components/content_settings/core/common/content_settings_pattern.h) |
| 74 | is basically a URL where every part (scheme, host port, path) is allowed to be |
| 75 | either `Wildcard` or a specified value. Any other form or regex is not |
| 76 | supported. |
| 77 | |
| 78 | A key that has `Wildcard` for both the primary and secondary patterns represents |
| 79 | the "Default" value for a specific |
| 80 | [ContentSettingsType](https://cs.chromium.org/chromium/src/components/content_settings/core/common/content_settings_types.h). |
| 81 | This is the least specific content setting that will match anything and serves |
| 82 | as a backup for when no more-specific setting has been set. |
| 83 | |
| 84 | ### Providers |
| 85 | |
| 86 | When setting or retrieving a content setting, the |
| 87 | [HostContentSettingsMap](https://cs.chromium.org/chromium/src/components/content_settings/core/browser/host_content_settings_map.h) |
| 88 | uses a list of registered |
| 89 | [providers](https://cs.chromium.org/chromium/src/components/content_settings/core/browser/host_content_settings_map.h?type=cs&g=0&l=54). |
| 90 | This enum is sorted from highest priority to lowest. If a provider is able to |
| 91 | handle a specific operation it will do so and the following providers are |
| 92 | ignored, otherwise the next provider is queried and so on. |
| 93 | |
| 94 | The underlying storage mechanism is provider-dependent. |
| 95 | |
| 96 | ## [PermissionRequestManager](https://cs.chromium.org/chromium/src/components/permissions/permission_request_manager.h) |
| 97 | |
| 98 | The |
| 99 | [PermissionRequestManager](https://cs.chromium.org/chromium/src/components/permissions/permission_request_manager.h) |
| 100 | facilitates making permission requests via `AddRequest()`. Only one request |
| 101 | prompt is allowed to be in progress at a time, the manager holds a deque of |
| 102 | pending requests for all requests that are kept waiting until the current prompt |
| 103 | is resolved. |
| 104 | |
| 105 | The |
| 106 | [PermissionRequestManager](https://cs.chromium.org/chromium/src/components/permissions/permission_request_manager.h) |
| 107 | is attached and scoped to the lifetime of a |
| 108 | [WebContents](https://cs.chromium.org/chromium/src/content/public/browser/web_contents.h?l=111). |
| 109 | When the |
| 110 | [WebContents](https://cs.chromium.org/chromium/src/content/public/browser/web_contents.h?l=111) |
| 111 | object is destroyed all current and queued requests are finalized as |
| 112 | "[IGNORED](https://cs.chromium.org/chromium/src/components/permissions/permission_util.h?l=26)". |
| 113 | |
| 114 | It is possible to have more than one request be tied in to the same prompt. This |
| 115 | only happens when the requests are allowed to be grouped together and they all |
| 116 | requested one after another. Currently this is only the case for the Camera and |
| 117 | Microphone permissions which can be grouped into one Camera+Microphone prompt. |
| 118 | |
| 119 | ### Automatic actions |
| 120 | |
| 121 | * The `--deny-permission-prompts` command line switch will cause all |
| 122 | permissions to be automatically denied. |
| 123 | * Notification permission requests that arrive too soon after a previous |
| 124 | notifications prompt has been resolved are automatically |
| 125 | "[DENIED](https://cs.chromium.org/chromium/src/components/permissions/permission_util.h?l=24)". |
| 126 | When a user denies a notifications permission prompt, the manager enters a |
| 127 | "notifications cooldown mode" and a user-initiated navigation needs to |
| 128 | happen before allowing another notifications permission prompt. This |
| 129 | prevents an abusive pattern observed in the wild where a site is cycling |
| 130 | through multiple subdomains and asking to show permissions until the user |
| 131 | gives up or gives in. |
| 132 | * On ChromeOS in WebKiosk mode, permission requests for the origin of the |
| 133 | installed app are automatically |
| 134 | "[GRANTED](https://cs.chromium.org/chromium/src/components/permissions/permission_util.h?l=23)". |
| 135 | This needs to be done because there is no "user" to grant a permissions when |
| 136 | the browser is simply used to continuously display some presentation app |
| 137 | (for example: a TV in a store that displays on screen the camera feed). |
| 138 | * Requests that duplicate a currently pending requests are put into a separate |
| 139 | list instead of the regular queue. When a request is resolved, its |
| 140 | duplicates are also resolved. |
| 141 | * Based on various indicators (user's behavior, settings, site score etc) a |
| 142 | request can be downgraded to use a quiet UI or be dropped entirely. For more |
| 143 | info see the [Quiet permissions prompts](#Quiet-permissions-prompts) |
| 144 | section. |
| 145 | * If the current permission prompt is [quiet](#Quiet-permissions-prompts), it |
| 146 | will be resolved as |
| 147 | "[IGNORED](https://cs.chromium.org/chromium/src/components/permissions/permission_util.h?l=26)" |
| 148 | when a new request is added. This prevents the permission requests being |
| 149 | stuck around a prompt that is easily ignored by the user. |
| 150 | |
| 151 | If the request has not been automatically resolved, it is added to deque of |
| 152 | `queued_requests_` from which it will be picked up as appropriate. |
| 153 | |
| 154 | ### Showing prompts |
| 155 | |
| 156 | When a trigger causes the `DequeueRequestIfNeeded` function to be called it will |
| 157 | check if the necessary conditions are met to show a new permission prompt and it |
| 158 | will trigger showing the prompt. The conditions are: |
| 159 | |
| 160 | * The document needs to be loaded and visible |
| 161 | * There is no permission prompt currently being shown to the user |
| 162 | * There is a queued request waiting to be shown to the user |
| 163 | |
| 164 | `DequeueRequestIfNeeded` is triggered when: |
| 165 | |
| 166 | * The document loads |
| 167 | * The document becomes visible |
| 168 | * A new request is added |
| 169 | * A permission prompt is resolved |
| 170 | * An async decision about a permission request is made |
| 171 | |
| 172 | When the prompt needs to be shown to the user, a platform specific subclass of |
| 173 | [PermissionPrompt](https://cs.chromium.org/chromium/src/chrome/browser/ui/permission_bubble/permission_prompt.h) |
| 174 | is created which handles the creation and lifetime of the UI element and will |
| 175 | report user actions back to the |
| 176 | [PermissionRequestManager](https://cs.chromium.org/chromium/src/components/permissions/permission_request_manager.h). |
| 177 | |
| 178 | The PermissionPrompt is responsible for deciding the exact UI surface and text |
| 179 | to present to the user based on information about the request. |
| 180 | |
| 181 | ### Quiet permissions prompts |
| 182 | |
| 183 | For specific permission prompt requests a decision could be made to enforce a |
| 184 | quiet UI version of the permission prompt. Currently this only applies to |
| 185 | NOTIFICATION permission requests. |
| 186 | |
| 187 | A quiet UI prompt can be triggered if any of these conditions are met: |
| 188 | |
| 189 | * The user has enabled quiet prompts in settings. |
| 190 | * The user's denial behavior has caused quiet prompts to be enabled |
| 191 | automatically. See below for more details on this. |
| 192 | * The site requesting the permissions is marked by Safe Browsing as having a |
| 193 | bad reputation. |
| 194 | |
| 195 | In order for the user's behavior to automatically enable quiet notification |
| 196 | prompts, the feature variation of |
| 197 | "[kQuietNotificationPromptsWithAdaptiveActivation](https://cs.chromium.org/chromium/src/chrome/browser/about_flags.cc?g=0&l=1444)" |
| 198 | needs to the enabled variation for the |
| 199 | "[quiet-notification-prompts](https://cs.chromium.org/chromium/src/chrome/browser/about_flags.cc?g=0&l=4626)" |
| 200 | feature to enable adaptively activating quiet notifications based on user |
| 201 | behavior. If adaptive activation is enabled, when the user has decided to deny 3 |
| 202 | notification prompts in a row (regardless if on the same site or entirely |
| 203 | different sites), they will automatically start receiving only quiet |
| 204 | notification permission prompts. |
| 205 | |
| 206 | The |
| 207 | [AdaptiveQuietNotificationPermissionUiEnabler](https://cs.chromium.org/chromium/src/chrome/browser/permissions/adaptive_quiet_notification_permission_ui_enabler.h) |
| 208 | is responsible for recording the permission prompts outcomes and, if needed, |
| 209 | enabling the quiet UI in settings. The |
| 210 | [ContextualNotificationPermissionUiSelector](https://cs.chromium.org/chromium/src/chrome/browser/permissions/contextual_notification_permission_ui_selector.h) |
| 211 | checks if the quiet UI is enabled in settings (among other things) when choosing |
| 212 | the appropriate UI flavor. |
| 213 | |
| 214 | A quiet UI prompt will use a right-side omnibox indicator on desktop or a |
| 215 | mini-infobar on Android. |