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
5#ifndef CHROME_BROWSER_UI_WEBSITE_SETTINGS_PERMISSION_BUBBLE_MANAGER_H_
6#define CHROME_BROWSER_UI_WEBSITE_SETTINGS_PERMISSION_BUBBLE_MANAGER_H_
7
8#include <vector>
9
10#include "base/memory/weak_ptr.h"
11#include "chrome/browser/ui/website_settings/permission_bubble_view.h"
12#include "content/public/browser/web_contents_observer.h"
13#include "content/public/browser/web_contents_user_data.h"
14
15class PermissionBubbleRequest;
16
17// Provides access to permissions bubbles. Allows clients to add a request
18// callback interface to the existing permission bubble configuration.
19// Depending on the situation and policy, that may add new UI to an existing
20// permission bubble, create and show a new permission bubble, or provide no
21// visible UI action at all. (In that case, the request will be immediately
22// informed that the permission request failed.)
23//
24// A PermissionBubbleManager is associated with a particular WebContents.
25// Requests attached to a particular WebContents' PBM must outlive it.
26//
27// The PermissionBubbleManager should be addressed on the UI thread.
28class PermissionBubbleManager
29    : public content::WebContentsObserver,
30      public content::WebContentsUserData<PermissionBubbleManager>,
31      public PermissionBubbleView::Delegate {
32 public:
33  // Return the flag-driven enabled state of permissions bubbles.
34  static bool Enabled();
35
36  virtual ~PermissionBubbleManager();
37
38  // Adds a new request to the permission bubble. Ownership of the request
39  // remains with the caller. The caller must arrange for the request to
40  // outlive the PermissionBubbleManager. If a bubble is visible when this
41  // call is made, the request will be queued up and shown after the current
42  // bubble closes. A request with message text identical to an outstanding
43  // request will receive a RequestFinished call immediately and not be added.
44  virtual void AddRequest(PermissionBubbleRequest* request);
45
46  // Cancels an outstanding request. This may have different effects depending
47  // on what is going on with the bubble. If the request is pending, it will be
48  // removed and never shown. If the request is showing, it will continue to be
49  // shown, but the user's action won't be reported back to the request object.
50  // In some circumstances, we can remove the request from the bubble, and may
51  // do so. The request will have RequestFinished executed on it if it is found,
52  // at which time the caller is free to delete the request.
53  virtual void CancelRequest(PermissionBubbleRequest* request);
54
55  // Sets the active view for the permission bubble. If this is NULL, it
56  // means any existing permission bubble can no longer be shown. Does not
57  // take ownership of the view.
58  virtual void SetView(PermissionBubbleView* view) OVERRIDE;
59
60 private:
61  friend class PermissionBubbleManagerTest;
62  friend class DownloadRequestLimiterTest;
63  friend class content::WebContentsUserData<PermissionBubbleManager>;
64
65  explicit PermissionBubbleManager(content::WebContents* web_contents);
66
67  // WebContentsObserver:
68  virtual void DocumentOnLoadCompletedInMainFrame() OVERRIDE;
69  virtual void DocumentLoadedInFrame(
70      content::RenderFrameHost* render_frame_host) OVERRIDE;
71
72  // If a page on which permissions requests are pending is navigated,
73  // they will be finalized as if canceled by the user.
74  virtual void NavigationEntryCommitted(
75      const content::LoadCommittedDetails& details) OVERRIDE;
76  virtual void WebContentsDestroyed() OVERRIDE;
77
78  // PermissionBubbleView::Delegate:
79  virtual void ToggleAccept(int request_index, bool new_value) OVERRIDE;
80  virtual void SetCustomizationMode() OVERRIDE;
81  virtual void Accept() OVERRIDE;
82  virtual void Deny() OVERRIDE;
83  virtual void Closing() OVERRIDE;
84
85  // Posts a task which will allow the bubble to become visible if it is needed.
86  void ScheduleShowBubble();
87
88  // Shows the bubble if it is not already visible and there are pending
89  // requests.
90  void TriggerShowBubble();
91
92  // Finalize the pending permissions request.
93  void FinalizeBubble();
94
95  // Cancel any pending requests. This is called if the WebContents
96  // on which permissions calls are pending is destroyed or navigated away
97  // from the requesting page.
98  void CancelPendingQueues();
99
100  // Returns whether or not |request| has already been added to |queue|.
101  // |same_object| must be non-null.  It will be set to true if |request|
102  // is the same object as an existing request in |queue|, false otherwise.
103  bool ExistingRequest(PermissionBubbleRequest* request,
104                       const std::vector<PermissionBubbleRequest*>& queue,
105                       bool* same_object);
106
107  // Returns true if |queue| contains a request which was generated by a user
108  // gesture.  Returns false otherwise.
109  bool HasUserGestureRequest(
110      const std::vector<PermissionBubbleRequest*>& queue);
111
112  // Whether or not we are showing the bubble in this tab.
113  bool bubble_showing_;
114
115  // Set to the UI surface to be used to display the permissions requests.
116  PermissionBubbleView* view_;
117
118  std::vector<PermissionBubbleRequest*> requests_;
119  std::vector<PermissionBubbleRequest*> queued_requests_;
120  std::vector<PermissionBubbleRequest*> queued_frame_requests_;
121
122  // URL of the main frame in the WebContents to which this manager is attached.
123  // TODO(gbillock): if there are iframes in the page, we need to deal with it.
124  GURL request_url_;
125  bool request_url_has_loaded_;
126
127  std::vector<bool> accept_states_;
128  bool customization_mode_;
129
130  base::WeakPtrFactory<PermissionBubbleManager> weak_factory_;
131};
132
133#endif  // CHROME_BROWSER_UI_WEBSITE_SETTINGS_PERMISSION_BUBBLE_MANAGER_H_
134