Fix emulator build error
[platform/framework/web/chromium-efl.git] / components / permissions / permission_request_manager.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_request_manager.h"
6
7 #include <string>
8
9 #include "base/auto_reset.h"
10 #include "base/command_line.h"
11 #include "base/containers/contains.h"
12 #include "base/functional/bind.h"
13 #include "base/metrics/histogram_functions.h"
14 #include "base/metrics/user_metrics.h"
15 #include "base/metrics/user_metrics_action.h"
16 #include "base/observer_list.h"
17 #include "base/rand_util.h"
18 #include "base/ranges/algorithm.h"
19 #include "base/task/sequenced_task_runner.h"
20 #include "base/time/clock.h"
21 #include "base/time/time.h"
22 #include "components/back_forward_cache/back_forward_cache_disable.h"
23 #include "components/permissions/constants.h"
24 #include "components/permissions/features.h"
25 #include "components/permissions/origin_keyed_permission_action_service.h"
26 #include "components/permissions/permission_decision_auto_blocker.h"
27 #include "components/permissions/permission_prompt.h"
28 #include "components/permissions/permission_request.h"
29 #include "components/permissions/permission_uma_util.h"
30 #include "components/permissions/permission_util.h"
31 #include "components/permissions/permissions_client.h"
32 #include "components/permissions/request_type.h"
33 #include "components/permissions/switches.h"
34 #include "content/public/browser/back_forward_cache.h"
35 #include "content/public/browser/browser_context.h"
36 #include "content/public/browser/browser_task_traits.h"
37 #include "content/public/browser/browser_thread.h"
38 #include "content/public/browser/disallow_activation_reason.h"
39 #include "content/public/browser/navigation_handle.h"
40 #include "content/public/browser/render_frame_host.h"
41 #include "content/public/browser/render_process_host.h"
42 #include "content/public/browser/web_contents.h"
43 #include "ui/base/window_open_disposition_utils.h"
44 #include "ui/events/event.h"
45 #include "url/gurl.h"
46 #include "url/origin.h"
47
48 #if BUILDFLAG(IS_ANDROID)
49 #include "components/permissions/android/android_permission_util.h"
50 #endif
51
52 namespace permissions {
53
54 const char kAbusiveNotificationRequestsEnforcementMessage[] =
55     "Chrome is blocking notification permission requests on this site because "
56     "the site tends to show permission requests that mislead, trick, or force "
57     "users into allowing notifications. You should fix the issues as soon as "
58     "possible and submit your site for another review. Learn more at "
59     "https://support.google.com/webtools/answer/9799048.";
60
61 const char kAbusiveNotificationRequestsWarningMessage[] =
62     "Chrome might start blocking notification permission requests on this site "
63     "in the future because the site tends to show permission requests that "
64     "mislead, trick, or force users into allowing notifications. You should "
65     "fix the issues as soon as possible and submit your site for another "
66     "review. Learn more at https://support.google.com/webtools/answer/9799048.";
67
68 constexpr char kAbusiveNotificationContentEnforcementMessage[] =
69     "Chrome is blocking notification permission requests on this site because "
70     "the site tends to show notifications with content that mislead or trick "
71     "users. You should fix the issues as soon as possible and submit your site "
72     "for another review. Learn more at "
73     "https://support.google.com/webtools/answer/9799048";
74
75 constexpr char kAbusiveNotificationContentWarningMessage[] =
76     "Chrome might start blocking notification permission requests on this site "
77     "in the future because the site tends to show notifications with content "
78     "that mislead or trick users. You should fix the issues as soon as "
79     "possible and submit your site for another review. Learn more at "
80     "https://support.google.com/webtools/answer/9799048";
81
82 constexpr char kDisruptiveNotificationBehaviorEnforcementMessage[] =
83     "Chrome is blocking notification permission requests on this site because "
84     "the site exhibits behaviors that may be disruptive to users.";
85
86 namespace {
87
88 // In case of multiple permission requests that use chip UI, a newly added
89 // request will preempt the currently showing request, which is put back to the
90 // queue, and will be shown later. To reduce user annoyance, if a quiet chip
91 // permission prompt was displayed longer than `kQuietChipIgnoreTimeout`, we
92 // consider it as shown long enough and it will not be shown again after it is
93 // preempted.
94 // TODO(crbug.com/1221083): If a user switched tabs, do not include that time as
95 // "shown".
96 bool ShouldShowQuietRequestAgainIfPreempted(
97     absl::optional<base::Time> request_display_start_time) {
98   if (request_display_start_time->is_null()) {
99     return true;
100   }
101
102   static constexpr base::TimeDelta kQuietChipIgnoreTimeout = base::Seconds(8.5);
103   return base::Time::Now() - request_display_start_time.value() <
104          kQuietChipIgnoreTimeout;
105 }
106
107 bool IsMediaRequest(RequestType type) {
108 #if !BUILDFLAG(IS_ANDROID)
109   if (type == RequestType::kCameraPanTiltZoom)
110     return true;
111 #endif
112   return type == RequestType::kMicStream || type == RequestType::kCameraStream;
113 }
114
115 bool ShouldGroupRequests(PermissionRequest* a, PermissionRequest* b) {
116   if (a->requesting_origin() != b->requesting_origin())
117     return false;
118
119   // Group if both requests are media requests.
120   if (IsMediaRequest(a->request_type()) && IsMediaRequest(b->request_type())) {
121     return true;
122   }
123
124   return false;
125 }
126
127 }  // namespace
128
129 // PermissionRequestManager ----------------------------------------------------
130
131 bool PermissionRequestManager::PermissionRequestSource::
132     IsSourceFrameInactiveAndDisallowActivation() const {
133   content::RenderFrameHost* rfh =
134       content::RenderFrameHost::FromID(requesting_frame_id);
135   return !rfh ||
136          rfh->IsInactiveAndDisallowActivation(
137              content::DisallowActivationReasonId::kPermissionRequestSource);
138 }
139
140 PermissionRequestManager::~PermissionRequestManager() {
141   DCHECK(!IsRequestInProgress());
142   DCHECK(duplicate_requests_.empty());
143   DCHECK(pending_permission_requests_.IsEmpty());
144
145   for (Observer& observer : observer_list_)
146     observer.OnPermissionRequestManagerDestructed();
147 }
148
149 void PermissionRequestManager::AddRequest(
150     content::RenderFrameHost* source_frame,
151     PermissionRequest* request) {
152   DCHECK(source_frame);
153   DCHECK_EQ(content::WebContents::FromRenderFrameHost(source_frame),
154             web_contents());
155
156   if (base::CommandLine::ForCurrentProcess()->HasSwitch(
157           switches::kDenyPermissionPrompts)) {
158     request->PermissionDenied();
159     request->RequestFinished();
160     return;
161   }
162
163   if (source_frame->IsInactiveAndDisallowActivation(
164           content::DisallowActivationReasonId::kPermissionAddRequest)) {
165     request->Cancelled();
166     request->RequestFinished();
167     return;
168   }
169
170   if (source_frame->IsNestedWithinFencedFrame()) {
171     request->Cancelled();
172     request->RequestFinished();
173     return;
174   }
175
176 #if BUILDFLAG(IS_ANDROID)
177   if (request->GetContentSettingsType() == ContentSettingsType::NOTIFICATIONS) {
178     bool app_level_settings_allow_site_notifications =
179         enabled_app_level_notification_permission_for_testing_.has_value()
180             ? enabled_app_level_notification_permission_for_testing_.value()
181             : DoesAppLevelSettingsAllowSiteNotifications();
182     base::UmaHistogramBoolean(
183         "Permissions.Prompt.Notifications.EnabledAppLevel",
184         app_level_settings_allow_site_notifications);
185
186     if (!app_level_settings_allow_site_notifications &&
187         base::FeatureList::IsEnabled(
188             features::kBlockNotificationPromptsIfDisabledOnAppLevel)) {
189       // Automatically cancel site Notification requests when Chrome is not able
190       // to send notifications in an app level.
191       request->Cancelled();
192       request->RequestFinished();
193       return;
194     }
195   }
196 #endif  // BUILDFLAG(IS_ANDROID)
197
198   if (is_notification_prompt_cooldown_active_ &&
199       request->GetContentSettingsType() == ContentSettingsType::NOTIFICATIONS) {
200     // Short-circuit by canceling rather than denying to avoid creating a large
201     // number of content setting exceptions on Desktop / disabled notification
202     // channels on Android.
203     request->Cancelled();
204     request->RequestFinished();
205     return;
206   }
207
208   if (!web_contents_supports_permission_requests_) {
209     request->Cancelled();
210     request->RequestFinished();
211     return;
212   }
213
214   // TODO(tsergeant): change the UMA to no longer mention bubble.
215   base::RecordAction(base::UserMetricsAction("PermissionBubbleRequest"));
216
217   // TODO(gbillock): is there a race between an early request on a
218   // newly-navigated page and the to-be-cleaned-up requests on the previous
219   // page? We should maybe listen to DidStartNavigationToPendingEntry (and
220   // any other renderer-side nav initiations?). Double-check this for
221   // correct behavior on interstitials -- we probably want to basically queue
222   // any request for which GetVisibleURL != GetLastCommittedURL.
223   CHECK(source_frame->GetMainFrame()->IsInPrimaryMainFrame());
224   const GURL main_frame_origin =
225       PermissionUtil::GetLastCommittedOriginAsURL(source_frame->GetMainFrame());
226   bool is_main_frame =
227       url::IsSameOriginWith(main_frame_origin, request->requesting_origin());
228
229   absl::optional<url::Origin> auto_approval_origin =
230       PermissionsClient::Get()->GetAutoApprovalOrigin();
231   if (auto_approval_origin) {
232     if (url::Origin::Create(request->requesting_origin()) ==
233         auto_approval_origin.value()) {
234       request->PermissionGranted(/*is_one_time=*/false);
235     }
236     request->RequestFinished();
237     return;
238   }
239
240   // Don't re-add an existing request or one with a duplicate text request.
241   if (auto* existing_request = GetExistingRequest(request)) {
242     if (request == existing_request) {
243       return;
244     }
245
246     // |request| is a duplicate. Add it to |duplicate_requests_| unless it's the
247     // same object as |existing_request| or an existing duplicate.
248     auto iter = FindDuplicateRequestList(existing_request);
249     if (iter == duplicate_requests_.end()) {
250       duplicate_requests_.push_back({request->GetWeakPtr()});
251       return;
252     }
253
254     for (const auto& weak_request : (*iter)) {
255       if (weak_request && request == weak_request.get()) {
256         return;
257       }
258     }
259     iter->push_back(request->GetWeakPtr());
260     return;
261   }
262
263   if (is_main_frame) {
264     if (IsRequestInProgress()) {
265       base::RecordAction(
266           base::UserMetricsAction("PermissionBubbleRequestQueued"));
267     }
268   } else {
269     base::RecordAction(
270         base::UserMetricsAction("PermissionBubbleIFrameRequestQueued"));
271   }
272
273   request->set_requesting_frame_id(source_frame->GetGlobalId());
274
275   QueueRequest(source_frame, request);
276
277   if (!IsRequestInProgress()) {
278     ScheduleDequeueRequestIfNeeded();
279     return;
280   }
281
282   ReprioritizeCurrentRequestIfNeeded();
283 }
284
285 bool PermissionRequestManager::ReprioritizeCurrentRequestIfNeeded() {
286   if (!IsRequestInProgress() ||
287       IsCurrentRequestEmbeddedPermissionElementInitiated()) {
288     return true;
289   }
290
291   // Pop out all invalid requests in front of the queue.
292   while (!pending_permission_requests_.IsEmpty() &&
293          !ValidateRequest(pending_permission_requests_.Peek())) {
294     pending_permission_requests_.Pop();
295   }
296
297   if (pending_permission_requests_.IsEmpty()) {
298     return true;
299   }
300
301   auto current_request_fate = CurrentRequestFate::kKeepCurrent;
302
303   if (PermissionUtil::DoesPlatformSupportChip()) {
304     if (ShouldCurrentRequestUseQuietUI() &&
305         !ShouldShowQuietRequestAgainIfPreempted(
306             current_request_first_display_time_)) {
307       current_request_fate = CurrentRequestFate::kFinalize;
308     } else {
309       // Preempt current request if it is a quiet UI request.
310       if (ShouldCurrentRequestUseQuietUI()) {
311         current_request_fate = CurrentRequestFate::kPreempt;
312       } else {
313         // Here we also try to prioritise the requests. If there's a valid high
314         // priority request (high acceptance rate request) in the pending queue,
315         // preempt the current request. The valid high priority request, if
316         // there's any, is always the front of the queue.
317         if (!pending_permission_requests_.IsEmpty() &&
318             !PermissionUtil::IsLowPriorityPermissionRequest(
319                 pending_permission_requests_.Peek())) {
320           current_request_fate = CurrentRequestFate::kPreempt;
321         }
322       }
323     }
324   } else if (ShouldCurrentRequestUseQuietUI()) {
325     // If we're displaying a quiet permission request, ignore it in favor of a
326     // new permission request.
327     current_request_fate = CurrentRequestFate::kFinalize;
328   }
329
330   if (current_request_fate == CurrentRequestFate::kKeepCurrent &&
331       !pending_permission_requests_.IsEmpty() &&
332       pending_permission_requests_.Peek()
333           ->IsEmbeddedPermissionElementInitiated()) {
334     current_request_fate = CurrentRequestFate::kPreempt;
335   }
336
337   switch (current_request_fate) {
338     case CurrentRequestFate::kKeepCurrent:
339       return true;
340     case CurrentRequestFate::kPreempt: {
341       CHECK(!pending_permission_requests_.IsEmpty());
342       auto* next_candidate = pending_permission_requests_.Peek();
343
344       // Consider a case of infinite loop here (eg: 2 low priority requests can
345       // preempt each other, causing a loop). We only preempt the current
346       // request if the next candidate has just been added to pending queue but
347       // not validated yet.
348       if (validated_requests_set_.find(next_candidate) !=
349           validated_requests_set_.end()) {
350         return true;
351       }
352
353       pending_permission_requests_.Pop();
354       PreemptAndRequeueCurrentRequest();
355       pending_permission_requests_.PushFront(next_candidate);
356       ScheduleDequeueRequestIfNeeded();
357       return false;
358     }
359     case CurrentRequestFate::kFinalize:
360       // FinalizeCurrentRequests() will call ScheduleDequeueRequestIfNeeded on
361       // its own.
362       CurrentRequestsDecided(PermissionAction::IGNORED);
363       return false;
364   }
365
366   return true;
367 }
368
369 bool PermissionRequestManager::ValidateRequest(PermissionRequest* request,
370                                                bool should_finalize) {
371   const auto iter = request_sources_map_.find(request);
372   if (iter == request_sources_map_.end()) {
373     return false;
374   }
375
376   if (!iter->second.IsSourceFrameInactiveAndDisallowActivation()) {
377     return true;
378   }
379
380   if (should_finalize) {
381     request->Cancelled();
382     request->RequestFinished();
383     validated_requests_set_.erase(request);
384     request_sources_map_.erase(request);
385   }
386
387   return false;
388 }
389
390 void PermissionRequestManager::QueueRequest(
391     content::RenderFrameHost* source_frame,
392     PermissionRequest* request) {
393   pending_permission_requests_.Push(request);
394   request_sources_map_.emplace(
395       request, PermissionRequestSource({source_frame->GetGlobalId()}));
396 }
397
398 void PermissionRequestManager::PreemptAndRequeueCurrentRequest() {
399   ResetViewStateForCurrentRequest();
400   for (auto* current_request : requests_) {
401     pending_permission_requests_.PushFront(current_request);
402   }
403
404   // Because the order of the requests is changed, we should not preignore it.
405   preignore_timer_.AbandonAndStop();
406
407   requests_.clear();
408 }
409
410 void PermissionRequestManager::UpdateAnchor() {
411   if (view_) {
412     // When the prompt's anchor is being updated, the prompt view can be
413     // recreated for the new browser. Because of that, ignore prompt callbacks
414     // while doing that.
415     base::AutoReset<bool> ignore(&ignore_callbacks_from_prompt_, true);
416     if (!view_->UpdateAnchor())
417       RecreateView();
418   }
419 }
420
421 void PermissionRequestManager::DidStartNavigation(
422     content::NavigationHandle* navigation_handle) {
423   for (Observer& observer : observer_list_)
424     observer.OnNavigation(navigation_handle);
425
426   if (!navigation_handle->IsInPrimaryMainFrame() ||
427       navigation_handle->IsSameDocument()) {
428     return;
429   }
430
431   // Cooldown lasts until the next user-initiated navigation, which is defined
432   // as either a renderer-initiated navigation with a user gesture, or a
433   // browser-initiated navigation.
434   //
435   // TODO(crbug.com/952347): This check has to be done at DidStartNavigation
436   // time, the HasUserGesture state is lost by the time the navigation
437   // commits.
438   if (!navigation_handle->IsRendererInitiated() ||
439       navigation_handle->HasUserGesture()) {
440     is_notification_prompt_cooldown_active_ = false;
441   }
442 }
443
444 void PermissionRequestManager::DidFinishNavigation(
445     content::NavigationHandle* navigation_handle) {
446   if (!navigation_handle->IsInPrimaryMainFrame() ||
447       !navigation_handle->HasCommitted() ||
448       navigation_handle->IsSameDocument()) {
449     return;
450   }
451
452   if (!navigation_handle->IsErrorPage()) {
453     permissions::PermissionUmaUtil::
454         RecordTopLevelPermissionsHeaderPolicyOnNavigation(
455             navigation_handle->GetRenderFrameHost());
456   }
457
458   if (!base::FeatureList::IsEnabled(
459           features::kBackForwardCacheUnblockPermissionRequest)) {
460     if (!pending_permission_requests_.IsEmpty() || IsRequestInProgress()) {
461       // |pending_permission_requests_| and |requests_| will be deleted below,
462       // which might be a problem for back-forward cache â€” the page might be
463       // restored later, but the requests won't be. Disable bfcache here if we
464       // have any requests here to prevent this from happening.
465       content::BackForwardCache::DisableForRenderFrameHost(
466           navigation_handle->GetPreviousRenderFrameHostId(),
467           back_forward_cache::DisabledReason(
468               back_forward_cache::DisabledReasonId::kPermissionRequestManager));
469     }
470   }
471   CleanUpRequests();
472 }
473
474 void PermissionRequestManager::DocumentOnLoadCompletedInPrimaryMainFrame() {
475   // This is scheduled because while all calls to the browser have been
476   // issued at DOMContentLoaded, they may be bouncing around in scheduled
477   // callbacks finding the UI thread still. This makes sure we allow those
478   // scheduled calls to AddRequest to complete before we show the page-load
479   // permissions prompt.
480   ScheduleDequeueRequestIfNeeded();
481 }
482
483 void PermissionRequestManager::DOMContentLoaded(
484     content::RenderFrameHost* render_frame_host) {
485   ScheduleDequeueRequestIfNeeded();
486 }
487
488 void PermissionRequestManager::WebContentsDestroyed() {
489   // If the web contents has been destroyed, treat the prompt as cancelled.
490   CleanUpRequests();
491
492   // The WebContents is going away; be aggressively paranoid and delete
493   // ourselves lest other parts of the system attempt to add permission
494   // prompts or use us otherwise during the destruction.
495   web_contents()->RemoveUserData(UserDataKey());
496   // That was the equivalent of "delete this". This object is now destroyed;
497   // returning from this function is the only safe thing to do.
498 }
499
500 void PermissionRequestManager::OnVisibilityChanged(
501     content::Visibility visibility) {
502   bool tab_was_hidden = tab_is_hidden_;
503   tab_is_hidden_ = visibility == content::Visibility::HIDDEN;
504   if (tab_was_hidden == tab_is_hidden_)
505     return;
506   NotifyTabVisibilityChanged(visibility);
507   if (tab_is_hidden_) {
508     if (view_) {
509       switch (view_->GetTabSwitchingBehavior()) {
510         case PermissionPrompt::TabSwitchingBehavior::
511             kDestroyPromptButKeepRequestPending:
512           DeletePrompt();
513           break;
514         case PermissionPrompt::TabSwitchingBehavior::
515             kDestroyPromptAndIgnoreRequest:
516           CurrentRequestsDecided(PermissionAction::IGNORED);
517           break;
518         case PermissionPrompt::TabSwitchingBehavior::kKeepPromptAlive:
519           break;
520       }
521     }
522
523     return;
524   }
525
526   if (!web_contents()->IsDocumentOnLoadCompletedInPrimaryMainFrame())
527     return;
528
529   if (!IsRequestInProgress()) {
530     ScheduleDequeueRequestIfNeeded();
531     return;
532   }
533
534   if (view_) {
535     // We switched tabs away and back while a prompt was active.
536     DCHECK_EQ(view_->GetTabSwitchingBehavior(),
537               PermissionPrompt::TabSwitchingBehavior::kKeepPromptAlive);
538   } else if (current_request_ui_to_use_.has_value()) {
539     ShowPrompt();
540   }
541 }
542
543 const std::vector<PermissionRequest*>& PermissionRequestManager::Requests() {
544   return requests_;
545 }
546
547 GURL PermissionRequestManager::GetRequestingOrigin() const {
548   CHECK(!requests_.empty());
549   GURL origin = requests_.front()->requesting_origin();
550   if (DCHECK_IS_ON()) {
551     for (auto* request : requests_)
552       DCHECK_EQ(origin, request->requesting_origin());
553   }
554   return origin;
555 }
556
557 GURL PermissionRequestManager::GetEmbeddingOrigin() const {
558   if (embedding_origin_for_testing_.has_value()) {
559     return embedding_origin_for_testing_.value();
560   }
561
562   return PermissionUtil::GetLastCommittedOriginAsURL(
563       web_contents()->GetPrimaryMainFrame());
564 }
565
566 void PermissionRequestManager::Accept() {
567   if (ignore_callbacks_from_prompt_)
568     return;
569   DCHECK(view_);
570   std::vector<PermissionRequest*>::iterator requests_iter;
571   for (requests_iter = requests_.begin(); requests_iter != requests_.end();
572        requests_iter++) {
573     StorePermissionActionForUMA((*requests_iter)->requesting_origin(),
574                                 (*requests_iter)->request_type(),
575                                 PermissionAction::GRANTED);
576     PermissionGrantedIncludingDuplicates(*requests_iter,
577                                          /*is_one_time=*/false);
578
579 #if !BUILDFLAG(IS_ANDROID)
580     absl::optional<ContentSettingsType> content_settings_type =
581         RequestTypeToContentSettingsType((*requests_iter)->request_type());
582     if (content_settings_type.has_value()) {
583       PermissionUmaUtil::RecordPermissionRegrantForUnusedSites(
584           (*requests_iter)->requesting_origin(), content_settings_type.value(),
585           PermissionSourceUI::PROMPT, web_contents()->GetBrowserContext(),
586           base::Time::Now());
587     }
588 #endif
589   }
590
591   NotifyRequestDecided(PermissionAction::GRANTED);
592   CurrentRequestsDecided(PermissionAction::GRANTED);
593 }
594
595 void PermissionRequestManager::AcceptThisTime() {
596   if (ignore_callbacks_from_prompt_)
597     return;
598   DCHECK(view_);
599   std::vector<PermissionRequest*>::iterator requests_iter;
600   for (requests_iter = requests_.begin(); requests_iter != requests_.end();
601        requests_iter++) {
602     StorePermissionActionForUMA((*requests_iter)->requesting_origin(),
603                                 (*requests_iter)->request_type(),
604                                 PermissionAction::GRANTED_ONCE);
605     PermissionGrantedIncludingDuplicates(*requests_iter,
606                                          /*is_one_time=*/true);
607   }
608
609   NotifyRequestDecided(PermissionAction::GRANTED_ONCE);
610   CurrentRequestsDecided(PermissionAction::GRANTED_ONCE);
611 }
612
613 void PermissionRequestManager::Deny() {
614   if (ignore_callbacks_from_prompt_)
615     return;
616   DCHECK(view_);
617
618   // Suppress any further prompts in this WebContents, from any origin, until
619   // there is a user-initiated navigation. This stops users from getting
620   // trapped in request loops where the website automatically navigates
621   // cross-origin (e.g. to another subdomain) to be able to prompt again after
622   // a rejection.
623   if (base::FeatureList::IsEnabled(
624           features::kBlockRepeatedNotificationPermissionPrompts) &&
625       base::Contains(requests_, ContentSettingsType::NOTIFICATIONS,
626                      &PermissionRequest::GetContentSettingsType)) {
627     is_notification_prompt_cooldown_active_ = true;
628   }
629
630   std::vector<PermissionRequest*>::iterator requests_iter;
631   for (requests_iter = requests_.begin(); requests_iter != requests_.end();
632        requests_iter++) {
633     StorePermissionActionForUMA((*requests_iter)->requesting_origin(),
634                                 (*requests_iter)->request_type(),
635                                 PermissionAction::DENIED);
636     PermissionDeniedIncludingDuplicates(*requests_iter);
637   }
638
639   NotifyRequestDecided(PermissionAction::DENIED);
640   CurrentRequestsDecided(PermissionAction::DENIED);
641 }
642
643 void PermissionRequestManager::Dismiss() {
644   if (ignore_callbacks_from_prompt_)
645     return;
646   DCHECK(view_);
647   std::vector<PermissionRequest*>::iterator requests_iter;
648   for (requests_iter = requests_.begin(); requests_iter != requests_.end();
649        requests_iter++) {
650     StorePermissionActionForUMA((*requests_iter)->requesting_origin(),
651                                 (*requests_iter)->request_type(),
652                                 PermissionAction::DISMISSED);
653     CancelledIncludingDuplicates(*requests_iter);
654   }
655
656   NotifyRequestDecided(PermissionAction::DISMISSED);
657   CurrentRequestsDecided(PermissionAction::DISMISSED);
658 }
659
660 void PermissionRequestManager::Ignore() {
661   if (ignore_callbacks_from_prompt_)
662     return;
663   DCHECK(view_);
664   std::vector<PermissionRequest*>::iterator requests_iter;
665   for (requests_iter = requests_.begin(); requests_iter != requests_.end();
666        requests_iter++) {
667     StorePermissionActionForUMA((*requests_iter)->requesting_origin(),
668                                 (*requests_iter)->request_type(),
669                                 PermissionAction::IGNORED);
670     CancelledIncludingDuplicates(*requests_iter);
671   }
672
673   NotifyRequestDecided(PermissionAction::IGNORED);
674   CurrentRequestsDecided(PermissionAction::IGNORED);
675 }
676
677 void PermissionRequestManager::FinalizeCurrentRequests() {
678   ResetViewStateForCurrentRequest();
679   std::vector<PermissionRequest*>::iterator requests_iter;
680   for (requests_iter = requests_.begin(); requests_iter != requests_.end();
681        requests_iter++) {
682     RequestFinishedIncludingDuplicates(*requests_iter);
683     validated_requests_set_.erase(*requests_iter);
684     request_sources_map_.erase(*requests_iter);
685   }
686
687   // No need to execute the preignore logic as we canceling currently active
688   // requests anyway.
689   preignore_timer_.AbandonAndStop();
690
691   requests_.clear();
692
693   for (Observer& observer : observer_list_) {
694     observer.OnRequestsFinalized();
695   }
696
697   ScheduleDequeueRequestIfNeeded();
698 }
699
700 void PermissionRequestManager::OpenHelpCenterLink(const ui::Event& event) {
701   CHECK_GT(requests_.size(), 0u);
702   switch (requests_[0]->request_type()) {
703     case permissions::RequestType::kStorageAccess:
704       GetAssociatedWebContents()->OpenURL(content::OpenURLParams(
705           GURL(permissions::kEmbeddedContentHelpCenterURL), content::Referrer(),
706           ui::DispositionFromEventFlags(
707               event.flags(), WindowOpenDisposition::NEW_FOREGROUND_TAB),
708           ui::PAGE_TRANSITION_LINK, /*is_renderer_initiated=*/false));
709       break;
710     default:
711       NOTREACHED_NORETURN();
712   }
713 }
714
715 void PermissionRequestManager::PreIgnoreQuietPrompt() {
716   // Random number of seconds in the range [1.0, 2.0).
717   double delay_seconds = 1.0 + 1.0 * base::RandDouble();
718   preignore_timer_.Start(
719       FROM_HERE, base::Seconds(delay_seconds), this,
720       &PermissionRequestManager::PreIgnoreQuietPromptInternal);
721 }
722
723 void PermissionRequestManager::PreIgnoreQuietPromptInternal() {
724   DCHECK(!requests_.empty());
725
726   if (requests_.empty()) {
727     // If `requests_` was cleared then there is nothing preignore.
728     return;
729   }
730
731   std::vector<PermissionRequest*>::iterator requests_iter;
732   for (requests_iter = requests_.begin(); requests_iter != requests_.end();
733        requests_iter++) {
734     CancelledIncludingDuplicates(*requests_iter, /*is_final_decision=*/false);
735   }
736
737   blink::PermissionType permission;
738   bool success = PermissionUtil::GetPermissionType(
739       requests_[0]->GetContentSettingsType(), &permission);
740   DCHECK(success);
741
742   PermissionUmaUtil::PermissionRequestPreignored(permission);
743 }
744
745 bool PermissionRequestManager::WasCurrentRequestAlreadyDisplayed() {
746   return current_request_already_displayed_;
747 }
748
749 void PermissionRequestManager::SetDismissOnTabClose() {
750   should_dismiss_current_request_ = true;
751 }
752
753 void PermissionRequestManager::SetPromptShown() {
754   did_show_prompt_ = true;
755 }
756
757 void PermissionRequestManager::SetDecisionTime() {
758   current_request_decision_time_ = base::Time::Now();
759 }
760
761 void PermissionRequestManager::SetManageClicked() {
762   set_manage_clicked();
763 }
764
765 void PermissionRequestManager::SetLearnMoreClicked() {
766   set_learn_more_clicked();
767 }
768
769 base::WeakPtr<PermissionPrompt::Delegate>
770 PermissionRequestManager::GetWeakPtr() {
771   return weak_factory_.GetWeakPtr();
772 }
773
774 content::WebContents* PermissionRequestManager::GetAssociatedWebContents() {
775   content::WebContents& web_contents = GetWebContents();
776   return &web_contents;
777 }
778
779 bool PermissionRequestManager::RecreateView() {
780   view_ = view_factory_.Run(web_contents(), this);
781   if (!view_) {
782     current_request_prompt_disposition_ =
783         PermissionPromptDisposition::NONE_VISIBLE;
784     if (ShouldDropCurrentRequestIfCannotShowQuietly()) {
785       CurrentRequestsDecided(PermissionAction::IGNORED);
786     }
787     NotifyPromptRecreateFailed();
788     return false;
789   }
790
791   current_request_prompt_disposition_ = view_->GetPromptDisposition();
792   return true;
793 }
794
795 absl::optional<gfx::Rect>
796 PermissionRequestManager::GetPromptBubbleViewBoundsInScreen() const {
797   return view_ ? view_->GetViewBoundsInScreen() : absl::nullopt;
798 }
799
800 PermissionRequestManager::PermissionRequestManager(
801     content::WebContents* web_contents)
802     : content::WebContentsObserver(web_contents),
803       content::WebContentsUserData<PermissionRequestManager>(*web_contents),
804       view_factory_(base::BindRepeating(&PermissionPrompt::Create)),
805       tab_is_hidden_(web_contents->GetVisibility() ==
806                      content::Visibility::HIDDEN),
807       auto_response_for_test_(NONE),
808       permission_ui_selectors_(
809           PermissionsClient::Get()->CreatePermissionUiSelectors(
810               web_contents->GetBrowserContext())) {}
811
812 void PermissionRequestManager::DequeueRequestIfNeeded() {
813   // TODO(olesiamarukhno): Media requests block other media requests from
814   // pre-empting them. For example, when a camera request is pending and mic
815   // is requested, the camera request remains pending and mic request appears
816   // only after the camera request is resolved. This is caused by code in
817   // PermissionBubbleMediaAccessHandler and UserMediaClient. We probably don't
818   // need two permission queues, so resolve the duplication.
819
820   if (!web_contents()->IsDocumentOnLoadCompletedInPrimaryMainFrame() || view_ ||
821       IsRequestInProgress()) {
822     return;
823   }
824
825   // Find first valid request.
826   while (!pending_permission_requests_.IsEmpty()) {
827     auto* next = pending_permission_requests_.Pop();
828     if (ValidateRequest(next)) {
829       validated_requests_set_.insert(next);
830       requests_.push_back(next);
831       break;
832     }
833   }
834
835   if (requests_.empty()) {
836     return;
837   }
838
839   // Find additional requests that can be grouped with the first one.
840   for (; !pending_permission_requests_.IsEmpty();
841        pending_permission_requests_.Pop()) {
842     auto* front = pending_permission_requests_.Peek();
843     if (!ValidateRequest(front))
844       continue;
845
846     validated_requests_set_.insert(front);
847     if (!ShouldGroupRequests(requests_.front(), front))
848       break;
849
850     requests_.push_back(front);
851   }
852
853   // Mark the remaining pending requests as validated, so only the "new and has
854   // not been validated" requests added to the queue could have effect to
855   // priority order
856   for (const auto& request_list : pending_permission_requests_) {
857     for (auto* request : request_list) {
858       if (ValidateRequest(request, /* should_finalize */ false)) {
859         validated_requests_set_.insert(request);
860       }
861     }
862   }
863
864   if (permission_ui_selectors_.empty()) {
865     current_request_ui_to_use_ =
866         UiDecision(UiDecision::UseNormalUi(), UiDecision::ShowNoWarning());
867     ShowPrompt();
868     return;
869   }
870
871   DCHECK(!current_request_ui_to_use_.has_value());
872   // Initialize the selector decisions vector.
873   DCHECK(selector_decisions_.empty());
874   selector_decisions_.resize(permission_ui_selectors_.size());
875
876   for (size_t selector_index = 0;
877        selector_index < permission_ui_selectors_.size(); ++selector_index) {
878     // Skip if we have already made a decision due to a higher priority
879     // selector
880     if (current_request_ui_to_use_.has_value() || !IsRequestInProgress()) {
881       break;
882     }
883
884     if (permission_ui_selectors_[selector_index]->IsPermissionRequestSupported(
885             requests_.front()->request_type())) {
886       permission_ui_selectors_[selector_index]->SelectUiToUse(
887           requests_.front(),
888           base::BindOnce(&PermissionRequestManager::OnPermissionUiSelectorDone,
889                          weak_factory_.GetWeakPtr(), selector_index));
890       continue;
891     }
892
893     OnPermissionUiSelectorDone(
894         selector_index,
895         PermissionUiSelector::Decision::UseNormalUiAndShowNoWarning());
896   }
897 }
898
899 void PermissionRequestManager::ScheduleDequeueRequestIfNeeded() {
900   base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
901       FROM_HERE,
902       base::BindOnce(&PermissionRequestManager::DequeueRequestIfNeeded,
903                      weak_factory_.GetWeakPtr()));
904 }
905
906 void PermissionRequestManager::ShowPrompt() {
907   // There is a race condition where the request might have been removed
908   // already so double-checking that there is a request in progress.
909   //
910   // There is no need to show a new prompt if the previous one still exists.
911   if (!IsRequestInProgress() || view_)
912     return;
913
914   DCHECK(web_contents()->IsDocumentOnLoadCompletedInPrimaryMainFrame());
915   DCHECK(current_request_ui_to_use_);
916
917   if (tab_is_hidden_) {
918     NotifyPromptCreationFailedHiddenTab();
919     return;
920   }
921
922   if (!ReprioritizeCurrentRequestIfNeeded())
923     return;
924
925   if (!RecreateView())
926     return;
927
928   if (!current_request_already_displayed_) {
929     PermissionUmaUtil::PermissionPromptShown(requests_);
930
931     auto quiet_ui_reason = ReasonForUsingQuietUi();
932     if (quiet_ui_reason) {
933       switch (*quiet_ui_reason) {
934         case QuietUiReason::kEnabledInPrefs:
935         case QuietUiReason::kTriggeredByCrowdDeny:
936         case QuietUiReason::kServicePredictedVeryUnlikelyGrant:
937         case QuietUiReason::kOnDevicePredictedVeryUnlikelyGrant:
938           break;
939         case QuietUiReason::kTriggeredDueToAbusiveRequests:
940           LogWarningToConsole(kAbusiveNotificationRequestsEnforcementMessage);
941           break;
942         case QuietUiReason::kTriggeredDueToAbusiveContent:
943           LogWarningToConsole(kAbusiveNotificationContentEnforcementMessage);
944           break;
945         case QuietUiReason::kTriggeredDueToDisruptiveBehavior:
946           LogWarningToConsole(
947               kDisruptiveNotificationBehaviorEnforcementMessage);
948           break;
949       }
950       base::RecordAction(base::UserMetricsAction(
951           "Notifications.Quiet.PermissionRequestShown"));
952     }
953
954 #if !BUILDFLAG(IS_ANDROID)
955     PermissionsClient::Get()->TriggerPromptHatsSurveyIfEnabled(
956         web_contents()->GetBrowserContext(), requests_[0]->request_type(),
957         absl::nullopt, DetermineCurrentRequestUIDisposition(),
958         DetermineCurrentRequestUIDispositionReasonForUMA(),
959         requests_[0]->GetGestureType(), absl::nullopt, false,
960         web_contents()->GetLastCommittedURL(),
961         hats_shown_callback_.has_value()
962             ? std::move(hats_shown_callback_.value())
963             : base::DoNothing());
964
965     hats_shown_callback_.reset();
966 #endif
967   }
968   current_request_already_displayed_ = true;
969   current_request_first_display_time_ = base::Time::Now();
970
971   NotifyPromptAdded();
972
973   // If in testing mode, automatically respond to the bubble that was shown.
974   if (auto_response_for_test_ != NONE) {
975     DoAutoResponseForTesting();
976   }
977 }
978
979 void PermissionRequestManager::SetHatsShownCallback(
980     base::OnceCallback<void()> callback) {
981   hats_shown_callback_ = std::move(callback);
982 }
983
984 void PermissionRequestManager::DeletePrompt() {
985   DCHECK(view_);
986   {
987     base::AutoReset<bool> deleting(&ignore_callbacks_from_prompt_, true);
988     view_.reset();
989   }
990   NotifyPromptRemoved();
991 }
992
993 void PermissionRequestManager::ResetViewStateForCurrentRequest() {
994   for (const auto& selector : permission_ui_selectors_)
995     selector->Cancel();
996
997   current_request_already_displayed_ = false;
998   current_request_first_display_time_ = base::Time();
999   current_request_decision_time_ = base::Time();
1000   current_request_prompt_disposition_.reset();
1001   prediction_grant_likelihood_.reset();
1002   current_request_ui_to_use_.reset();
1003   was_decision_held_back_.reset();
1004   selector_decisions_.clear();
1005   should_dismiss_current_request_ = false;
1006   did_show_prompt_ = false;
1007   did_click_manage_ = false;
1008   did_click_learn_more_ = false;
1009   hats_shown_callback_.reset();
1010   if (view_)
1011     DeletePrompt();
1012 }
1013
1014 void PermissionRequestManager::CurrentRequestsDecided(
1015     PermissionAction permission_action) {
1016   DCHECK(IsRequestInProgress());
1017   base::TimeDelta time_to_decision;
1018   if (!current_request_first_display_time_.is_null() &&
1019       permission_action != PermissionAction::IGNORED) {
1020     if (current_request_decision_time_.is_null()) {
1021       current_request_decision_time_ = base::Time::Now();
1022     }
1023     time_to_decision =
1024         current_request_decision_time_ - current_request_first_display_time_;
1025   }
1026
1027   if (time_to_decision_for_test_.has_value()) {
1028     time_to_decision = time_to_decision_for_test_.value();
1029     time_to_decision_for_test_.reset();
1030   }
1031
1032   content::BrowserContext* browser_context =
1033       web_contents()->GetBrowserContext();
1034   PermissionUmaUtil::PermissionPromptResolved(
1035       requests_, web_contents(), permission_action, time_to_decision,
1036       DetermineCurrentRequestUIDisposition(),
1037       DetermineCurrentRequestUIDispositionReasonForUMA(),
1038       prediction_grant_likelihood_, was_decision_held_back_,
1039       permission_action == PermissionAction::IGNORED
1040           ? absl::make_optional(
1041                 PermissionsClient::Get()->DetermineIgnoreReason(web_contents()))
1042           : absl::nullopt,
1043       did_show_prompt_, did_click_manage_, did_click_learn_more_);
1044
1045   PermissionDecisionAutoBlocker* autoblocker =
1046       PermissionsClient::Get()->GetPermissionDecisionAutoBlocker(
1047           browser_context);
1048
1049   absl::optional<QuietUiReason> quiet_ui_reason;
1050   if (ShouldCurrentRequestUseQuietUI())
1051     quiet_ui_reason = ReasonForUsingQuietUi();
1052
1053   for (PermissionRequest* request : requests_) {
1054     // TODO(timloh): We only support dismiss and ignore embargo for
1055     // permissions which use PermissionRequestImpl as the other subclasses
1056     // don't support GetContentSettingsType.
1057     if (request->GetContentSettingsType() == ContentSettingsType::DEFAULT)
1058       continue;
1059
1060     auto time_since_shown =
1061         current_request_first_display_time_.is_null()
1062             ? base::TimeDelta::Max()
1063             : base::Time::Now() - current_request_first_display_time_;
1064     PermissionsClient::Get()->OnPromptResolved(
1065         request->request_type(), permission_action,
1066         request->requesting_origin(), DetermineCurrentRequestUIDisposition(),
1067         DetermineCurrentRequestUIDispositionReasonForUMA(),
1068         request->GetGestureType(), quiet_ui_reason, time_since_shown,
1069         web_contents());
1070
1071     PermissionEmbargoStatus embargo_status =
1072         PermissionEmbargoStatus::NOT_EMBARGOED;
1073     if (permission_action == PermissionAction::DISMISSED) {
1074       if (autoblocker->RecordDismissAndEmbargo(
1075               request->requesting_origin(), request->GetContentSettingsType(),
1076               ShouldCurrentRequestUseQuietUI())) {
1077         embargo_status = PermissionEmbargoStatus::REPEATED_DISMISSALS;
1078       }
1079     } else if (permission_action == PermissionAction::IGNORED) {
1080       if (autoblocker->RecordIgnoreAndEmbargo(
1081               request->requesting_origin(), request->GetContentSettingsType(),
1082               ShouldCurrentRequestUseQuietUI())) {
1083         embargo_status = PermissionEmbargoStatus::REPEATED_IGNORES;
1084       }
1085     } else if (permission_action == PermissionAction::GRANTED_ONCE) {
1086       autoblocker->RemoveEmbargoAndResetCounts(
1087           request->requesting_origin(), request->GetContentSettingsType());
1088     }
1089     PermissionUmaUtil::RecordEmbargoStatus(embargo_status);
1090   }
1091
1092   // IGNORED is not a decision on the prompt and it occurs because of external
1093   // factors (e.g. tab switching). Therefore |ShouldFinalizeRequestAfterDecided|
1094   // does not take effect when the action is IGNORED.
1095   if (ShouldFinalizeRequestAfterDecided(permission_action)) {
1096     FinalizeCurrentRequests();
1097   }
1098 }
1099
1100 void PermissionRequestManager::CleanUpRequests() {
1101   // No need to execute the preignore logic as we canceling currently active
1102   // requests anyway.
1103   preignore_timer_.AbandonAndStop();
1104
1105   for (; !pending_permission_requests_.IsEmpty();
1106        pending_permission_requests_.Pop()) {
1107     auto* pending_request = pending_permission_requests_.Peek();
1108     CancelledIncludingDuplicates(pending_request);
1109     RequestFinishedIncludingDuplicates(pending_request);
1110     validated_requests_set_.erase(pending_request);
1111     request_sources_map_.erase(pending_request);
1112   }
1113
1114   if (IsRequestInProgress()) {
1115     std::vector<PermissionRequest*>::iterator requests_iter;
1116     for (requests_iter = requests_.begin(); requests_iter != requests_.end();
1117          requests_iter++) {
1118       CancelledIncludingDuplicates(*requests_iter);
1119     }
1120
1121     CurrentRequestsDecided(should_dismiss_current_request_
1122                                ? PermissionAction::DISMISSED
1123                                : PermissionAction::IGNORED);
1124     should_dismiss_current_request_ = false;
1125   }
1126 }
1127
1128 PermissionRequest* PermissionRequestManager::GetExistingRequest(
1129     PermissionRequest* request) const {
1130   for (PermissionRequest* existing_request : requests_) {
1131     if (request->IsDuplicateOf(existing_request)) {
1132       return existing_request;
1133     }
1134   }
1135   return pending_permission_requests_.FindDuplicate(request);
1136 }
1137
1138 PermissionRequestManager::WeakPermissionRequestList::iterator
1139 PermissionRequestManager::FindDuplicateRequestList(PermissionRequest* request) {
1140   for (auto request_list = duplicate_requests_.begin();
1141        request_list != duplicate_requests_.end(); ++request_list) {
1142     for (auto iter = request_list->begin(); iter != request_list->end();) {
1143       // Remove any requests that have been destroyed.
1144       const auto& weak_request = (*iter);
1145       if (!weak_request) {
1146         iter = request_list->erase(iter);
1147         continue;
1148       }
1149
1150       // The first valid request in the list will indicate whether all other
1151       // members are duplicate or not.
1152       if (weak_request->IsDuplicateOf(request)) {
1153         return request_list;
1154       }
1155
1156       break;
1157     }
1158   }
1159
1160   return duplicate_requests_.end();
1161 }
1162
1163 PermissionRequestManager::WeakPermissionRequestList::iterator
1164 PermissionRequestManager::VisitDuplicateRequests(
1165     DuplicateRequestVisitor visitor,
1166     PermissionRequest* request) {
1167   auto request_list = FindDuplicateRequestList(request);
1168   if (request_list == duplicate_requests_.end()) {
1169     return request_list;
1170   }
1171
1172   for (auto iter = request_list->begin(); iter != request_list->end();) {
1173     if (auto& weak_request = (*iter)) {
1174       visitor.Run(weak_request);
1175       ++iter;
1176     } else {
1177       // Remove any requests that have been destroyed.
1178       iter = request_list->erase(iter);
1179     }
1180   }
1181
1182   return request_list;
1183 }
1184
1185 void PermissionRequestManager::PermissionGrantedIncludingDuplicates(
1186     PermissionRequest* request,
1187     bool is_one_time) {
1188   DCHECK_EQ(1ul, base::ranges::count(requests_, request) +
1189                      pending_permission_requests_.Count(request))
1190       << "Only requests in [pending_permission_]requests_ can have duplicates";
1191   request->PermissionGranted(is_one_time);
1192   VisitDuplicateRequests(
1193       base::BindRepeating(
1194           [](bool is_one_time,
1195              const base::WeakPtr<PermissionRequest>& weak_request) {
1196             weak_request->PermissionGranted(is_one_time);
1197           },
1198           is_one_time),
1199       request);
1200 }
1201
1202 void PermissionRequestManager::PermissionDeniedIncludingDuplicates(
1203     PermissionRequest* request) {
1204   DCHECK_EQ(1ul, base::ranges::count(requests_, request) +
1205                      pending_permission_requests_.Count(request))
1206       << "Only requests in [pending_permission_]requests_ can have duplicates";
1207   request->PermissionDenied();
1208   VisitDuplicateRequests(
1209       base::BindRepeating(
1210           [](const base::WeakPtr<PermissionRequest>& weak_request) {
1211             weak_request->PermissionDenied();
1212           }),
1213       request);
1214 }
1215
1216 void PermissionRequestManager::CancelledIncludingDuplicates(
1217     PermissionRequest* request,
1218     bool is_final_decision) {
1219   DCHECK_EQ(1ul, base::ranges::count(requests_, request) +
1220                      pending_permission_requests_.Count(request))
1221       << "Only requests in [pending_permission_]requests_ can have duplicates";
1222   request->Cancelled(is_final_decision);
1223   VisitDuplicateRequests(
1224       base::BindRepeating(
1225           [](bool is_final,
1226              const base::WeakPtr<PermissionRequest>& weak_request) {
1227             weak_request->Cancelled(is_final);
1228           },
1229           is_final_decision),
1230       request);
1231 }
1232
1233 void PermissionRequestManager::RequestFinishedIncludingDuplicates(
1234     PermissionRequest* request) {
1235   DCHECK_EQ(1ul, base::ranges::count(requests_, request) +
1236                      pending_permission_requests_.Count(request))
1237       << "Only requests in [pending_permission_]requests_ can have duplicates";
1238   auto duplicate_list = VisitDuplicateRequests(
1239       base::BindRepeating(
1240           [](const base::WeakPtr<PermissionRequest>& weak_request) {
1241             weak_request->RequestFinished();
1242           }),
1243       request);
1244
1245   // Note: beyond this point, |request| has probably been deleted, any
1246   // dereference of |request| must be done prior this point.
1247   request->RequestFinished();
1248
1249   // Additionally, we can now remove the duplicates.
1250   if (duplicate_list != duplicate_requests_.end()) {
1251     duplicate_requests_.erase(duplicate_list);
1252   }
1253 }
1254
1255 void PermissionRequestManager::AddObserver(Observer* observer) {
1256   observer_list_.AddObserver(observer);
1257 }
1258
1259 void PermissionRequestManager::RemoveObserver(Observer* observer) {
1260   observer_list_.RemoveObserver(observer);
1261 }
1262
1263 bool PermissionRequestManager::ShouldCurrentRequestUseQuietUI() const {
1264   // ContentSettingImageModel might call into this method if the user switches
1265   // between tabs while the |notification_permission_ui_selectors_| are
1266   // pending.
1267   return ReasonForUsingQuietUi() != absl::nullopt;
1268 }
1269
1270 absl::optional<PermissionRequestManager::QuietUiReason>
1271 PermissionRequestManager::ReasonForUsingQuietUi() const {
1272   if (!IsRequestInProgress() || !current_request_ui_to_use_ ||
1273       !current_request_ui_to_use_->quiet_ui_reason)
1274     return absl::nullopt;
1275
1276   return *(current_request_ui_to_use_->quiet_ui_reason);
1277 }
1278
1279 bool PermissionRequestManager::IsRequestInProgress() const {
1280   return !requests_.empty();
1281 }
1282
1283 bool PermissionRequestManager::CanRestorePrompt() {
1284 #if BUILDFLAG(IS_ANDROID)
1285   return false;
1286 #else
1287   return IsRequestInProgress() &&
1288          current_request_prompt_disposition_.has_value() && !view_;
1289 #endif
1290 }
1291
1292 void PermissionRequestManager::RestorePrompt() {
1293   if (CanRestorePrompt())
1294     ShowPrompt();
1295 }
1296
1297 bool PermissionRequestManager::ShouldDropCurrentRequestIfCannotShowQuietly()
1298     const {
1299   absl::optional<QuietUiReason> quiet_ui_reason = ReasonForUsingQuietUi();
1300   if (quiet_ui_reason.has_value()) {
1301     switch (quiet_ui_reason.value()) {
1302       case QuietUiReason::kEnabledInPrefs:
1303       case QuietUiReason::kServicePredictedVeryUnlikelyGrant:
1304       case QuietUiReason::kOnDevicePredictedVeryUnlikelyGrant:
1305       case QuietUiReason::kTriggeredByCrowdDeny:
1306         return false;
1307       case QuietUiReason::kTriggeredDueToAbusiveRequests:
1308       case QuietUiReason::kTriggeredDueToAbusiveContent:
1309       case QuietUiReason::kTriggeredDueToDisruptiveBehavior:
1310         return true;
1311     }
1312   }
1313
1314   return false;
1315 }
1316
1317 void PermissionRequestManager::NotifyTabVisibilityChanged(
1318     content::Visibility visibility) {
1319   for (Observer& observer : observer_list_) {
1320     observer.OnTabVisibilityChanged(visibility);
1321   }
1322 }
1323
1324 void PermissionRequestManager::NotifyPromptAdded() {
1325   for (Observer& observer : observer_list_)
1326     observer.OnPromptAdded();
1327 }
1328
1329 void PermissionRequestManager::NotifyPromptRemoved() {
1330   for (Observer& observer : observer_list_) {
1331     observer.OnPromptRemoved();
1332   }
1333 }
1334
1335 void PermissionRequestManager::NotifyPromptRecreateFailed() {
1336   for (Observer& observer : observer_list_)
1337     observer.OnPromptRecreateViewFailed();
1338 }
1339
1340 void PermissionRequestManager::NotifyPromptCreationFailedHiddenTab() {
1341   for (Observer& observer : observer_list_)
1342     observer.OnPromptCreationFailedHiddenTab();
1343 }
1344
1345 void PermissionRequestManager::NotifyRequestDecided(
1346     permissions::PermissionAction permission_action) {
1347   for (Observer& observer : observer_list_)
1348     observer.OnRequestDecided(permission_action);
1349 }
1350
1351 void PermissionRequestManager::StorePermissionActionForUMA(
1352     const GURL& origin,
1353     RequestType request_type,
1354     PermissionAction permission_action) {
1355   absl::optional<ContentSettingsType> content_settings_type =
1356       RequestTypeToContentSettingsType(request_type);
1357   if (content_settings_type.has_value()) {
1358     PermissionsClient::Get()
1359         ->GetOriginKeyedPermissionActionService(
1360             web_contents()->GetBrowserContext())
1361         ->RecordAction(PermissionUtil::GetLastCommittedOriginAsURL(
1362                            web_contents()->GetPrimaryMainFrame()),
1363                        content_settings_type.value(), permission_action);
1364   }
1365 }
1366
1367 void PermissionRequestManager::OnPermissionUiSelectorDone(
1368     size_t selector_index,
1369     const UiDecision& decision) {
1370   if (decision.warning_reason) {
1371     switch (*(decision.warning_reason)) {
1372       case WarningReason::kAbusiveRequests:
1373         LogWarningToConsole(kAbusiveNotificationRequestsWarningMessage);
1374         break;
1375       case WarningReason::kAbusiveContent:
1376         LogWarningToConsole(kAbusiveNotificationContentWarningMessage);
1377         break;
1378       case WarningReason::kDisruptiveBehavior:
1379         break;
1380     }
1381   }
1382
1383   // We have already made a decision because of a higher priority selector
1384   // therefore this selector's decision can be discarded.
1385   if (current_request_ui_to_use_.has_value())
1386     return;
1387
1388   CHECK_LT(selector_index, selector_decisions_.size());
1389   selector_decisions_[selector_index] = decision;
1390
1391   size_t decision_index = 0;
1392   while (decision_index < selector_decisions_.size() &&
1393          selector_decisions_[decision_index].has_value()) {
1394     const UiDecision& current_decision =
1395         selector_decisions_[decision_index].value();
1396
1397     if (!prediction_grant_likelihood_.has_value()) {
1398       prediction_grant_likelihood_ = permission_ui_selectors_[decision_index]
1399                                          ->PredictedGrantLikelihoodForUKM();
1400     }
1401
1402     if (!was_decision_held_back_.has_value()) {
1403       was_decision_held_back_ = permission_ui_selectors_[decision_index]
1404                                     ->WasSelectorDecisionHeldback();
1405     }
1406
1407     if (current_decision.quiet_ui_reason.has_value()) {
1408       current_request_ui_to_use_ = current_decision;
1409       break;
1410     }
1411
1412     ++decision_index;
1413   }
1414
1415   // All decisions have been considered and none was conclusive.
1416   if (decision_index == selector_decisions_.size() &&
1417       !current_request_ui_to_use_.has_value()) {
1418     current_request_ui_to_use_ = UiDecision::UseNormalUiAndShowNoWarning();
1419   }
1420
1421   if (current_request_ui_to_use_.has_value()) {
1422     ShowPrompt();
1423   }
1424 }
1425
1426 PermissionPromptDisposition
1427 PermissionRequestManager::DetermineCurrentRequestUIDisposition() {
1428   if (current_request_prompt_disposition_.has_value())
1429     return current_request_prompt_disposition_.value();
1430   return PermissionPromptDisposition::NONE_VISIBLE;
1431 }
1432
1433 PermissionPromptDispositionReason
1434 PermissionRequestManager::DetermineCurrentRequestUIDispositionReasonForUMA() {
1435   auto quiet_ui_reason = ReasonForUsingQuietUi();
1436   if (!quiet_ui_reason)
1437     return PermissionPromptDispositionReason::DEFAULT_FALLBACK;
1438   switch (*quiet_ui_reason) {
1439     case QuietUiReason::kEnabledInPrefs:
1440       return PermissionPromptDispositionReason::USER_PREFERENCE_IN_SETTINGS;
1441     case QuietUiReason::kTriggeredByCrowdDeny:
1442     case QuietUiReason::kTriggeredDueToAbusiveRequests:
1443     case QuietUiReason::kTriggeredDueToAbusiveContent:
1444     case QuietUiReason::kTriggeredDueToDisruptiveBehavior:
1445       return PermissionPromptDispositionReason::SAFE_BROWSING_VERDICT;
1446     case QuietUiReason::kServicePredictedVeryUnlikelyGrant:
1447       return PermissionPromptDispositionReason::PREDICTION_SERVICE;
1448     case QuietUiReason::kOnDevicePredictedVeryUnlikelyGrant:
1449       return PermissionPromptDispositionReason::ON_DEVICE_PREDICTION_MODEL;
1450   }
1451 }
1452
1453 void PermissionRequestManager::LogWarningToConsole(const char* message) {
1454   web_contents()->GetPrimaryMainFrame()->AddMessageToConsole(
1455       blink::mojom::ConsoleMessageLevel::kWarning, message);
1456 }
1457
1458 void PermissionRequestManager::DoAutoResponseForTesting() {
1459   switch (auto_response_for_test_) {
1460     case ACCEPT_ONCE:
1461       AcceptThisTime();
1462       break;
1463     case ACCEPT_ALL:
1464       Accept();
1465       break;
1466     case DENY_ALL:
1467       Deny();
1468       break;
1469     case DISMISS:
1470       Dismiss();
1471       break;
1472     case NONE:
1473       NOTREACHED();
1474   }
1475 }
1476
1477 bool PermissionRequestManager::
1478     IsCurrentRequestEmbeddedPermissionElementInitiated() const {
1479   return IsRequestInProgress() &&
1480          requests_[0]->IsEmbeddedPermissionElementInitiated();
1481 }
1482
1483 bool PermissionRequestManager::ShouldFinalizeRequestAfterDecided(
1484     PermissionAction action) const {
1485   // If the action is IGNORED, it is not coming from the prompt itself but
1486   // rather from external circumstance (like tab switching) and therefore
1487   // |view_->ShouldFinalizeRequestAfterDecided| is not queried.
1488
1489   // If there is an autoresponse set, or there is no |view_|, finalize the
1490   // request since there won't be a separate |FinalizeCurrentRequests()| call.
1491   if (action == PermissionAction::IGNORED || auto_response_for_test_ != NONE ||
1492       !view_) {
1493     return true;
1494   }
1495
1496   return view_->ShouldFinalizeRequestAfterDecided();
1497 }
1498
1499 WEB_CONTENTS_USER_DATA_KEY_IMPL(PermissionRequestManager);
1500
1501 }  // namespace permissions