Chromium Code Reviews| 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 "content/browser/download/download_manager_impl.h" | 5 #include "content/browser/download/download_manager_impl.h" |
| 6 | 6 |
| 7 #include <iterator> | 7 #include <iterator> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/callback.h" | 10 #include "base/callback.h" |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 32 #include "content/public/browser/browser_thread.h" | 32 #include "content/public/browser/browser_thread.h" |
| 33 #include "content/public/browser/content_browser_client.h" | 33 #include "content/public/browser/content_browser_client.h" |
| 34 #include "content/public/browser/download_interrupt_reasons.h" | 34 #include "content/public/browser/download_interrupt_reasons.h" |
| 35 #include "content/public/browser/download_manager_delegate.h" | 35 #include "content/public/browser/download_manager_delegate.h" |
| 36 #include "content/public/browser/download_url_parameters.h" | 36 #include "content/public/browser/download_url_parameters.h" |
| 37 #include "content/public/browser/notification_service.h" | 37 #include "content/public/browser/notification_service.h" |
| 38 #include "content/public/browser/notification_types.h" | 38 #include "content/public/browser/notification_types.h" |
| 39 #include "content/public/browser/render_process_host.h" | 39 #include "content/public/browser/render_process_host.h" |
| 40 #include "content/public/browser/resource_context.h" | 40 #include "content/public/browser/resource_context.h" |
| 41 #include "content/public/browser/web_contents_delegate.h" | 41 #include "content/public/browser/web_contents_delegate.h" |
| 42 #include "content/public/common/referrer.h" | |
| 42 #include "net/base/load_flags.h" | 43 #include "net/base/load_flags.h" |
| 43 #include "net/base/upload_bytes_element_reader.h" | 44 #include "net/base/upload_bytes_element_reader.h" |
| 44 #include "net/base/upload_data_stream.h" | 45 #include "net/base/upload_data_stream.h" |
| 45 #include "net/url_request/url_request_context.h" | 46 #include "net/url_request/url_request_context.h" |
| 46 #include "webkit/glue/webkit_glue.h" | 47 #include "webkit/glue/webkit_glue.h" |
| 47 | 48 |
| 48 namespace content { | 49 namespace content { |
| 49 namespace { | 50 namespace { |
| 50 | 51 |
| 51 void BeginDownload(scoped_ptr<DownloadUrlParameters> params) { | 52 void BeginDownload(scoped_ptr<DownloadUrlParameters> params, |
| 53 DownloadId download_id) { | |
| 52 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 54 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 53 // ResourceDispatcherHost{Base} is-not-a URLRequest::Delegate, and | 55 // ResourceDispatcherHost{Base} is-not-a URLRequest::Delegate, and |
| 54 // DownloadUrlParameters can-not include resource_dispatcher_host_impl.h, so | 56 // DownloadUrlParameters can-not include resource_dispatcher_host_impl.h, so |
| 55 // we must down cast. RDHI is the only subclass of RDH as of 2012 May 4. | 57 // we must down cast. RDHI is the only subclass of RDH as of 2012 May 4. |
| 56 scoped_ptr<net::URLRequest> request( | 58 scoped_ptr<net::URLRequest> request( |
| 57 params->resource_context()->GetRequestContext()->CreateRequest( | 59 params->resource_context()->GetRequestContext()->CreateRequest( |
| 58 params->url(), NULL)); | 60 params->url(), NULL)); |
| 59 request->set_referrer(params->referrer().url.spec()); | 61 request->set_referrer(params->referrer().url.spec()); |
| 60 webkit_glue::ConfigureURLRequestForReferrerPolicy( | 62 webkit_glue::ConfigureURLRequestForReferrerPolicy( |
| 61 request.get(), params->referrer().policy); | 63 request.get(), params->referrer().policy); |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 72 // The POST in this case does not have an actual body, and only works | 74 // The POST in this case does not have an actual body, and only works |
| 73 // when retrieving data from cache. This is done because we don't want | 75 // when retrieving data from cache. This is done because we don't want |
| 74 // to do a re-POST without user consent, and currently don't have a good | 76 // to do a re-POST without user consent, and currently don't have a good |
| 75 // plan on how to display the UI for that. | 77 // plan on how to display the UI for that. |
| 76 DCHECK(params->prefer_cache()); | 78 DCHECK(params->prefer_cache()); |
| 77 DCHECK(params->method() == "POST"); | 79 DCHECK(params->method() == "POST"); |
| 78 ScopedVector<net::UploadElementReader> element_readers; | 80 ScopedVector<net::UploadElementReader> element_readers; |
| 79 request->set_upload(make_scoped_ptr( | 81 request->set_upload(make_scoped_ptr( |
| 80 new net::UploadDataStream(&element_readers, params->post_id()))); | 82 new net::UploadDataStream(&element_readers, params->post_id()))); |
| 81 } | 83 } |
| 84 | |
| 85 // If we're not at the beginning of the file, retrieve only the remaining | |
| 86 // portion. | |
| 87 if (params->offset() > 0) { | |
| 88 request->SetExtraRequestHeaderByName( | |
| 89 "Range", | |
| 90 StringPrintf("bytes=%" PRId64 "-", params->offset()), | |
| 91 true); | |
| 92 | |
| 93 // If we've asked for a range, we want to make sure that we only | |
| 94 // get that range if our current copy of the information is good. | |
| 95 if (!params->last_modified().empty()) { | |
| 96 request->SetExtraRequestHeaderByName("If-Unmodified-Since", | |
| 97 params->last_modified(), | |
| 98 true); | |
| 99 } | |
| 100 if (!params->etag().empty()) { | |
| 101 request->SetExtraRequestHeaderByName("If-Match", params->etag(), true); | |
| 102 } | |
| 103 } | |
| 104 | |
| 82 for (DownloadUrlParameters::RequestHeadersType::const_iterator iter | 105 for (DownloadUrlParameters::RequestHeadersType::const_iterator iter |
| 83 = params->request_headers_begin(); | 106 = params->request_headers_begin(); |
| 84 iter != params->request_headers_end(); | 107 iter != params->request_headers_end(); |
| 85 ++iter) { | 108 ++iter) { |
| 86 request->SetExtraRequestHeaderByName( | 109 request->SetExtraRequestHeaderByName( |
| 87 iter->first, iter->second, false/*overwrite*/); | 110 iter->first, iter->second, false/*overwrite*/); |
| 88 } | 111 } |
| 89 | 112 |
| 90 scoped_ptr<DownloadSaveInfo> save_info(new DownloadSaveInfo()); | 113 scoped_ptr<DownloadSaveInfo> save_info(new DownloadSaveInfo()); |
| 91 save_info->file_path = params->file_path(); | 114 save_info->file_path = params->file_path(); |
| 92 save_info->suggested_name = params->suggested_name(); | 115 save_info->suggested_name = params->suggested_name(); |
| 93 save_info->offset = params->offset(); | 116 save_info->offset = params->offset(); |
| 94 save_info->hash_state = params->hash_state(); | 117 save_info->hash_state = params->hash_state(); |
| 95 save_info->prompt_for_save_location = params->prompt(); | 118 save_info->prompt_for_save_location = params->prompt(); |
| 96 save_info->file_stream = params->GetFileStream(); | 119 save_info->file_stream = params->GetFileStream(); |
| 97 | 120 |
| 98 params->resource_dispatcher_host()->BeginDownload( | 121 params->resource_dispatcher_host()->BeginDownload( |
| 99 request.Pass(), | 122 request.Pass(), |
| 100 params->content_initiated(), | 123 params->content_initiated(), |
| 101 params->resource_context(), | 124 params->resource_context(), |
| 102 params->render_process_host_id(), | 125 params->render_process_host_id(), |
| 103 params->render_view_host_routing_id(), | 126 params->render_view_host_routing_id(), |
| 104 params->prefer_cache(), | 127 params->prefer_cache(), |
| 105 save_info.Pass(), | 128 save_info.Pass(), |
| 129 download_id, | |
| 106 params->callback()); | 130 params->callback()); |
| 107 } | 131 } |
| 108 | 132 |
| 109 class MapValueIteratorAdapter { | 133 class MapValueIteratorAdapter { |
| 110 public: | 134 public: |
| 111 explicit MapValueIteratorAdapter( | 135 explicit MapValueIteratorAdapter( |
| 112 base::hash_map<int64, DownloadItem*>::const_iterator iter) | 136 base::hash_map<int64, DownloadItem*>::const_iterator iter) |
| 113 : iter_(iter) { | 137 : iter_(iter) { |
| 114 } | 138 } |
| 115 ~MapValueIteratorAdapter() {} | 139 ~MapValueIteratorAdapter() {} |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 166 received_bytes, | 190 received_bytes, |
| 167 total_bytes, | 191 total_bytes, |
| 168 state, | 192 state, |
| 169 opened, | 193 opened, |
| 170 bound_net_log); | 194 bound_net_log); |
| 171 } | 195 } |
| 172 | 196 |
| 173 virtual DownloadItemImpl* CreateActiveItem( | 197 virtual DownloadItemImpl* CreateActiveItem( |
| 174 DownloadItemImplDelegate* delegate, | 198 DownloadItemImplDelegate* delegate, |
| 175 const DownloadCreateInfo& info, | 199 const DownloadCreateInfo& info, |
| 176 scoped_ptr<DownloadRequestHandleInterface> request_handle, | |
| 177 const net::BoundNetLog& bound_net_log) OVERRIDE { | 200 const net::BoundNetLog& bound_net_log) OVERRIDE { |
| 178 return new DownloadItemImpl(delegate, info, request_handle.Pass(), | 201 return new DownloadItemImpl(delegate, info, bound_net_log); |
| 179 bound_net_log); | |
| 180 } | 202 } |
| 181 | 203 |
| 182 virtual DownloadItemImpl* CreateSavePageItem( | 204 virtual DownloadItemImpl* CreateSavePageItem( |
| 183 DownloadItemImplDelegate* delegate, | 205 DownloadItemImplDelegate* delegate, |
| 184 const FilePath& path, | 206 const FilePath& path, |
| 185 const GURL& url, | 207 const GURL& url, |
| 186 DownloadId download_id, | 208 DownloadId download_id, |
| 187 const std::string& mime_type, | 209 const std::string& mime_type, |
| 188 const net::BoundNetLog& bound_net_log) OVERRIDE { | 210 const net::BoundNetLog& bound_net_log) OVERRIDE { |
| 189 return new DownloadItemImpl(delegate, path, url, download_id, | 211 return new DownloadItemImpl(delegate, path, url, download_id, |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 332 browser_context_ = browser_context; | 354 browser_context_ = browser_context; |
| 333 | 355 |
| 334 return true; | 356 return true; |
| 335 } | 357 } |
| 336 | 358 |
| 337 DownloadItem* DownloadManagerImpl::StartDownload( | 359 DownloadItem* DownloadManagerImpl::StartDownload( |
| 338 scoped_ptr<DownloadCreateInfo> info, | 360 scoped_ptr<DownloadCreateInfo> info, |
| 339 scoped_ptr<ByteStreamReader> stream) { | 361 scoped_ptr<ByteStreamReader> stream) { |
| 340 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 362 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 341 | 363 |
| 342 net::BoundNetLog bound_net_log = | |
| 343 net::BoundNetLog::Make(net_log_, net::NetLog::SOURCE_DOWNLOAD); | |
| 344 | |
| 345 FilePath default_download_directory; | 364 FilePath default_download_directory; |
| 346 if (delegate_) { | 365 if (delegate_) { |
| 347 FilePath website_save_directory; // Unused | 366 FilePath website_save_directory; // Unused |
| 348 bool skip_dir_check = false; // Unused | 367 bool skip_dir_check = false; // Unused |
| 349 delegate_->GetSaveDir(GetBrowserContext(), &website_save_directory, | 368 delegate_->GetSaveDir(GetBrowserContext(), &website_save_directory, |
| 350 &default_download_directory, &skip_dir_check); | 369 &default_download_directory, &skip_dir_check); |
| 351 } | 370 } |
| 352 | 371 |
| 353 // We create the DownloadItem before the DownloadFile because the | 372 // We create the DownloadItem before the DownloadFile because the |
| 354 // DownloadItem already needs to handle a state in which there is | 373 // DownloadItem already needs to handle a state in which there is |
| 355 // no associated DownloadFile (history downloads, !IN_PROGRESS downloads) | 374 // no associated DownloadFile (history downloads, !IN_PROGRESS downloads) |
| 356 DownloadItemImpl* download = | 375 DownloadItemImpl* download = GetOrCreateDownloadItem(info.get()); |
| 357 CreateDownloadItem(info.get(), bound_net_log); | |
| 358 scoped_ptr<DownloadFile> download_file( | 376 scoped_ptr<DownloadFile> download_file( |
| 359 file_factory_->CreateFile( | 377 file_factory_->CreateFile( |
| 360 info->save_info.Pass(), default_download_directory, | 378 info->save_info.Pass(), default_download_directory, |
| 361 info->url(), info->referrer_url, | 379 info->url(), info->referrer_url, |
| 362 delegate_->GenerateFileHash(), | 380 delegate_->GenerateFileHash(), |
| 363 stream.Pass(), bound_net_log, | 381 stream.Pass(), download->GetBoundNetLog(), |
| 364 download->DestinationObserverAsWeakPtr())); | 382 download->DestinationObserverAsWeakPtr())); |
| 365 download->Start(download_file.Pass()); | 383 scoped_ptr<DownloadRequestHandleInterface> req_handle( |
| 384 new DownloadRequestHandle(info->request_handle)); | |
| 385 download->Start(download_file.Pass(), req_handle.Pass()); | |
| 366 | 386 |
| 367 // Delay notification until after Start() so that download_file is bound | 387 // Delay notification until after Start() so that download_file is bound |
| 368 // to download and all the usual setters (e.g. Cancel) work. | 388 // to download and all the usual setters (e.g. Cancel) work. |
| 369 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadCreated(this, download)); | 389 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadCreated(this, download)); |
| 370 | 390 |
| 371 return download; | 391 return download; |
| 372 } | 392 } |
| 373 | 393 |
| 374 void DownloadManagerImpl::CheckForHistoryFilesRemoval() { | 394 void DownloadManagerImpl::CheckForHistoryFilesRemoval() { |
| 375 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 395 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 407 void DownloadManagerImpl::OnFileRemovalDetected(int32 download_id) { | 427 void DownloadManagerImpl::OnFileRemovalDetected(int32 download_id) { |
| 408 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 428 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 409 if (ContainsKey(downloads_, download_id)) | 429 if (ContainsKey(downloads_, download_id)) |
| 410 downloads_[download_id]->OnDownloadedFileRemoved(); | 430 downloads_[download_id]->OnDownloadedFileRemoved(); |
| 411 } | 431 } |
| 412 | 432 |
| 413 BrowserContext* DownloadManagerImpl::GetBrowserContext() const { | 433 BrowserContext* DownloadManagerImpl::GetBrowserContext() const { |
| 414 return browser_context_; | 434 return browser_context_; |
| 415 } | 435 } |
| 416 | 436 |
| 417 DownloadItemImpl* DownloadManagerImpl::CreateDownloadItem( | 437 DownloadItemImpl* DownloadManagerImpl::GetOrCreateDownloadItem( |
| 418 DownloadCreateInfo* info, const net::BoundNetLog& bound_net_log) { | 438 DownloadCreateInfo* info) { |
| 419 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 439 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 420 | 440 |
| 421 if (!info->download_id.IsValid()) | 441 if (!info->download_id.IsValid()) |
| 422 info->download_id = GetNextId(); | 442 info->download_id = GetNextId(); |
| 423 DownloadItemImpl* download = item_factory_->CreateActiveItem( | |
| 424 this, *info, | |
| 425 scoped_ptr<DownloadRequestHandleInterface>( | |
| 426 new DownloadRequestHandle(info->request_handle)).Pass(), | |
| 427 bound_net_log); | |
| 428 | 443 |
| 429 DCHECK(!ContainsKey(downloads_, download->GetId())); | 444 DownloadItemImpl* download = NULL; |
| 430 downloads_[download->GetId()] = download; | 445 if (ContainsKey(downloads_, info->download_id.local())) { |
| 446 // Resuming an existing download. | |
| 447 download = downloads_[info->download_id.local()]; | |
| 448 DCHECK(download->IsInterrupted()); | |
| 449 } else { | |
| 450 // New download | |
| 451 net::BoundNetLog bound_net_log = | |
| 452 net::BoundNetLog::Make(net_log_, net::NetLog::SOURCE_DOWNLOAD); | |
| 453 download = item_factory_->CreateActiveItem(this, *info, bound_net_log); | |
| 454 downloads_[download->GetId()] = download; | |
| 455 } | |
| 456 | |
| 431 return download; | 457 return download; |
| 432 } | 458 } |
| 433 | 459 |
| 434 DownloadItemImpl* DownloadManagerImpl::CreateSavePackageDownloadItem( | 460 DownloadItemImpl* DownloadManagerImpl::CreateSavePackageDownloadItem( |
| 435 const FilePath& main_file_path, | 461 const FilePath& main_file_path, |
| 436 const GURL& page_url, | 462 const GURL& page_url, |
| 437 const std::string& mime_type, | 463 const std::string& mime_type, |
| 438 DownloadItem::Observer* observer) { | 464 DownloadItem::Observer* observer) { |
| 439 net::BoundNetLog bound_net_log = | 465 net::BoundNetLog bound_net_log = |
| 440 net::BoundNetLog::Make(net_log_, net::NetLog::SOURCE_DOWNLOAD); | 466 net::BoundNetLog::Make(net_log_, net::NetLog::SOURCE_DOWNLOAD); |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 458 return download_item; | 484 return download_item; |
| 459 } | 485 } |
| 460 | 486 |
| 461 void DownloadManagerImpl::CancelDownload(int32 download_id) { | 487 void DownloadManagerImpl::CancelDownload(int32 download_id) { |
| 462 DownloadItem* download = GetDownload(download_id); | 488 DownloadItem* download = GetDownload(download_id); |
| 463 if (!download || !download->IsInProgress()) | 489 if (!download || !download->IsInProgress()) |
| 464 return; | 490 return; |
| 465 download->Cancel(true); | 491 download->Cancel(true); |
| 466 } | 492 } |
| 467 | 493 |
| 494 // Resume a download of a specific URL. We send the request to the | |
| 495 // ResourceDispatcherHost, and let it send us responses like a regular | |
| 496 // download. | |
| 497 void DownloadManagerImpl::ResumeInterruptedDownload( | |
|
benjhayden
2013/01/06 15:46:04
Could this be merged with DownloadUrl if DownloadU
Randy Smith (Not in Mondays)
2013/01/07 20:54:10
I don't think it should be--the routines have two
| |
| 498 scoped_ptr<content::DownloadUrlParameters> params, | |
| 499 content::DownloadId id) { | |
| 500 BrowserThread::PostTask( | |
| 501 BrowserThread::IO, | |
| 502 FROM_HERE, | |
| 503 base::Bind(&BeginDownload, base::Passed(params.Pass()), id)); | |
| 504 } | |
| 505 | |
| 468 void DownloadManagerImpl::SetDownloadItemFactoryForTesting( | 506 void DownloadManagerImpl::SetDownloadItemFactoryForTesting( |
| 469 scoped_ptr<DownloadItemFactory> item_factory) { | 507 scoped_ptr<DownloadItemFactory> item_factory) { |
| 470 item_factory_ = item_factory.Pass(); | 508 item_factory_ = item_factory.Pass(); |
| 471 } | 509 } |
| 472 | 510 |
| 473 void DownloadManagerImpl::SetDownloadFileFactoryForTesting( | 511 void DownloadManagerImpl::SetDownloadFileFactoryForTesting( |
| 474 scoped_ptr<DownloadFileFactory> file_factory) { | 512 scoped_ptr<DownloadFileFactory> file_factory) { |
| 475 file_factory_ = file_factory.Pass(); | 513 file_factory_ = file_factory.Pass(); |
| 476 } | 514 } |
| 477 | 515 |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 537 } | 575 } |
| 538 | 576 |
| 539 void DownloadManagerImpl::DownloadUrl( | 577 void DownloadManagerImpl::DownloadUrl( |
| 540 scoped_ptr<DownloadUrlParameters> params) { | 578 scoped_ptr<DownloadUrlParameters> params) { |
| 541 if (params->post_id() >= 0) { | 579 if (params->post_id() >= 0) { |
| 542 // Check this here so that the traceback is more useful. | 580 // Check this here so that the traceback is more useful. |
| 543 DCHECK(params->prefer_cache()); | 581 DCHECK(params->prefer_cache()); |
| 544 DCHECK(params->method() == "POST"); | 582 DCHECK(params->method() == "POST"); |
| 545 } | 583 } |
| 546 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind( | 584 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind( |
| 547 &BeginDownload, base::Passed(¶ms))); | 585 &BeginDownload, base::Passed(¶ms), DownloadId())); |
| 548 } | 586 } |
| 549 | 587 |
| 550 void DownloadManagerImpl::AddObserver(Observer* observer) { | 588 void DownloadManagerImpl::AddObserver(Observer* observer) { |
| 551 observers_.AddObserver(observer); | 589 observers_.AddObserver(observer); |
| 552 } | 590 } |
| 553 | 591 |
| 554 void DownloadManagerImpl::RemoveObserver(Observer* observer) { | 592 void DownloadManagerImpl::RemoveObserver(Observer* observer) { |
| 555 observers_.RemoveObserver(observer); | 593 observers_.RemoveObserver(observer); |
| 556 } | 594 } |
| 557 | 595 |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 627 it != downloads_.end(); ++it) { | 665 it != downloads_.end(); ++it) { |
| 628 DownloadItemImpl* item = it->second; | 666 DownloadItemImpl* item = it->second; |
| 629 if (item->IsComplete() && | 667 if (item->IsComplete() && |
| 630 !item->GetOpened()) | 668 !item->GetOpened()) |
| 631 ++num_unopened; | 669 ++num_unopened; |
| 632 } | 670 } |
| 633 RecordOpensOutstanding(num_unopened); | 671 RecordOpensOutstanding(num_unopened); |
| 634 } | 672 } |
| 635 | 673 |
| 636 } // namespace content | 674 } // namespace content |
| OLD | NEW |