Fix emulator build error
[platform/framework/web/chromium-efl.git] / components / permissions / permission_context_base.cc
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.
4
5 #include "components/permissions/permission_context_base.h"
6
7 #include <stddef.h>
8
9 #include <string>
10 #include <utility>
11
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"
45 #include "url/gurl.h"
46
47 #if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
48 #include "components/guest_view/browser/guest_view_base.h"
49 #endif
50
51 namespace permissions {
52 namespace {
53
54 using PermissionStatus = blink::mojom::PermissionStatus;
55
56 const char kPermissionBlockedKillSwitchMessage[] =
57     "%s permission has been blocked.";
58
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 "
64     "information.";
65
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 "
70     "information.";
71 #else
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 "
77     "information.";
78
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 "
84     "information.";
85 #endif
86
87 const char kPermissionBlockedRecentDisplayMessage[] =
88     "%s permission has been blocked as the prompt has already been displayed "
89     "to the user recently.";
90
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.";
94
95 void LogPermissionBlockedMessage(content::RenderFrameHost* rfh,
96                                  const char* message,
97                                  ContentSettingsType type) {
98   rfh->GetOutermostMainFrame()->AddMessageToConsole(
99       blink::mojom::ConsoleMessageLevel::kWarning,
100       base::StringPrintfNonConstexpr(
101           message, PermissionUtil::GetPermissionString(type).c_str()));
102 }
103
104 }  // namespace
105
106 // static
107 const char PermissionContextBase::kPermissionsKillSwitchFieldStudy[] =
108     "PermissionsKillSwitch";
109 // static
110 const char PermissionContextBase::kPermissionsKillSwitchBlockedValue[] =
111     "blocked";
112
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();
122 }
123
124 PermissionContextBase::~PermissionContextBase() {
125   DCHECK(permission_observers_.empty());
126   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
127 }
128
129 void PermissionContextBase::RequestPermission(
130     PermissionRequestData request_data,
131     BrowserPermissionCallback callback) {
132   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
133
134   content::RenderFrameHost* const rfh = content::RenderFrameHost::FromID(
135       request_data.id.global_render_frame_host_id());
136
137   if (!rfh) {
138     // Permission request is not allowed without a valid RenderFrameHost.
139     std::move(callback).Run(CONTENT_SETTING_ASK);
140     return;
141   }
142
143   request_data
144       .WithRequestingOrigin(
145           request_data.requesting_origin.DeprecatedGetOriginAsURL())
146       .WithEmbeddingOrigin(
147           PermissionUtil::GetLastCommittedOriginAsURL(rfh->GetMainFrame()));
148
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_);
153
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);
163     return;
164   }
165
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.
168   DCHECK(rfh);
169   content::PermissionResult result = GetPermissionStatus(
170       rfh, request_data.requesting_origin, request_data.embedding_origin);
171
172   bool status_ignorable = PermissionUtil::CanPermissionRequestIgnoreStatus(
173       request_data, result.source);
174
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);
185         return;
186       case content::PermissionStatusSource::MULTIPLE_DISMISSALS:
187         LogPermissionBlockedMessage(rfh,
188                                     kPermissionBlockedRepeatedDismissalsMessage,
189                                     content_settings_type_);
190         PermissionUmaUtil::RecordPermissionRequestedFromFrame(
191             content_settings_type_, rfh);
192         break;
193       case content::PermissionStatusSource::MULTIPLE_IGNORES:
194         LogPermissionBlockedMessage(rfh,
195                                     kPermissionBlockedRepeatedIgnoresMessage,
196                                     content_settings_type_);
197         PermissionUmaUtil::RecordPermissionRequestedFromFrame(
198             content_settings_type_, rfh);
199         break;
200       case content::PermissionStatusSource::FEATURE_POLICY:
201         LogPermissionBlockedMessage(rfh,
202                                     kPermissionBlockedPermissionsPolicyMessage,
203                                     content_settings_type_);
204         break;
205       case content::PermissionStatusSource::RECENT_DISPLAY:
206         LogPermissionBlockedMessage(rfh, kPermissionBlockedRecentDisplayMessage,
207                                     content_settings_type_);
208         break;
209       case content::PermissionStatusSource::UNSPECIFIED:
210         PermissionUmaUtil::RecordPermissionRequestedFromFrame(
211             content_settings_type_, rfh);
212         break;
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:
217         break;
218     }
219
220     // If we are under embargo, record the embargo reason for which we have
221     // suppressed the prompt.
222     PermissionUmaUtil::RecordEmbargoPromptSuppressionFromSource(result.source);
223     NotifyPermissionSet(
224         request_data.id, request_data.requesting_origin,
225         request_data.embedding_origin, std::move(callback),
226         /*persist=*/false,
227         PermissionUtil::PermissionStatusToContentSetting(result.status),
228         /*is_one_time=*/false,
229         /*is_final_decision=*/true);
230     return;
231   }
232
233   PermissionUmaUtil::RecordPermissionRequestedFromFrame(content_settings_type_,
234                                                         rfh);
235
236   // We are going to show a prompt now.
237   PermissionUmaUtil::PermissionRequested(content_settings_type_);
238   PermissionUmaUtil::RecordEmbargoPromptSuppression(
239       PermissionEmbargoStatus::NOT_EMBARGOED);
240
241   DecidePermission(std::move(request_data), std::move(callback));
242 }
243
244 bool PermissionContextBase::IsRestrictedToSecureOrigins() const {
245   return true;
246 }
247
248 void PermissionContextBase::UserMadePermissionDecision(
249     const PermissionRequestID& id,
250     const GURL& requesting_origin,
251     const GURL& embedding_origin,
252     ContentSetting content_setting) {}
253
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));
263 }
264
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);
273   }
274
275   if (!IsPermissionAvailableToOrigins(requesting_origin, embedding_origin)) {
276     return content::PermissionResult(
277         PermissionStatus::DENIED,
278         content::PermissionStatusSource::INSECURE_ORIGIN);
279   }
280
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);
288   }
289
290   if (render_frame_host) {
291     content::WebContents* web_contents =
292         content::WebContents::FromRenderFrameHost(render_frame_host);
293
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();
301     if (entry) {
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);
310       }
311     }
312   }
313
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);
332     }
333   }
334 #endif
335
336   ContentSetting content_setting = GetPermissionStatusInternal(
337       render_frame_host, requesting_origin, embedding_origin);
338
339   if (content_setting != CONTENT_SETTING_ASK) {
340     return content::PermissionResult(
341         PermissionUtil::ContentSettingToPermissionStatus(content_setting),
342         content::PermissionStatusSource::UNSPECIFIED);
343   }
344
345   absl::optional<content::PermissionResult> result =
346       PermissionsClient::Get()
347           ->GetPermissionDecisionAutoBlocker(browser_context_)
348           ->GetEmbargoResult(requesting_origin, content_settings_type_);
349   if (result) {
350     DCHECK(result->status == PermissionStatus::DENIED);
351     return result.value();
352   }
353   return content::PermissionResult(
354       PermissionStatus::ASK, content::PermissionStatusSource::UNSPECIFIED);
355 }
356
357 bool PermissionContextBase::IsPermissionAvailableToOrigins(
358     const GURL& requesting_origin,
359     const GURL& embedding_origin) const {
360   if (IsRestrictedToSecureOrigins()) {
361     if (!network::IsUrlPotentiallyTrustworthy(requesting_origin))
362       return false;
363
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)) {
371       return false;
372     }
373   }
374   return true;
375 }
376
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_;
387
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;
392
393   if (should_notify_observers) {
394     NotifyObservers(ContentSettingsPattern::Wildcard(),
395                     ContentSettingsPattern::Wildcard(),
396                     ContentSettingsTypeSet(content_settings_type()));
397   }
398
399   // If the site content setting is ASK/BLOCKED the device-level permission
400   // won't affect it.
401   if (result.status != blink::mojom::PermissionStatus::GRANTED) {
402     return result;
403   }
404
405   // If the device-level permission is granted, it has no effect on the result.
406   if (has_device_permission) {
407     return result;
408   }
409
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;
416
417   return result;
418 }
419
420 void PermissionContextBase::ResetPermission(const GURL& requesting_origin,
421                                             const GURL& embedding_origin) {
422   if (!content_settings::ContentSettingsRegistry::GetInstance()->Get(
423           content_settings_type_)) {
424     return;
425   }
426   PermissionsClient::Get()
427       ->GetSettingsMap(browser_context_)
428       ->SetContentSettingDefaultScope(requesting_origin, embedding_origin,
429                                       content_settings_type_,
430                                       CONTENT_SETTING_DEFAULT);
431 }
432
433 bool PermissionContextBase::IsPermissionKillSwitchOn() const {
434   const std::string param = base::GetFieldTrialParamValue(
435       kPermissionsKillSwitchFieldStudy,
436       PermissionUtil::GetPermissionString(content_settings_type_));
437
438   return param == kPermissionsKillSwitchBlockedValue;
439 }
440
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_);
449 }
450
451 void PermissionContextBase::DecidePermission(
452     PermissionRequestData request_data,
453     BrowserPermissionCallback callback) {
454   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
455
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);
464
465   content::RenderFrameHost* rfh = content::RenderFrameHost::FromID(
466       request_data.id.global_render_frame_host_id());
467   DCHECK(rfh);
468
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);
477     return;
478   }
479
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;
487
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();
492
493   bool inserted =
494       pending_requests_
495           .insert(std::make_pair(
496               permission_request_id.ToString(),
497               std::make_pair(std::move(request_ptr), std::move(callback))))
498           .second;
499   DCHECK(inserted) << "Duplicate id " << permission_request_id.ToString();
500
501   permission_request_manager->AddRequest(rfh, request);
502 }
503
504 void PermissionContextBase::PermissionDecided(const PermissionRequestID& id,
505                                               const GURL& requesting_origin,
506                                               const GURL& embedding_origin,
507                                               ContentSetting content_setting,
508                                               bool is_one_time,
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,
514                              content_setting);
515
516   bool persist = content_setting != CONTENT_SETTING_DEFAULT;
517
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
522   // origin about it.
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);
527   } else {
528     NotifyPermissionSet(id, requesting_origin, embedding_origin,
529                         base::DoNothing(), persist, content_setting,
530                         is_one_time, is_final_decision);
531   }
532 }
533
534 content::BrowserContext* PermissionContextBase::browser_context() const {
535   return browser_context_;
536 }
537
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);
543 }
544
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_)
551         ->AddObserver(this);
552   }
553   permission_observers_.AddObserver(permission_observer);
554 }
555
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);
564   }
565 }
566
567 void PermissionContextBase::NotifyPermissionSet(
568     const PermissionRequestID& id,
569     const GURL& requesting_origin,
570     const GURL& embedding_origin,
571     BrowserPermissionCallback callback,
572     bool persist,
573     ContentSetting content_setting,
574     bool is_one_time,
575     bool is_final_decision) {
576   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
577
578   if (persist) {
579     UpdateContentSetting(requesting_origin, embedding_origin, content_setting,
580                          is_one_time);
581   }
582
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);
591       }
592     }
593   }
594
595   if (content_setting == CONTENT_SETTING_DEFAULT)
596     content_setting = CONTENT_SETTING_ASK;
597
598   std::move(callback).Run(content_setting);
599 }
600
601 void PermissionContextBase::CleanUpRequest(const PermissionRequestID& id) {
602   size_t success = pending_requests_.erase(id.ToString());
603   DCHECK(success == 1) << "Missing request " << id.ToString();
604 }
605
606 void PermissionContextBase::UpdateContentSetting(const GURL& requesting_origin,
607                                                  const GURL& embedding_origin,
608                                                  ContentSetting content_setting,
609                                                  bool is_one_time) {
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);
614
615   content_settings::ContentSettingConstraints constraints;
616   constraints.set_session_model(is_one_time
617                                     ? content_settings::SessionModel::OneTime
618                                     : content_settings::SessionModel::Durable);
619
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);
632     }
633   }
634 #endif  // !BUILDFLAG(IS_ANDROID)
635
636   if (base::FeatureList::IsEnabled(permissions::features::kOneTimePermission) &&
637       is_one_time) {
638     if (base::FeatureList::IsEnabled(
639             content_settings::features::kActiveContentSettingExpiry)) {
640       constraints.set_lifetime(kOneTimePermissionMaximumLifetime);
641     }
642   }
643
644   PermissionsClient::Get()
645       ->GetSettingsMap(browser_context_)
646       ->SetContentSettingDefaultScope(requesting_origin, embedding_origin,
647                                       content_settings_type_, content_setting,
648                                       constraints);
649 }
650
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)
656     return true;
657
658   return rfh->IsFeatureEnabled(permissions_policy_feature_);
659 }
660
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_)) {
666     return;
667   }
668
669   for (permissions::Observer& obs : permission_observers_) {
670     obs.OnPermissionChanged(primary_pattern, secondary_pattern,
671                             content_type_set);
672   }
673 }
674
675 }  // namespace permissions