Fix emulator build error
[platform/framework/web/chromium-efl.git] / components / permissions / permission_request_manager.h
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 #ifndef COMPONENTS_PERMISSIONS_PERMISSION_REQUEST_MANAGER_H_
6 #define COMPONENTS_PERMISSIONS_PERMISSION_REQUEST_MANAGER_H_
7
8 #include <algorithm>
9 #include <utility>
10 #include <vector>
11
12 #include "base/check_is_test.h"
13 #include "base/gtest_prod_util.h"
14 #include "base/memory/weak_ptr.h"
15 #include "base/observer_list.h"
16 #include "base/time/time.h"
17 #include "base/timer/timer.h"
18 #include "components/permissions/permission_prompt.h"
19 #include "components/permissions/permission_request_queue.h"
20 #include "components/permissions/permission_ui_selector.h"
21 #include "components/permissions/permission_uma_util.h"
22 #include "components/permissions/request_type.h"
23 #include "content/public/browser/global_routing_id.h"
24 #include "content/public/browser/web_contents.h"
25 #include "content/public/browser/web_contents_observer.h"
26 #include "content/public/browser/web_contents_user_data.h"
27 #include "third_party/abseil-cpp/absl/types/optional.h"
28 #include "ui/gfx/geometry/rect.h"
29
30 class GURL;
31
32 namespace content {
33 class RenderFrameHost;
34 }
35
36 namespace test {
37 class PermissionRequestManagerTestApi;
38 }
39
40 namespace permissions {
41 class PermissionRequest;
42 enum class PermissionAction;
43 enum class PermissionPromptDisposition;
44 enum class PermissionPromptDispositionReason;
45
46 // The message to be printed in the Developer Tools console when the quiet
47 // notification permission prompt UI is shown on sites with abusive permission
48 // request flows.
49 extern const char kAbusiveNotificationRequestsEnforcementMessage[];
50
51 // The message to be printed in the Developer Tools console when the site is on
52 // the warning list for abusive permission request flows.
53 extern const char kAbusiveNotificationRequestsWarningMessage[];
54
55 // The message to be printed in the Developer Tools console when the site is on
56 // the blocking list for showing abusive notification content.
57 extern const char kAbusiveNotificationContentEnforcementMessage[];
58
59 // The message to be printed in the Developer Tools console when the site is on
60 // the warning list for showing abusive notification content.
61 extern const char kAbusiveNotificationContentWarningMessage[];
62
63 // Provides access to permissions bubbles. Allows clients to add a request
64 // callback interface to the existing permission bubble configuration.
65 // Depending on the situation and policy, that may add new UI to an existing
66 // permission bubble, create and show a new permission bubble, or provide no
67 // visible UI action at all. (In that case, the request will be immediately
68 // informed that the permission request failed.)
69 //
70 // A PermissionRequestManager is associated with a particular WebContents.
71 // Requests attached to a particular WebContents' PBM must outlive it.
72 //
73 // The PermissionRequestManager should be addressed on the UI thread.
74 class PermissionRequestManager
75     : public content::WebContentsObserver,
76       public content::WebContentsUserData<PermissionRequestManager>,
77       public PermissionPrompt::Delegate {
78  public:
79   class Observer : public base::CheckedObserver {
80    public:
81     virtual void OnTabVisibilityChanged(content::Visibility visibility) {}
82     virtual void OnPromptAdded() {}
83     virtual void OnPromptRemoved() {}
84     // Called when recreation of the permission prompt is not possible. It means
85     // that `PermissionRequestManager` is ready to display a prompt but the UI
86     // layer was not able to display it.
87     virtual void OnPromptRecreateViewFailed() {}
88     // Called when permission prompt creation was aborted because the current
89     // tab is no longer visible, hance it is not possible to display a prompt.
90     virtual void OnPromptCreationFailedHiddenTab() {}
91     // Called when the current batch of requests have been handled and the
92     // prompt is no longer visible. Note that there might be some queued
93     // permission requests that will get shown after this. This differs from
94     // OnPromptRemoved() in that the prompt may disappear while there are
95     // still in-flight requests (e.g. when switching tabs while the prompt is
96     // still visible).
97     virtual void OnRequestsFinalized() {}
98
99     virtual void OnPermissionRequestManagerDestructed() {}
100     virtual void OnNavigation(content::NavigationHandle* navigation_handle) {}
101
102     virtual void OnRequestDecided(permissions::PermissionAction action) {}
103   };
104
105   enum AutoResponseType { NONE, ACCEPT_ONCE, ACCEPT_ALL, DENY_ALL, DISMISS };
106
107   using UiDecision = PermissionUiSelector::Decision;
108   using QuietUiReason = PermissionUiSelector::QuietUiReason;
109   using WarningReason = PermissionUiSelector::WarningReason;
110
111   ~PermissionRequestManager() override;
112
113   // Adds a new request to the permission bubble. Ownership of the request
114   // remains with the caller. The caller must arrange for the request to
115   // outlive the PermissionRequestManager. If a bubble is visible when this
116   // call is made, the request will be queued up and shown after the current
117   // bubble closes. A request with message text identical to an outstanding
118   // request will be merged with the outstanding request, and will have the same
119   // callbacks called as the outstanding request.
120   void AddRequest(content::RenderFrameHost* source_frame,
121                   PermissionRequest* request);
122
123   // Will reposition the bubble (may change parent if necessary).
124   void UpdateAnchor();
125
126   // For observing the status of the permission bubble manager.
127   void AddObserver(Observer* observer);
128   void RemoveObserver(Observer* observer);
129
130   bool IsRequestInProgress() const;
131
132   // Returns `true` if a permission request is in progress but a prompt view is
133   // nullptr.
134   bool CanRestorePrompt();
135
136   // Recreates a permission prompt.
137   void RestorePrompt();
138
139   // Do NOT use this methods in production code. Use this methods in browser
140   // tests that need to accept or deny permissions when requested in
141   // JavaScript. Your test needs to set this appropriately, and then the bubble
142   // will proceed as desired as soon as Show() is called.
143   void set_auto_response_for_test(AutoResponseType response) {
144     auto_response_for_test_ = response;
145   }
146
147   // WebContentsObserver:
148   void DidStartNavigation(
149       content::NavigationHandle* navigation_handle) override;
150   void DidFinishNavigation(
151       content::NavigationHandle* navigation_handle) override;
152   void DocumentOnLoadCompletedInPrimaryMainFrame() override;
153   void DOMContentLoaded(content::RenderFrameHost* render_frame_host) override;
154   void WebContentsDestroyed() override;
155   void OnVisibilityChanged(content::Visibility visibility) override;
156
157   // PermissionPrompt::Delegate:
158   const std::vector<PermissionRequest*>& Requests() override;
159   GURL GetRequestingOrigin() const override;
160   GURL GetEmbeddingOrigin() const override;
161   void Accept() override;
162   void AcceptThisTime() override;
163   void Deny() override;
164   void Dismiss() override;
165   void Ignore() override;
166   void FinalizeCurrentRequests() override;
167   void OpenHelpCenterLink(const ui::Event& event) override;
168   void PreIgnoreQuietPrompt() override;
169   bool WasCurrentRequestAlreadyDisplayed() override;
170   bool ShouldDropCurrentRequestIfCannotShowQuietly() const override;
171   bool ShouldCurrentRequestUseQuietUI() const override;
172   absl::optional<PermissionUiSelector::QuietUiReason> ReasonForUsingQuietUi()
173       const override;
174   void SetDismissOnTabClose() override;
175   void SetPromptShown() override;
176   void SetDecisionTime() override;
177   void SetManageClicked() override;
178   void SetLearnMoreClicked() override;
179   base::WeakPtr<PermissionPrompt::Delegate> GetWeakPtr() override;
180   content::WebContents* GetAssociatedWebContents() override;
181   bool RecreateView() override;
182
183   // Returns the bounds of the active permission prompt view if we're
184   // displaying one.
185   absl::optional<gfx::Rect> GetPromptBubbleViewBoundsInScreen() const;
186
187   void set_manage_clicked() { did_click_manage_ = true; }
188   void set_learn_more_clicked() { did_click_learn_more_ = true; }
189
190   void set_web_contents_supports_permission_requests(
191       bool web_contents_supports_permission_requests) {
192     web_contents_supports_permission_requests_ =
193         web_contents_supports_permission_requests;
194   }
195
196   // For testing only, used to override the default UI selectors and instead use
197   // a new one.
198   void set_permission_ui_selector_for_testing(
199       std::unique_ptr<PermissionUiSelector> selector) {
200     clear_permission_ui_selector_for_testing();
201     add_permission_ui_selector_for_testing(std::move(selector));
202   }
203
204   // For testing only, used to add a new selector without overriding the
205   // existing ones.
206   void add_permission_ui_selector_for_testing(
207       std::unique_ptr<PermissionUiSelector> selector) {
208     permission_ui_selectors_.emplace_back(std::move(selector));
209   }
210
211   // For testing only, clear the existing ui selectors.
212   void clear_permission_ui_selector_for_testing() {
213     permission_ui_selectors_.clear();
214   }
215
216   // Getter for testing.
217   const std::vector<std::unique_ptr<PermissionUiSelector>>&
218   get_permission_ui_selectors_for_testing() {
219     return permission_ui_selectors_;
220   }
221
222   void set_view_factory_for_testing(PermissionPrompt::Factory view_factory) {
223     view_factory_ = std::move(view_factory);
224   }
225
226   PermissionPrompt* view_for_testing() const { return view_.get(); }
227
228   void set_current_request_first_display_time_for_testing(base::Time time) {
229     current_request_first_display_time_ = time;
230   }
231
232   absl::optional<PermissionUmaUtil::PredictionGrantLikelihood>
233   prediction_grant_likelihood_for_testing() const {
234     return prediction_grant_likelihood_;
235   }
236
237   absl::optional<permissions::PermissionPromptDisposition>
238   current_request_prompt_disposition_for_testing() const {
239     return current_request_prompt_disposition_;
240   }
241
242   void set_time_to_decision_for_test(base::TimeDelta time_to_decision) {
243     time_to_decision_for_test_ = time_to_decision;
244   }
245
246   void set_enabled_app_level_notification_permission_for_testing(bool enabled) {
247     enabled_app_level_notification_permission_for_testing_ = enabled;
248   }
249
250   void set_embedding_origin_for_testing(const GURL& embedding_origin) {
251     embedding_origin_for_testing_ = embedding_origin;
252   }
253
254   base::ObserverList<Observer>* get_observer_list_for_testing() {
255     CHECK_IS_TEST();
256     return &observer_list_;
257   }
258
259   bool has_pending_requests() {
260     return !pending_permission_requests_.IsEmpty();
261   }
262
263   void SetHatsShownCallback(base::OnceCallback<void()> callback) override;
264
265  private:
266   friend class test::PermissionRequestManagerTestApi;
267   friend class content::WebContentsUserData<PermissionRequestManager>;
268   FRIEND_TEST_ALL_PREFIXES(PermissionRequestManagerTest, WeakDuplicateRequests);
269   FRIEND_TEST_ALL_PREFIXES(PermissionRequestManagerTest,
270                            WeakDuplicateRequestsAccept);
271
272   explicit PermissionRequestManager(content::WebContents* web_contents);
273
274   // Defines how to handle the current request, when new requests arrive
275   enum class CurrentRequestFate {
276     // Keep showing the current request. The incoming requests should not take
277     // priority over the current request and will be pushed to pending requests
278     // queue.
279     kKeepCurrent,
280
281     // Put the current request back to the pending requests queue for displaying
282     // later when it returns to the front of the queue.
283     kPreempt,
284
285     // Finalize/ignore the current request and show the new request.
286     kFinalize
287   };
288
289   // Reprioritize the current requests (preempting, finalizing) based on what
290   // type of UI has been shown for `requests_` and current pending requests
291   // queue.
292   // Determine the next request candidate would be prompted later and push the
293   // candidate to front of the pending queue.
294   // Return true if we keep showing the current request, otherwise return false
295   bool ReprioritizeCurrentRequestIfNeeded();
296
297   // Validate the input request. If the request is invalid and |should_finalize|
298   // is set, cancel and remove it from *_map_ and *_set_.
299   // Return true if the request is valid, otherwise false.
300   bool ValidateRequest(PermissionRequest* request, bool should_finalize = true);
301
302   // Adds `request` into `pending_permission_requests_`, and request's
303   // `source_frame` into `request_sources_map_`.
304   void QueueRequest(content::RenderFrameHost* source_frame,
305                     PermissionRequest* request);
306
307   // Because the requests are shown in a different order for Normal and Quiet
308   // Chip, pending requests are returned back to pending_permission_requests_ to
309   // process them after the new requests.
310   void PreemptAndRequeueCurrentRequest();
311
312   // If a request isn't already in progress, dequeue and show the request
313   // prompt.
314   void DequeueRequestIfNeeded();
315
316   // Schedule a call to |DequeueRequestIfNeeded|. Is needed to ensure requests
317   // that can be grouped together have time to all be added to the queue.
318   void ScheduleDequeueRequestIfNeeded();
319
320   // Shows the prompt for a request that has just been dequeued, or re-show a
321   // prompt after switching tabs away and back.
322   void ShowPrompt();
323
324   // Delete the view object
325   void DeletePrompt();
326
327   // Finalize request.
328   void ResetViewStateForCurrentRequest();
329
330   // Records metrics and informs embargo and autoblocker about the requests
331   // being decided. Based on |view_->ShouldFinalizeRequestAfterDecided()| it
332   // will also call |FinalizeCurrentRequests()|. Otherwise a separate
333   // |FinalizeCurrentRequests()| call must be made to release the |view_|.
334   void CurrentRequestsDecided(PermissionAction permission_action);
335
336   // Cancel all pending or active requests and destroy the PermissionPrompt if
337   // one exists. This is called if the WebContents is destroyed or navigates its
338   // main frame.
339   void CleanUpRequests();
340
341   // Searches |requests_| and |pending_permission_requests_| - but *not*
342   // |duplicate_requests_| - for a request matching |request|, and returns the
343   // matching request, or |nullptr| if no match. Note that the matching request
344   // may or may not be the same object as |request|.
345   PermissionRequest* GetExistingRequest(PermissionRequest* request) const;
346
347   // Returns an iterator into |duplicate_requests_|, points the matching list,
348   // or duplicate_requests_.end() if no match. The matching list contains all
349   // the weak requests which are duplicate of the given |request| (see
350   // |IsDuplicateOf|)
351   using WeakPermissionRequestList =
352       std::list<std::list<base::WeakPtr<PermissionRequest>>>;
353   WeakPermissionRequestList::iterator FindDuplicateRequestList(
354       PermissionRequest* request);
355
356   // Trigger |visitor| for each live weak request which matches the given
357   // request (see |IsDuplicateOf|) in the |duplicate_requests_|. Returns an
358   // iterator into |duplicate_requests_|, points the matching list, or
359   // duplicate_requests_.end() if no match.
360   using DuplicateRequestVisitor =
361       base::RepeatingCallback<void(const base::WeakPtr<PermissionRequest>&)>;
362   WeakPermissionRequestList::iterator VisitDuplicateRequests(
363       DuplicateRequestVisitor visitor,
364       PermissionRequest* request);
365
366   // Calls PermissionGranted on a request and all its duplicates.
367   void PermissionGrantedIncludingDuplicates(PermissionRequest* request,
368                                             bool is_one_time);
369   // Calls PermissionDenied on a request and all its duplicates.
370   void PermissionDeniedIncludingDuplicates(PermissionRequest* request);
371   // Calls Cancelled on a request and all its duplicates.
372   void CancelledIncludingDuplicates(PermissionRequest* request,
373                                     bool is_final_decision = true);
374   // Calls RequestFinished on a request and all its duplicates.
375   void RequestFinishedIncludingDuplicates(PermissionRequest* request);
376
377   void NotifyTabVisibilityChanged(content::Visibility visibility);
378   void NotifyPromptAdded();
379   void NotifyPromptRemoved();
380   void NotifyPromptRecreateFailed();
381   void NotifyPromptCreationFailedHiddenTab();
382   void NotifyRequestDecided(permissions::PermissionAction permission_action);
383
384   void StorePermissionActionForUMA(const GURL& origin,
385                                    RequestType request_type,
386                                    PermissionAction permission_action);
387
388   void OnPermissionUiSelectorDone(size_t selector_index,
389                                   const UiDecision& decision);
390
391   PermissionPromptDisposition DetermineCurrentRequestUIDisposition();
392   PermissionPromptDispositionReason
393   DetermineCurrentRequestUIDispositionReasonForUMA();
394
395   void LogWarningToConsole(const char* message);
396
397   void DoAutoResponseForTesting();
398
399   void PreIgnoreQuietPromptInternal();
400
401   // Returns true if there is a request in progress that is initiated by an
402   // embedded permission element.
403   bool IsCurrentRequestEmbeddedPermissionElementInitiated() const;
404
405   // Returns true when the current request should be finalized together with the
406   // permission decision.
407   bool ShouldFinalizeRequestAfterDecided(PermissionAction action) const;
408
409   // Factory to be used to create views when needed.
410   PermissionPrompt::Factory view_factory_;
411
412   // The UI surface for an active permission prompt if we're displaying one.
413   // On Desktop, we destroy this upon tab switching, while on Android we keep
414   // the object alive. The infobar system hides the actual infobar UI and modals
415   // prevent tab switching.
416   std::unique_ptr<PermissionPrompt> view_;
417
418   // The disposition for the currently active permission prompt, if any.
419   // Recorded separately because the `view_` might not be available at prompt
420   // resolution in order to determine the disposition.
421   absl::optional<permissions::PermissionPromptDisposition>
422       current_request_prompt_disposition_;
423
424   // We only show new prompts when |tab_is_hidden_| is false.
425   bool tab_is_hidden_;
426
427   // The request (or requests) that the user is currently being prompted for.
428   // When this is non-empty, the |view_| is generally non-null as long as the
429   // tab is visible.
430   std::vector<PermissionRequest*> requests_;
431
432   struct PermissionRequestSource {
433     content::GlobalRenderFrameHostId requesting_frame_id;
434
435     bool IsSourceFrameInactiveAndDisallowActivation() const;
436   };
437
438   PermissionRequestQueue pending_permission_requests_;
439
440   // Stores the weak pointers of duplicated requests in a 2D list.
441   WeakPermissionRequestList duplicate_requests_;
442
443   // Maps each PermissionRequest currently in |requests_| or
444   // |pending_permission_requests_| to which RenderFrameHost it originated from.
445   // Note that no date is stored for |duplicate_requests_|.
446   std::map<PermissionRequest*, PermissionRequestSource> request_sources_map_;
447
448   // Sequence of requests from pending queue will be marked as validated, when
449   // we are extracting a group of requests from the queue to show to user. This
450   // is an immature solution to avoid an infinitive loop of preempting, we would
451   // not prempt a request if the incoming request is already validated.
452   std::set<PermissionRequest*> validated_requests_set_;
453
454   base::ObserverList<Observer> observer_list_;
455   AutoResponseType auto_response_for_test_ = NONE;
456
457   // Suppress notification permission prompts in this tab, regardless of the
458   // origin requesting the permission.
459   bool is_notification_prompt_cooldown_active_ = false;
460
461   // A vector of selectors which decide if the quiet prompt UI should be used
462   // to display permission requests. Sorted from the highest priority to the
463   // lowest priority selector.
464   std::vector<std::unique_ptr<PermissionUiSelector>> permission_ui_selectors_;
465
466   // Holds the decisions returned by selectors. Needed in case a lower priority
467   // selector returns a decision first and we need to wait for the decisions of
468   // higher priority selectors before making use of it.
469   std::vector<absl::optional<PermissionUiSelector::Decision>>
470       selector_decisions_;
471
472   // Whether the view for the current |requests_| has been shown to the user at
473   // least once.
474   bool current_request_already_displayed_ = false;
475
476   // When the view for the current |requests_| has been first shown to the user,
477   // or zero if not at all.
478   base::Time current_request_first_display_time_;
479
480   // Whether to use the normal or quiet UI to display the current permission
481   // |requests_|, and whether to show warnings. This will be nullopt if we are
482   // still waiting on the result from |permission_ui_selectors_|.
483   absl::optional<UiDecision> current_request_ui_to_use_;
484
485   // The likelihood value returned by the Web Permission Predictions Service,
486   // to be recoreded in UKM.
487   absl::optional<PermissionUmaUtil::PredictionGrantLikelihood>
488       prediction_grant_likelihood_;
489
490   // Status of the decision made by the Web Permission Prediction Service, if
491   // it was held back or not.
492   absl::optional<bool> was_decision_held_back_;
493
494   // True when the prompt is being temporary destroyed to be recreated for the
495   // correct browser or when the tab is hidden. In those cases, callbacks from
496   // the bubble itself should be ignored.
497   bool ignore_callbacks_from_prompt_ = false;
498
499   // Whether the web contents associated with this request manager supports
500   // permission prompts.
501   bool web_contents_supports_permission_requests_ = true;
502
503   // Whether the current request should be dismissed if the current tab is
504   // closed.
505   bool should_dismiss_current_request_ = false;
506
507   // Whether the permission prompt was shown for the current request.
508   bool did_show_prompt_ = false;
509
510   // When the user made any decision for the current |requests_|, or zero if not
511   // at all.
512   base::Time current_request_decision_time_;
513
514   bool did_click_manage_ = false;
515
516   bool did_click_learn_more_ = false;
517
518   absl::optional<base::TimeDelta> time_to_decision_for_test_;
519
520   absl::optional<bool> enabled_app_level_notification_permission_for_testing_;
521
522   absl::optional<GURL> embedding_origin_for_testing_;
523
524   // A timer is used to pre-ignore the permission request if it's been displayed
525   // as a quiet chip.
526   base::OneShotTimer preignore_timer_;
527
528   absl::optional<base::OnceCallback<void()>> hats_shown_callback_;
529
530   base::WeakPtrFactory<PermissionRequestManager> weak_factory_{this};
531   WEB_CONTENTS_USER_DATA_KEY_DECL();
532 };
533
534 }  // namespace permissions
535
536 #endif  // COMPONENTS_PERMISSIONS_PERMISSION_REQUEST_MANAGER_H_