1 // Copyright 2014 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "components/permissions/permission_context_base.h"
12 #include "base/functional/bind.h"
13 #include "base/functional/callback.h"
14 #include "base/logging.h"
15 #include "base/metrics/field_trial_params.h"
16 #include "base/observer_list.h"
17 #include "base/strings/stringprintf.h"
18 #include "base/time/time.h"
19 #include "build/build_config.h"
20 #include "components/content_settings/core/browser/content_settings_registry.h"
21 #include "components/content_settings/core/browser/content_settings_utils.h"
22 #include "components/content_settings/core/browser/host_content_settings_map.h"
23 #include "components/content_settings/core/common/content_settings.h"
24 #include "components/content_settings/core/common/content_settings_pattern.h"
25 #include "components/content_settings/core/common/content_settings_types.h"
26 #include "components/content_settings/core/common/features.h"
27 #include "components/permissions/features.h"
28 #include "components/permissions/permission_context_base.h"
29 #include "components/permissions/permission_decision_auto_blocker.h"
30 #include "components/permissions/permission_request.h"
31 #include "components/permissions/permission_request_id.h"
32 #include "components/permissions/permission_request_manager.h"
33 #include "components/permissions/permission_uma_util.h"
34 #include "components/permissions/permission_util.h"
35 #include "components/permissions/permissions_client.h"
36 #include "components/permissions/request_type.h"
37 #include "content/public/browser/browser_thread.h"
38 #include "content/public/browser/global_routing_id.h"
39 #include "content/public/browser/navigation_entry.h"
40 #include "content/public/browser/render_frame_host.h"
41 #include "content/public/browser/web_contents.h"
42 #include "content/public/common/content_features.h"
43 #include "services/network/public/cpp/is_potentially_trustworthy.h"
44 #include "third_party/blink/public/mojom/permissions_policy/permissions_policy_feature.mojom.h"
47 #if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
48 #include "components/guest_view/browser/guest_view_base.h"
51 namespace permissions {
54 using PermissionStatus = blink::mojom::PermissionStatus;
56 const char kPermissionBlockedKillSwitchMessage[] =
57 "%s permission has been blocked.";
59 #if BUILDFLAG(IS_ANDROID)
60 const char kPermissionBlockedRepeatedDismissalsMessage[] =
61 "%s permission has been blocked as the user has dismissed the permission "
62 "prompt several times. This can be reset in Site Settings. See "
63 "https://www.chromestatus.com/feature/6443143280984064 for more "
66 const char kPermissionBlockedRepeatedIgnoresMessage[] =
67 "%s permission has been blocked as the user has ignored the permission "
68 "prompt several times. This can be reset in Site Settings. See "
69 "https://www.chromestatus.com/feature/6443143280984064 for more "
72 const char kPermissionBlockedRepeatedDismissalsMessage[] =
73 "%s permission has been blocked as the user has dismissed the permission "
74 "prompt several times. This can be reset in Page Info which can be "
75 "accessed by clicking the lock icon next to the URL. See "
76 "https://www.chromestatus.com/feature/6443143280984064 for more "
79 const char kPermissionBlockedRepeatedIgnoresMessage[] =
80 "%s permission has been blocked as the user has ignored the permission "
81 "prompt several times. This can be reset in Page Info which can be "
82 "accessed by clicking the lock icon next to the URL. See "
83 "https://www.chromestatus.com/feature/6443143280984064 for more "
87 const char kPermissionBlockedRecentDisplayMessage[] =
88 "%s permission has been blocked as the prompt has already been displayed "
89 "to the user recently.";
91 const char kPermissionBlockedPermissionsPolicyMessage[] =
92 "%s permission has been blocked because of a permissions policy applied to"
93 " the current document. See https://goo.gl/EuHzyv for more details.";
95 void LogPermissionBlockedMessage(content::RenderFrameHost* rfh,
97 ContentSettingsType type) {
98 rfh->GetOutermostMainFrame()->AddMessageToConsole(
99 blink::mojom::ConsoleMessageLevel::kWarning,
100 base::StringPrintfNonConstexpr(
101 message, PermissionUtil::GetPermissionString(type).c_str()));
107 const char PermissionContextBase::kPermissionsKillSwitchFieldStudy[] =
108 "PermissionsKillSwitch";
110 const char PermissionContextBase::kPermissionsKillSwitchBlockedValue[] =
113 PermissionContextBase::PermissionContextBase(
114 content::BrowserContext* browser_context,
115 ContentSettingsType content_settings_type,
116 blink::mojom::PermissionsPolicyFeature permissions_policy_feature)
117 : browser_context_(browser_context),
118 content_settings_type_(content_settings_type),
119 permissions_policy_feature_(permissions_policy_feature) {
120 CHECK(permissions::PermissionUtil::IsPermission(content_settings_type_));
121 PermissionDecisionAutoBlocker::UpdateFromVariations();
124 PermissionContextBase::~PermissionContextBase() {
125 DCHECK(permission_observers_.empty());
126 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
129 void PermissionContextBase::RequestPermission(
130 PermissionRequestData request_data,
131 BrowserPermissionCallback callback) {
132 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
134 content::RenderFrameHost* const rfh = content::RenderFrameHost::FromID(
135 request_data.id.global_render_frame_host_id());
138 // Permission request is not allowed without a valid RenderFrameHost.
139 std::move(callback).Run(CONTENT_SETTING_ASK);
144 .WithRequestingOrigin(
145 request_data.requesting_origin.DeprecatedGetOriginAsURL())
146 .WithEmbeddingOrigin(
147 PermissionUtil::GetLastCommittedOriginAsURL(rfh->GetMainFrame()));
149 if (!request_data.requesting_origin.is_valid() ||
150 !request_data.embedding_origin.is_valid()) {
151 std::string type_name =
152 PermissionUtil::GetPermissionString(content_settings_type_);
154 DVLOG(1) << "Attempt to use " << type_name
155 << " from an invalid URL: " << request_data.requesting_origin
156 << "," << request_data.embedding_origin << " (" << type_name
157 << " is not supported in popups)";
158 NotifyPermissionSet(request_data.id, request_data.requesting_origin,
159 request_data.embedding_origin, std::move(callback),
160 /*persist=*/false, CONTENT_SETTING_BLOCK,
161 /*is_one_time=*/false,
162 /*is_final_decision=*/true);
166 // Check the content setting to see if the user has already made a decision,
167 // or if the origin is under embargo. If so, respect that decision.
169 content::PermissionResult result = GetPermissionStatus(
170 rfh, request_data.requesting_origin, request_data.embedding_origin);
172 bool status_ignorable = PermissionUtil::CanPermissionRequestIgnoreStatus(
173 request_data, result.source);
175 if (!status_ignorable && (result.status == PermissionStatus::GRANTED ||
176 result.status == PermissionStatus::DENIED)) {
177 switch (result.source) {
178 case content::PermissionStatusSource::KILL_SWITCH:
179 // Block the request and log to the developer console.
180 LogPermissionBlockedMessage(rfh, kPermissionBlockedKillSwitchMessage,
181 content_settings_type_);
182 PermissionUmaUtil::RecordPermissionRequestedFromFrame(
183 content_settings_type_, rfh);
184 std::move(callback).Run(CONTENT_SETTING_BLOCK);
186 case content::PermissionStatusSource::MULTIPLE_DISMISSALS:
187 LogPermissionBlockedMessage(rfh,
188 kPermissionBlockedRepeatedDismissalsMessage,
189 content_settings_type_);
190 PermissionUmaUtil::RecordPermissionRequestedFromFrame(
191 content_settings_type_, rfh);
193 case content::PermissionStatusSource::MULTIPLE_IGNORES:
194 LogPermissionBlockedMessage(rfh,
195 kPermissionBlockedRepeatedIgnoresMessage,
196 content_settings_type_);
197 PermissionUmaUtil::RecordPermissionRequestedFromFrame(
198 content_settings_type_, rfh);
200 case content::PermissionStatusSource::FEATURE_POLICY:
201 LogPermissionBlockedMessage(rfh,
202 kPermissionBlockedPermissionsPolicyMessage,
203 content_settings_type_);
205 case content::PermissionStatusSource::RECENT_DISPLAY:
206 LogPermissionBlockedMessage(rfh, kPermissionBlockedRecentDisplayMessage,
207 content_settings_type_);
209 case content::PermissionStatusSource::UNSPECIFIED:
210 PermissionUmaUtil::RecordPermissionRequestedFromFrame(
211 content_settings_type_, rfh);
213 case content::PermissionStatusSource::PORTAL:
214 case content::PermissionStatusSource::FENCED_FRAME:
215 case content::PermissionStatusSource::INSECURE_ORIGIN:
216 case content::PermissionStatusSource::VIRTUAL_URL_DIFFERENT_ORIGIN:
220 // If we are under embargo, record the embargo reason for which we have
221 // suppressed the prompt.
222 PermissionUmaUtil::RecordEmbargoPromptSuppressionFromSource(result.source);
224 request_data.id, request_data.requesting_origin,
225 request_data.embedding_origin, std::move(callback),
227 PermissionUtil::PermissionStatusToContentSetting(result.status),
228 /*is_one_time=*/false,
229 /*is_final_decision=*/true);
233 PermissionUmaUtil::RecordPermissionRequestedFromFrame(content_settings_type_,
236 // We are going to show a prompt now.
237 PermissionUmaUtil::PermissionRequested(content_settings_type_);
238 PermissionUmaUtil::RecordEmbargoPromptSuppression(
239 PermissionEmbargoStatus::NOT_EMBARGOED);
241 DecidePermission(std::move(request_data), std::move(callback));
244 bool PermissionContextBase::IsRestrictedToSecureOrigins() const {
248 void PermissionContextBase::UserMadePermissionDecision(
249 const PermissionRequestID& id,
250 const GURL& requesting_origin,
251 const GURL& embedding_origin,
252 ContentSetting content_setting) {}
254 std::unique_ptr<PermissionRequest>
255 PermissionContextBase::CreatePermissionRequest(
256 content::WebContents* web_contents,
257 PermissionRequestData request_data,
258 PermissionRequest::PermissionDecidedCallback permission_decided_callback,
259 base::OnceClosure delete_callback) const {
260 return std::make_unique<PermissionRequest>(
261 std::move(request_data), std::move(permission_decided_callback),
262 std::move(delete_callback));
265 content::PermissionResult PermissionContextBase::GetPermissionStatus(
266 content::RenderFrameHost* render_frame_host,
267 const GURL& requesting_origin,
268 const GURL& embedding_origin) const {
269 // If the permission has been disabled through Finch, block all requests.
270 if (IsPermissionKillSwitchOn()) {
271 return content::PermissionResult(
272 PermissionStatus::DENIED, content::PermissionStatusSource::KILL_SWITCH);
275 if (!IsPermissionAvailableToOrigins(requesting_origin, embedding_origin)) {
276 return content::PermissionResult(
277 PermissionStatus::DENIED,
278 content::PermissionStatusSource::INSECURE_ORIGIN);
281 // Check whether the feature is enabled for the frame by permissions policy.
282 // We can only do this when a RenderFrameHost has been provided.
283 if (render_frame_host &&
284 !PermissionAllowedByPermissionsPolicy(render_frame_host)) {
285 return content::PermissionResult(
286 PermissionStatus::DENIED,
287 content::PermissionStatusSource::FEATURE_POLICY);
290 if (render_frame_host) {
291 content::WebContents* web_contents =
292 content::WebContents::FromRenderFrameHost(render_frame_host);
294 // Automatically deny all HTTP or HTTPS requests where the virtual URL and
295 // the loaded URL are for different origins. The loaded URL is the one
296 // actually in the renderer, but the virtual URL is the one
297 // seen by the user. This may be very confusing for a user to see in a
298 // permissions request.
299 content::NavigationEntry* entry =
300 web_contents->GetController().GetLastCommittedEntry();
302 const GURL virtual_url = entry->GetVirtualURL();
303 const GURL loaded_url = entry->GetURL();
304 if (virtual_url.SchemeIsHTTPOrHTTPS() &&
305 loaded_url.SchemeIsHTTPOrHTTPS() &&
306 !url::IsSameOriginWith(virtual_url, loaded_url)) {
307 return content::PermissionResult(
308 PermissionStatus::DENIED,
309 content::PermissionStatusSource::VIRTUAL_URL_DIFFERENT_ORIGIN);
314 #if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
315 // Some GuestViews are loaded in a separate StoragePartition. Given that
316 // permissions are scoped to a BrowserContext, not a StoragePartition, we may
317 // have a situation where a user has granted a permission to an origin in a
318 // tab and then visits the same origin in a guest. This would lead to
319 // inappropriate sharing of the permission with the guest. To mitigate this,
320 // we drop permission requests from guests for cases where it's not possible
321 // for the guest to have been granted the permission. Note that sharing of
322 // permissions that the guest could legitimately be granted is still possible.
323 // TODO(crbug.com/1469672): Scope granted permissions to a StoragePartition.
324 if (base::FeatureList::IsEnabled(
325 features::kMitigateUnpartitionedWebviewPermissions)) {
326 guest_view::GuestViewBase* guest =
327 guest_view::GuestViewBase::FromRenderFrameHost(render_frame_host);
328 if (guest && !guest->IsPermissionRequestable(content_settings_type_)) {
329 return content::PermissionResult(
330 PermissionStatus::DENIED,
331 content::PermissionStatusSource::UNSPECIFIED);
336 ContentSetting content_setting = GetPermissionStatusInternal(
337 render_frame_host, requesting_origin, embedding_origin);
339 if (content_setting != CONTENT_SETTING_ASK) {
340 return content::PermissionResult(
341 PermissionUtil::ContentSettingToPermissionStatus(content_setting),
342 content::PermissionStatusSource::UNSPECIFIED);
345 absl::optional<content::PermissionResult> result =
346 PermissionsClient::Get()
347 ->GetPermissionDecisionAutoBlocker(browser_context_)
348 ->GetEmbargoResult(requesting_origin, content_settings_type_);
350 DCHECK(result->status == PermissionStatus::DENIED);
351 return result.value();
353 return content::PermissionResult(
354 PermissionStatus::ASK, content::PermissionStatusSource::UNSPECIFIED);
357 bool PermissionContextBase::IsPermissionAvailableToOrigins(
358 const GURL& requesting_origin,
359 const GURL& embedding_origin) const {
360 if (IsRestrictedToSecureOrigins()) {
361 if (!network::IsUrlPotentiallyTrustworthy(requesting_origin))
364 // TODO(raymes): We should check the entire chain of embedders here whenever
365 // possible as this corresponds to the requirements of the secure contexts
366 // spec and matches what is implemented in blink. Right now we just check
367 // the top level and requesting origins.
368 if (!PermissionsClient::Get()->CanBypassEmbeddingOriginCheck(
369 requesting_origin, embedding_origin) &&
370 !network::IsUrlPotentiallyTrustworthy(embedding_origin)) {
377 content::PermissionResult
378 PermissionContextBase::UpdatePermissionStatusWithDeviceStatus(
379 content::PermissionResult result,
380 const GURL& requesting_origin,
381 const GURL& embedding_origin) const {
382 const bool has_device_permission =
383 PermissionsClient::Get()->HasDevicePermission(content_settings_type());
384 const bool should_notify_observers =
385 last_has_device_permission_result_.has_value() &&
386 has_device_permission != last_has_device_permission_result_;
388 // We need to update |last_has_device_permission_result_| before calling
389 // |OnContentSettingChanged| to avoid causing a re-entrancy issue since the
390 // |OnContentSettingChanged| will likely end up calling |GetPermissionStatus|.
391 last_has_device_permission_result_ = has_device_permission;
393 if (should_notify_observers) {
394 NotifyObservers(ContentSettingsPattern::Wildcard(),
395 ContentSettingsPattern::Wildcard(),
396 ContentSettingsTypeSet(content_settings_type()));
399 // If the site content setting is ASK/BLOCKED the device-level permission
401 if (result.status != blink::mojom::PermissionStatus::GRANTED) {
405 // If the device-level permission is granted, it has no effect on the result.
406 if (has_device_permission) {
410 // Otherwise the result will be "ASK" if the browser can ask for the
411 // device-level permission, and "BLOCKED" otherwise.
412 result.status = PermissionsClient::Get()->CanRequestDevicePermission(
413 content_settings_type())
414 ? blink::mojom::PermissionStatus::ASK
415 : blink::mojom::PermissionStatus::DENIED;
420 void PermissionContextBase::ResetPermission(const GURL& requesting_origin,
421 const GURL& embedding_origin) {
422 if (!content_settings::ContentSettingsRegistry::GetInstance()->Get(
423 content_settings_type_)) {
426 PermissionsClient::Get()
427 ->GetSettingsMap(browser_context_)
428 ->SetContentSettingDefaultScope(requesting_origin, embedding_origin,
429 content_settings_type_,
430 CONTENT_SETTING_DEFAULT);
433 bool PermissionContextBase::IsPermissionKillSwitchOn() const {
434 const std::string param = base::GetFieldTrialParamValue(
435 kPermissionsKillSwitchFieldStudy,
436 PermissionUtil::GetPermissionString(content_settings_type_));
438 return param == kPermissionsKillSwitchBlockedValue;
441 ContentSetting PermissionContextBase::GetPermissionStatusInternal(
442 content::RenderFrameHost* render_frame_host,
443 const GURL& requesting_origin,
444 const GURL& embedding_origin) const {
445 return PermissionsClient::Get()
446 ->GetSettingsMap(browser_context_)
447 ->GetContentSetting(requesting_origin, embedding_origin,
448 content_settings_type_);
451 void PermissionContextBase::DecidePermission(
452 PermissionRequestData request_data,
453 BrowserPermissionCallback callback) {
454 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
456 // Under permission delegation, when we display a permission prompt, the
457 // origin displayed in the prompt should never differ from the top-level
458 // origin. Storage access API requests are excluded as they are expected to
459 // request permissions from the frame origin needing access.
460 DCHECK(PermissionsClient::Get()->CanBypassEmbeddingOriginCheck(
461 request_data.requesting_origin, request_data.embedding_origin) ||
462 request_data.requesting_origin == request_data.embedding_origin ||
463 content_settings_type_ == ContentSettingsType::STORAGE_ACCESS);
465 content::RenderFrameHost* rfh = content::RenderFrameHost::FromID(
466 request_data.id.global_render_frame_host_id());
469 content::WebContents* web_contents =
470 content::WebContents::FromRenderFrameHost(rfh);
471 PermissionRequestManager* permission_request_manager =
472 PermissionRequestManager::FromWebContents(web_contents);
473 // TODO(felt): sometimes |permission_request_manager| is null. This check is
474 // meant to prevent crashes. See crbug.com/457091.
475 if (!permission_request_manager) {
476 std::move(callback).Run(CONTENT_SETTING_ASK);
480 auto decided_cb = base::BindRepeating(
481 &PermissionContextBase::PermissionDecided, weak_factory_.GetWeakPtr(),
482 request_data.id, request_data.requesting_origin,
483 request_data.embedding_origin);
484 auto cleanup_cb = base::BindOnce(&PermissionContextBase::CleanUpRequest,
485 weak_factory_.GetWeakPtr(), request_data.id);
486 PermissionRequestID permission_request_id = request_data.id;
488 std::unique_ptr<PermissionRequest> request_ptr =
489 CreatePermissionRequest(web_contents, std::move(request_data),
490 std::move(decided_cb), std::move(cleanup_cb));
491 PermissionRequest* request = request_ptr.get();
495 .insert(std::make_pair(
496 permission_request_id.ToString(),
497 std::make_pair(std::move(request_ptr), std::move(callback))))
499 DCHECK(inserted) << "Duplicate id " << permission_request_id.ToString();
501 permission_request_manager->AddRequest(rfh, request);
504 void PermissionContextBase::PermissionDecided(const PermissionRequestID& id,
505 const GURL& requesting_origin,
506 const GURL& embedding_origin,
507 ContentSetting content_setting,
509 bool is_final_decision) {
510 DCHECK(content_setting == CONTENT_SETTING_ALLOW ||
511 content_setting == CONTENT_SETTING_BLOCK ||
512 content_setting == CONTENT_SETTING_DEFAULT);
513 UserMadePermissionDecision(id, requesting_origin, embedding_origin,
516 bool persist = content_setting != CONTENT_SETTING_DEFAULT;
518 auto request = pending_requests_.find(id.ToString());
519 DCHECK(request != pending_requests_.end());
520 // Check if `request` has `BrowserPermissionCallback`. The call back might be
521 // missing if a permission prompt was preignored and we already notified an
523 if (request->second.second) {
524 NotifyPermissionSet(id, requesting_origin, embedding_origin,
525 std::move(request->second.second), persist,
526 content_setting, is_one_time, is_final_decision);
528 NotifyPermissionSet(id, requesting_origin, embedding_origin,
529 base::DoNothing(), persist, content_setting,
530 is_one_time, is_final_decision);
534 content::BrowserContext* PermissionContextBase::browser_context() const {
535 return browser_context_;
538 void PermissionContextBase::OnContentSettingChanged(
539 const ContentSettingsPattern& primary_pattern,
540 const ContentSettingsPattern& secondary_pattern,
541 ContentSettingsTypeSet content_type_set) {
542 NotifyObservers(primary_pattern, secondary_pattern, content_type_set);
545 void PermissionContextBase::AddObserver(
546 permissions::Observer* permission_observer) {
547 if (permission_observers_.empty() &&
548 !content_setting_observer_registered_by_subclass_) {
549 PermissionsClient::Get()
550 ->GetSettingsMap(browser_context_)
553 permission_observers_.AddObserver(permission_observer);
556 void PermissionContextBase::RemoveObserver(
557 permissions::Observer* permission_observer) {
558 permission_observers_.RemoveObserver(permission_observer);
559 if (permission_observers_.empty() &&
560 !content_setting_observer_registered_by_subclass_) {
561 PermissionsClient::Get()
562 ->GetSettingsMap(browser_context_)
563 ->RemoveObserver(this);
567 void PermissionContextBase::NotifyPermissionSet(
568 const PermissionRequestID& id,
569 const GURL& requesting_origin,
570 const GURL& embedding_origin,
571 BrowserPermissionCallback callback,
573 ContentSetting content_setting,
575 bool is_final_decision) {
576 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
579 UpdateContentSetting(requesting_origin, embedding_origin, content_setting,
583 if (is_final_decision) {
584 UpdateTabContext(id, requesting_origin,
585 content_setting == CONTENT_SETTING_ALLOW);
586 if (content_setting == CONTENT_SETTING_ALLOW) {
587 if (auto* rfh = content::RenderFrameHost::FromID(
588 id.global_render_frame_host_id())) {
589 PermissionUmaUtil::RecordPermissionsUsageSourceAndPolicyConfiguration(
590 content_settings_type_, rfh);
595 if (content_setting == CONTENT_SETTING_DEFAULT)
596 content_setting = CONTENT_SETTING_ASK;
598 std::move(callback).Run(content_setting);
601 void PermissionContextBase::CleanUpRequest(const PermissionRequestID& id) {
602 size_t success = pending_requests_.erase(id.ToString());
603 DCHECK(success == 1) << "Missing request " << id.ToString();
606 void PermissionContextBase::UpdateContentSetting(const GURL& requesting_origin,
607 const GURL& embedding_origin,
608 ContentSetting content_setting,
610 DCHECK_EQ(requesting_origin, requesting_origin.DeprecatedGetOriginAsURL());
611 DCHECK_EQ(embedding_origin, embedding_origin.DeprecatedGetOriginAsURL());
612 DCHECK(content_setting == CONTENT_SETTING_ALLOW ||
613 content_setting == CONTENT_SETTING_BLOCK);
615 content_settings::ContentSettingConstraints constraints;
616 constraints.set_session_model(is_one_time
617 ? content_settings::SessionModel::OneTime
618 : content_settings::SessionModel::Durable);
620 #if !BUILDFLAG(IS_ANDROID)
621 if (base::FeatureList::IsEnabled(
622 features::kRecordPermissionExpirationTimestamps)) {
623 // The Permissions module in Safety check will revoke permissions after
624 // a finite amount of time if the permission can be revoked.
625 if (content_settings::CanBeAutoRevoked(content_settings_type_,
626 content_setting, is_one_time)) {
627 // For #2, by definition, that should be all of them. If that changes in
628 // the future, consider whether revocation for such permission makes
629 // sense, and/or change this to an early return so that we don't
630 // unnecessarily record timestamps where we don't need them.
631 constraints.set_track_last_visit_for_autoexpiration(true);
634 #endif // !BUILDFLAG(IS_ANDROID)
636 if (base::FeatureList::IsEnabled(permissions::features::kOneTimePermission) &&
638 if (base::FeatureList::IsEnabled(
639 content_settings::features::kActiveContentSettingExpiry)) {
640 constraints.set_lifetime(kOneTimePermissionMaximumLifetime);
644 PermissionsClient::Get()
645 ->GetSettingsMap(browser_context_)
646 ->SetContentSettingDefaultScope(requesting_origin, embedding_origin,
647 content_settings_type_, content_setting,
651 bool PermissionContextBase::PermissionAllowedByPermissionsPolicy(
652 content::RenderFrameHost* rfh) const {
653 // Some features don't have an associated permissions policy yet. Allow those.
654 if (permissions_policy_feature_ ==
655 blink::mojom::PermissionsPolicyFeature::kNotFound)
658 return rfh->IsFeatureEnabled(permissions_policy_feature_);
661 void PermissionContextBase::NotifyObservers(
662 const ContentSettingsPattern& primary_pattern,
663 const ContentSettingsPattern& secondary_pattern,
664 ContentSettingsTypeSet content_type_set) const {
665 if (!content_type_set.Contains(content_settings_type_)) {
669 for (permissions::Observer& obs : permission_observers_) {
670 obs.OnPermissionChanged(primary_pattern, secondary_pattern,
675 } // namespace permissions