permission_request_manager.cc 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114
  1. // Copyright 2014 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "components/permissions/permission_request_manager.h"
  5. #include <algorithm>
  6. #include <string>
  7. #include "base/auto_reset.h"
  8. #include "base/bind.h"
  9. #include "base/command_line.h"
  10. #include "base/metrics/histogram_functions.h"
  11. #include "base/metrics/user_metrics.h"
  12. #include "base/metrics/user_metrics_action.h"
  13. #include "base/observer_list.h"
  14. #include "base/stl_util.h"
  15. #include "base/threading/sequenced_task_runner_handle.h"
  16. #include "components/autofill_assistant/browser/public/runtime_manager.h"
  17. #include "components/back_forward_cache/back_forward_cache_disable.h"
  18. #include "components/permissions/features.h"
  19. #include "components/permissions/permission_decision_auto_blocker.h"
  20. #include "components/permissions/permission_prompt.h"
  21. #include "components/permissions/permission_request.h"
  22. #include "components/permissions/permissions_client.h"
  23. #include "components/permissions/request_type.h"
  24. #include "components/permissions/switches.h"
  25. #include "content/public/browser/back_forward_cache.h"
  26. #include "content/public/browser/browser_task_traits.h"
  27. #include "content/public/browser/browser_thread.h"
  28. #include "content/public/browser/disallow_activation_reason.h"
  29. #include "content/public/browser/navigation_handle.h"
  30. #include "content/public/browser/render_frame_host.h"
  31. #include "content/public/browser/render_process_host.h"
  32. #include "content/public/browser/web_contents.h"
  33. #include "url/gurl.h"
  34. #include "url/origin.h"
  35. #if BUILDFLAG(IS_ANDROID)
  36. #include "components/permissions/android/android_permission_util.h"
  37. #endif
  38. namespace permissions {
  39. const char kAbusiveNotificationRequestsEnforcementMessage[] =
  40. "Chrome is blocking notification permission requests on this site because "
  41. "the site tends to show permission requests that mislead, trick, or force "
  42. "users into allowing notifications. You should fix the issues as soon as "
  43. "possible and submit your site for another review. Learn more at "
  44. "https://support.google.com/webtools/answer/9799048.";
  45. const char kAbusiveNotificationRequestsWarningMessage[] =
  46. "Chrome might start blocking notification permission requests on this site "
  47. "in the future because the site tends to show permission requests that "
  48. "mislead, trick, or force users into allowing notifications. You should "
  49. "fix the issues as soon as possible and submit your site for another "
  50. "review. Learn more at https://support.google.com/webtools/answer/9799048.";
  51. constexpr char kAbusiveNotificationContentEnforcementMessage[] =
  52. "Chrome is blocking notification permission requests on this site because "
  53. "the site tends to show notifications with content that mislead or trick "
  54. "users. You should fix the issues as soon as possible and submit your site "
  55. "for another review. Learn more at "
  56. "https://support.google.com/webtools/answer/9799048";
  57. constexpr char kAbusiveNotificationContentWarningMessage[] =
  58. "Chrome might start blocking notification permission requests on this site "
  59. "in the future because the site tends to show notifications with content "
  60. "that mislead or trick users. You should fix the issues as soon as "
  61. "possible and submit your site for another review. Learn more at "
  62. "https://support.google.com/webtools/answer/9799048";
  63. constexpr char kDisruptiveNotificationBehaviorEnforcementMessage[] =
  64. "Chrome is blocking notification permission requests on this site because "
  65. "the site exhibits behaviors that may be disruptive to users.";
  66. namespace {
  67. // When there are multiple permissions requests in
  68. // `pending_permission_requests_`, we try to prioritize them based on the
  69. // acceptance rates. Notifications and Geolocations have one of the lowest
  70. // acceptance, hence they have the lowest priority and will be shown the last.
  71. bool IsLowPriorityRequest(PermissionRequest* request) {
  72. return request->request_type() == RequestType::kNotifications ||
  73. request->request_type() == RequestType::kGeolocation;
  74. }
  75. // In case of multiple permission requests that use chip UI, a newly added
  76. // request will preempt the currently showing request, which is put back to the
  77. // queue, and will be shown later. To reduce user annoyance, if a quiet chip
  78. // permission prompt was displayed longer than `kQuietChipIgnoreTimeout`, we
  79. // consider it as shown long enough and it will not be shown again after it is
  80. // preempted.
  81. // TODO(crbug.com/1221083): If a user switched tabs, do not include that time as
  82. // "shown".
  83. bool ShouldShowQuietRequestAgainIfPreempted(
  84. absl::optional<base::Time> request_display_start_time) {
  85. if (request_display_start_time->is_null()) {
  86. return true;
  87. }
  88. static constexpr base::TimeDelta kQuietChipIgnoreTimeout = base::Seconds(8.5);
  89. return base::Time::Now() - request_display_start_time.value() <
  90. kQuietChipIgnoreTimeout;
  91. }
  92. bool IsMediaRequest(RequestType type) {
  93. #if !BUILDFLAG(IS_ANDROID)
  94. if (type == RequestType::kCameraPanTiltZoom)
  95. return true;
  96. #endif
  97. return type == RequestType::kMicStream || type == RequestType::kCameraStream;
  98. }
  99. bool ShouldGroupRequests(PermissionRequest* a, PermissionRequest* b) {
  100. if (a->requesting_origin() != b->requesting_origin())
  101. return false;
  102. // Group if both requests are media requests.
  103. if (IsMediaRequest(a->request_type()) && IsMediaRequest(b->request_type())) {
  104. return true;
  105. }
  106. return false;
  107. }
  108. } // namespace
  109. // PermissionRequestManager ----------------------------------------------------
  110. bool PermissionRequestManager::PermissionRequestSource::
  111. IsSourceFrameInactiveAndDisallowActivation() const {
  112. content::RenderFrameHost* rfh =
  113. content::RenderFrameHost::FromID(render_process_id, render_frame_id);
  114. return !rfh ||
  115. rfh->IsInactiveAndDisallowActivation(
  116. content::DisallowActivationReasonId::kPermissionRequestSource);
  117. }
  118. PermissionRequestManager::~PermissionRequestManager() {
  119. DCHECK(!IsRequestInProgress());
  120. DCHECK(duplicate_requests_.empty());
  121. DCHECK(pending_permission_requests_.IsEmpty());
  122. }
  123. void PermissionRequestManager::AddRequest(
  124. content::RenderFrameHost* source_frame,
  125. PermissionRequest* request) {
  126. DCHECK(source_frame);
  127. DCHECK_EQ(content::WebContents::FromRenderFrameHost(source_frame),
  128. web_contents());
  129. if (base::CommandLine::ForCurrentProcess()->HasSwitch(
  130. switches::kDenyPermissionPrompts)) {
  131. request->PermissionDenied();
  132. request->RequestFinished();
  133. return;
  134. }
  135. if (source_frame->IsInactiveAndDisallowActivation(
  136. content::DisallowActivationReasonId::kPermissionAddRequest)) {
  137. request->Cancelled();
  138. request->RequestFinished();
  139. return;
  140. }
  141. if (source_frame->IsNestedWithinFencedFrame()) {
  142. request->Cancelled();
  143. request->RequestFinished();
  144. return;
  145. }
  146. #if BUILDFLAG(IS_ANDROID)
  147. if (request->GetContentSettingsType() == ContentSettingsType::NOTIFICATIONS) {
  148. bool app_level_settings_allow_site_notifications =
  149. enabled_app_level_notification_permission_for_testing_.has_value()
  150. ? enabled_app_level_notification_permission_for_testing_.value()
  151. : DoesAppLevelSettingsAllowSiteNotifications();
  152. base::UmaHistogramBoolean(
  153. "Permissions.Prompt.Notifications.EnabledAppLevel",
  154. app_level_settings_allow_site_notifications);
  155. if (!app_level_settings_allow_site_notifications &&
  156. base::FeatureList::IsEnabled(
  157. features::kBlockNotificationPromptsIfDisabledOnAppLevel)) {
  158. // Automatically cancel site Notification requests when Chrome is not able
  159. // to send notifications in an app level.
  160. request->Cancelled();
  161. request->RequestFinished();
  162. return;
  163. }
  164. }
  165. #endif // BUILDFLAG(IS_ANDROID)
  166. if (is_notification_prompt_cooldown_active_ &&
  167. request->GetContentSettingsType() == ContentSettingsType::NOTIFICATIONS) {
  168. // Short-circuit by canceling rather than denying to avoid creating a large
  169. // number of content setting exceptions on Desktop / disabled notification
  170. // channels on Android.
  171. request->Cancelled();
  172. request->RequestFinished();
  173. return;
  174. }
  175. if (!web_contents_supports_permission_requests_) {
  176. request->Cancelled();
  177. request->RequestFinished();
  178. return;
  179. }
  180. // TODO(tsergeant): change the UMA to no longer mention bubbles.
  181. base::RecordAction(base::UserMetricsAction("PermissionBubbleRequest"));
  182. // TODO(gbillock): is there a race between an early request on a
  183. // newly-navigated page and the to-be-cleaned-up requests on the previous
  184. // page? We should maybe listen to DidStartNavigationToPendingEntry (and
  185. // any other renderer-side nav initiations?). Double-check this for
  186. // correct behavior on interstitials -- we probably want to basically queue
  187. // any request for which GetVisibleURL != GetLastCommittedURL.
  188. CHECK_EQ(source_frame->GetMainFrame(), web_contents()->GetPrimaryMainFrame());
  189. const GURL main_frame_origin =
  190. PermissionUtil::GetLastCommittedOriginAsURL(source_frame->GetMainFrame());
  191. bool is_main_frame =
  192. url::IsSameOriginWith(main_frame_origin, request->requesting_origin());
  193. absl::optional<url::Origin> auto_approval_origin =
  194. PermissionsClient::Get()->GetAutoApprovalOrigin();
  195. if (auto_approval_origin) {
  196. if (url::Origin::Create(request->requesting_origin()) ==
  197. auto_approval_origin.value()) {
  198. request->PermissionGranted(/*is_one_time=*/false);
  199. }
  200. request->RequestFinished();
  201. return;
  202. }
  203. // Cancel permission requests wile Autofill Assistant's UI is shown.
  204. auto* assistant_runtime_manager =
  205. autofill_assistant::RuntimeManager::GetForWebContents(web_contents());
  206. if (assistant_runtime_manager && assistant_runtime_manager->GetState() ==
  207. autofill_assistant::UIState::kShown) {
  208. request->Cancelled();
  209. request->RequestFinished();
  210. return;
  211. }
  212. // Don't re-add an existing request or one with a duplicate text request.
  213. PermissionRequest* existing_request = GetExistingRequest(request);
  214. if (existing_request) {
  215. // |request| is a duplicate. Add it to |duplicate_requests_| unless it's the
  216. // same object as |existing_request| or an existing duplicate.
  217. if (request == existing_request)
  218. return;
  219. auto range = duplicate_requests_.equal_range(existing_request);
  220. for (auto it = range.first; it != range.second; ++it) {
  221. if (request == it->second)
  222. return;
  223. }
  224. duplicate_requests_.insert(std::make_pair(existing_request, request));
  225. return;
  226. }
  227. if (is_main_frame) {
  228. if (IsRequestInProgress()) {
  229. base::RecordAction(
  230. base::UserMetricsAction("PermissionBubbleRequestQueued"));
  231. }
  232. } else {
  233. base::RecordAction(
  234. base::UserMetricsAction("PermissionBubbleIFrameRequestQueued"));
  235. }
  236. CurrentRequestFate current_request_fate =
  237. GetCurrentRequestFateInFaceOfNewRequest(request);
  238. if (current_request_fate == CurrentRequestFate::Preempt) {
  239. PreemptAndRequeueCurrentRequest();
  240. }
  241. QueueRequest(source_frame, request);
  242. if (current_request_fate == CurrentRequestFate::Finalize) {
  243. // FinalizeCurrentRequests will call ScheduleDequeueRequest on its own.
  244. FinalizeCurrentRequests(PermissionAction::IGNORED);
  245. } else {
  246. ScheduleDequeueRequestIfNeeded();
  247. }
  248. }
  249. PermissionRequestManager::CurrentRequestFate
  250. PermissionRequestManager::GetCurrentRequestFateInFaceOfNewRequest(
  251. PermissionRequest* new_request) {
  252. if (base::FeatureList::IsEnabled(features::kPermissionQuietChip)) {
  253. if (ShouldCurrentRequestUseQuietUI() &&
  254. !ShouldShowQuietRequestAgainIfPreempted(
  255. current_request_first_display_time_)) {
  256. return CurrentRequestFate::Finalize;
  257. }
  258. if (base::FeatureList::IsEnabled(features::kPermissionChip)) {
  259. // Preempt current request if it is a quiet UI request or it is not
  260. // Notifications or Geolocation.
  261. if (ShouldCurrentRequestUseQuietUI() ||
  262. !IsLowPriorityRequest(new_request)) {
  263. return CurrentRequestFate::Preempt;
  264. }
  265. } else {
  266. if (ShouldCurrentRequestUseQuietUI()) {
  267. return CurrentRequestFate::Preempt;
  268. }
  269. }
  270. } else {
  271. if (base::FeatureList::IsEnabled(features::kPermissionChip)) {
  272. return CurrentRequestFate::Preempt;
  273. } else if (ShouldCurrentRequestUseQuietUI()) {
  274. // If we're displaying a quiet permission request, ignore it in favor of a
  275. // new permission request.
  276. return CurrentRequestFate::Finalize;
  277. }
  278. }
  279. return CurrentRequestFate::KeepCurrent;
  280. }
  281. void PermissionRequestManager::QueueRequest(
  282. content::RenderFrameHost* source_frame,
  283. PermissionRequest* request) {
  284. pending_permission_requests_.Push(request);
  285. request_sources_map_.emplace(
  286. request, PermissionRequestSource({source_frame->GetProcess()->GetID(),
  287. source_frame->GetRoutingID()}));
  288. }
  289. void PermissionRequestManager::PreemptAndRequeueCurrentRequest() {
  290. ResetViewStateForCurrentRequest();
  291. for (auto* current_request : requests_) {
  292. pending_permission_requests_.Push(current_request);
  293. }
  294. requests_.clear();
  295. }
  296. void PermissionRequestManager::UpdateAnchor() {
  297. if (view_) {
  298. // When the prompt's anchor is being updated, the prompt view can be
  299. // recreated for the new browser. Because of that, ignore prompt callbacks
  300. // while doing that.
  301. base::AutoReset<bool> ignore(&ignore_callbacks_from_prompt_, true);
  302. view_->UpdateAnchor();
  303. }
  304. }
  305. void PermissionRequestManager::DidStartNavigation(
  306. content::NavigationHandle* navigation_handle) {
  307. if (!navigation_handle->IsInPrimaryMainFrame() ||
  308. navigation_handle->IsSameDocument()) {
  309. return;
  310. }
  311. // Cooldown lasts until the next user-initiated navigation, which is defined
  312. // as either a renderer-initiated navigation with a user gesture, or a
  313. // browser-initiated navigation.
  314. //
  315. // TODO(crbug.com/952347): This check has to be done at DidStartNavigation
  316. // time, the HasUserGesture state is lost by the time the navigation
  317. // commits.
  318. if (!navigation_handle->IsRendererInitiated() ||
  319. navigation_handle->HasUserGesture()) {
  320. is_notification_prompt_cooldown_active_ = false;
  321. }
  322. }
  323. void PermissionRequestManager::DidFinishNavigation(
  324. content::NavigationHandle* navigation_handle) {
  325. if (!navigation_handle->IsInPrimaryMainFrame() ||
  326. !navigation_handle->HasCommitted() ||
  327. navigation_handle->IsSameDocument()) {
  328. return;
  329. }
  330. if (!pending_permission_requests_.IsEmpty() || IsRequestInProgress()) {
  331. // |pending_permission_requests_| and |requests_| will be deleted below,
  332. // which might be a problem for back-forward cache — the page might be
  333. // restored later, but the requests won't be. Disable bfcache here if we
  334. // have any requests here to prevent this from happening.
  335. content::BackForwardCache::DisableForRenderFrameHost(
  336. navigation_handle->GetPreviousRenderFrameHostId(),
  337. back_forward_cache::DisabledReason(
  338. back_forward_cache::DisabledReasonId::kPermissionRequestManager));
  339. }
  340. CleanUpRequests();
  341. }
  342. void PermissionRequestManager::DocumentOnLoadCompletedInPrimaryMainFrame() {
  343. // This is scheduled because while all calls to the browser have been
  344. // issued at DOMContentLoaded, they may be bouncing around in scheduled
  345. // callbacks finding the UI thread still. This makes sure we allow those
  346. // scheduled calls to AddRequest to complete before we show the page-load
  347. // permissions bubble.
  348. ScheduleDequeueRequestIfNeeded();
  349. }
  350. void PermissionRequestManager::DOMContentLoaded(
  351. content::RenderFrameHost* render_frame_host) {
  352. ScheduleDequeueRequestIfNeeded();
  353. }
  354. void PermissionRequestManager::WebContentsDestroyed() {
  355. // If the web contents has been destroyed, treat the bubble as cancelled.
  356. CleanUpRequests();
  357. // The WebContents is going away; be aggressively paranoid and delete
  358. // ourselves lest other parts of the system attempt to add permission
  359. // bubbles or use us otherwise during the destruction.
  360. web_contents()->RemoveUserData(UserDataKey());
  361. // That was the equivalent of "delete this". This object is now destroyed;
  362. // returning from this function is the only safe thing to do.
  363. }
  364. void PermissionRequestManager::OnVisibilityChanged(
  365. content::Visibility visibility) {
  366. bool tab_was_hidden = tab_is_hidden_;
  367. tab_is_hidden_ = visibility == content::Visibility::HIDDEN;
  368. if (tab_was_hidden == tab_is_hidden_)
  369. return;
  370. if (tab_is_hidden_) {
  371. if (view_) {
  372. switch (view_->GetTabSwitchingBehavior()) {
  373. case PermissionPrompt::TabSwitchingBehavior::
  374. kDestroyPromptButKeepRequestPending:
  375. DeleteBubble();
  376. break;
  377. case PermissionPrompt::TabSwitchingBehavior::
  378. kDestroyPromptAndIgnoreRequest:
  379. FinalizeCurrentRequests(PermissionAction::IGNORED);
  380. break;
  381. case PermissionPrompt::TabSwitchingBehavior::kKeepPromptAlive:
  382. break;
  383. }
  384. }
  385. return;
  386. }
  387. if (!web_contents()->IsDocumentOnLoadCompletedInPrimaryMainFrame())
  388. return;
  389. if (!IsRequestInProgress()) {
  390. ScheduleDequeueRequestIfNeeded();
  391. return;
  392. }
  393. if (view_) {
  394. // We switched tabs away and back while a prompt was active.
  395. DCHECK_EQ(view_->GetTabSwitchingBehavior(),
  396. PermissionPrompt::TabSwitchingBehavior::kKeepPromptAlive);
  397. } else if (current_request_ui_to_use_.has_value()) {
  398. ShowBubble();
  399. }
  400. }
  401. const std::vector<PermissionRequest*>& PermissionRequestManager::Requests() {
  402. return requests_;
  403. }
  404. GURL PermissionRequestManager::GetRequestingOrigin() const {
  405. CHECK(!requests_.empty());
  406. GURL origin = requests_.front()->requesting_origin();
  407. if (DCHECK_IS_ON()) {
  408. for (auto* request : requests_)
  409. DCHECK_EQ(origin, request->requesting_origin());
  410. }
  411. return origin;
  412. }
  413. GURL PermissionRequestManager::GetEmbeddingOrigin() const {
  414. return PermissionUtil::GetLastCommittedOriginAsURL(
  415. web_contents()->GetPrimaryMainFrame());
  416. }
  417. void PermissionRequestManager::Accept() {
  418. if (ignore_callbacks_from_prompt_)
  419. return;
  420. DCHECK(view_);
  421. std::vector<PermissionRequest*>::iterator requests_iter;
  422. for (requests_iter = requests_.begin(); requests_iter != requests_.end();
  423. requests_iter++) {
  424. PermissionGrantedIncludingDuplicates(*requests_iter,
  425. /*is_one_time=*/false);
  426. }
  427. FinalizeCurrentRequests(PermissionAction::GRANTED);
  428. }
  429. void PermissionRequestManager::AcceptThisTime() {
  430. if (ignore_callbacks_from_prompt_)
  431. return;
  432. DCHECK(view_);
  433. std::vector<PermissionRequest*>::iterator requests_iter;
  434. for (requests_iter = requests_.begin(); requests_iter != requests_.end();
  435. requests_iter++) {
  436. PermissionGrantedIncludingDuplicates(*requests_iter,
  437. /*is_one_time=*/true);
  438. }
  439. FinalizeCurrentRequests(PermissionAction::GRANTED_ONCE);
  440. }
  441. void PermissionRequestManager::Deny() {
  442. if (ignore_callbacks_from_prompt_)
  443. return;
  444. DCHECK(view_);
  445. // Suppress any further prompts in this WebContents, from any origin, until
  446. // there is a user-initiated navigation. This stops users from getting
  447. // trapped in request loops where the website automatically navigates
  448. // cross-origin (e.g. to another subdomain) to be able to prompt again after
  449. // a rejection.
  450. if (base::FeatureList::IsEnabled(
  451. features::kBlockRepeatedNotificationPermissionPrompts) &&
  452. std::any_of(requests_.begin(), requests_.end(), [](const auto* request) {
  453. return request->GetContentSettingsType() ==
  454. ContentSettingsType::NOTIFICATIONS;
  455. })) {
  456. is_notification_prompt_cooldown_active_ = true;
  457. }
  458. std::vector<PermissionRequest*>::iterator requests_iter;
  459. for (requests_iter = requests_.begin(); requests_iter != requests_.end();
  460. requests_iter++) {
  461. PermissionDeniedIncludingDuplicates(*requests_iter);
  462. }
  463. FinalizeCurrentRequests(PermissionAction::DENIED);
  464. }
  465. void PermissionRequestManager::Dismiss() {
  466. if (ignore_callbacks_from_prompt_)
  467. return;
  468. DCHECK(view_);
  469. std::vector<PermissionRequest*>::iterator requests_iter;
  470. for (requests_iter = requests_.begin(); requests_iter != requests_.end();
  471. requests_iter++) {
  472. CancelledIncludingDuplicates(*requests_iter);
  473. }
  474. FinalizeCurrentRequests(PermissionAction::DISMISSED);
  475. }
  476. void PermissionRequestManager::Ignore() {
  477. if (ignore_callbacks_from_prompt_)
  478. return;
  479. DCHECK(view_);
  480. std::vector<PermissionRequest*>::iterator requests_iter;
  481. for (requests_iter = requests_.begin(); requests_iter != requests_.end();
  482. requests_iter++) {
  483. CancelledIncludingDuplicates(*requests_iter);
  484. }
  485. FinalizeCurrentRequests(PermissionAction::IGNORED);
  486. }
  487. bool PermissionRequestManager::WasCurrentRequestAlreadyDisplayed() {
  488. return current_request_already_displayed_;
  489. }
  490. void PermissionRequestManager::SetDismissOnTabClose() {
  491. should_dismiss_current_request_ = true;
  492. }
  493. void PermissionRequestManager::SetBubbleShown() {
  494. did_show_bubble_ = true;
  495. }
  496. void PermissionRequestManager::SetDecisionTime() {
  497. current_request_decision_time_ = base::Time::Now();
  498. }
  499. void PermissionRequestManager::SetManageClicked() {
  500. set_manage_clicked();
  501. }
  502. void PermissionRequestManager::SetLearnMoreClicked() {
  503. set_learn_more_clicked();
  504. }
  505. base::WeakPtr<PermissionPrompt::Delegate>
  506. PermissionRequestManager::GetWeakPtr() {
  507. return weak_factory_.GetWeakPtr();
  508. }
  509. bool PermissionRequestManager::RecreateView() {
  510. view_ = view_factory_.Run(web_contents(), this);
  511. if (!view_) {
  512. current_request_prompt_disposition_ =
  513. PermissionPromptDisposition::NONE_VISIBLE;
  514. FinalizeCurrentRequests(PermissionAction::IGNORED);
  515. return false;
  516. }
  517. current_request_prompt_disposition_ = view_->GetPromptDisposition();
  518. return true;
  519. }
  520. PermissionRequestManager::PermissionRequestManager(
  521. content::WebContents* web_contents)
  522. : content::WebContentsObserver(web_contents),
  523. content::WebContentsUserData<PermissionRequestManager>(*web_contents),
  524. view_factory_(base::BindRepeating(&PermissionPrompt::Create)),
  525. view_(nullptr),
  526. tab_is_hidden_(web_contents->GetVisibility() ==
  527. content::Visibility::HIDDEN),
  528. auto_response_for_test_(NONE),
  529. permission_ui_selectors_(
  530. PermissionsClient::Get()->CreatePermissionUiSelectors(
  531. web_contents->GetBrowserContext())) {}
  532. void PermissionRequestManager::ScheduleShowBubble() {
  533. base::RecordAction(base::UserMetricsAction("PermissionBubbleRequest"));
  534. content::GetUIThreadTaskRunner({})->PostTask(
  535. FROM_HERE, base::BindOnce(&PermissionRequestManager::ShowBubble,
  536. weak_factory_.GetWeakPtr()));
  537. }
  538. void PermissionRequestManager::DequeueRequestIfNeeded() {
  539. // TODO(olesiamarukhno): Media requests block other media requests from
  540. // pre-empting them. For example, when a camera request is pending and mic
  541. // is requested, the camera request remains pending and mic request appears
  542. // only after the camera request is resolved. This is caused by code in
  543. // PermissionBubbleMediaAccessHandler and UserMediaClient. We probably don't
  544. // need two permission queues, so resolve the duplication.
  545. if (!web_contents()->IsDocumentOnLoadCompletedInPrimaryMainFrame() || view_ ||
  546. IsRequestInProgress()) {
  547. return;
  548. }
  549. // Find first valid request.
  550. while (!pending_permission_requests_.IsEmpty()) {
  551. PermissionRequest* next = pending_permission_requests_.Pop();
  552. PermissionRequestSource& source = request_sources_map_.find(next)->second;
  553. if (!source.IsSourceFrameInactiveAndDisallowActivation()) {
  554. requests_.push_back(next);
  555. break;
  556. }
  557. next->Cancelled();
  558. next->RequestFinished();
  559. request_sources_map_.erase(request_sources_map_.find(next));
  560. }
  561. if (requests_.empty()) {
  562. return;
  563. }
  564. // Find additional requests that can be grouped with the first one.
  565. for (; !pending_permission_requests_.IsEmpty();
  566. pending_permission_requests_.Pop()) {
  567. PermissionRequest* front = pending_permission_requests_.Peek();
  568. PermissionRequestSource& source = request_sources_map_.find(front)->second;
  569. if (source.IsSourceFrameInactiveAndDisallowActivation()) {
  570. front->Cancelled();
  571. front->RequestFinished();
  572. request_sources_map_.erase(request_sources_map_.find(front));
  573. } else if (ShouldGroupRequests(requests_.front(), front)) {
  574. requests_.push_back(front);
  575. } else {
  576. break;
  577. }
  578. }
  579. if (!permission_ui_selectors_.empty()) {
  580. DCHECK(!current_request_ui_to_use_.has_value());
  581. // Initialize the selector decisions vector.
  582. DCHECK(selector_decisions_.empty());
  583. selector_decisions_.resize(permission_ui_selectors_.size());
  584. for (size_t selector_index = 0;
  585. selector_index < permission_ui_selectors_.size(); ++selector_index) {
  586. if (permission_ui_selectors_[selector_index]
  587. ->IsPermissionRequestSupported(
  588. requests_.front()->request_type())) {
  589. permission_ui_selectors_[selector_index]->SelectUiToUse(
  590. requests_.front(),
  591. base::BindOnce(
  592. &PermissionRequestManager::OnPermissionUiSelectorDone,
  593. weak_factory_.GetWeakPtr(), selector_index));
  594. } else {
  595. OnPermissionUiSelectorDone(
  596. selector_index,
  597. PermissionUiSelector::Decision::UseNormalUiAndShowNoWarning());
  598. }
  599. }
  600. } else {
  601. current_request_ui_to_use_ =
  602. UiDecision(UiDecision::UseNormalUi(), UiDecision::ShowNoWarning());
  603. ScheduleShowBubble();
  604. }
  605. }
  606. void PermissionRequestManager::ScheduleDequeueRequestIfNeeded() {
  607. base::SequencedTaskRunnerHandle::Get()->PostTask(
  608. FROM_HERE,
  609. base::BindOnce(&PermissionRequestManager::DequeueRequestIfNeeded,
  610. weak_factory_.GetWeakPtr()));
  611. }
  612. void PermissionRequestManager::ShowBubble() {
  613. // There is a race condition where the request might have been removed
  614. // already so double-checking that there is a request in progress.
  615. //
  616. // There is no need to show a new bubble if the previous one still exists.
  617. if (!IsRequestInProgress() || view_)
  618. return;
  619. DCHECK(web_contents()->IsDocumentOnLoadCompletedInPrimaryMainFrame());
  620. DCHECK(current_request_ui_to_use_);
  621. if (tab_is_hidden_)
  622. return;
  623. if (!RecreateView())
  624. return;
  625. if (!current_request_already_displayed_) {
  626. PermissionUmaUtil::PermissionPromptShown(requests_);
  627. auto quiet_ui_reason = ReasonForUsingQuietUi();
  628. if (quiet_ui_reason) {
  629. switch (*quiet_ui_reason) {
  630. case QuietUiReason::kEnabledInPrefs:
  631. case QuietUiReason::kTriggeredByCrowdDeny:
  632. case QuietUiReason::kServicePredictedVeryUnlikelyGrant:
  633. case QuietUiReason::kOnDevicePredictedVeryUnlikelyGrant:
  634. break;
  635. case QuietUiReason::kTriggeredDueToAbusiveRequests:
  636. LogWarningToConsole(kAbusiveNotificationRequestsEnforcementMessage);
  637. break;
  638. case QuietUiReason::kTriggeredDueToAbusiveContent:
  639. LogWarningToConsole(kAbusiveNotificationContentEnforcementMessage);
  640. break;
  641. case QuietUiReason::kTriggeredDueToDisruptiveBehavior:
  642. LogWarningToConsole(
  643. kDisruptiveNotificationBehaviorEnforcementMessage);
  644. break;
  645. }
  646. base::RecordAction(base::UserMetricsAction(
  647. "Notifications.Quiet.PermissionRequestShown"));
  648. }
  649. }
  650. current_request_already_displayed_ = true;
  651. current_request_first_display_time_ = base::Time::Now();
  652. NotifyBubbleAdded();
  653. // If in testing mode, automatically respond to the bubble that was shown.
  654. if (auto_response_for_test_ != NONE)
  655. DoAutoResponseForTesting();
  656. }
  657. void PermissionRequestManager::DeleteBubble() {
  658. DCHECK(view_);
  659. {
  660. base::AutoReset<bool> deleting(&ignore_callbacks_from_prompt_, true);
  661. view_.reset();
  662. }
  663. NotifyBubbleRemoved();
  664. }
  665. void PermissionRequestManager::ResetViewStateForCurrentRequest() {
  666. for (const auto& selector : permission_ui_selectors_)
  667. selector->Cancel();
  668. current_request_already_displayed_ = false;
  669. current_request_first_display_time_ = base::Time();
  670. current_request_decision_time_ = base::Time();
  671. current_request_prompt_disposition_.reset();
  672. prediction_grant_likelihood_.reset();
  673. current_request_ui_to_use_.reset();
  674. was_decision_held_back_.reset();
  675. selector_decisions_.clear();
  676. should_dismiss_current_request_ = false;
  677. did_show_bubble_ = false;
  678. did_click_manage_ = false;
  679. did_click_learn_more_ = false;
  680. if (view_)
  681. DeleteBubble();
  682. }
  683. void PermissionRequestManager::FinalizeCurrentRequests(
  684. PermissionAction permission_action) {
  685. DCHECK(IsRequestInProgress());
  686. base::TimeDelta time_to_decision;
  687. if (!current_request_first_display_time_.is_null() &&
  688. permission_action != PermissionAction::IGNORED) {
  689. if (current_request_decision_time_.is_null()) {
  690. current_request_decision_time_ = base::Time::Now();
  691. }
  692. time_to_decision =
  693. current_request_decision_time_ - current_request_first_display_time_;
  694. }
  695. if (time_to_decision_for_test_.has_value()) {
  696. time_to_decision = time_to_decision_for_test_.value();
  697. time_to_decision_for_test_.reset();
  698. }
  699. PermissionUmaUtil::PermissionPromptResolved(
  700. requests_, web_contents(), permission_action, time_to_decision,
  701. DetermineCurrentRequestUIDisposition(),
  702. DetermineCurrentRequestUIDispositionReasonForUMA(),
  703. prediction_grant_likelihood_, was_decision_held_back_, did_show_bubble_,
  704. did_click_manage_, did_click_learn_more_);
  705. content::BrowserContext* browser_context =
  706. web_contents()->GetBrowserContext();
  707. PermissionDecisionAutoBlocker* autoblocker =
  708. PermissionsClient::Get()->GetPermissionDecisionAutoBlocker(
  709. browser_context);
  710. absl::optional<QuietUiReason> quiet_ui_reason;
  711. if (ShouldCurrentRequestUseQuietUI())
  712. quiet_ui_reason = ReasonForUsingQuietUi();
  713. for (PermissionRequest* request : requests_) {
  714. // TODO(timloh): We only support dismiss and ignore embargo for
  715. // permissions which use PermissionRequestImpl as the other subclasses
  716. // don't support GetContentSettingsType.
  717. if (request->GetContentSettingsType() == ContentSettingsType::DEFAULT)
  718. continue;
  719. PermissionsClient::Get()->OnPromptResolved(
  720. browser_context, request->request_type(), permission_action,
  721. request->requesting_origin(), DetermineCurrentRequestUIDisposition(),
  722. DetermineCurrentRequestUIDispositionReasonForUMA(),
  723. request->GetGestureType(), quiet_ui_reason);
  724. PermissionEmbargoStatus embargo_status =
  725. PermissionEmbargoStatus::NOT_EMBARGOED;
  726. if (permission_action == PermissionAction::DISMISSED) {
  727. if (autoblocker->RecordDismissAndEmbargo(
  728. request->requesting_origin(), request->GetContentSettingsType(),
  729. ShouldCurrentRequestUseQuietUI())) {
  730. embargo_status = PermissionEmbargoStatus::REPEATED_DISMISSALS;
  731. }
  732. } else if (permission_action == PermissionAction::IGNORED) {
  733. if (autoblocker->RecordIgnoreAndEmbargo(
  734. request->requesting_origin(), request->GetContentSettingsType(),
  735. ShouldCurrentRequestUseQuietUI())) {
  736. embargo_status = PermissionEmbargoStatus::REPEATED_IGNORES;
  737. }
  738. }
  739. PermissionUmaUtil::RecordEmbargoStatus(embargo_status);
  740. }
  741. ResetViewStateForCurrentRequest();
  742. std::vector<PermissionRequest*>::iterator requests_iter;
  743. for (requests_iter = requests_.begin(); requests_iter != requests_.end();
  744. requests_iter++) {
  745. RequestFinishedIncludingDuplicates(*requests_iter);
  746. request_sources_map_.erase(request_sources_map_.find(*requests_iter));
  747. }
  748. requests_.clear();
  749. for (Observer& observer : observer_list_)
  750. observer.OnRequestsFinalized();
  751. ScheduleDequeueRequestIfNeeded();
  752. }
  753. void PermissionRequestManager::CleanUpRequests() {
  754. for (; !pending_permission_requests_.IsEmpty();
  755. pending_permission_requests_.Pop()) {
  756. auto* pending_request = pending_permission_requests_.Peek();
  757. CancelledIncludingDuplicates(pending_request);
  758. RequestFinishedIncludingDuplicates(pending_request);
  759. request_sources_map_.erase(request_sources_map_.find(pending_request));
  760. }
  761. if (IsRequestInProgress()) {
  762. std::vector<PermissionRequest*>::iterator requests_iter;
  763. for (requests_iter = requests_.begin(); requests_iter != requests_.end();
  764. requests_iter++) {
  765. CancelledIncludingDuplicates(*requests_iter);
  766. }
  767. FinalizeCurrentRequests(should_dismiss_current_request_
  768. ? PermissionAction::DISMISSED
  769. : PermissionAction::IGNORED);
  770. should_dismiss_current_request_ = false;
  771. }
  772. }
  773. PermissionRequest* PermissionRequestManager::GetExistingRequest(
  774. PermissionRequest* request) {
  775. for (PermissionRequest* existing_request : requests_) {
  776. if (request->IsDuplicateOf(existing_request))
  777. return existing_request;
  778. }
  779. return pending_permission_requests_.FindDuplicate(request);
  780. }
  781. void PermissionRequestManager::PermissionGrantedIncludingDuplicates(
  782. PermissionRequest* request,
  783. bool is_one_time) {
  784. DCHECK_EQ(1ul, base::STLCount(requests_, request) +
  785. pending_permission_requests_.Count(request))
  786. << "Only requests in [pending_permission_]requests_ can have duplicates";
  787. request->PermissionGranted(is_one_time);
  788. auto range = duplicate_requests_.equal_range(request);
  789. for (auto it = range.first; it != range.second; ++it)
  790. it->second->PermissionGranted(is_one_time);
  791. }
  792. void PermissionRequestManager::PermissionDeniedIncludingDuplicates(
  793. PermissionRequest* request) {
  794. DCHECK_EQ(1ul, base::STLCount(requests_, request) +
  795. pending_permission_requests_.Count(request))
  796. << "Only requests in [pending_permission_]requests_ can have duplicates";
  797. request->PermissionDenied();
  798. auto range = duplicate_requests_.equal_range(request);
  799. for (auto it = range.first; it != range.second; ++it)
  800. it->second->PermissionDenied();
  801. }
  802. void PermissionRequestManager::CancelledIncludingDuplicates(
  803. PermissionRequest* request) {
  804. DCHECK_EQ(1ul, base::STLCount(requests_, request) +
  805. pending_permission_requests_.Count(request))
  806. << "Only requests in [pending_permission_]requests_ can have duplicates";
  807. request->Cancelled();
  808. auto range = duplicate_requests_.equal_range(request);
  809. for (auto it = range.first; it != range.second; ++it)
  810. it->second->Cancelled();
  811. }
  812. void PermissionRequestManager::RequestFinishedIncludingDuplicates(
  813. PermissionRequest* request) {
  814. DCHECK_EQ(1ul, base::STLCount(requests_, request) +
  815. pending_permission_requests_.Count(request))
  816. << "Only requests in [pending_permission_]requests_ can have duplicates";
  817. request->RequestFinished();
  818. // Beyond this point, |request| has probably been deleted.
  819. auto range = duplicate_requests_.equal_range(request);
  820. for (auto it = range.first; it != range.second; ++it)
  821. it->second->RequestFinished();
  822. // Additionally, we can now remove the duplicates.
  823. duplicate_requests_.erase(request);
  824. }
  825. void PermissionRequestManager::AddObserver(Observer* observer) {
  826. observer_list_.AddObserver(observer);
  827. }
  828. void PermissionRequestManager::RemoveObserver(Observer* observer) {
  829. observer_list_.RemoveObserver(observer);
  830. }
  831. bool PermissionRequestManager::ShouldCurrentRequestUseQuietUI() const {
  832. // ContentSettingImageModel might call into this method if the user switches
  833. // between tabs while the |notification_permission_ui_selectors_| are
  834. // pending.
  835. return ReasonForUsingQuietUi() != absl::nullopt;
  836. }
  837. absl::optional<PermissionRequestManager::QuietUiReason>
  838. PermissionRequestManager::ReasonForUsingQuietUi() const {
  839. if (!IsRequestInProgress() || !current_request_ui_to_use_ ||
  840. !current_request_ui_to_use_->quiet_ui_reason)
  841. return absl::nullopt;
  842. return *(current_request_ui_to_use_->quiet_ui_reason);
  843. }
  844. bool PermissionRequestManager::IsRequestInProgress() const {
  845. return !requests_.empty();
  846. }
  847. bool PermissionRequestManager::ShouldDropCurrentRequestIfCannotShowQuietly()
  848. const {
  849. absl::optional<QuietUiReason> quiet_ui_reason = ReasonForUsingQuietUi();
  850. if (quiet_ui_reason.has_value()) {
  851. switch (quiet_ui_reason.value()) {
  852. case QuietUiReason::kEnabledInPrefs:
  853. case QuietUiReason::kServicePredictedVeryUnlikelyGrant:
  854. case QuietUiReason::kOnDevicePredictedVeryUnlikelyGrant:
  855. case QuietUiReason::kTriggeredByCrowdDeny:
  856. return false;
  857. case QuietUiReason::kTriggeredDueToAbusiveRequests:
  858. case QuietUiReason::kTriggeredDueToAbusiveContent:
  859. case QuietUiReason::kTriggeredDueToDisruptiveBehavior:
  860. return true;
  861. }
  862. }
  863. return false;
  864. }
  865. void PermissionRequestManager::NotifyBubbleAdded() {
  866. for (Observer& observer : observer_list_)
  867. observer.OnBubbleAdded();
  868. }
  869. void PermissionRequestManager::NotifyBubbleRemoved() {
  870. for (Observer& observer : observer_list_)
  871. observer.OnBubbleRemoved();
  872. }
  873. void PermissionRequestManager::OnPermissionUiSelectorDone(
  874. size_t selector_index,
  875. const UiDecision& decision) {
  876. if (decision.warning_reason) {
  877. switch (*(decision.warning_reason)) {
  878. case WarningReason::kAbusiveRequests:
  879. LogWarningToConsole(kAbusiveNotificationRequestsWarningMessage);
  880. break;
  881. case WarningReason::kAbusiveContent:
  882. LogWarningToConsole(kAbusiveNotificationContentWarningMessage);
  883. break;
  884. case WarningReason::kDisruptiveBehavior:
  885. break;
  886. }
  887. }
  888. // We have already made a decision because of a higher priority selector
  889. // therefore this selector's decision can be discarded.
  890. if (current_request_ui_to_use_.has_value())
  891. return;
  892. CHECK_LT(selector_index, selector_decisions_.size());
  893. selector_decisions_[selector_index] = decision;
  894. size_t decision_index = 0;
  895. while (decision_index < selector_decisions_.size() &&
  896. selector_decisions_[decision_index].has_value()) {
  897. const UiDecision& current_decision =
  898. selector_decisions_[decision_index].value();
  899. if (!prediction_grant_likelihood_.has_value()) {
  900. prediction_grant_likelihood_ = permission_ui_selectors_[decision_index]
  901. ->PredictedGrantLikelihoodForUKM();
  902. }
  903. if (!was_decision_held_back_.has_value()) {
  904. was_decision_held_back_ = permission_ui_selectors_[decision_index]
  905. ->WasSelectorDecisionHeldback();
  906. }
  907. if (current_decision.quiet_ui_reason.has_value()) {
  908. current_request_ui_to_use_ = current_decision;
  909. break;
  910. }
  911. ++decision_index;
  912. }
  913. // All decisions have been considered and none was conclusive.
  914. if (decision_index == selector_decisions_.size() &&
  915. !current_request_ui_to_use_.has_value()) {
  916. current_request_ui_to_use_ = UiDecision::UseNormalUiAndShowNoWarning();
  917. }
  918. if (current_request_ui_to_use_.has_value()) {
  919. ScheduleShowBubble();
  920. }
  921. }
  922. PermissionPromptDisposition
  923. PermissionRequestManager::DetermineCurrentRequestUIDisposition() {
  924. if (current_request_prompt_disposition_.has_value())
  925. return current_request_prompt_disposition_.value();
  926. return PermissionPromptDisposition::NONE_VISIBLE;
  927. }
  928. PermissionPromptDispositionReason
  929. PermissionRequestManager::DetermineCurrentRequestUIDispositionReasonForUMA() {
  930. auto quiet_ui_reason = ReasonForUsingQuietUi();
  931. if (!quiet_ui_reason)
  932. return PermissionPromptDispositionReason::DEFAULT_FALLBACK;
  933. switch (*quiet_ui_reason) {
  934. case QuietUiReason::kEnabledInPrefs:
  935. return PermissionPromptDispositionReason::USER_PREFERENCE_IN_SETTINGS;
  936. case QuietUiReason::kTriggeredByCrowdDeny:
  937. case QuietUiReason::kTriggeredDueToAbusiveRequests:
  938. case QuietUiReason::kTriggeredDueToAbusiveContent:
  939. case QuietUiReason::kTriggeredDueToDisruptiveBehavior:
  940. return PermissionPromptDispositionReason::SAFE_BROWSING_VERDICT;
  941. case QuietUiReason::kServicePredictedVeryUnlikelyGrant:
  942. return PermissionPromptDispositionReason::PREDICTION_SERVICE;
  943. case QuietUiReason::kOnDevicePredictedVeryUnlikelyGrant:
  944. return PermissionPromptDispositionReason::ON_DEVICE_PREDICTION_MODEL;
  945. }
  946. }
  947. void PermissionRequestManager::LogWarningToConsole(const char* message) {
  948. web_contents()->GetPrimaryMainFrame()->AddMessageToConsole(
  949. blink::mojom::ConsoleMessageLevel::kWarning, message);
  950. }
  951. void PermissionRequestManager::DoAutoResponseForTesting() {
  952. switch (auto_response_for_test_) {
  953. case ACCEPT_ONCE:
  954. AcceptThisTime();
  955. break;
  956. case ACCEPT_ALL:
  957. Accept();
  958. break;
  959. case DENY_ALL:
  960. Deny();
  961. break;
  962. case DISMISS:
  963. Dismiss();
  964. break;
  965. case NONE:
  966. NOTREACHED();
  967. }
  968. }
  969. WEB_CONTENTS_USER_DATA_KEY_IMPL(PermissionRequestManager);
  970. } // namespace permissions