components/permissions/README.md
[TOC]
The
PermissionController
is the entry point for clients of the permissions infrastructure from both the
//content and the embedder (e.g. //chrome) layers.
PermissionController
provides access to the permissions API and can be reached as
content::BrowserContext::GetPermissionController() or
Profile::GetPermissionController().
PermissionController has the following API:
blink::mojom::PermissionStatus PermissionController::GetPermissionStatusForWorkerblink::mojom::PermissionStatus PermissionController::GetPermissionStatusForCurrentDocumentblink::mojom::PermissionStatus PermissionController::GetPermissionStatusForOriginWithoutContext
Use this API only in special cases when there is no active document or
worker. E.g., PermissionType::PAYMENT_HANDLER permission verification of
payment providers in a PWA's manifest.PermissionController::RequestPermissionFromCurrentDocumentPermissionController::RequestPermissionsFromCurrentDocumentThe PermissionControllerImpl
is the implementation of the
PermissionController.
PermissionControllerImpl
is meant to be used only internally in //content and is not available for
external clients.
PermissionControllerImpl provides various functionality such as:
The PermissionManager is an implementation of PermissionControllerDelegate. PermissionManager is a KeyedService which means it is attached to a BrowserContext. It allows to get permission status for ContentSettingsType. That API should be used only to display permission status in UI like PageInfo and SiteSettings.
Internally,
PermissionManager
holds a list of PermissionsContexts, one per
ContentSettingsType.
PermissionContextBase
is the base class for these contexts, and for every
ContentSettingsType
there is a specific ...PermissionsContext subclass.
EXAMPLE: NotificationPermissionContext handles the "NOTIFICATIONS" content setting.
In order to query, set, and reset the state of a permission, the HostContentSettingsMap KeyedService is used, which internally handles the more complicated things related to Content Settings.
In order to present the user with a permission prompt when a permission is requested, PermissionRequestManager is used.
In order to determine whether a permission is granted, blocked, needs a user decision, etc, the appropriate content setting is checked. Content settings are saved and retrieved using a key consisting of a 3-tuple of values:
A
ContentSettingsPattern
is basically a URL where every part (scheme, host port, path) is allowed to be
either Wildcard or a specified value. Any other form or regex is not
supported.
A key that has Wildcard for both the primary and secondary patterns represents
the "Default" value for a specific
ContentSettingsType.
This is the least specific content setting that will match anything and serves
as a backup for when no more-specific setting has been set.
When setting or retrieving a content setting, the HostContentSettingsMap uses a list of registered providers. This enum is sorted from highest priority to lowest. If a provider is able to handle a specific operation it will do so and the following providers are ignored, otherwise the next provider is queried and so on.
The underlying storage mechanism is provider-dependent.
The
PermissionRequestManager
facilitates making permission requests via AddRequest(). Only one request
prompt is allowed to be in progress at a time, the manager holds a deque of
pending requests for all requests that are kept waiting until the current prompt
is resolved.
The PermissionRequestManager is attached and scoped to the lifetime of a WebContents. When the WebContents object is destroyed all current and queued requests are finalized as "IGNORED".
It is possible to have more than one request be tied in to the same prompt. This only happens when the requests are allowed to be grouped together and they all requested one after another. Currently this is only the case for the Camera and Microphone permissions which can be grouped into one Camera+Microphone prompt.
--deny-permission-prompts command line switch will cause all
permissions to be automatically denied.If the request has not been automatically resolved, it is added to deque of
queued_requests_ from which it will be picked up as appropriate.
When a trigger causes the DequeueRequestIfNeeded function to be called it will
check if the necessary conditions are met to show a new permission prompt and it
will trigger showing the prompt. The conditions are:
DequeueRequestIfNeeded is triggered when:
When the prompt needs to be shown to the user, a platform specific subclass of PermissionPrompt is created which handles the creation and lifetime of the UI element and will report user actions back to the PermissionRequestManager.
The PermissionPrompt is responsible for deciding the exact UI surface and text to present to the user based on information about the request.
For specific permission prompt requests a decision could be made to enforce a quiet UI version of the permission prompt. Currently this only applies to NOTIFICATIONS permission requests.
A quiet UI prompt can be triggered if any of these conditions are met:
The ContextualNotificationPermissionUiSelector checks if the quiet UI is enabled in settings (among other things) when choosing the appropriate UI flavor.
A quiet UI prompt will use a right-side omnibox indicator on desktop or a mini-infobar on Android.
Permission requests and status queries undergo several security and environment-specific verifications before a decision is made. These checks are primarily implemented in PermissionContextBase and PermissionControllerImpl.
content::RenderFrameHost::IsNestedWithinFencedFrame()). Fenced frames do not currently support permission requests to preserve privacy boundaries.network::IsUrlPotentiallyTrustworthy(). Some permissions can bypass this check under specific conditions controlled by the embedder.PermissionContextBase::IsPermissionKillSwitchOn).GuestView (like <webview>) may have different permission behavior. Checks ensure that permissions granted inside a guest are not inappropriately shared across separate StoragePartitions.WebContents to prevent ambient eavesdropping or privilege escalation risks.Requesting and verification of permissions does not feature unified behavior in different environments. In other words, based on the preconditions, a permission request could be shown or automatically declined. To make sure that all cases work as intended, we introduced PermissionsSecurityModelInteractiveUITest.
If you're adding a new environment that requires non-default behavior for permissions, then you need to add a test in PermissionsSecurityModelInteractiveUITest.
Steps to follow:
VerifyPermissionForXYZ, where XYZ is the name of your
environment. You can use the already defined VerifyPermission method if you
expect to have default behavior for permissions. In VerifyPermissionForXYZ
define a new behavior you expect to have.VerifyPermissionForXYZ from your newly created test fixture.EXAMPLE:
PermissionRequestFencedFrameTestverifies that permissions are disabled inside fenced frames.VerifyPermissionsDeniedForFencedFrame(line 367) encapsulates all logic needed for a particular permission verification.
The permissions embargo system automatically blocks permission requests from
origins that users have repeatedly dismissed or ignored. When an origin is
placed under embargo, all subsequent permission requests are automatically
denied with PermissionStatus::DENIED until the embargo expires. After expiry,
the origin may request permission again — but if the user dismisses or ignores the
prompt again, it will be re-embargoed.
The PermissionDecisionAutoBlocker is responsible for the core logic of recording actions, incrementing counters, and determining if an origin should be under embargo. This is orchestrated by the PermissionRequestManager.
Embargoes are triggered when a user performs a specific number of dismissals or ignores. The exact threshold values and embargo durations depend on the permission type (e.g., standard permissions, FedCM) and the UI surface presented to the user (e.g., loud vs. quiet prompts). There are three types of actions that can trigger an embargo: dismissals, ignores, and prompt displays.
Thresholds are evaluated using OR logic between the general and quiet-UI specific
counters. For example, an embargo is triggered if either the general ignore counter
OR the quiet-UI ignore counter exceeds its respective threshold.
kDefaultDismissalsBeforeBlock dismissals
or kDefaultIgnoresBeforeBlock ignores. The
embargo lasts for kDefaultEmbargoDays days.kDefaultDismissalsBeforeBlockWithQuietUi
dismissals or
kDefaultIgnoresBeforeBlockWithQuietUi
ignores. The embargo lasts for
kDefaultEmbargoDays days.kPermissionsAndroidClapperLoud
feature is enabled, the ignore threshold drops to
kClapperIgnoresBeforeBlock ignores.kFederatedIdentityApiDismissalsBeforeBlock
dismissals. Has escalating embargo durations based on the number of
consecutive dismissals, defined in
kFederatedIdentityApiEmbargoDurationDismiss.kFederatedIdentityAutoReauthnEmbargoDuration.Action counters persist across embargo expiry. This means that if an origin is unembargoed because the time duration expired, a single subsequent dismissal or ignore will immediately re-trigger the embargo because the underlying counter still meets the threshold.
When a user explicitly grants a permission (resulting in GRANTED/GRANTED_ONCE), any
existing embargo and all associated counters for that origin and permission type
are cleared.
Certain requests bypass the embargo system entirely:
<permission> HTML element are not subject to embargo recording.PermissionRequest subclasses can
opt out of the embargo system by returning false for
uses_automatic_embargo().components/permissions/permission_decision_auto_blocker.h
/ .cc: Core logic, embargo status
evaluation, and all constants defining thresholds and durations.components/permissions/permission_request_manager.h
/ .cc: Orchestration, action recording,
and recording quiet UI prompt timeouts as ignores.components/permissions/permission_request.h:
Defines exemptions (e.g., uses_automatic_embargo()).components/permissions/features.h:
Feature flags controlling new permission UIs and embargo behaviors.