Remove the old signature of NotificationManager::closePersistent().
[chromium-blink-merge.git] / chrome / browser / download / download_request_limiter.h
blob57a66bc93a0058f23ceea3550158122c9e5b3c32
1 // Copyright (c) 2012 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.
5 #ifndef CHROME_BROWSER_DOWNLOAD_DOWNLOAD_REQUEST_LIMITER_H_
6 #define CHROME_BROWSER_DOWNLOAD_DOWNLOAD_REQUEST_LIMITER_H_
8 #include <map>
9 #include <string>
10 #include <vector>
12 #include "base/callback.h"
13 #include "base/gtest_prod_util.h"
14 #include "base/memory/ref_counted.h"
15 #include "base/memory/weak_ptr.h"
16 #include "components/content_settings/core/common/content_settings.h"
17 #include "content/public/browser/notification_observer.h"
18 #include "content/public/browser/notification_registrar.h"
19 #include "content/public/browser/web_contents_observer.h"
21 class HostContentSettingsMap;
22 class DownloadRequestInfoBarDelegate;
24 namespace content {
25 class NavigationController;
26 class WebContents;
29 // DownloadRequestLimiter is responsible for determining whether a download
30 // should be allowed or not. It is designed to keep pages from downloading
31 // multiple files without user interaction. DownloadRequestLimiter is invoked
32 // from ResourceDispatcherHost any time a download begins
33 // (CanDownloadOnIOThread). The request is processed on the UI thread, and the
34 // request is notified (back on the IO thread) as to whether the download should
35 // be allowed or denied.
37 // Invoking CanDownloadOnIOThread notifies the callback and may update the
38 // download status. The following details the various states:
39 // . Each NavigationController initially starts out allowing a download
40 // (ALLOW_ONE_DOWNLOAD).
41 // . The first time CanDownloadOnIOThread is invoked the download is allowed and
42 // the state changes to PROMPT_BEFORE_DOWNLOAD.
43 // . If the state is PROMPT_BEFORE_DOWNLOAD and the user clicks the mouse,
44 // presses enter, the space bar or navigates to another page the state is
45 // reset to ALLOW_ONE_DOWNLOAD.
46 // . If a download is attempted and the state is PROMPT_BEFORE_DOWNLOAD the user
47 // is prompted as to whether the download is allowed or disallowed. The users
48 // choice stays until the user navigates to a different host. For example, if
49 // the user allowed the download, multiple downloads are allowed without any
50 // user intervention until the user navigates to a different host.
51 class DownloadRequestLimiter
52 : public base::RefCountedThreadSafe<DownloadRequestLimiter> {
53 public:
54 // Download status for a particular page. See class description for details.
55 enum DownloadStatus {
56 ALLOW_ONE_DOWNLOAD,
57 PROMPT_BEFORE_DOWNLOAD,
58 ALLOW_ALL_DOWNLOADS,
59 DOWNLOADS_NOT_ALLOWED
62 // Max number of downloads before a "Prompt Before Download" Dialog is shown.
63 static const size_t kMaxDownloadsAtOnce = 50;
65 // The callback from CanDownloadOnIOThread. This is invoked on the io thread.
66 // The boolean parameter indicates whether or not the download is allowed.
67 typedef base::Callback<void(bool /*allow*/)> Callback;
69 // TabDownloadState maintains the download state for a particular tab.
70 // TabDownloadState prompts the user with an infobar as necessary.
71 // TabDownloadState deletes itself (by invoking
72 // DownloadRequestLimiter::Remove) as necessary.
73 // TODO(gbillock): just make this class implement PermissionBubbleRequest.
74 class TabDownloadState : public content::NotificationObserver,
75 public content::WebContentsObserver {
76 public:
77 // Creates a new TabDownloadState. |controller| is the controller the
78 // TabDownloadState tracks the state of and is the host for any dialogs that
79 // are displayed. |originating_controller| is used to determine the host of
80 // the initial download. If |originating_controller| is null, |controller|
81 // is used. |originating_controller| is typically null, but differs from
82 // |controller| in the case of a constrained popup requesting the download.
83 TabDownloadState(DownloadRequestLimiter* host,
84 content::WebContents* web_contents,
85 content::WebContents* originating_web_contents);
86 ~TabDownloadState() override;
88 // Status of the download.
89 void set_download_status(DownloadRequestLimiter::DownloadStatus status) {
90 status_ = status;
92 DownloadRequestLimiter::DownloadStatus download_status() const {
93 return status_;
96 // Number of "ALLOWED" downloads.
97 void increment_download_count() {
98 download_count_++;
100 size_t download_count() const {
101 return download_count_;
104 // content::WebContentsObserver overrides.
105 void DidNavigateMainFrame(
106 const content::LoadCommittedDetails& details,
107 const content::FrameNavigateParams& params) override;
108 // Invoked when a user gesture occurs (mouse click, enter or space). This
109 // may result in invoking Remove on DownloadRequestLimiter.
110 void DidGetUserGesture() override;
111 void WebContentsDestroyed() override;
113 // Asks the user if they really want to allow the download.
114 // See description above CanDownloadOnIOThread for details on lifetime of
115 // callback.
116 void PromptUserForDownload(
117 const DownloadRequestLimiter::Callback& callback);
119 // Invoked from DownloadRequestDialogDelegate. Notifies the delegates and
120 // changes the status appropriately. Virtual for testing.
121 virtual void Cancel();
122 virtual void CancelOnce();
123 virtual void Accept();
125 protected:
126 // Used for testing.
127 TabDownloadState();
129 private:
130 // Are we showing a prompt to the user? Determined by whether
131 // we have an outstanding weak pointer--weak pointers are only
132 // given to the info bar delegate or permission bubble request.
133 bool is_showing_prompt() const;
135 // content::NotificationObserver method.
136 void Observe(int type,
137 const content::NotificationSource& source,
138 const content::NotificationDetails& details) override;
140 // Remember to either block or allow automatic downloads from this origin.
141 void SetContentSetting(ContentSetting setting);
143 // Notifies the callbacks as to whether the download is allowed or not.
144 // Updates status_ appropriately.
145 void NotifyCallbacks(bool allow);
147 content::WebContents* web_contents_;
149 DownloadRequestLimiter* host_;
151 // Host of the first page the download started on. This may be empty.
152 std::string initial_page_host_;
154 DownloadRequestLimiter::DownloadStatus status_;
156 size_t download_count_;
158 // Callbacks we need to notify. This is only non-empty if we're showing a
159 // dialog.
160 // See description above CanDownloadOnIOThread for details on lifetime of
161 // callbacks.
162 std::vector<DownloadRequestLimiter::Callback> callbacks_;
164 // Used to remove observers installed on NavigationController.
165 content::NotificationRegistrar registrar_;
167 // Weak pointer factory for generating a weak pointer to pass to the
168 // infobar. User responses to the throttling prompt will be returned
169 // through this channel, and it can be revoked if the user prompt result
170 // becomes moot.
171 base::WeakPtrFactory<DownloadRequestLimiter::TabDownloadState> factory_;
173 DISALLOW_COPY_AND_ASSIGN(TabDownloadState);
176 static void SetContentSettingsForTesting(HostContentSettingsMap* settings);
178 DownloadRequestLimiter();
180 // Returns the download status for a page. This does not change the state in
181 // anyway.
182 DownloadStatus GetDownloadStatus(content::WebContents* tab);
184 // Updates the state of the page as necessary and notifies the callback.
185 // WARNING: both this call and the callback are invoked on the io thread.
186 void CanDownloadOnIOThread(int render_process_host_id,
187 int render_view_id,
188 const GURL& url,
189 const std::string& request_method,
190 const Callback& callback);
192 private:
193 FRIEND_TEST_ALL_PREFIXES(DownloadTest, DownloadResourceThrottleCancels);
194 friend class base::RefCountedThreadSafe<DownloadRequestLimiter>;
195 friend class DownloadRequestLimiterTest;
196 friend class TabDownloadState;
198 ~DownloadRequestLimiter();
200 // Gets the download state for the specified controller. If the
201 // TabDownloadState does not exist and |create| is true, one is created.
202 // See TabDownloadState's constructor description for details on the two
203 // controllers.
205 // The returned TabDownloadState is owned by the DownloadRequestLimiter and
206 // deleted when no longer needed (the Remove method is invoked).
207 TabDownloadState* GetDownloadState(
208 content::WebContents* web_contents,
209 content::WebContents* originating_web_contents,
210 bool create);
212 // CanDownloadOnIOThread invokes this on the UI thread. This determines the
213 // tab and invokes CanDownloadImpl.
214 void CanDownload(int render_process_host_id,
215 int render_view_id,
216 const GURL& url,
217 const std::string& request_method,
218 const Callback& callback);
220 // Does the work of updating the download status on the UI thread and
221 // potentially prompting the user.
222 void CanDownloadImpl(content::WebContents* originating_contents,
223 const std::string& request_method,
224 const Callback& callback);
226 // Invoked when decision to download has been made.
227 void OnCanDownloadDecided(int render_process_host_id,
228 int render_view_id,
229 const std::string& request_method,
230 const Callback& orig_callback,
231 bool allow);
233 // Invoked on the UI thread. Schedules a call to NotifyCallback on the io
234 // thread.
235 void ScheduleNotification(const Callback& callback, bool allow);
237 // Removes the specified TabDownloadState from the internal map and deletes
238 // it. This has the effect of resetting the status for the tab to
239 // ALLOW_ONE_DOWNLOAD.
240 void Remove(TabDownloadState* state, content::WebContents* contents);
242 static HostContentSettingsMap* content_settings_;
243 static HostContentSettingsMap* GetContentSettings(
244 content::WebContents* contents);
246 // Maps from tab to download state. The download state for a tab only exists
247 // if the state is other than ALLOW_ONE_DOWNLOAD. Similarly once the state
248 // transitions from anything but ALLOW_ONE_DOWNLOAD back to ALLOW_ONE_DOWNLOAD
249 // the TabDownloadState is removed and deleted (by way of Remove).
250 typedef std::map<content::WebContents*, TabDownloadState*> StateMap;
251 StateMap state_map_;
253 // Weak ptr factory used when |CanDownload| asks the delegate asynchronously
254 // about the download.
255 base::WeakPtrFactory<DownloadRequestLimiter> factory_;
257 DISALLOW_COPY_AND_ASSIGN(DownloadRequestLimiter);
260 #endif // CHROME_BROWSER_DOWNLOAD_DOWNLOAD_REQUEST_LIMITER_H_