| 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 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 333 browser_context_ = browser_context; | 355 browser_context_ = browser_context; |
| 334 | 356 |
| 335 return true; | 357 return true; |
| 336 } | 358 } |
| 337 | 359 |
| 338 DownloadItem* DownloadManagerImpl::StartDownload( | 360 DownloadItem* DownloadManagerImpl::StartDownload( |
| 339 scoped_ptr<DownloadCreateInfo> info, | 361 scoped_ptr<DownloadCreateInfo> info, |
| 340 scoped_ptr<ByteStreamReader> stream) { | 362 scoped_ptr<ByteStreamReader> stream) { |
| 341 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 363 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 342 | 364 |
| 343 net::BoundNetLog bound_net_log = | |
| 344 net::BoundNetLog::Make(net_log_, net::NetLog::SOURCE_DOWNLOAD); | |
| 345 | |
| 346 FilePath default_download_directory; | 365 FilePath default_download_directory; |
| 347 if (delegate_) { | 366 if (delegate_) { |
| 348 FilePath website_save_directory; // Unused | 367 FilePath website_save_directory; // Unused |
| 349 bool skip_dir_check = false; // Unused | 368 bool skip_dir_check = false; // Unused |
| 350 delegate_->GetSaveDir(GetBrowserContext(), &website_save_directory, | 369 delegate_->GetSaveDir(GetBrowserContext(), &website_save_directory, |
| 351 &default_download_directory, &skip_dir_check); | 370 &default_download_directory, &skip_dir_check); |
| 352 } | 371 } |
| 353 | 372 |
| 354 // We create the DownloadItem before the DownloadFile because the | 373 // We create the DownloadItem before the DownloadFile because the |
| 355 // DownloadItem already needs to handle a state in which there is | 374 // DownloadItem already needs to handle a state in which there is |
| 356 // no associated DownloadFile (history downloads, !IN_PROGRESS downloads) | 375 // no associated DownloadFile (history downloads, !IN_PROGRESS downloads) |
| 357 DownloadItemImpl* download = | 376 DownloadItemImpl* download = GetOrCreateDownloadItem(info.get()); |
| 358 CreateDownloadItem(info.get(), bound_net_log); | |
| 359 scoped_ptr<DownloadFile> download_file( | 377 scoped_ptr<DownloadFile> download_file( |
| 360 file_factory_->CreateFile( | 378 file_factory_->CreateFile( |
| 361 info->save_info.Pass(), default_download_directory, | 379 info->save_info.Pass(), default_download_directory, |
| 362 info->url(), info->referrer_url, | 380 info->url(), info->referrer_url, |
| 363 delegate_->GenerateFileHash(), | 381 delegate_->GenerateFileHash(), |
| 364 stream.Pass(), bound_net_log, | 382 stream.Pass(), download->GetBoundNetLog(), |
| 365 download->DestinationObserverAsWeakPtr())); | 383 download->DestinationObserverAsWeakPtr())); |
| 366 download->Start(download_file.Pass()); | 384 scoped_ptr<DownloadRequestHandleInterface> req_handle( |
| 385 new DownloadRequestHandle(info->request_handle)); |
| 386 download->Start(download_file.Pass(), req_handle.Pass()); |
| 367 | 387 |
| 368 // Delay notification until after Start() so that download_file is bound | 388 // Delay notification until after Start() so that download_file is bound |
| 369 // to download and all the usual setters (e.g. Cancel) work. | 389 // to download and all the usual setters (e.g. Cancel) work. |
| 370 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadCreated(this, download)); | 390 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadCreated(this, download)); |
| 371 | 391 |
| 372 return download; | 392 return download; |
| 373 } | 393 } |
| 374 | 394 |
| 375 void DownloadManagerImpl::CheckForHistoryFilesRemoval() { | 395 void DownloadManagerImpl::CheckForHistoryFilesRemoval() { |
| 376 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 396 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 408 void DownloadManagerImpl::OnFileRemovalDetected(int32 download_id) { | 428 void DownloadManagerImpl::OnFileRemovalDetected(int32 download_id) { |
| 409 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 429 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 410 if (ContainsKey(downloads_, download_id)) | 430 if (ContainsKey(downloads_, download_id)) |
| 411 downloads_[download_id]->OnDownloadedFileRemoved(); | 431 downloads_[download_id]->OnDownloadedFileRemoved(); |
| 412 } | 432 } |
| 413 | 433 |
| 414 BrowserContext* DownloadManagerImpl::GetBrowserContext() const { | 434 BrowserContext* DownloadManagerImpl::GetBrowserContext() const { |
| 415 return browser_context_; | 435 return browser_context_; |
| 416 } | 436 } |
| 417 | 437 |
| 418 DownloadItemImpl* DownloadManagerImpl::CreateDownloadItem( | 438 DownloadItemImpl* DownloadManagerImpl::GetOrCreateDownloadItem( |
| 419 DownloadCreateInfo* info, const net::BoundNetLog& bound_net_log) { | 439 DownloadCreateInfo* info) { |
| 420 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 440 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 421 | 441 |
| 422 if (!info->download_id.IsValid()) | 442 if (!info->download_id.IsValid()) |
| 423 info->download_id = GetNextId(); | 443 info->download_id = GetNextId(); |
| 424 DownloadItemImpl* download = item_factory_->CreateActiveItem( | |
| 425 this, *info, | |
| 426 scoped_ptr<DownloadRequestHandleInterface>( | |
| 427 new DownloadRequestHandle(info->request_handle)).Pass(), | |
| 428 bound_net_log); | |
| 429 | 444 |
| 430 DCHECK(!ContainsKey(downloads_, download->GetId())); | 445 DownloadItemImpl* download = NULL; |
| 431 downloads_[download->GetId()] = download; | 446 if (ContainsKey(downloads_, info->download_id.local())) { |
| 447 // Resuming an existing download. |
| 448 download = downloads_[info->download_id.local()]; |
| 449 DCHECK(download->IsInterrupted()); |
| 450 } else { |
| 451 // New download |
| 452 net::BoundNetLog bound_net_log = |
| 453 net::BoundNetLog::Make(net_log_, net::NetLog::SOURCE_DOWNLOAD); |
| 454 download = item_factory_->CreateActiveItem(this, *info, bound_net_log); |
| 455 downloads_[download->GetId()] = download; |
| 456 } |
| 457 |
| 432 return download; | 458 return download; |
| 433 } | 459 } |
| 434 | 460 |
| 435 DownloadItemImpl* DownloadManagerImpl::CreateSavePackageDownloadItem( | 461 DownloadItemImpl* DownloadManagerImpl::CreateSavePackageDownloadItem( |
| 436 const FilePath& main_file_path, | 462 const FilePath& main_file_path, |
| 437 const GURL& page_url, | 463 const GURL& page_url, |
| 438 const std::string& mime_type, | 464 const std::string& mime_type, |
| 439 DownloadItem::Observer* observer) { | 465 DownloadItem::Observer* observer) { |
| 440 net::BoundNetLog bound_net_log = | 466 net::BoundNetLog bound_net_log = |
| 441 net::BoundNetLog::Make(net_log_, net::NetLog::SOURCE_DOWNLOAD); | 467 net::BoundNetLog::Make(net_log_, net::NetLog::SOURCE_DOWNLOAD); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 459 return download_item; | 485 return download_item; |
| 460 } | 486 } |
| 461 | 487 |
| 462 void DownloadManagerImpl::CancelDownload(int32 download_id) { | 488 void DownloadManagerImpl::CancelDownload(int32 download_id) { |
| 463 DownloadItem* download = GetDownload(download_id); | 489 DownloadItem* download = GetDownload(download_id); |
| 464 if (!download || !download->IsInProgress()) | 490 if (!download || !download->IsInProgress()) |
| 465 return; | 491 return; |
| 466 download->Cancel(true); | 492 download->Cancel(true); |
| 467 } | 493 } |
| 468 | 494 |
| 495 // Resume a download of a specific URL. We send the request to the |
| 496 // ResourceDispatcherHost, and let it send us responses like a regular |
| 497 // download. |
| 498 void DownloadManagerImpl::ResumeInterruptedDownload( |
| 499 scoped_ptr<content::DownloadUrlParameters> params, |
| 500 content::DownloadId id) { |
| 501 BrowserThread::PostTask( |
| 502 BrowserThread::IO, |
| 503 FROM_HERE, |
| 504 base::Bind(&BeginDownload, base::Passed(params.Pass()), id)); |
| 505 } |
| 506 |
| 469 void DownloadManagerImpl::SetDownloadItemFactoryForTesting( | 507 void DownloadManagerImpl::SetDownloadItemFactoryForTesting( |
| 470 scoped_ptr<DownloadItemFactory> item_factory) { | 508 scoped_ptr<DownloadItemFactory> item_factory) { |
| 471 item_factory_ = item_factory.Pass(); | 509 item_factory_ = item_factory.Pass(); |
| 472 } | 510 } |
| 473 | 511 |
| 474 void DownloadManagerImpl::SetDownloadFileFactoryForTesting( | 512 void DownloadManagerImpl::SetDownloadFileFactoryForTesting( |
| 475 scoped_ptr<DownloadFileFactory> file_factory) { | 513 scoped_ptr<DownloadFileFactory> file_factory) { |
| 476 file_factory_ = file_factory.Pass(); | 514 file_factory_ = file_factory.Pass(); |
| 477 } | 515 } |
| 478 | 516 |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 538 } | 576 } |
| 539 | 577 |
| 540 void DownloadManagerImpl::DownloadUrl( | 578 void DownloadManagerImpl::DownloadUrl( |
| 541 scoped_ptr<DownloadUrlParameters> params) { | 579 scoped_ptr<DownloadUrlParameters> params) { |
| 542 if (params->post_id() >= 0) { | 580 if (params->post_id() >= 0) { |
| 543 // Check this here so that the traceback is more useful. | 581 // Check this here so that the traceback is more useful. |
| 544 DCHECK(params->prefer_cache()); | 582 DCHECK(params->prefer_cache()); |
| 545 DCHECK(params->method() == "POST"); | 583 DCHECK(params->method() == "POST"); |
| 546 } | 584 } |
| 547 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind( | 585 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind( |
| 548 &BeginDownload, base::Passed(¶ms))); | 586 &BeginDownload, base::Passed(¶ms), DownloadId())); |
| 549 } | 587 } |
| 550 | 588 |
| 551 void DownloadManagerImpl::AddObserver(Observer* observer) { | 589 void DownloadManagerImpl::AddObserver(Observer* observer) { |
| 552 observers_.AddObserver(observer); | 590 observers_.AddObserver(observer); |
| 553 } | 591 } |
| 554 | 592 |
| 555 void DownloadManagerImpl::RemoveObserver(Observer* observer) { | 593 void DownloadManagerImpl::RemoveObserver(Observer* observer) { |
| 556 observers_.RemoveObserver(observer); | 594 observers_.RemoveObserver(observer); |
| 557 } | 595 } |
| 558 | 596 |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 628 it != downloads_.end(); ++it) { | 666 it != downloads_.end(); ++it) { |
| 629 DownloadItemImpl* item = it->second; | 667 DownloadItemImpl* item = it->second; |
| 630 if (item->IsComplete() && | 668 if (item->IsComplete() && |
| 631 !item->GetOpened()) | 669 !item->GetOpened()) |
| 632 ++num_unopened; | 670 ++num_unopened; |
| 633 } | 671 } |
| 634 RecordOpensOutstanding(num_unopened); | 672 RecordOpensOutstanding(num_unopened); |
| 635 } | 673 } |
| 636 | 674 |
| 637 } // namespace content | 675 } // namespace content |
| OLD | NEW |