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

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: Implement DidFinishNavigation 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"
28 #include "content/public/common/browser_side_navigation_policy.h"
27 #include "url/gurl.h" 29 #include "url/gurl.h"
28 30
29 #if BUILDFLAG(ANDROID_JAVA_UI) 31 #if BUILDFLAG(ANDROID_JAVA_UI)
30 #include "chrome/browser/download/download_request_infobar_delegate_android.h" 32 #include "chrome/browser/download/download_request_infobar_delegate_android.h"
31 #else 33 #else
32 #include "chrome/browser/download/download_permission_request.h" 34 #include "chrome/browser/download/download_permission_request.h"
33 #include "chrome/browser/ui/website_settings/permission_bubble_manager.h" 35 #include "chrome/browser/ui/website_settings/permission_bubble_manager.h"
34 #endif 36 #endif
35 37
36 using content::BrowserThread; 38 using content::BrowserThread;
(...skipping 10 matching lines...) Expand all
47 web_contents_(contents), 49 web_contents_(contents),
48 host_(host), 50 host_(host),
49 status_(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD), 51 status_(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD),
50 download_count_(0), 52 download_count_(0),
51 factory_(this) { 53 factory_(this) {
52 registrar_.Add( 54 registrar_.Add(
53 this, content::NOTIFICATION_NAV_ENTRY_PENDING, 55 this, content::NOTIFICATION_NAV_ENTRY_PENDING,
54 content::Source<NavigationController>(&contents->GetController())); 56 content::Source<NavigationController>(&contents->GetController()));
55 registrar_.Add(this, chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED, 57 registrar_.Add(this, chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED,
56 content::Source<content::WebContents>(contents)); 58 content::Source<content::WebContents>(contents));
57 NavigationEntry* last_entry = originating_web_contents ? 59 NavigationEntry* last_entry =
58 originating_web_contents->GetController().GetLastCommittedEntry() : 60 originating_web_contents
59 contents->GetController().GetLastCommittedEntry(); 61 ? originating_web_contents->GetController().GetLastCommittedEntry()
62 : contents->GetController().GetLastCommittedEntry();
60 if (last_entry) 63 if (last_entry)
61 initial_page_host_ = last_entry->GetURL().host(); 64 initial_page_host_ = last_entry->GetURL().host();
62 } 65 }
63 66
64 DownloadRequestLimiter::TabDownloadState::~TabDownloadState() { 67 DownloadRequestLimiter::TabDownloadState::~TabDownloadState() {
65 // We should only be destroyed after the callbacks have been notified. 68 // We should only be destroyed after the callbacks have been notified.
66 DCHECK(callbacks_.empty()); 69 DCHECK(callbacks_.empty());
67 70
68 // And we should have invalidated the back pointer. 71 // And we should have invalidated the back pointer.
69 DCHECK(!factory_.HasWeakPtrs()); 72 DCHECK(!factory_.HasWeakPtrs());
70 } 73 }
71 74
72 void DownloadRequestLimiter::TabDownloadState::DidNavigateMainFrame( 75 void DownloadRequestLimiter::TabDownloadState::DidStartNavigation(
73 const content::LoadCommittedDetails& details, 76 content::NavigationHandle* navigation_handle) {
74 const content::FrameNavigateParams& params) { 77 if (!navigation_handle->IsInMainFrame())
Charlie Reis 2016/05/11 21:50:03 Sanity check: Do we limit downloads in subframes s
dominickn 2016/05/12 04:22:58 There is one limiter per WebContents, and that lim
75 switch (status_) { 78 return;
76 case ALLOW_ONE_DOWNLOAD: 79
77 case PROMPT_BEFORE_DOWNLOAD: 80 // If the navigation is renderer-initiated, ensure that a prompting or
78 // When the user reloads the page without responding to the infobar, they 81 // blocking limiter state is not reset, so window.location.href or meta
79 // are expecting DownloadRequestLimiter to behave as if they had just 82 // refresh can't be abused to avoid the limiter.
80 // initially navigated to this page. See http://crbug.com/171372 83 // NOTE: this can only ever be true when PlzNavigate launches (or when
81 NotifyCallbacks(false); 84 // content::IsBrowserSideNavigationEnabled() returns true).
Charlie Reis 2016/05/11 21:50:03 This doesn't sound right. We should know IsRender
dominickn 2016/05/12 04:22:58 This comment was added because I couldn't get the
82 host_->Remove(this, web_contents()); 85 if (navigation_handle->IsRendererInitiated() &&
83 // WARNING: We've been deleted. 86 (status_ == PROMPT_BEFORE_DOWNLOAD || status_ == DOWNLOADS_NOT_ALLOWED)) {
84 break; 87 return;
85 case DOWNLOADS_NOT_ALLOWED: 88 }
86 case ALLOW_ALL_DOWNLOADS: 89
87 // Don't drop this information. The user has explicitly said that they 90 if (status_ == DownloadRequestLimiter::ALLOW_ALL_DOWNLOADS ||
88 // do/don't want downloads from this host. If they accidentally Accepted 91 status_ == DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED) {
89 // or Canceled, they can adjust the limiter state by adjusting the 92 // User has either allowed all downloads or canceled all downloads. Only
90 // automatic downloads content settings. Alternatively, they can copy the 93 // reset the download state if the user is navigating to a different host
91 // URL into a new tab, which will make a new DownloadRequestLimiter. 94 // (or host is empty).
92 // See also the initial_page_host_ logic in Observe() for 95 if (!initial_page_host_.empty() &&
93 // NOTIFICATION_NAV_ENTRY_PENDING. 96 navigation_handle->GetURL().host() == initial_page_host_) {
94 break; 97 return;
95 default: 98 }
96 NOTREACHED(); 99 }
100
101 NotifyCallbacks(false);
102 host_->Remove(this, web_contents());
103 }
104
105 void DownloadRequestLimiter::TabDownloadState::DidFinishNavigation(
106 content::NavigationHandle* navigation_handle) {
107 if (!navigation_handle->IsInMainFrame())
108 return;
109
110 // When the status is ALLOW_ALL_DOWNLOADS or DOWNLOADS_NOT_ALLOWED, don't drop
111 // this information. The user has explicitly said that they
112 // do/don't want downloads from this host. If they accidentally Accepted
113 // or Canceled, they can adjust the limiter state by adjusting the
114 // automatic downloads content settings. Alternatively, they can copy
115 // the URL into a new tab, which will make a new DownloadRequestLimiter.
116 // See also the initial_page_host_ logic in DidStartNavigation or Observe()
117 // for NOTIFICATION_NAV_ENTRY_PENDING.
118 if (status_ == ALLOW_ONE_DOWNLOAD ||
119 (status_ == PROMPT_BEFORE_DOWNLOAD &&
120 !navigation_handle->IsRendererInitiated())) {
121 // When the user reloads the page without responding to the infobar,
122 // they are expecting DownloadRequestLimiter to behave as if they had
123 // just initially navigated to this page. See http://crbug.com/171372.
124 // However, explicitly leave the limiter in place if the navigation was
125 // renderer-initiated and we are in a prompt state.
126 NotifyCallbacks(false);
127 host_->Remove(this, web_contents());
128 // WARNING: We've been deleted.
97 } 129 }
98 } 130 }
99 131
100 void DownloadRequestLimiter::TabDownloadState::DidGetUserInteraction( 132 void DownloadRequestLimiter::TabDownloadState::DidGetUserInteraction(
101 const blink::WebInputEvent::Type type) { 133 const blink::WebInputEvent::Type type) {
102 if (is_showing_prompt() || type == blink::WebInputEvent::GestureScrollBegin) { 134 if (is_showing_prompt() || type == blink::WebInputEvent::GestureScrollBegin) {
103 // Don't change state if a prompt is showing or if the user has scrolled. 135 // Don't change state if a prompt is showing or if the user has scrolled.
104 return; 136 return;
105 } 137 }
106 138
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
138 if (is_showing_prompt()) 170 if (is_showing_prompt())
139 return; 171 return;
140 172
141 #if BUILDFLAG(ANDROID_JAVA_UI) 173 #if BUILDFLAG(ANDROID_JAVA_UI)
142 DownloadRequestInfoBarDelegateAndroid::Create( 174 DownloadRequestInfoBarDelegateAndroid::Create(
143 InfoBarService::FromWebContents(web_contents_), factory_.GetWeakPtr()); 175 InfoBarService::FromWebContents(web_contents_), factory_.GetWeakPtr());
144 #else 176 #else
145 PermissionBubbleManager* bubble_manager = 177 PermissionBubbleManager* bubble_manager =
146 PermissionBubbleManager::FromWebContents(web_contents_); 178 PermissionBubbleManager::FromWebContents(web_contents_);
147 if (bubble_manager) { 179 if (bubble_manager) {
148 bubble_manager->AddRequest(new DownloadPermissionRequest( 180 bubble_manager->AddRequest(
149 factory_.GetWeakPtr())); 181 new DownloadPermissionRequest(factory_.GetWeakPtr()));
150 } else { 182 } else {
151 Cancel(); 183 Cancel();
152 } 184 }
153 #endif 185 #endif
154 } 186 }
155 187
156 void DownloadRequestLimiter::TabDownloadState::SetContentSetting( 188 void DownloadRequestLimiter::TabDownloadState::SetContentSetting(
157 ContentSetting setting) { 189 ContentSetting setting) {
158 if (!web_contents_) 190 if (!web_contents_)
159 return; 191 return;
160 HostContentSettingsMap* settings = 192 HostContentSettingsMap* settings =
161 DownloadRequestLimiter::GetContentSettings(web_contents_); 193 DownloadRequestLimiter::GetContentSettings(web_contents_);
162 if (!settings) 194 if (!settings)
163 return; 195 return;
164 settings->SetContentSettingDefaultScope( 196 settings->SetContentSettingDefaultScope(
165 web_contents_->GetURL(), GURL(), 197 web_contents_->GetURL(), GURL(),
166 CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, std::string(), setting); 198 CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, std::string(), setting);
167 } 199 }
168 200
169 void DownloadRequestLimiter::TabDownloadState::Cancel() { 201 void DownloadRequestLimiter::TabDownloadState::Cancel() {
170 SetContentSetting(CONTENT_SETTING_BLOCK); 202 SetContentSetting(CONTENT_SETTING_BLOCK);
171 NotifyCallbacks(false); 203 NotifyCallbacks(false);
172 } 204 }
173 205
174 void DownloadRequestLimiter::TabDownloadState::CancelOnce() { 206 void DownloadRequestLimiter::TabDownloadState::CancelOnce() {
175 NotifyCallbacks(false); 207 NotifyCallbacks(false);
176 } 208 }
177 209
178 void DownloadRequestLimiter::TabDownloadState::Accept() { 210 void DownloadRequestLimiter::TabDownloadState::Accept() {
179 SetContentSetting(CONTENT_SETTING_ALLOW); 211 SetContentSetting(CONTENT_SETTING_ALLOW);
180 NotifyCallbacks(true); 212 NotifyCallbacks(true);
181 } 213 }
182 214
183 DownloadRequestLimiter::TabDownloadState::TabDownloadState() 215 DownloadRequestLimiter::TabDownloadState::TabDownloadState()
184 : web_contents_(NULL), 216 : web_contents_(NULL),
185 host_(NULL), 217 host_(NULL),
186 status_(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD), 218 status_(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD),
187 download_count_(0), 219 download_count_(0),
188 factory_(this) { 220 factory_(this) {}
189 }
190 221
191 bool DownloadRequestLimiter::TabDownloadState::is_showing_prompt() const { 222 bool DownloadRequestLimiter::TabDownloadState::is_showing_prompt() const {
192 return factory_.HasWeakPtrs(); 223 return factory_.HasWeakPtrs();
193 } 224 }
194 225
195 void DownloadRequestLimiter::TabDownloadState::Observe( 226 void DownloadRequestLimiter::TabDownloadState::Observe(
196 int type, 227 int type,
197 const content::NotificationSource& source, 228 const content::NotificationSource& source,
198 const content::NotificationDetails& details) { 229 const content::NotificationDetails& details) {
199 DCHECK(type == chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED || 230 DCHECK(type == chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED ||
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
233 case CONTENT_SETTING_SESSION_ONLY: 264 case CONTENT_SETTING_SESSION_ONLY:
234 set_download_status(PROMPT_BEFORE_DOWNLOAD); 265 set_download_status(PROMPT_BEFORE_DOWNLOAD);
235 break; 266 break;
236 case CONTENT_SETTING_NUM_SETTINGS: 267 case CONTENT_SETTING_NUM_SETTINGS:
237 case CONTENT_SETTING_DETECT_IMPORTANT_CONTENT: 268 case CONTENT_SETTING_DETECT_IMPORTANT_CONTENT:
238 NOTREACHED(); 269 NOTREACHED();
239 return; 270 return;
240 } 271 }
241 } 272 }
242 return; 273 return;
274 } else if (!content::IsBrowserSideNavigationEnabled()) {
275 // TODO(dominickn): remove this branch entirely when PlzNavigate launches.
276 content::NavigationController* controller =
277 &web_contents()->GetController();
278 DCHECK_EQ(controller, content::Source<NavigationController>(source).ptr());
279
280 // NOTE: Resetting state on a pending navigate isn't ideal. In particular it
281 // is possible that queued up downloads for the page before the pending
282 // navigation will be delivered to us after we process this request. If this
283 // happens we may let a download through that we shouldn't have. But this is
284 // rather rare, and it is difficult to get 100% right, so we don't deal with
285 // it.
286 NavigationEntry* entry = controller->GetPendingEntry();
287 if (!entry)
288 return;
289
290 // Redirects don't count.
291 if (ui::PageTransitionIsRedirect(entry->GetTransitionType()))
292 return;
293
294 if (status_ == DownloadRequestLimiter::ALLOW_ALL_DOWNLOADS ||
295 status_ == DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED) {
296 // User has either allowed all downloads or canceled all downloads. Only
297 // reset the download state if the user is navigating to a different host
298 // (or host is empty).
299 if (!initial_page_host_.empty() && !entry->GetURL().host().empty() &&
300 entry->GetURL().host() == initial_page_host_)
301 return;
302 }
303
304 NotifyCallbacks(false);
305 host_->Remove(this, web_contents());
243 } 306 }
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 } 307 }
276 308
277 void DownloadRequestLimiter::TabDownloadState::NotifyCallbacks(bool allow) { 309 void DownloadRequestLimiter::TabDownloadState::NotifyCallbacks(bool allow) {
278 set_download_status(allow ? 310 set_download_status(allow ? DownloadRequestLimiter::ALLOW_ALL_DOWNLOADS
279 DownloadRequestLimiter::ALLOW_ALL_DOWNLOADS : 311 : DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED);
280 DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED);
281 std::vector<DownloadRequestLimiter::Callback> callbacks; 312 std::vector<DownloadRequestLimiter::Callback> callbacks;
282 bool change_status = false; 313 bool change_status = false;
283 314
284 // Selectively send first few notifications only if number of downloads exceed 315 // Selectively send first few notifications only if number of downloads exceed
285 // kMaxDownloadsAtOnce. In that case, we also retain the infobar instance and 316 // 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 317 // don't close it. If allow is false, we send all the notifications to cancel
287 // all remaining downloads and close the infobar. 318 // all remaining downloads and close the infobar.
288 if (!allow || (callbacks_.size() < kMaxDownloadsAtOnce)) { 319 if (!allow || (callbacks_.size() < kMaxDownloadsAtOnce)) {
289 // Null the generated weak pointer so we don't get notified again. 320 // Null the generated weak pointer so we don't get notified again.
290 factory_.InvalidateWeakPtrs(); 321 factory_.InvalidateWeakPtrs();
(...skipping 19 matching lines...) Expand all
310 341
311 // DownloadRequestLimiter ------------------------------------------------------ 342 // DownloadRequestLimiter ------------------------------------------------------
312 343
313 HostContentSettingsMap* DownloadRequestLimiter::content_settings_ = NULL; 344 HostContentSettingsMap* DownloadRequestLimiter::content_settings_ = NULL;
314 345
315 void DownloadRequestLimiter::SetContentSettingsForTesting( 346 void DownloadRequestLimiter::SetContentSettingsForTesting(
316 HostContentSettingsMap* content_settings) { 347 HostContentSettingsMap* content_settings) {
317 content_settings_ = content_settings; 348 content_settings_ = content_settings;
318 } 349 }
319 350
320 DownloadRequestLimiter::DownloadRequestLimiter() 351 DownloadRequestLimiter::DownloadRequestLimiter() : factory_(this) {}
321 : factory_(this) {
322 }
323 352
324 DownloadRequestLimiter::~DownloadRequestLimiter() { 353 DownloadRequestLimiter::~DownloadRequestLimiter() {
325 // All the tabs should have closed before us, which sends notification and 354 // 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. 355 // removes from state_map_. As such, there should be no pending callbacks.
327 DCHECK(state_map_.empty()); 356 DCHECK(state_map_.empty());
328 } 357 }
329 358
330 DownloadRequestLimiter::DownloadStatus 359 DownloadRequestLimiter::DownloadStatus
331 DownloadRequestLimiter::GetDownloadStatus(content::WebContents* web_contents) { 360 DownloadRequestLimiter::GetDownloadStatus(content::WebContents* web_contents) {
332 TabDownloadState* state = GetDownloadState(web_contents, NULL, false); 361 TabDownloadState* state = GetDownloadState(web_contents, NULL, false);
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
371 return; 400 return;
372 } 401 }
373 402
374 // Note that because |originating_contents| might go away before 403 // Note that because |originating_contents| might go away before
375 // OnCanDownloadDecided is invoked, we look it up by |render_process_host_id| 404 // OnCanDownloadDecided is invoked, we look it up by |render_process_host_id|
376 // and |render_view_id|. 405 // and |render_view_id|.
377 base::Callback<void(bool)> can_download_callback = base::Bind( 406 base::Callback<void(bool)> can_download_callback = base::Bind(
378 &DownloadRequestLimiter::OnCanDownloadDecided, factory_.GetWeakPtr(), 407 &DownloadRequestLimiter::OnCanDownloadDecided, factory_.GetWeakPtr(),
379 web_contents_getter, request_method, callback); 408 web_contents_getter, request_method, callback);
380 409
381 originating_contents->GetDelegate()->CanDownload( 410 originating_contents->GetDelegate()->CanDownload(url, request_method,
382 url, 411 can_download_callback);
383 request_method,
384 can_download_callback);
385 } 412 }
386 413
387 void DownloadRequestLimiter::OnCanDownloadDecided( 414 void DownloadRequestLimiter::OnCanDownloadDecided(
388 const content::ResourceRequestInfo::WebContentsGetter& web_contents_getter, 415 const content::ResourceRequestInfo::WebContentsGetter& web_contents_getter,
389 const std::string& request_method, 416 const std::string& request_method,
390 const Callback& orig_callback, 417 const Callback& orig_callback,
391 bool allow) { 418 bool allow) {
392 DCHECK_CURRENTLY_ON(BrowserThread::UI); 419 DCHECK_CURRENTLY_ON(BrowserThread::UI);
393 content::WebContents* originating_contents = web_contents_getter.Run(); 420 content::WebContents* originating_contents = web_contents_getter.Run();
394 if (!originating_contents || !allow) { 421 if (!originating_contents || !allow) {
395 orig_callback.Run(false); 422 orig_callback.Run(false);
396 return; 423 return;
397 } 424 }
398 425
399 CanDownloadImpl(originating_contents, 426 CanDownloadImpl(originating_contents, request_method, orig_callback);
400 request_method,
401 orig_callback);
402 } 427 }
403 428
404 HostContentSettingsMap* DownloadRequestLimiter::GetContentSettings( 429 HostContentSettingsMap* DownloadRequestLimiter::GetContentSettings(
405 content::WebContents* contents) { 430 content::WebContents* contents) {
406 return content_settings_ ? content_settings_ : 431 return content_settings_
407 HostContentSettingsMapFactory::GetForProfile( 432 ? content_settings_
408 Profile::FromBrowserContext(contents->GetBrowserContext())); 433 : HostContentSettingsMapFactory::GetForProfile(
434 Profile::FromBrowserContext(contents->GetBrowserContext()));
409 } 435 }
410 436
411 void DownloadRequestLimiter::CanDownloadImpl( 437 void DownloadRequestLimiter::CanDownloadImpl(
412 content::WebContents* originating_contents, 438 content::WebContents* originating_contents,
413 const std::string& request_method, 439 const std::string& request_method,
414 const Callback& callback) { 440 const Callback& callback) {
415 DCHECK(originating_contents); 441 DCHECK(originating_contents);
416 442
417 TabDownloadState* state = GetDownloadState( 443 TabDownloadState* state =
418 originating_contents, originating_contents, true); 444 GetDownloadState(originating_contents, originating_contents, true);
419 switch (state->download_status()) { 445 switch (state->download_status()) {
420 case ALLOW_ALL_DOWNLOADS: 446 case ALLOW_ALL_DOWNLOADS:
421 if (state->download_count() && !(state->download_count() % 447 if (state->download_count() &&
448 !(state->download_count() %
422 DownloadRequestLimiter::kMaxDownloadsAtOnce)) 449 DownloadRequestLimiter::kMaxDownloadsAtOnce))
423 state->set_download_status(PROMPT_BEFORE_DOWNLOAD); 450 state->set_download_status(PROMPT_BEFORE_DOWNLOAD);
424 callback.Run(true); 451 callback.Run(true);
425 state->increment_download_count(); 452 state->increment_download_count();
426 break; 453 break;
427 454
428 case ALLOW_ONE_DOWNLOAD: 455 case ALLOW_ONE_DOWNLOAD:
429 state->set_download_status(PROMPT_BEFORE_DOWNLOAD); 456 state->set_download_status(PROMPT_BEFORE_DOWNLOAD);
430 callback.Run(true); 457 callback.Run(true);
431 state->increment_download_count(); 458 state->increment_download_count();
432 break; 459 break;
433 460
434 case DOWNLOADS_NOT_ALLOWED: 461 case DOWNLOADS_NOT_ALLOWED:
435 callback.Run(false); 462 callback.Run(false);
436 break; 463 break;
437 464
438 case PROMPT_BEFORE_DOWNLOAD: { 465 case PROMPT_BEFORE_DOWNLOAD: {
439 HostContentSettingsMap* content_settings = GetContentSettings( 466 HostContentSettingsMap* content_settings =
440 originating_contents); 467 GetContentSettings(originating_contents);
441 ContentSetting setting = CONTENT_SETTING_ASK; 468 ContentSetting setting = CONTENT_SETTING_ASK;
442 if (content_settings) 469 if (content_settings)
443 setting = content_settings->GetContentSetting( 470 setting = content_settings->GetContentSetting(
444 originating_contents->GetURL(), 471 originating_contents->GetURL(), originating_contents->GetURL(),
445 originating_contents->GetURL(), 472 CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, std::string());
446 CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS,
447 std::string());
448 switch (setting) { 473 switch (setting) {
449 case CONTENT_SETTING_ALLOW: { 474 case CONTENT_SETTING_ALLOW: {
450 TabSpecificContentSettings* settings = 475 TabSpecificContentSettings* settings =
451 TabSpecificContentSettings::FromWebContents( 476 TabSpecificContentSettings::FromWebContents(originating_contents);
452 originating_contents);
453 if (settings) 477 if (settings)
454 settings->SetDownloadsBlocked(false); 478 settings->SetDownloadsBlocked(false);
455 callback.Run(true); 479 callback.Run(true);
456 state->increment_download_count(); 480 state->increment_download_count();
457 return; 481 return;
458 } 482 }
459 case CONTENT_SETTING_BLOCK: { 483 case CONTENT_SETTING_BLOCK: {
460 TabSpecificContentSettings* settings = 484 TabSpecificContentSettings* settings =
461 TabSpecificContentSettings::FromWebContents( 485 TabSpecificContentSettings::FromWebContents(originating_contents);
462 originating_contents);
463 if (settings) 486 if (settings)
464 settings->SetDownloadsBlocked(true); 487 settings->SetDownloadsBlocked(true);
465 callback.Run(false); 488 callback.Run(false);
466 return; 489 return;
467 } 490 }
468 case CONTENT_SETTING_DEFAULT: 491 case CONTENT_SETTING_DEFAULT:
469 case CONTENT_SETTING_ASK: 492 case CONTENT_SETTING_ASK:
470 case CONTENT_SETTING_SESSION_ONLY: 493 case CONTENT_SETTING_SESSION_ONLY:
471 state->PromptUserForDownload(callback); 494 state->PromptUserForDownload(callback);
472 state->increment_download_count(); 495 state->increment_download_count();
(...skipping 10 matching lines...) Expand all
483 NOTREACHED(); 506 NOTREACHED();
484 } 507 }
485 } 508 }
486 509
487 void DownloadRequestLimiter::Remove(TabDownloadState* state, 510 void DownloadRequestLimiter::Remove(TabDownloadState* state,
488 content::WebContents* contents) { 511 content::WebContents* contents) {
489 DCHECK(ContainsKey(state_map_, contents)); 512 DCHECK(ContainsKey(state_map_, contents));
490 state_map_.erase(contents); 513 state_map_.erase(contents);
491 delete state; 514 delete state;
492 } 515 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698