Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(967)

Side by Side Diff: chrome/browser/download/download_request_limiter.cc

Issue 1964863002: Persist prompt/block download limiter state on renderer-initiated loads. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Addressing reviewer comments Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/download/download_request_limiter.h" 5 #include "chrome/browser/download/download_request_limiter.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/stl_util.h" 8 #include "base/stl_util.h"
9 #include "chrome/browser/chrome_notification_types.h" 9 #include "chrome/browser/chrome_notification_types.h"
10 #include "chrome/browser/content_settings/host_content_settings_map_factory.h" 10 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
11 #include "chrome/browser/content_settings/tab_specific_content_settings.h" 11 #include "chrome/browser/content_settings/tab_specific_content_settings.h"
12 #include "chrome/browser/infobars/infobar_service.h" 12 #include "chrome/browser/infobars/infobar_service.h"
13 #include "chrome/browser/profiles/profile.h" 13 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/browser/tab_contents/tab_util.h" 14 #include "chrome/browser/tab_contents/tab_util.h"
15 #include "chrome/common/features.h" 15 #include "chrome/common/features.h"
16 #include "components/content_settings/core/browser/host_content_settings_map.h" 16 #include "components/content_settings/core/browser/host_content_settings_map.h"
17 #include "content/public/browser/browser_context.h" 17 #include "content/public/browser/browser_context.h"
18 #include "content/public/browser/browser_thread.h" 18 #include "content/public/browser/browser_thread.h"
19 #include "content/public/browser/navigation_controller.h" 19 #include "content/public/browser/navigation_controller.h"
20 #include "content/public/browser/navigation_entry.h" 20 #include "content/public/browser/navigation_entry.h"
21 #include "content/public/browser/navigation_handle.h"
21 #include "content/public/browser/notification_source.h" 22 #include "content/public/browser/notification_source.h"
22 #include "content/public/browser/notification_types.h" 23 #include "content/public/browser/notification_types.h"
23 #include "content/public/browser/render_process_host.h" 24 #include "content/public/browser/render_process_host.h"
24 #include "content/public/browser/resource_dispatcher_host.h" 25 #include "content/public/browser/resource_dispatcher_host.h"
25 #include "content/public/browser/web_contents.h" 26 #include "content/public/browser/web_contents.h"
26 #include "content/public/browser/web_contents_delegate.h" 27 #include "content/public/browser/web_contents_delegate.h"
27 #include "url/gurl.h" 28 #include "url/gurl.h"
28 29
29 #if BUILDFLAG(ANDROID_JAVA_UI) 30 #if BUILDFLAG(ANDROID_JAVA_UI)
30 #include "chrome/browser/download/download_request_infobar_delegate_android.h" 31 #include "chrome/browser/download/download_request_infobar_delegate_android.h"
(...skipping 11 matching lines...) Expand all
42 DownloadRequestLimiter::TabDownloadState::TabDownloadState( 43 DownloadRequestLimiter::TabDownloadState::TabDownloadState(
43 DownloadRequestLimiter* host, 44 DownloadRequestLimiter* host,
44 content::WebContents* contents, 45 content::WebContents* contents,
45 content::WebContents* originating_web_contents) 46 content::WebContents* originating_web_contents)
46 : content::WebContentsObserver(contents), 47 : content::WebContentsObserver(contents),
47 web_contents_(contents), 48 web_contents_(contents),
48 host_(host), 49 host_(host),
49 status_(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD), 50 status_(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD),
50 download_count_(0), 51 download_count_(0),
51 factory_(this) { 52 factory_(this) {
52 registrar_.Add(
53 this, content::NOTIFICATION_NAV_ENTRY_PENDING,
54 content::Source<NavigationController>(&contents->GetController()));
55 registrar_.Add(this, chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED, 53 registrar_.Add(this, chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED,
56 content::Source<content::WebContents>(contents)); 54 content::Source<content::WebContents>(contents));
57 NavigationEntry* last_entry = originating_web_contents ? 55 NavigationEntry* last_entry =
58 originating_web_contents->GetController().GetLastCommittedEntry() : 56 originating_web_contents
59 contents->GetController().GetLastCommittedEntry(); 57 ? originating_web_contents->GetController().GetLastCommittedEntry()
58 : contents->GetController().GetLastCommittedEntry();
60 if (last_entry) 59 if (last_entry)
61 initial_page_host_ = last_entry->GetURL().host(); 60 initial_page_host_ = last_entry->GetURL().host();
62 } 61 }
63 62
64 DownloadRequestLimiter::TabDownloadState::~TabDownloadState() { 63 DownloadRequestLimiter::TabDownloadState::~TabDownloadState() {
65 // We should only be destroyed after the callbacks have been notified. 64 // We should only be destroyed after the callbacks have been notified.
66 DCHECK(callbacks_.empty()); 65 DCHECK(callbacks_.empty());
67 66
68 // And we should have invalidated the back pointer. 67 // And we should have invalidated the back pointer.
69 DCHECK(!factory_.HasWeakPtrs()); 68 DCHECK(!factory_.HasWeakPtrs());
70 } 69 }
71 70
72 void DownloadRequestLimiter::TabDownloadState::DidNavigateMainFrame( 71 void DownloadRequestLimiter::TabDownloadState::DidStartNavigation(
73 const content::LoadCommittedDetails& details, 72 content::NavigationHandle* navigation_handle) {
74 const content::FrameNavigateParams& params) { 73 if (!navigation_handle->IsInMainFrame())
75 switch (status_) { 74 return;
76 case ALLOW_ONE_DOWNLOAD: 75
77 case PROMPT_BEFORE_DOWNLOAD: 76 // If the navigation is renderer-initiated, ensure that a prompting or
78 // When the user reloads the page without responding to the infobar, they 77 // blocking limiter state is not reset, so window.location.href or meta
79 // are expecting DownloadRequestLimiter to behave as if they had just 78 // refresh can't be abused to avoid the limiter.
Charlie Reis 2016/05/13 00:36:12 Might mention where renderer-initiated navigations
dominickn 2016/05/17 01:31:48 Done.
80 // initially navigated to this page. See http://crbug.com/171372 79 if (navigation_handle->IsRendererInitiated() &&
81 NotifyCallbacks(false); 80 (status_ == PROMPT_BEFORE_DOWNLOAD || status_ == DOWNLOADS_NOT_ALLOWED)) {
82 host_->Remove(this, web_contents()); 81 return;
83 // WARNING: We've been deleted. 82 }
84 break; 83
85 case DOWNLOADS_NOT_ALLOWED: 84 if (status_ == DownloadRequestLimiter::ALLOW_ALL_DOWNLOADS ||
86 case ALLOW_ALL_DOWNLOADS: 85 status_ == DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED) {
87 // Don't drop this information. The user has explicitly said that they 86 // User has either allowed all downloads or canceled all downloads. Only
88 // do/don't want downloads from this host. If they accidentally Accepted 87 // reset the download state if the user is navigating to a different host
89 // or Canceled, they can adjust the limiter state by adjusting the 88 // (or host is empty).
90 // automatic downloads content settings. Alternatively, they can copy the 89 if (!initial_page_host_.empty() &&
91 // URL into a new tab, which will make a new DownloadRequestLimiter. 90 navigation_handle->GetURL().host() == initial_page_host_) {
Charlie Reis 2016/05/13 00:36:12 Host comparisons always catch my eye, since there'
dominickn 2016/05/17 01:31:48 I think the fact that a prompt/block state is pers
asanka 2016/05/19 02:18:30 I believe this is safe. If the navigation was rend
92 // See also the initial_page_host_ logic in Observe() for 91 return;
93 // NOTIFICATION_NAV_ENTRY_PENDING. 92 }
94 break; 93 }
95 default: 94
96 NOTREACHED(); 95 NotifyCallbacks(false);
96 host_->Remove(this, web_contents());
97 }
98
99 void DownloadRequestLimiter::TabDownloadState::DidFinishNavigation(
100 content::NavigationHandle* navigation_handle) {
101 if (!navigation_handle->IsInMainFrame())
102 return;
103
104 // When the status is ALLOW_ALL_DOWNLOADS or DOWNLOADS_NOT_ALLOWED, don't drop
105 // this information. The user has explicitly said that they
106 // do/don't want downloads from this host. If they accidentally Accepted
107 // or Canceled, they can adjust the limiter state by adjusting the
108 // automatic downloads content settings. Alternatively, they can copy
109 // the URL into a new tab, which will make a new DownloadRequestLimiter.
110 // See also the initial_page_host_ logic in DidStartNavigation or Observe()
111 // for NOTIFICATION_NAV_ENTRY_PENDING.
112 if (status_ == ALLOW_ONE_DOWNLOAD ||
113 (status_ == PROMPT_BEFORE_DOWNLOAD &&
114 !navigation_handle->IsRendererInitiated())) {
115 // When the user reloads the page without responding to the infobar,
116 // they are expecting DownloadRequestLimiter to behave as if they had
117 // just initially navigated to this page. See http://crbug.com/171372.
118 // However, explicitly leave the limiter in place if the navigation was
119 // renderer-initiated and we are in a prompt state.
120 NotifyCallbacks(false);
121 host_->Remove(this, web_contents());
122 // WARNING: We've been deleted.
97 } 123 }
98 } 124 }
99 125
100 void DownloadRequestLimiter::TabDownloadState::DidGetUserInteraction( 126 void DownloadRequestLimiter::TabDownloadState::DidGetUserInteraction(
101 const blink::WebInputEvent::Type type) { 127 const blink::WebInputEvent::Type type) {
102 if (is_showing_prompt() || type == blink::WebInputEvent::GestureScrollBegin) { 128 if (is_showing_prompt() || type == blink::WebInputEvent::GestureScrollBegin) {
103 // Don't change state if a prompt is showing or if the user has scrolled. 129 // Don't change state if a prompt is showing or if the user has scrolled.
104 return; 130 return;
105 } 131 }
106 132
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
138 if (is_showing_prompt()) 164 if (is_showing_prompt())
139 return; 165 return;
140 166
141 #if BUILDFLAG(ANDROID_JAVA_UI) 167 #if BUILDFLAG(ANDROID_JAVA_UI)
142 DownloadRequestInfoBarDelegateAndroid::Create( 168 DownloadRequestInfoBarDelegateAndroid::Create(
143 InfoBarService::FromWebContents(web_contents_), factory_.GetWeakPtr()); 169 InfoBarService::FromWebContents(web_contents_), factory_.GetWeakPtr());
144 #else 170 #else
145 PermissionBubbleManager* bubble_manager = 171 PermissionBubbleManager* bubble_manager =
146 PermissionBubbleManager::FromWebContents(web_contents_); 172 PermissionBubbleManager::FromWebContents(web_contents_);
147 if (bubble_manager) { 173 if (bubble_manager) {
148 bubble_manager->AddRequest(new DownloadPermissionRequest( 174 bubble_manager->AddRequest(
149 factory_.GetWeakPtr())); 175 new DownloadPermissionRequest(factory_.GetWeakPtr()));
150 } else { 176 } else {
151 Cancel(); 177 Cancel();
152 } 178 }
153 #endif 179 #endif
154 } 180 }
155 181
156 void DownloadRequestLimiter::TabDownloadState::SetContentSetting( 182 void DownloadRequestLimiter::TabDownloadState::SetContentSetting(
157 ContentSetting setting) { 183 ContentSetting setting) {
158 if (!web_contents_) 184 if (!web_contents_)
159 return; 185 return;
160 HostContentSettingsMap* settings = 186 HostContentSettingsMap* settings =
161 DownloadRequestLimiter::GetContentSettings(web_contents_); 187 DownloadRequestLimiter::GetContentSettings(web_contents_);
162 if (!settings) 188 if (!settings)
163 return; 189 return;
164 settings->SetContentSettingDefaultScope( 190 settings->SetContentSettingDefaultScope(
165 web_contents_->GetURL(), GURL(), 191 web_contents_->GetURL(), GURL(),
166 CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, std::string(), setting); 192 CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, std::string(), setting);
167 } 193 }
168 194
169 void DownloadRequestLimiter::TabDownloadState::Cancel() { 195 void DownloadRequestLimiter::TabDownloadState::Cancel() {
170 SetContentSetting(CONTENT_SETTING_BLOCK); 196 SetContentSetting(CONTENT_SETTING_BLOCK);
171 NotifyCallbacks(false); 197 NotifyCallbacks(false);
172 } 198 }
173 199
174 void DownloadRequestLimiter::TabDownloadState::CancelOnce() { 200 void DownloadRequestLimiter::TabDownloadState::CancelOnce() {
175 NotifyCallbacks(false); 201 NotifyCallbacks(false);
176 } 202 }
177 203
178 void DownloadRequestLimiter::TabDownloadState::Accept() { 204 void DownloadRequestLimiter::TabDownloadState::Accept() {
179 SetContentSetting(CONTENT_SETTING_ALLOW); 205 SetContentSetting(CONTENT_SETTING_ALLOW);
180 NotifyCallbacks(true); 206 NotifyCallbacks(true);
181 } 207 }
182 208
183 DownloadRequestLimiter::TabDownloadState::TabDownloadState() 209 DownloadRequestLimiter::TabDownloadState::TabDownloadState()
184 : web_contents_(NULL), 210 : web_contents_(NULL),
185 host_(NULL), 211 host_(NULL),
186 status_(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD), 212 status_(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD),
187 download_count_(0), 213 download_count_(0),
188 factory_(this) { 214 factory_(this) {}
189 }
190 215
191 bool DownloadRequestLimiter::TabDownloadState::is_showing_prompt() const { 216 bool DownloadRequestLimiter::TabDownloadState::is_showing_prompt() const {
192 return factory_.HasWeakPtrs(); 217 return factory_.HasWeakPtrs();
193 } 218 }
194 219
195 void DownloadRequestLimiter::TabDownloadState::Observe( 220 void DownloadRequestLimiter::TabDownloadState::Observe(
196 int type, 221 int type,
197 const content::NotificationSource& source, 222 const content::NotificationSource& source,
198 const content::NotificationDetails& details) { 223 const content::NotificationDetails& details) {
199 DCHECK(type == chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED || 224 DCHECK(type == chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED);
200 type == content::NOTIFICATION_NAV_ENTRY_PENDING);
201 225
202 // Content settings have been updated for our web contents, e.g. via the OIB 226 // Content settings have been updated for our web contents, e.g. via the OIB
203 // or the settings page. Check to see if the automatic downloads setting is 227 // or the settings page. Check to see if the automatic downloads setting is
204 // different to our internal state, and update the internal state to match if 228 // different to our internal state, and update the internal state to match if
205 // necessary. If there is no content setting persisted, then retain the 229 // necessary. If there is no content setting persisted, then retain the
206 // current state and do nothing. 230 // current state and do nothing.
207 // 231 //
208 // NotifyCallbacks is not called as this notification should be triggered when 232 // NotifyCallbacks is not called as this notification should be triggered when
209 // a download is not pending. 233 // a download is not pending.
210 if (type == chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED) { 234 content::WebContents* contents =
211 content::WebContents* contents = 235 content::Source<content::WebContents>(source).ptr();
212 content::Source<content::WebContents>(source).ptr(); 236 DCHECK_EQ(contents, web_contents());
213 DCHECK_EQ(contents, web_contents());
214 237
215 // Fetch the content settings map for this web contents, and extract the 238 // Fetch the content settings map for this web contents, and extract the
216 // automatic downloads permission value. 239 // automatic downloads permission value.
217 HostContentSettingsMap* content_settings = GetContentSettings(contents); 240 HostContentSettingsMap* content_settings = GetContentSettings(contents);
218 if (content_settings) { 241 if (content_settings) {
219 ContentSetting setting = content_settings->GetContentSetting( 242 ContentSetting setting = content_settings->GetContentSetting(
220 contents->GetURL(), contents->GetURL(), 243 contents->GetURL(), contents->GetURL(),
221 CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, std::string()); 244 CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, std::string());
222 245
223 // Update the internal state to match if necessary. 246 // Update the internal state to match if necessary.
224 switch (setting) { 247 switch (setting) {
225 case CONTENT_SETTING_ALLOW: 248 case CONTENT_SETTING_ALLOW:
226 set_download_status(ALLOW_ALL_DOWNLOADS); 249 set_download_status(ALLOW_ALL_DOWNLOADS);
227 break; 250 break;
228 case CONTENT_SETTING_BLOCK: 251 case CONTENT_SETTING_BLOCK:
229 set_download_status(DOWNLOADS_NOT_ALLOWED); 252 set_download_status(DOWNLOADS_NOT_ALLOWED);
230 break; 253 break;
231 case CONTENT_SETTING_ASK: 254 case CONTENT_SETTING_ASK:
232 case CONTENT_SETTING_DEFAULT: 255 case CONTENT_SETTING_DEFAULT:
233 case CONTENT_SETTING_SESSION_ONLY: 256 case CONTENT_SETTING_SESSION_ONLY:
234 set_download_status(PROMPT_BEFORE_DOWNLOAD); 257 set_download_status(PROMPT_BEFORE_DOWNLOAD);
235 break; 258 break;
236 case CONTENT_SETTING_NUM_SETTINGS: 259 case CONTENT_SETTING_NUM_SETTINGS:
237 case CONTENT_SETTING_DETECT_IMPORTANT_CONTENT: 260 case CONTENT_SETTING_DETECT_IMPORTANT_CONTENT:
238 NOTREACHED(); 261 NOTREACHED();
239 return; 262 return;
240 }
241 } 263 }
242 return;
243 } 264 }
244
245 // Otherwise, there is a pending navigation entry.
246 content::NavigationController* controller = &web_contents()->GetController();
247 DCHECK_EQ(controller, content::Source<NavigationController>(source).ptr());
248
249 // NOTE: Resetting state on a pending navigate isn't ideal. In particular it
250 // is possible that queued up downloads for the page before the pending
251 // navigation will be delivered to us after we process this request. If this
252 // happens we may let a download through that we shouldn't have. But this is
253 // rather rare, and it is difficult to get 100% right, so we don't deal with
254 // it.
255 NavigationEntry* entry = controller->GetPendingEntry();
256 if (!entry)
257 return;
258
259 // Redirects don't count.
260 if (ui::PageTransitionIsRedirect(entry->GetTransitionType()))
261 return;
262
263 if (status_ == DownloadRequestLimiter::ALLOW_ALL_DOWNLOADS ||
264 status_ == DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED) {
265 // User has either allowed all downloads or canceled all downloads. Only
266 // reset the download state if the user is navigating to a different host
267 // (or host is empty).
268 if (!initial_page_host_.empty() && !entry->GetURL().host().empty() &&
269 entry->GetURL().host() == initial_page_host_)
270 return;
271 }
272
273 NotifyCallbacks(false);
274 host_->Remove(this, web_contents());
275 } 265 }
276 266
277 void DownloadRequestLimiter::TabDownloadState::NotifyCallbacks(bool allow) { 267 void DownloadRequestLimiter::TabDownloadState::NotifyCallbacks(bool allow) {
278 set_download_status(allow ? 268 set_download_status(allow ? DownloadRequestLimiter::ALLOW_ALL_DOWNLOADS
279 DownloadRequestLimiter::ALLOW_ALL_DOWNLOADS : 269 : DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED);
280 DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED);
281 std::vector<DownloadRequestLimiter::Callback> callbacks; 270 std::vector<DownloadRequestLimiter::Callback> callbacks;
282 bool change_status = false; 271 bool change_status = false;
283 272
284 // Selectively send first few notifications only if number of downloads exceed 273 // Selectively send first few notifications only if number of downloads exceed
285 // kMaxDownloadsAtOnce. In that case, we also retain the infobar instance and 274 // kMaxDownloadsAtOnce. In that case, we also retain the infobar instance and
286 // don't close it. If allow is false, we send all the notifications to cancel 275 // don't close it. If allow is false, we send all the notifications to cancel
287 // all remaining downloads and close the infobar. 276 // all remaining downloads and close the infobar.
288 if (!allow || (callbacks_.size() < kMaxDownloadsAtOnce)) { 277 if (!allow || (callbacks_.size() < kMaxDownloadsAtOnce)) {
289 // Null the generated weak pointer so we don't get notified again. 278 // Null the generated weak pointer so we don't get notified again.
290 factory_.InvalidateWeakPtrs(); 279 factory_.InvalidateWeakPtrs();
(...skipping 19 matching lines...) Expand all
310 299
311 // DownloadRequestLimiter ------------------------------------------------------ 300 // DownloadRequestLimiter ------------------------------------------------------
312 301
313 HostContentSettingsMap* DownloadRequestLimiter::content_settings_ = NULL; 302 HostContentSettingsMap* DownloadRequestLimiter::content_settings_ = NULL;
314 303
315 void DownloadRequestLimiter::SetContentSettingsForTesting( 304 void DownloadRequestLimiter::SetContentSettingsForTesting(
316 HostContentSettingsMap* content_settings) { 305 HostContentSettingsMap* content_settings) {
317 content_settings_ = content_settings; 306 content_settings_ = content_settings;
318 } 307 }
319 308
320 DownloadRequestLimiter::DownloadRequestLimiter() 309 DownloadRequestLimiter::DownloadRequestLimiter() : factory_(this) {}
321 : factory_(this) {
322 }
323 310
324 DownloadRequestLimiter::~DownloadRequestLimiter() { 311 DownloadRequestLimiter::~DownloadRequestLimiter() {
325 // All the tabs should have closed before us, which sends notification and 312 // All the tabs should have closed before us, which sends notification and
326 // removes from state_map_. As such, there should be no pending callbacks. 313 // removes from state_map_. As such, there should be no pending callbacks.
327 DCHECK(state_map_.empty()); 314 DCHECK(state_map_.empty());
328 } 315 }
329 316
330 DownloadRequestLimiter::DownloadStatus 317 DownloadRequestLimiter::DownloadStatus
331 DownloadRequestLimiter::GetDownloadStatus(content::WebContents* web_contents) { 318 DownloadRequestLimiter::GetDownloadStatus(content::WebContents* web_contents) {
332 TabDownloadState* state = GetDownloadState(web_contents, NULL, false); 319 TabDownloadState* state = GetDownloadState(web_contents, NULL, false);
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
371 return; 358 return;
372 } 359 }
373 360
374 // Note that because |originating_contents| might go away before 361 // Note that because |originating_contents| might go away before
375 // OnCanDownloadDecided is invoked, we look it up by |render_process_host_id| 362 // OnCanDownloadDecided is invoked, we look it up by |render_process_host_id|
376 // and |render_view_id|. 363 // and |render_view_id|.
377 base::Callback<void(bool)> can_download_callback = base::Bind( 364 base::Callback<void(bool)> can_download_callback = base::Bind(
378 &DownloadRequestLimiter::OnCanDownloadDecided, factory_.GetWeakPtr(), 365 &DownloadRequestLimiter::OnCanDownloadDecided, factory_.GetWeakPtr(),
379 web_contents_getter, request_method, callback); 366 web_contents_getter, request_method, callback);
380 367
381 originating_contents->GetDelegate()->CanDownload( 368 originating_contents->GetDelegate()->CanDownload(url, request_method,
382 url, 369 can_download_callback);
383 request_method,
384 can_download_callback);
385 } 370 }
386 371
387 void DownloadRequestLimiter::OnCanDownloadDecided( 372 void DownloadRequestLimiter::OnCanDownloadDecided(
388 const content::ResourceRequestInfo::WebContentsGetter& web_contents_getter, 373 const content::ResourceRequestInfo::WebContentsGetter& web_contents_getter,
389 const std::string& request_method, 374 const std::string& request_method,
390 const Callback& orig_callback, 375 const Callback& orig_callback,
391 bool allow) { 376 bool allow) {
392 DCHECK_CURRENTLY_ON(BrowserThread::UI); 377 DCHECK_CURRENTLY_ON(BrowserThread::UI);
393 content::WebContents* originating_contents = web_contents_getter.Run(); 378 content::WebContents* originating_contents = web_contents_getter.Run();
394 if (!originating_contents || !allow) { 379 if (!originating_contents || !allow) {
395 orig_callback.Run(false); 380 orig_callback.Run(false);
396 return; 381 return;
397 } 382 }
398 383
399 CanDownloadImpl(originating_contents, 384 CanDownloadImpl(originating_contents, request_method, orig_callback);
400 request_method,
401 orig_callback);
402 } 385 }
403 386
404 HostContentSettingsMap* DownloadRequestLimiter::GetContentSettings( 387 HostContentSettingsMap* DownloadRequestLimiter::GetContentSettings(
405 content::WebContents* contents) { 388 content::WebContents* contents) {
406 return content_settings_ ? content_settings_ : 389 return content_settings_
407 HostContentSettingsMapFactory::GetForProfile( 390 ? content_settings_
408 Profile::FromBrowserContext(contents->GetBrowserContext())); 391 : HostContentSettingsMapFactory::GetForProfile(
392 Profile::FromBrowserContext(contents->GetBrowserContext()));
409 } 393 }
410 394
411 void DownloadRequestLimiter::CanDownloadImpl( 395 void DownloadRequestLimiter::CanDownloadImpl(
412 content::WebContents* originating_contents, 396 content::WebContents* originating_contents,
413 const std::string& request_method, 397 const std::string& request_method,
414 const Callback& callback) { 398 const Callback& callback) {
415 DCHECK(originating_contents); 399 DCHECK(originating_contents);
416 400
417 TabDownloadState* state = GetDownloadState( 401 TabDownloadState* state =
418 originating_contents, originating_contents, true); 402 GetDownloadState(originating_contents, originating_contents, true);
419 switch (state->download_status()) { 403 switch (state->download_status()) {
420 case ALLOW_ALL_DOWNLOADS: 404 case ALLOW_ALL_DOWNLOADS:
421 if (state->download_count() && !(state->download_count() % 405 if (state->download_count() &&
406 !(state->download_count() %
422 DownloadRequestLimiter::kMaxDownloadsAtOnce)) 407 DownloadRequestLimiter::kMaxDownloadsAtOnce))
423 state->set_download_status(PROMPT_BEFORE_DOWNLOAD); 408 state->set_download_status(PROMPT_BEFORE_DOWNLOAD);
424 callback.Run(true); 409 callback.Run(true);
425 state->increment_download_count(); 410 state->increment_download_count();
426 break; 411 break;
427 412
428 case ALLOW_ONE_DOWNLOAD: 413 case ALLOW_ONE_DOWNLOAD:
429 state->set_download_status(PROMPT_BEFORE_DOWNLOAD); 414 state->set_download_status(PROMPT_BEFORE_DOWNLOAD);
430 callback.Run(true); 415 callback.Run(true);
431 state->increment_download_count(); 416 state->increment_download_count();
432 break; 417 break;
433 418
434 case DOWNLOADS_NOT_ALLOWED: 419 case DOWNLOADS_NOT_ALLOWED:
435 callback.Run(false); 420 callback.Run(false);
436 break; 421 break;
437 422
438 case PROMPT_BEFORE_DOWNLOAD: { 423 case PROMPT_BEFORE_DOWNLOAD: {
439 HostContentSettingsMap* content_settings = GetContentSettings( 424 HostContentSettingsMap* content_settings =
440 originating_contents); 425 GetContentSettings(originating_contents);
441 ContentSetting setting = CONTENT_SETTING_ASK; 426 ContentSetting setting = CONTENT_SETTING_ASK;
442 if (content_settings) 427 if (content_settings)
443 setting = content_settings->GetContentSetting( 428 setting = content_settings->GetContentSetting(
444 originating_contents->GetURL(), 429 originating_contents->GetURL(), originating_contents->GetURL(),
445 originating_contents->GetURL(), 430 CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, std::string());
446 CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS,
447 std::string());
448 switch (setting) { 431 switch (setting) {
449 case CONTENT_SETTING_ALLOW: { 432 case CONTENT_SETTING_ALLOW: {
450 TabSpecificContentSettings* settings = 433 TabSpecificContentSettings* settings =
451 TabSpecificContentSettings::FromWebContents( 434 TabSpecificContentSettings::FromWebContents(originating_contents);
452 originating_contents);
453 if (settings) 435 if (settings)
454 settings->SetDownloadsBlocked(false); 436 settings->SetDownloadsBlocked(false);
455 callback.Run(true); 437 callback.Run(true);
456 state->increment_download_count(); 438 state->increment_download_count();
457 return; 439 return;
458 } 440 }
459 case CONTENT_SETTING_BLOCK: { 441 case CONTENT_SETTING_BLOCK: {
460 TabSpecificContentSettings* settings = 442 TabSpecificContentSettings* settings =
461 TabSpecificContentSettings::FromWebContents( 443 TabSpecificContentSettings::FromWebContents(originating_contents);
462 originating_contents);
463 if (settings) 444 if (settings)
464 settings->SetDownloadsBlocked(true); 445 settings->SetDownloadsBlocked(true);
465 callback.Run(false); 446 callback.Run(false);
466 return; 447 return;
467 } 448 }
468 case CONTENT_SETTING_DEFAULT: 449 case CONTENT_SETTING_DEFAULT:
469 case CONTENT_SETTING_ASK: 450 case CONTENT_SETTING_ASK:
470 case CONTENT_SETTING_SESSION_ONLY: 451 case CONTENT_SETTING_SESSION_ONLY:
471 state->PromptUserForDownload(callback); 452 state->PromptUserForDownload(callback);
472 state->increment_download_count(); 453 state->increment_download_count();
(...skipping 10 matching lines...) Expand all
483 NOTREACHED(); 464 NOTREACHED();
484 } 465 }
485 } 466 }
486 467
487 void DownloadRequestLimiter::Remove(TabDownloadState* state, 468 void DownloadRequestLimiter::Remove(TabDownloadState* state,
488 content::WebContents* contents) { 469 content::WebContents* contents) {
489 DCHECK(ContainsKey(state_map_, contents)); 470 DCHECK(ContainsKey(state_map_, contents));
490 state_map_.erase(contents); 471 state_map_.erase(contents);
491 delete state; 472 delete state;
492 } 473 }
OLDNEW
« no previous file with comments | « chrome/browser/download/download_request_limiter.h ('k') | chrome/browser/download/download_request_limiter_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698