OLD | NEW |
---|---|
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/content_settings/tab_specific_content_settings.h" | 9 #include "chrome/browser/content_settings/tab_specific_content_settings.h" |
10 #include "chrome/browser/download/download_permission_request.h" | 10 #include "chrome/browser/download/download_permission_request.h" |
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
240 callbacks.swap(callbacks_); | 240 callbacks.swap(callbacks_); |
241 } else { | 241 } else { |
242 std::vector<DownloadRequestLimiter::Callback>::iterator start, end; | 242 std::vector<DownloadRequestLimiter::Callback>::iterator start, end; |
243 start = callbacks_.begin(); | 243 start = callbacks_.begin(); |
244 end = callbacks_.begin() + kMaxDownloadsAtOnce; | 244 end = callbacks_.begin() + kMaxDownloadsAtOnce; |
245 callbacks.assign(start, end); | 245 callbacks.assign(start, end); |
246 callbacks_.erase(start, end); | 246 callbacks_.erase(start, end); |
247 change_status = true; | 247 change_status = true; |
248 } | 248 } |
249 | 249 |
250 for (size_t i = 0; i < callbacks.size(); ++i) | 250 for (size_t i = 0; i < callbacks.size(); ++i) { |
asanka
2015/07/21 01:14:00
Nit:
for (const auto& callback : callbacks)
qinmin
2015/07/21 22:42:17
Done.
| |
251 host_->ScheduleNotification(callbacks[i], allow); | 251 BrowserThread::PostTask( |
252 BrowserThread::UI, FROM_HERE, base::Bind(callbacks[i], allow)); | |
253 } | |
252 | 254 |
253 if (change_status) | 255 if (change_status) |
254 set_download_status(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD); | 256 set_download_status(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD); |
255 } | 257 } |
256 | 258 |
257 // DownloadRequestLimiter ------------------------------------------------------ | 259 // DownloadRequestLimiter ------------------------------------------------------ |
258 | 260 |
259 HostContentSettingsMap* DownloadRequestLimiter::content_settings_ = NULL; | 261 HostContentSettingsMap* DownloadRequestLimiter::content_settings_ = NULL; |
260 | 262 |
261 void DownloadRequestLimiter::SetContentSettingsForTesting( | 263 void DownloadRequestLimiter::SetContentSettingsForTesting( |
(...skipping 10 matching lines...) Expand all Loading... | |
272 // removes from state_map_. As such, there should be no pending callbacks. | 274 // removes from state_map_. As such, there should be no pending callbacks. |
273 DCHECK(state_map_.empty()); | 275 DCHECK(state_map_.empty()); |
274 } | 276 } |
275 | 277 |
276 DownloadRequestLimiter::DownloadStatus | 278 DownloadRequestLimiter::DownloadStatus |
277 DownloadRequestLimiter::GetDownloadStatus(content::WebContents* web_contents) { | 279 DownloadRequestLimiter::GetDownloadStatus(content::WebContents* web_contents) { |
278 TabDownloadState* state = GetDownloadState(web_contents, NULL, false); | 280 TabDownloadState* state = GetDownloadState(web_contents, NULL, false); |
279 return state ? state->download_status() : ALLOW_ONE_DOWNLOAD; | 281 return state ? state->download_status() : ALLOW_ONE_DOWNLOAD; |
280 } | 282 } |
281 | 283 |
282 void DownloadRequestLimiter::CanDownloadOnIOThread( | |
283 int render_process_host_id, | |
284 int render_view_id, | |
285 const GURL& url, | |
286 const std::string& request_method, | |
287 const Callback& callback) { | |
288 // This is invoked on the IO thread. Schedule the task to run on the UI | |
289 // thread so that we can query UI state. | |
290 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
291 BrowserThread::PostTask( | |
292 BrowserThread::UI, FROM_HERE, | |
293 base::Bind(&DownloadRequestLimiter::CanDownload, this, | |
294 render_process_host_id, render_view_id, url, | |
295 request_method, callback)); | |
296 } | |
297 | |
298 DownloadRequestLimiter::TabDownloadState* | 284 DownloadRequestLimiter::TabDownloadState* |
299 DownloadRequestLimiter::GetDownloadState( | 285 DownloadRequestLimiter::GetDownloadState( |
300 content::WebContents* web_contents, | 286 content::WebContents* web_contents, |
301 content::WebContents* originating_web_contents, | 287 content::WebContents* originating_web_contents, |
302 bool create) { | 288 bool create) { |
303 DCHECK(web_contents); | 289 DCHECK(web_contents); |
304 StateMap::iterator i = state_map_.find(web_contents); | 290 StateMap::iterator i = state_map_.find(web_contents); |
305 if (i != state_map_.end()) | 291 if (i != state_map_.end()) |
306 return i->second; | 292 return i->second; |
307 | 293 |
(...skipping 10 matching lines...) Expand all Loading... | |
318 int render_view_id, | 304 int render_view_id, |
319 const GURL& url, | 305 const GURL& url, |
320 const std::string& request_method, | 306 const std::string& request_method, |
321 const Callback& callback) { | 307 const Callback& callback) { |
322 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 308 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
323 | 309 |
324 content::WebContents* originating_contents = | 310 content::WebContents* originating_contents = |
325 tab_util::GetWebContentsByID(render_process_host_id, render_view_id); | 311 tab_util::GetWebContentsByID(render_process_host_id, render_view_id); |
326 if (!originating_contents) { | 312 if (!originating_contents) { |
327 // The WebContents was closed, don't allow the download. | 313 // The WebContents was closed, don't allow the download. |
328 ScheduleNotification(callback, false); | 314 callback.Run(false); |
329 return; | 315 return; |
330 } | 316 } |
331 | 317 |
332 if (!originating_contents->GetDelegate()) { | 318 if (!originating_contents->GetDelegate()) { |
333 ScheduleNotification(callback, false); | 319 callback.Run(false); |
334 return; | 320 return; |
335 } | 321 } |
336 | 322 |
337 // Note that because |originating_contents| might go away before | 323 // Note that because |originating_contents| might go away before |
338 // OnCanDownloadDecided is invoked, we look it up by |render_process_host_id| | 324 // OnCanDownloadDecided is invoked, we look it up by |render_process_host_id| |
339 // and |render_view_id|. | 325 // and |render_view_id|. |
340 base::Callback<void(bool)> can_download_callback = base::Bind( | 326 base::Callback<void(bool)> can_download_callback = base::Bind( |
341 &DownloadRequestLimiter::OnCanDownloadDecided, | 327 &DownloadRequestLimiter::OnCanDownloadDecided, |
342 factory_.GetWeakPtr(), | 328 factory_.GetWeakPtr(), |
343 render_process_host_id, | 329 render_process_host_id, |
344 render_view_id, | 330 render_view_id, |
345 request_method, | 331 request_method, |
346 callback); | 332 callback); |
347 | 333 |
348 originating_contents->GetDelegate()->CanDownload( | 334 originating_contents->GetDelegate()->CanDownload( |
349 url, | 335 url, |
350 request_method, | 336 request_method, |
351 can_download_callback); | 337 can_download_callback); |
352 } | 338 } |
353 | 339 |
354 void DownloadRequestLimiter::OnCanDownloadDecided( | 340 void DownloadRequestLimiter::OnCanDownloadDecided( |
355 int render_process_host_id, | 341 int render_process_host_id, |
356 int render_view_id, | 342 int render_view_id, |
357 const std::string& request_method, | 343 const std::string& request_method, |
358 const Callback& orig_callback, bool allow) { | 344 const Callback& orig_callback, bool allow) { |
359 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 345 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
360 content::WebContents* originating_contents = | 346 content::WebContents* originating_contents = |
361 tab_util::GetWebContentsByID(render_process_host_id, render_view_id); | 347 tab_util::GetWebContentsByID(render_process_host_id, render_view_id); |
362 if (!originating_contents || !allow) { | 348 if (!originating_contents || !allow) { |
363 ScheduleNotification(orig_callback, false); | 349 orig_callback.Run(false); |
364 return; | 350 return; |
365 } | 351 } |
366 | 352 |
367 CanDownloadImpl(originating_contents, | 353 CanDownloadImpl(originating_contents, |
368 request_method, | 354 request_method, |
369 orig_callback); | 355 orig_callback); |
370 } | 356 } |
371 | 357 |
372 HostContentSettingsMap* DownloadRequestLimiter::GetContentSettings( | 358 HostContentSettingsMap* DownloadRequestLimiter::GetContentSettings( |
373 content::WebContents* contents) { | 359 content::WebContents* contents) { |
374 return content_settings_ ? content_settings_ : Profile::FromBrowserContext( | 360 return content_settings_ ? content_settings_ : Profile::FromBrowserContext( |
375 contents->GetBrowserContext())->GetHostContentSettingsMap(); | 361 contents->GetBrowserContext())->GetHostContentSettingsMap(); |
376 } | 362 } |
377 | 363 |
378 void DownloadRequestLimiter::CanDownloadImpl( | 364 void DownloadRequestLimiter::CanDownloadImpl( |
379 content::WebContents* originating_contents, | 365 content::WebContents* originating_contents, |
380 const std::string& request_method, | 366 const std::string& request_method, |
381 const Callback& callback) { | 367 const Callback& callback) { |
382 DCHECK(originating_contents); | 368 DCHECK(originating_contents); |
383 | 369 |
384 TabDownloadState* state = GetDownloadState( | 370 TabDownloadState* state = GetDownloadState( |
385 originating_contents, originating_contents, true); | 371 originating_contents, originating_contents, true); |
386 switch (state->download_status()) { | 372 switch (state->download_status()) { |
387 case ALLOW_ALL_DOWNLOADS: | 373 case ALLOW_ALL_DOWNLOADS: |
388 if (state->download_count() && !(state->download_count() % | 374 if (state->download_count() && !(state->download_count() % |
389 DownloadRequestLimiter::kMaxDownloadsAtOnce)) | 375 DownloadRequestLimiter::kMaxDownloadsAtOnce)) |
390 state->set_download_status(PROMPT_BEFORE_DOWNLOAD); | 376 state->set_download_status(PROMPT_BEFORE_DOWNLOAD); |
391 ScheduleNotification(callback, true); | 377 callback.Run(true); |
392 state->increment_download_count(); | 378 state->increment_download_count(); |
393 break; | 379 break; |
394 | 380 |
395 case ALLOW_ONE_DOWNLOAD: | 381 case ALLOW_ONE_DOWNLOAD: |
396 state->set_download_status(PROMPT_BEFORE_DOWNLOAD); | 382 state->set_download_status(PROMPT_BEFORE_DOWNLOAD); |
397 ScheduleNotification(callback, true); | 383 callback.Run(true); |
398 state->increment_download_count(); | 384 state->increment_download_count(); |
399 break; | 385 break; |
400 | 386 |
401 case DOWNLOADS_NOT_ALLOWED: | 387 case DOWNLOADS_NOT_ALLOWED: |
402 ScheduleNotification(callback, false); | 388 callback.Run(false); |
403 break; | 389 break; |
404 | 390 |
405 case PROMPT_BEFORE_DOWNLOAD: { | 391 case PROMPT_BEFORE_DOWNLOAD: { |
406 HostContentSettingsMap* content_settings = GetContentSettings( | 392 HostContentSettingsMap* content_settings = GetContentSettings( |
407 originating_contents); | 393 originating_contents); |
408 ContentSetting setting = CONTENT_SETTING_ASK; | 394 ContentSetting setting = CONTENT_SETTING_ASK; |
409 if (content_settings) | 395 if (content_settings) |
410 setting = content_settings->GetContentSetting( | 396 setting = content_settings->GetContentSetting( |
411 originating_contents->GetURL(), | 397 originating_contents->GetURL(), |
412 originating_contents->GetURL(), | 398 originating_contents->GetURL(), |
413 CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, | 399 CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, |
414 std::string()); | 400 std::string()); |
415 switch (setting) { | 401 switch (setting) { |
416 case CONTENT_SETTING_ALLOW: { | 402 case CONTENT_SETTING_ALLOW: { |
417 TabSpecificContentSettings* settings = | 403 TabSpecificContentSettings* settings = |
418 TabSpecificContentSettings::FromWebContents( | 404 TabSpecificContentSettings::FromWebContents( |
419 originating_contents); | 405 originating_contents); |
420 if (settings) | 406 if (settings) |
421 settings->SetDownloadsBlocked(false); | 407 settings->SetDownloadsBlocked(false); |
422 ScheduleNotification(callback, true); | 408 callback.Run(true); |
423 state->increment_download_count(); | 409 state->increment_download_count(); |
424 return; | 410 return; |
425 } | 411 } |
426 case CONTENT_SETTING_BLOCK: { | 412 case CONTENT_SETTING_BLOCK: { |
427 TabSpecificContentSettings* settings = | 413 TabSpecificContentSettings* settings = |
428 TabSpecificContentSettings::FromWebContents( | 414 TabSpecificContentSettings::FromWebContents( |
429 originating_contents); | 415 originating_contents); |
430 if (settings) | 416 if (settings) |
431 settings->SetDownloadsBlocked(true); | 417 settings->SetDownloadsBlocked(true); |
432 ScheduleNotification(callback, false); | 418 callback.Run(false); |
433 return; | 419 return; |
434 } | 420 } |
435 case CONTENT_SETTING_DEFAULT: | 421 case CONTENT_SETTING_DEFAULT: |
436 case CONTENT_SETTING_ASK: | 422 case CONTENT_SETTING_ASK: |
437 case CONTENT_SETTING_SESSION_ONLY: | 423 case CONTENT_SETTING_SESSION_ONLY: |
438 state->PromptUserForDownload(callback); | 424 state->PromptUserForDownload(callback); |
439 state->increment_download_count(); | 425 state->increment_download_count(); |
440 break; | 426 break; |
441 case CONTENT_SETTING_NUM_SETTINGS: | 427 case CONTENT_SETTING_NUM_SETTINGS: |
442 default: | 428 default: |
443 NOTREACHED(); | 429 NOTREACHED(); |
444 return; | 430 return; |
445 } | 431 } |
446 break; | 432 break; |
447 } | 433 } |
448 | 434 |
449 default: | 435 default: |
450 NOTREACHED(); | 436 NOTREACHED(); |
451 } | 437 } |
452 } | 438 } |
453 | 439 |
454 void DownloadRequestLimiter::ScheduleNotification(const Callback& callback, | |
455 bool allow) { | |
456 BrowserThread::PostTask( | |
457 BrowserThread::IO, FROM_HERE, base::Bind(callback, allow)); | |
458 } | |
459 | |
460 void DownloadRequestLimiter::Remove(TabDownloadState* state, | 440 void DownloadRequestLimiter::Remove(TabDownloadState* state, |
461 content::WebContents* contents) { | 441 content::WebContents* contents) { |
462 DCHECK(ContainsKey(state_map_, contents)); | 442 DCHECK(ContainsKey(state_map_, contents)); |
463 state_map_.erase(contents); | 443 state_map_.erase(contents); |
464 delete state; | 444 delete state; |
465 } | 445 } |
OLD | NEW |