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

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: Adding subframe limiter test 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 (but not user-initiated), ensure
78 // When the user reloads the page without responding to the infobar, they 77 // that a prompting or blocking limiter state is not reset, so
79 // are expecting DownloadRequestLimiter to behave as if they had just 78 // window.location.href or meta refresh can't be abused to avoid the limiter.
80 // initially navigated to this page. See http://crbug.com/171372 79 // User-initiated navigations will trigger DidGetUserInteraction, which resets
81 NotifyCallbacks(false); 80 // the limiter before the navigation starts.
82 host_->Remove(this, web_contents()); 81 if (navigation_handle->IsRendererInitiated() &&
83 // WARNING: We've been deleted. 82 (status_ == PROMPT_BEFORE_DOWNLOAD || status_ == DOWNLOADS_NOT_ALLOWED)) {
84 break; 83 return;
85 case DOWNLOADS_NOT_ALLOWED: 84 }
86 case ALLOW_ALL_DOWNLOADS: 85
87 // Don't drop this information. The user has explicitly said that they 86 if (status_ == DownloadRequestLimiter::ALLOW_ALL_DOWNLOADS ||
88 // do/don't want downloads from this host. If they accidentally Accepted 87 status_ == DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED) {
89 // or Canceled, they can adjust the limiter state by adjusting the 88 // User has either allowed all downloads or blocked all downloads. Only
90 // automatic downloads content settings. Alternatively, they can copy the 89 // 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. 90 // (or host is empty).
92 // See also the initial_page_host_ logic in Observe() for 91 if (!initial_page_host_.empty() &&
93 // NOTIFICATION_NAV_ENTRY_PENDING. 92 navigation_handle->GetURL().host() == initial_page_host_) {
94 break; 93 return;
95 default: 94 }
96 NOTREACHED(); 95 }
96
97 NotifyCallbacks(false);
98 host_->Remove(this, web_contents());
99 }
100
101 void DownloadRequestLimiter::TabDownloadState::DidFinishNavigation(
102 content::NavigationHandle* navigation_handle) {
103 if (!navigation_handle->IsInMainFrame())
104 return;
105
106 // When the status is ALLOW_ALL_DOWNLOADS or DOWNLOADS_NOT_ALLOWED, don't drop
107 // this information. The user has explicitly said that they do/don't want
108 // downloads from this host. If they accidentally Accepted or Canceled, they
109 // can adjust the limiter state by adjusting the automatic downloads content
110 // settings. Alternatively, they can copy the URL into a new tab, which will
111 // make a new DownloadRequestLimiter. See also the initial_page_host_ logic in
112 // DidStartNavigation.
113 if (status_ == ALLOW_ONE_DOWNLOAD ||
114 (status_ == PROMPT_BEFORE_DOWNLOAD &&
115 !navigation_handle->IsRendererInitiated())) {
116 // When the user reloads the page without responding to the infobar,
117 // they are expecting DownloadRequestLimiter to behave as if they had
118 // just initially navigated to this page. See http://crbug.com/171372.
119 // However, explicitly leave the limiter in place if the navigation was
120 // renderer-initiated and we are in a prompt state.
121 NotifyCallbacks(false);
122 host_->Remove(this, web_contents());
123 // WARNING: We've been deleted.
97 } 124 }
98 } 125 }
99 126
100 void DownloadRequestLimiter::TabDownloadState::DidGetUserInteraction( 127 void DownloadRequestLimiter::TabDownloadState::DidGetUserInteraction(
101 const blink::WebInputEvent::Type type) { 128 const blink::WebInputEvent::Type type) {
102 if (is_showing_prompt() || type == blink::WebInputEvent::GestureScrollBegin) { 129 if (is_showing_prompt() || type == blink::WebInputEvent::GestureScrollBegin) {
103 // Don't change state if a prompt is showing or if the user has scrolled. 130 // Don't change state if a prompt is showing or if the user has scrolled.
104 return; 131 return;
105 } 132 }
106 133
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
138 if (is_showing_prompt()) 165 if (is_showing_prompt())
139 return; 166 return;
140 167
141 #if BUILDFLAG(ANDROID_JAVA_UI) 168 #if BUILDFLAG(ANDROID_JAVA_UI)
142 DownloadRequestInfoBarDelegateAndroid::Create( 169 DownloadRequestInfoBarDelegateAndroid::Create(
143 InfoBarService::FromWebContents(web_contents_), factory_.GetWeakPtr()); 170 InfoBarService::FromWebContents(web_contents_), factory_.GetWeakPtr());
144 #else 171 #else
145 PermissionBubbleManager* bubble_manager = 172 PermissionBubbleManager* bubble_manager =
146 PermissionBubbleManager::FromWebContents(web_contents_); 173 PermissionBubbleManager::FromWebContents(web_contents_);
147 if (bubble_manager) { 174 if (bubble_manager) {
148 bubble_manager->AddRequest(new DownloadPermissionRequest( 175 bubble_manager->AddRequest(
149 factory_.GetWeakPtr())); 176 new DownloadPermissionRequest(factory_.GetWeakPtr()));
150 } else { 177 } else {
151 Cancel(); 178 Cancel();
152 } 179 }
153 #endif 180 #endif
154 } 181 }
155 182
156 void DownloadRequestLimiter::TabDownloadState::SetContentSetting( 183 void DownloadRequestLimiter::TabDownloadState::SetContentSetting(
157 ContentSetting setting) { 184 ContentSetting setting) {
158 if (!web_contents_) 185 if (!web_contents_)
159 return; 186 return;
160 HostContentSettingsMap* settings = 187 HostContentSettingsMap* settings =
161 DownloadRequestLimiter::GetContentSettings(web_contents_); 188 DownloadRequestLimiter::GetContentSettings(web_contents_);
162 if (!settings) 189 if (!settings)
163 return; 190 return;
164 settings->SetContentSettingDefaultScope( 191 settings->SetContentSettingDefaultScope(
165 web_contents_->GetURL(), GURL(), 192 web_contents_->GetURL(), GURL(),
166 CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, std::string(), setting); 193 CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, std::string(), setting);
167 } 194 }
168 195
169 void DownloadRequestLimiter::TabDownloadState::Cancel() { 196 void DownloadRequestLimiter::TabDownloadState::Cancel() {
170 SetContentSetting(CONTENT_SETTING_BLOCK); 197 SetContentSetting(CONTENT_SETTING_BLOCK);
171 NotifyCallbacks(false); 198 NotifyCallbacks(false);
172 } 199 }
173 200
174 void DownloadRequestLimiter::TabDownloadState::CancelOnce() { 201 void DownloadRequestLimiter::TabDownloadState::CancelOnce() {
175 NotifyCallbacks(false); 202 NotifyCallbacks(false);
176 } 203 }
177 204
178 void DownloadRequestLimiter::TabDownloadState::Accept() { 205 void DownloadRequestLimiter::TabDownloadState::Accept() {
179 SetContentSetting(CONTENT_SETTING_ALLOW); 206 SetContentSetting(CONTENT_SETTING_ALLOW);
180 NotifyCallbacks(true); 207 NotifyCallbacks(true);
181 } 208 }
182 209
183 DownloadRequestLimiter::TabDownloadState::TabDownloadState() 210 DownloadRequestLimiter::TabDownloadState::TabDownloadState()
184 : web_contents_(NULL), 211 : web_contents_(NULL),
185 host_(NULL), 212 host_(NULL),
186 status_(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD), 213 status_(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD),
187 download_count_(0), 214 download_count_(0),
188 factory_(this) { 215 factory_(this) {}
189 }
190 216
191 bool DownloadRequestLimiter::TabDownloadState::is_showing_prompt() const { 217 bool DownloadRequestLimiter::TabDownloadState::is_showing_prompt() const {
192 return factory_.HasWeakPtrs(); 218 return factory_.HasWeakPtrs();
193 } 219 }
194 220
195 void DownloadRequestLimiter::TabDownloadState::Observe( 221 void DownloadRequestLimiter::TabDownloadState::Observe(
196 int type, 222 int type,
197 const content::NotificationSource& source, 223 const content::NotificationSource& source,
198 const content::NotificationDetails& details) { 224 const content::NotificationDetails& details) {
199 DCHECK(type == chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED || 225 DCHECK(type == chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED);
200 type == content::NOTIFICATION_NAV_ENTRY_PENDING);
201 226
202 // Content settings have been updated for our web contents, e.g. via the OIB 227 // 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 228 // 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 229 // 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 230 // necessary. If there is no content setting persisted, then retain the
206 // current state and do nothing. 231 // current state and do nothing.
207 // 232 //
208 // NotifyCallbacks is not called as this notification should be triggered when 233 // NotifyCallbacks is not called as this notification should be triggered when
209 // a download is not pending. 234 // a download is not pending.
210 if (type == chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED) { 235 content::WebContents* contents =
211 content::WebContents* contents = 236 content::Source<content::WebContents>(source).ptr();
212 content::Source<content::WebContents>(source).ptr(); 237 DCHECK_EQ(contents, web_contents());
213 DCHECK_EQ(contents, web_contents());
214 238
215 // Fetch the content settings map for this web contents, and extract the 239 // Fetch the content settings map for this web contents, and extract the
216 // automatic downloads permission value. 240 // automatic downloads permission value.
217 HostContentSettingsMap* content_settings = GetContentSettings(contents); 241 HostContentSettingsMap* content_settings = GetContentSettings(contents);
218 if (content_settings) { 242 if (!content_settings)
219 ContentSetting setting = content_settings->GetContentSetting(
220 contents->GetURL(), contents->GetURL(),
221 CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, std::string());
222
223 // Update the internal state to match if necessary.
224 switch (setting) {
225 case CONTENT_SETTING_ALLOW:
226 set_download_status(ALLOW_ALL_DOWNLOADS);
227 break;
228 case CONTENT_SETTING_BLOCK:
229 set_download_status(DOWNLOADS_NOT_ALLOWED);
230 break;
231 case CONTENT_SETTING_ASK:
232 case CONTENT_SETTING_DEFAULT:
233 case CONTENT_SETTING_SESSION_ONLY:
234 set_download_status(PROMPT_BEFORE_DOWNLOAD);
235 break;
236 case CONTENT_SETTING_NUM_SETTINGS:
237 case CONTENT_SETTING_DETECT_IMPORTANT_CONTENT:
238 NOTREACHED();
239 return;
240 }
241 }
242 return;
243 }
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; 243 return;
258 244
259 // Redirects don't count. 245 ContentSetting setting = content_settings->GetContentSetting(
260 if (ui::PageTransitionIsRedirect(entry->GetTransitionType())) 246 contents->GetURL(), contents->GetURL(),
261 return; 247 CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, std::string());
262 248
263 if (status_ == DownloadRequestLimiter::ALLOW_ALL_DOWNLOADS || 249 // Update the internal state to match if necessary.
264 status_ == DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED) { 250 switch (setting) {
265 // User has either allowed all downloads or canceled all downloads. Only 251 case CONTENT_SETTING_ALLOW:
266 // reset the download state if the user is navigating to a different host 252 set_download_status(ALLOW_ALL_DOWNLOADS);
267 // (or host is empty). 253 break;
268 if (!initial_page_host_.empty() && !entry->GetURL().host().empty() && 254 case CONTENT_SETTING_BLOCK:
269 entry->GetURL().host() == initial_page_host_) 255 set_download_status(DOWNLOADS_NOT_ALLOWED);
256 break;
257 case CONTENT_SETTING_ASK:
258 case CONTENT_SETTING_DEFAULT:
259 case CONTENT_SETTING_SESSION_ONLY:
260 set_download_status(PROMPT_BEFORE_DOWNLOAD);
261 break;
262 case CONTENT_SETTING_NUM_SETTINGS:
263 case CONTENT_SETTING_DETECT_IMPORTANT_CONTENT:
264 NOTREACHED();
270 return; 265 return;
271 } 266 }
272
273 NotifyCallbacks(false);
274 host_->Remove(this, web_contents());
275 } 267 }
276 268
277 void DownloadRequestLimiter::TabDownloadState::NotifyCallbacks(bool allow) { 269 void DownloadRequestLimiter::TabDownloadState::NotifyCallbacks(bool allow) {
278 set_download_status(allow ? 270 set_download_status(allow ? DownloadRequestLimiter::ALLOW_ALL_DOWNLOADS
279 DownloadRequestLimiter::ALLOW_ALL_DOWNLOADS : 271 : DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED);
280 DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED);
281 std::vector<DownloadRequestLimiter::Callback> callbacks; 272 std::vector<DownloadRequestLimiter::Callback> callbacks;
282 bool change_status = false; 273 bool change_status = false;
283 274
284 // Selectively send first few notifications only if number of downloads exceed 275 // Selectively send first few notifications only if number of downloads exceed
285 // kMaxDownloadsAtOnce. In that case, we also retain the infobar instance and 276 // 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 277 // don't close it. If allow is false, we send all the notifications to cancel
287 // all remaining downloads and close the infobar. 278 // all remaining downloads and close the infobar.
288 if (!allow || (callbacks_.size() < kMaxDownloadsAtOnce)) { 279 if (!allow || (callbacks_.size() < kMaxDownloadsAtOnce)) {
289 // Null the generated weak pointer so we don't get notified again. 280 // Null the generated weak pointer so we don't get notified again.
290 factory_.InvalidateWeakPtrs(); 281 factory_.InvalidateWeakPtrs();
(...skipping 19 matching lines...) Expand all
310 301
311 // DownloadRequestLimiter ------------------------------------------------------ 302 // DownloadRequestLimiter ------------------------------------------------------
312 303
313 HostContentSettingsMap* DownloadRequestLimiter::content_settings_ = NULL; 304 HostContentSettingsMap* DownloadRequestLimiter::content_settings_ = NULL;
314 305
315 void DownloadRequestLimiter::SetContentSettingsForTesting( 306 void DownloadRequestLimiter::SetContentSettingsForTesting(
316 HostContentSettingsMap* content_settings) { 307 HostContentSettingsMap* content_settings) {
317 content_settings_ = content_settings; 308 content_settings_ = content_settings;
318 } 309 }
319 310
320 DownloadRequestLimiter::DownloadRequestLimiter() 311 DownloadRequestLimiter::DownloadRequestLimiter() : factory_(this) {}
321 : factory_(this) {
322 }
323 312
324 DownloadRequestLimiter::~DownloadRequestLimiter() { 313 DownloadRequestLimiter::~DownloadRequestLimiter() {
325 // All the tabs should have closed before us, which sends notification and 314 // 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. 315 // removes from state_map_. As such, there should be no pending callbacks.
327 DCHECK(state_map_.empty()); 316 DCHECK(state_map_.empty());
328 } 317 }
329 318
330 DownloadRequestLimiter::DownloadStatus 319 DownloadRequestLimiter::DownloadStatus
331 DownloadRequestLimiter::GetDownloadStatus(content::WebContents* web_contents) { 320 DownloadRequestLimiter::GetDownloadStatus(content::WebContents* web_contents) {
332 TabDownloadState* state = GetDownloadState(web_contents, NULL, false); 321 TabDownloadState* state = GetDownloadState(web_contents, NULL, false);
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
371 return; 360 return;
372 } 361 }
373 362
374 // Note that because |originating_contents| might go away before 363 // Note that because |originating_contents| might go away before
375 // OnCanDownloadDecided is invoked, we look it up by |render_process_host_id| 364 // OnCanDownloadDecided is invoked, we look it up by |render_process_host_id|
376 // and |render_view_id|. 365 // and |render_view_id|.
377 base::Callback<void(bool)> can_download_callback = base::Bind( 366 base::Callback<void(bool)> can_download_callback = base::Bind(
378 &DownloadRequestLimiter::OnCanDownloadDecided, factory_.GetWeakPtr(), 367 &DownloadRequestLimiter::OnCanDownloadDecided, factory_.GetWeakPtr(),
379 web_contents_getter, request_method, callback); 368 web_contents_getter, request_method, callback);
380 369
381 originating_contents->GetDelegate()->CanDownload( 370 originating_contents->GetDelegate()->CanDownload(url, request_method,
382 url, 371 can_download_callback);
383 request_method,
384 can_download_callback);
385 } 372 }
386 373
387 void DownloadRequestLimiter::OnCanDownloadDecided( 374 void DownloadRequestLimiter::OnCanDownloadDecided(
388 const content::ResourceRequestInfo::WebContentsGetter& web_contents_getter, 375 const content::ResourceRequestInfo::WebContentsGetter& web_contents_getter,
389 const std::string& request_method, 376 const std::string& request_method,
390 const Callback& orig_callback, 377 const Callback& orig_callback,
391 bool allow) { 378 bool allow) {
392 DCHECK_CURRENTLY_ON(BrowserThread::UI); 379 DCHECK_CURRENTLY_ON(BrowserThread::UI);
393 content::WebContents* originating_contents = web_contents_getter.Run(); 380 content::WebContents* originating_contents = web_contents_getter.Run();
394 if (!originating_contents || !allow) { 381 if (!originating_contents || !allow) {
395 orig_callback.Run(false); 382 orig_callback.Run(false);
396 return; 383 return;
397 } 384 }
398 385
399 CanDownloadImpl(originating_contents, 386 CanDownloadImpl(originating_contents, request_method, orig_callback);
400 request_method,
401 orig_callback);
402 } 387 }
403 388
404 HostContentSettingsMap* DownloadRequestLimiter::GetContentSettings( 389 HostContentSettingsMap* DownloadRequestLimiter::GetContentSettings(
405 content::WebContents* contents) { 390 content::WebContents* contents) {
406 return content_settings_ ? content_settings_ : 391 return content_settings_
407 HostContentSettingsMapFactory::GetForProfile( 392 ? content_settings_
408 Profile::FromBrowserContext(contents->GetBrowserContext())); 393 : HostContentSettingsMapFactory::GetForProfile(
394 Profile::FromBrowserContext(contents->GetBrowserContext()));
409 } 395 }
410 396
411 void DownloadRequestLimiter::CanDownloadImpl( 397 void DownloadRequestLimiter::CanDownloadImpl(
412 content::WebContents* originating_contents, 398 content::WebContents* originating_contents,
413 const std::string& request_method, 399 const std::string& request_method,
414 const Callback& callback) { 400 const Callback& callback) {
415 DCHECK(originating_contents); 401 DCHECK(originating_contents);
416 402
417 TabDownloadState* state = GetDownloadState( 403 TabDownloadState* state =
418 originating_contents, originating_contents, true); 404 GetDownloadState(originating_contents, originating_contents, true);
419 switch (state->download_status()) { 405 switch (state->download_status()) {
420 case ALLOW_ALL_DOWNLOADS: 406 case ALLOW_ALL_DOWNLOADS:
421 if (state->download_count() && !(state->download_count() % 407 if (state->download_count() &&
408 !(state->download_count() %
422 DownloadRequestLimiter::kMaxDownloadsAtOnce)) 409 DownloadRequestLimiter::kMaxDownloadsAtOnce))
423 state->set_download_status(PROMPT_BEFORE_DOWNLOAD); 410 state->set_download_status(PROMPT_BEFORE_DOWNLOAD);
424 callback.Run(true); 411 callback.Run(true);
425 state->increment_download_count(); 412 state->increment_download_count();
426 break; 413 break;
427 414
428 case ALLOW_ONE_DOWNLOAD: 415 case ALLOW_ONE_DOWNLOAD:
429 state->set_download_status(PROMPT_BEFORE_DOWNLOAD); 416 state->set_download_status(PROMPT_BEFORE_DOWNLOAD);
430 callback.Run(true); 417 callback.Run(true);
431 state->increment_download_count(); 418 state->increment_download_count();
432 break; 419 break;
433 420
434 case DOWNLOADS_NOT_ALLOWED: 421 case DOWNLOADS_NOT_ALLOWED:
435 callback.Run(false); 422 callback.Run(false);
436 break; 423 break;
437 424
438 case PROMPT_BEFORE_DOWNLOAD: { 425 case PROMPT_BEFORE_DOWNLOAD: {
439 HostContentSettingsMap* content_settings = GetContentSettings( 426 HostContentSettingsMap* content_settings =
440 originating_contents); 427 GetContentSettings(originating_contents);
441 ContentSetting setting = CONTENT_SETTING_ASK; 428 ContentSetting setting = CONTENT_SETTING_ASK;
442 if (content_settings) 429 if (content_settings)
443 setting = content_settings->GetContentSetting( 430 setting = content_settings->GetContentSetting(
444 originating_contents->GetURL(), 431 originating_contents->GetURL(), originating_contents->GetURL(),
445 originating_contents->GetURL(), 432 CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, std::string());
446 CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS,
447 std::string());
448 switch (setting) { 433 switch (setting) {
449 case CONTENT_SETTING_ALLOW: { 434 case CONTENT_SETTING_ALLOW: {
450 TabSpecificContentSettings* settings = 435 TabSpecificContentSettings* settings =
451 TabSpecificContentSettings::FromWebContents( 436 TabSpecificContentSettings::FromWebContents(originating_contents);
452 originating_contents);
453 if (settings) 437 if (settings)
454 settings->SetDownloadsBlocked(false); 438 settings->SetDownloadsBlocked(false);
455 callback.Run(true); 439 callback.Run(true);
456 state->increment_download_count(); 440 state->increment_download_count();
457 return; 441 return;
458 } 442 }
459 case CONTENT_SETTING_BLOCK: { 443 case CONTENT_SETTING_BLOCK: {
460 TabSpecificContentSettings* settings = 444 TabSpecificContentSettings* settings =
461 TabSpecificContentSettings::FromWebContents( 445 TabSpecificContentSettings::FromWebContents(originating_contents);
462 originating_contents);
463 if (settings) 446 if (settings)
464 settings->SetDownloadsBlocked(true); 447 settings->SetDownloadsBlocked(true);
465 callback.Run(false); 448 callback.Run(false);
466 return; 449 return;
467 } 450 }
468 case CONTENT_SETTING_DEFAULT: 451 case CONTENT_SETTING_DEFAULT:
469 case CONTENT_SETTING_ASK: 452 case CONTENT_SETTING_ASK:
470 case CONTENT_SETTING_SESSION_ONLY: 453 case CONTENT_SETTING_SESSION_ONLY:
471 state->PromptUserForDownload(callback); 454 state->PromptUserForDownload(callback);
472 state->increment_download_count(); 455 state->increment_download_count();
(...skipping 10 matching lines...) Expand all
483 NOTREACHED(); 466 NOTREACHED();
484 } 467 }
485 } 468 }
486 469
487 void DownloadRequestLimiter::Remove(TabDownloadState* state, 470 void DownloadRequestLimiter::Remove(TabDownloadState* state,
488 content::WebContents* contents) { 471 content::WebContents* contents) {
489 DCHECK(ContainsKey(state_map_, contents)); 472 DCHECK(ContainsKey(state_map_, contents));
490 state_map_.erase(contents); 473 state_map_.erase(contents);
491 delete state; 474 delete state;
492 } 475 }
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