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/content_browser_client.h" | 32 #include "content/public/browser/content_browser_client.h" |
| 33 #include "content/public/browser/download_interrupt_reasons.h" | 33 #include "content/public/browser/download_interrupt_reasons.h" |
| 34 #include "content/public/browser/download_manager_delegate.h" | 34 #include "content/public/browser/download_manager_delegate.h" |
| 35 #include "content/public/browser/download_persistent_store_info.h" | 35 #include "content/public/browser/download_persistent_store_info.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_data.h" | 44 #include "net/base/upload_data.h" |
| 44 #include "net/url_request/url_request_context.h" | 45 #include "net/url_request/url_request_context.h" |
| 45 #include "webkit/glue/webkit_glue.h" | 46 #include "webkit/glue/webkit_glue.h" |
| 46 | 47 |
| 47 using content::BrowserThread; | 48 using content::BrowserThread; |
| 48 using content::DownloadId; | 49 using content::DownloadId; |
| 49 using content::DownloadItem; | 50 using content::DownloadItem; |
| 50 using content::DownloadPersistentStoreInfo; | 51 using content::DownloadPersistentStoreInfo; |
| 51 using content::ResourceDispatcherHostImpl; | 52 using content::ResourceDispatcherHostImpl; |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 68 virtual ~SavePageData() {} | 69 virtual ~SavePageData() {} |
| 69 | 70 |
| 70 private: | 71 private: |
| 71 static const char kKey[]; | 72 static const char kKey[]; |
| 72 | 73 |
| 73 DISALLOW_COPY_AND_ASSIGN(SavePageData); | 74 DISALLOW_COPY_AND_ASSIGN(SavePageData); |
| 74 }; | 75 }; |
| 75 | 76 |
| 76 const char SavePageData::kKey[] = "DownloadItem SavePageData"; | 77 const char SavePageData::kKey[] = "DownloadItem SavePageData"; |
| 77 | 78 |
| 78 void BeginDownload(content::DownloadUrlParameters* params) { | 79 void BeginDownload(content::DownloadUrlParameters* params, |
| 80 DownloadId download_id) { | |
| 79 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 81 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 80 // ResourceDispatcherHost{Base} is-not-a URLRequest::Delegate, and | 82 // ResourceDispatcherHost{Base} is-not-a URLRequest::Delegate, and |
| 81 // DownloadUrlParameters can-not include resource_dispatcher_host_impl.h, so | 83 // DownloadUrlParameters can-not include resource_dispatcher_host_impl.h, so |
| 82 // we must down cast. RDHI is the only subclass of RDH as of 2012 May 4. | 84 // we must down cast. RDHI is the only subclass of RDH as of 2012 May 4. |
| 83 scoped_ptr<net::URLRequest> request( | 85 scoped_ptr<net::URLRequest> request( |
| 84 params->resource_context()->GetRequestContext()->CreateRequest( | 86 params->resource_context()->GetRequestContext()->CreateRequest( |
| 85 params->url(), NULL)); | 87 params->url(), NULL)); |
| 86 request->set_referrer(params->referrer().url.spec()); | 88 request->set_referrer(params->referrer().url.spec()); |
| 87 webkit_glue::ConfigureURLRequestForReferrerPolicy( | 89 webkit_glue::ConfigureURLRequestForReferrerPolicy( |
| 88 request.get(), params->referrer().policy); | 90 request.get(), params->referrer().policy); |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 110 iter->first, iter->second, false/*overwrite*/); | 112 iter->first, iter->second, false/*overwrite*/); |
| 111 } | 113 } |
| 112 params->resource_dispatcher_host()->BeginDownload( | 114 params->resource_dispatcher_host()->BeginDownload( |
| 113 request.Pass(), | 115 request.Pass(), |
| 114 params->content_initiated(), | 116 params->content_initiated(), |
| 115 params->resource_context(), | 117 params->resource_context(), |
| 116 params->render_process_host_id(), | 118 params->render_process_host_id(), |
| 117 params->render_view_host_routing_id(), | 119 params->render_view_host_routing_id(), |
| 118 params->prefer_cache(), | 120 params->prefer_cache(), |
| 119 params->save_info(), | 121 params->save_info(), |
| 122 params->last_modified(), | |
| 123 params->etag(), | |
| 124 download_id, | |
| 120 params->callback()); | 125 params->callback()); |
| 121 } | 126 } |
| 122 | 127 |
| 123 class MapValueIteratorAdapter { | 128 class MapValueIteratorAdapter { |
| 124 public: | 129 public: |
| 125 explicit MapValueIteratorAdapter( | 130 explicit MapValueIteratorAdapter( |
| 126 base::hash_map<int64, DownloadItem*>::const_iterator iter) | 131 base::hash_map<int64, DownloadItem*>::const_iterator iter) |
| 127 : iter_(iter) { | 132 : iter_(iter) { |
| 128 } | 133 } |
| 129 ~MapValueIteratorAdapter() {} | 134 ~MapValueIteratorAdapter() {} |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 170 DownloadItemImplDelegate* delegate, | 175 DownloadItemImplDelegate* delegate, |
| 171 content::DownloadId download_id, | 176 content::DownloadId download_id, |
| 172 const content::DownloadPersistentStoreInfo& info, | 177 const content::DownloadPersistentStoreInfo& info, |
| 173 const net::BoundNetLog& bound_net_log) OVERRIDE { | 178 const net::BoundNetLog& bound_net_log) OVERRIDE { |
| 174 return new DownloadItemImpl(delegate, download_id, info, bound_net_log); | 179 return new DownloadItemImpl(delegate, download_id, info, bound_net_log); |
| 175 } | 180 } |
| 176 | 181 |
| 177 virtual DownloadItemImpl* CreateActiveItem( | 182 virtual DownloadItemImpl* CreateActiveItem( |
| 178 DownloadItemImplDelegate* delegate, | 183 DownloadItemImplDelegate* delegate, |
| 179 const DownloadCreateInfo& info, | 184 const DownloadCreateInfo& info, |
| 180 scoped_ptr<DownloadRequestHandleInterface> request_handle, | |
| 181 const net::BoundNetLog& bound_net_log) OVERRIDE { | 185 const net::BoundNetLog& bound_net_log) OVERRIDE { |
| 182 return new DownloadItemImpl(delegate, info, request_handle.Pass(), | 186 return new DownloadItemImpl(delegate, info, bound_net_log); |
| 183 bound_net_log); | |
| 184 } | 187 } |
| 185 | 188 |
| 186 virtual DownloadItemImpl* CreateSavePageItem( | 189 virtual DownloadItemImpl* CreateSavePageItem( |
| 187 DownloadItemImplDelegate* delegate, | 190 DownloadItemImplDelegate* delegate, |
| 188 const FilePath& path, | 191 const FilePath& path, |
| 189 const GURL& url, | 192 const GURL& url, |
| 190 content::DownloadId download_id, | 193 content::DownloadId download_id, |
| 191 const std::string& mime_type, | 194 const std::string& mime_type, |
| 192 const net::BoundNetLog& bound_net_log) OVERRIDE { | 195 const net::BoundNetLog& bound_net_log) OVERRIDE { |
| 193 return new DownloadItemImpl(delegate, path, url, download_id, | 196 return new DownloadItemImpl(delegate, path, url, download_id, |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 346 | 349 |
| 347 return true; | 350 return true; |
| 348 } | 351 } |
| 349 | 352 |
| 350 // We have received a message from DownloadFileManager about a new download. | 353 // We have received a message from DownloadFileManager about a new download. |
| 351 DownloadItem* DownloadManagerImpl::StartDownload( | 354 DownloadItem* DownloadManagerImpl::StartDownload( |
| 352 scoped_ptr<DownloadCreateInfo> info, | 355 scoped_ptr<DownloadCreateInfo> info, |
| 353 scoped_ptr<content::ByteStreamReader> stream) { | 356 scoped_ptr<content::ByteStreamReader> stream) { |
| 354 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 357 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 355 | 358 |
| 359 bool resuming = | |
| 360 (downloads_.find(info->download_id.local()) != downloads_.end()); | |
| 361 | |
| 356 // |bound_net_log| will be used for logging both the download item's and | 362 // |bound_net_log| will be used for logging both the download item's and |
| 357 // the download file's events. | 363 // the download file's events. |
| 358 net::BoundNetLog bound_net_log = CreateDownloadItem(info.get()); | 364 net::BoundNetLog bound_net_log = CreateDownloadItem(info.get()); |
| 359 | 365 |
| 360 // If info->download_id was unknown on entry to this function, it was | 366 // If info->download_id was unknown on entry to this function, it was |
| 361 // assigned in CreateDownloadItem. | 367 // assigned in CreateDownloadItem. |
| 362 DownloadId download_id = info->download_id; | 368 DownloadId download_id = info->download_id; |
| 363 | 369 |
| 364 if (delegate_) { | 370 if (delegate_) { |
| 365 FilePath website_save_directory; // Unused | 371 FilePath website_save_directory; // Unused |
| 366 bool skip_dir_check = false; // Unused | 372 bool skip_dir_check = false; // Unused |
| 367 delegate_->GetSaveDir(GetBrowserContext(), &website_save_directory, | 373 delegate_->GetSaveDir(GetBrowserContext(), &website_save_directory, |
| 368 &info->default_download_directory, &skip_dir_check); | 374 &info->default_download_directory, &skip_dir_check); |
| 369 } | 375 } |
| 370 | 376 |
| 371 DownloadFileManager::CreateDownloadFileCallback callback( | 377 DownloadFileManager::CreateDownloadFileCallback callback( |
| 372 base::Bind(&DownloadManagerImpl::OnDownloadFileCreated, | 378 base::Bind(resuming ? |
| 379 &DownloadManagerImpl::ContinueStartingDownload : | |
| 380 &DownloadManagerImpl::OnDownloadFileCreated, | |
| 373 this, download_id.local())); | 381 this, download_id.local())); |
| 374 | 382 |
| 375 BrowserThread::PostTask( | 383 BrowserThread::PostTask( |
| 376 BrowserThread::FILE, FROM_HERE, | 384 BrowserThread::FILE, FROM_HERE, |
| 377 base::Bind(&DownloadFileManager::CreateDownloadFile, | 385 base::Bind(&DownloadFileManager::CreateDownloadFile, |
| 378 file_manager_, base::Passed(info.Pass()), | 386 file_manager_, base::Passed(info.Pass()), |
| 379 base::Passed(stream.Pass()), make_scoped_refptr(this), | 387 base::Passed(stream.Pass()), make_scoped_refptr(this), |
| 380 (delegate_ && delegate_->GenerateFileHash()), bound_net_log, | 388 (delegate_ && delegate_->GenerateFileHash()), bound_net_log, |
| 381 callback)); | 389 callback)); |
| 382 | 390 |
| 383 return GetDownload(download_id.local()); | 391 return GetDownload(download_id.local()); |
| 384 } | 392 } |
| 385 | 393 |
| 394 // We have received a message from DownloadFileManager about a new download. | |
| 395 void DownloadManagerImpl::ContinueStartingDownload( | |
| 396 int32 download_id, content::DownloadInterruptReason reason) { | |
| 397 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 398 | |
| 399 if (reason != content::DOWNLOAD_INTERRUPT_REASON_NONE) { | |
| 400 OnDownloadInterrupted(download_id, reason); | |
| 401 // TODO(rdsmith): It makes no sense to continue along the | |
| 402 // regular download path after we've gotten an error. But it's | |
| 403 // the way the code has historically worked, and this allows us | |
| 404 // to get the download persisted and observers of the download manager | |
| 405 // notified, so tests work. When we execute all side effects of cancel | |
| 406 // (including queue removal) immedately rather than waiting for | |
| 407 // persistence we should replace this comment with a "return;". | |
| 408 } | |
| 409 | |
| 410 DownloadItem* download = GetActiveDownload(download_id); | |
| 411 if (!download) | |
| 412 return; | |
| 413 | |
| 414 MaybeCompleteDownload(download_id); | |
| 415 } | |
| 416 | |
| 386 void DownloadManagerImpl::OnDownloadFileCreated( | 417 void DownloadManagerImpl::OnDownloadFileCreated( |
| 387 int32 download_id, content::DownloadInterruptReason reason) { | 418 int32 download_id, content::DownloadInterruptReason reason) { |
| 419 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 388 if (reason != content::DOWNLOAD_INTERRUPT_REASON_NONE) { | 420 if (reason != content::DOWNLOAD_INTERRUPT_REASON_NONE) { |
| 389 OnDownloadInterrupted(download_id, reason); | 421 OnDownloadInterrupted(download_id, reason); |
| 390 // TODO(rdsmith): It makes no sense to continue along the | 422 // TODO(rdsmith): It makes no sense to continue along the |
| 391 // regular download path after we've gotten an error. But it's | 423 // regular download path after we've gotten an error. But it's |
| 392 // the way the code has historically worked, and this allows us | 424 // the way the code has historically worked, and this allows us |
| 393 // to get the download persisted and observers of the download manager | 425 // to get the download persisted and observers of the download manager |
| 394 // notified, so tests work. When we execute all side effects of cancel | 426 // notified, so tests work. When we execute all side effects of cancel |
| 395 // (including queue removal) immedately rather than waiting for | 427 // (including queue removal) immedately rather than waiting for |
| 396 // persistence we should replace this comment with a "return;". | 428 // persistence we should replace this comment with a "return;". |
| 397 } | 429 } |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 472 } | 504 } |
| 473 | 505 |
| 474 content::BrowserContext* DownloadManagerImpl::GetBrowserContext() const { | 506 content::BrowserContext* DownloadManagerImpl::GetBrowserContext() const { |
| 475 return browser_context_; | 507 return browser_context_; |
| 476 } | 508 } |
| 477 | 509 |
| 478 net::BoundNetLog DownloadManagerImpl::CreateDownloadItem( | 510 net::BoundNetLog DownloadManagerImpl::CreateDownloadItem( |
| 479 DownloadCreateInfo* info) { | 511 DownloadCreateInfo* info) { |
| 480 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 512 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 481 | 513 |
| 482 net::BoundNetLog bound_net_log = | 514 // |bound_net_log| will be used for logging the both the download item's and |
| 483 net::BoundNetLog::Make(net_log_, net::NetLog::SOURCE_DOWNLOAD); | 515 // the download file's events. |
| 516 net::BoundNetLog bound_net_log; | |
| 517 | |
| 484 if (!info->download_id.IsValid()) | 518 if (!info->download_id.IsValid()) |
| 485 info->download_id = GetNextId(); | 519 info->download_id = GetNextId(); |
| 486 DownloadItemImpl* download = factory_->CreateActiveItem( | |
| 487 this, *info, | |
| 488 scoped_ptr<DownloadRequestHandleInterface>( | |
| 489 new DownloadRequestHandle(info->request_handle)).Pass(), | |
| 490 bound_net_log); | |
| 491 | 520 |
| 492 DCHECK(!ContainsKey(downloads_, download->GetId())); | 521 int32 download_id = info->download_id.local(); |
| 493 downloads_[download->GetId()] = download; | 522 DownloadItemImpl* download = NULL; |
| 523 scoped_ptr<DownloadRequestHandleInterface> req_handle( | |
| 524 new DownloadRequestHandle(info->request_handle)); | |
| 525 bool resuming = (downloads_.find(download_id) != downloads_.end()); | |
| 526 if (resuming) { | |
| 527 download = downloads_[download_id]; | |
| 528 DCHECK(download != NULL); | |
| 529 } | |
| 530 | |
| 531 if (download) { | |
| 532 // Reuse an interrupted |DownloadItem|. | |
| 533 DCHECK(download->IsInterrupted()); | |
| 534 bound_net_log = download->GetBoundNetLog(); // Connect to its net log. | |
| 535 download->Resume(req_handle.Pass()); | |
| 536 } else { | |
| 537 // Create a new |DownloadItem|. | |
| 538 bound_net_log = | |
| 539 net::BoundNetLog::Make(net_log_, net::NetLog::SOURCE_DOWNLOAD); | |
| 540 download = factory_->CreateActiveItem(this, *info, bound_net_log); | |
| 541 | |
| 542 download->SetRequest(req_handle.Pass()); | |
| 543 | |
| 544 DCHECK(!ContainsKey(downloads_, download->GetId())); | |
| 545 downloads_[download->GetId()] = download; | |
| 546 } | |
| 547 | |
| 548 DVLOG(20) << __FUNCTION__ << "()" | |
| 549 << " info " << info->DebugString() | |
| 550 << " download " << download->DebugString(true); | |
| 551 | |
| 494 DCHECK(!ContainsKey(active_downloads_, download->GetId())); | 552 DCHECK(!ContainsKey(active_downloads_, download->GetId())); |
| 495 active_downloads_[download->GetId()] = download; | 553 active_downloads_[download->GetId()] = download; |
| 496 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadCreated(this, download)); | 554 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadCreated(this, download)); |
| 497 | 555 |
| 498 return bound_net_log; | 556 return bound_net_log; |
| 499 } | 557 } |
| 500 | 558 |
| 501 DownloadItemImpl* DownloadManagerImpl::CreateSavePackageDownloadItem( | 559 DownloadItemImpl* DownloadManagerImpl::CreateSavePackageDownloadItem( |
| 502 const FilePath& main_file_path, | 560 const FilePath& main_file_path, |
| 503 const GURL& page_url, | 561 const GURL& page_url, |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 554 << " size = " << size; | 612 << " size = " << size; |
| 555 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 613 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 556 | 614 |
| 557 // If it's not in active_downloads_, that means it was cancelled; just | 615 // If it's not in active_downloads_, that means it was cancelled; just |
| 558 // ignore the notification. | 616 // ignore the notification. |
| 559 if (active_downloads_.count(download_id) == 0) | 617 if (active_downloads_.count(download_id) == 0) |
| 560 return; | 618 return; |
| 561 | 619 |
| 562 DownloadItemImpl* download = active_downloads_[download_id]; | 620 DownloadItemImpl* download = active_downloads_[download_id]; |
| 563 download->OnAllDataSaved(size, hash); | 621 download->OnAllDataSaved(size, hash); |
| 564 MaybeCompleteDownload(download); | 622 MaybeCompleteDownload(download_id); |
| 565 } | 623 } |
| 566 | 624 |
| 567 void DownloadManagerImpl::AssertStateConsistent( | 625 void DownloadManagerImpl::AssertStateConsistent( |
| 568 DownloadItemImpl* download) const { | 626 DownloadItemImpl* download) const { |
| 569 CHECK(ContainsKey(downloads_, download->GetId())); | 627 CHECK(ContainsKey(downloads_, download->GetId())); |
| 570 | 628 |
| 571 int64 state = download->GetState(); | 629 int64 state = download->GetState(); |
| 572 base::debug::Alias(&state); | 630 base::debug::Alias(&state); |
| 573 if (ContainsKey(active_downloads_, download->GetId())) { | 631 if (ContainsKey(active_downloads_, download->GetId())) { |
| 574 if (download->IsPersisted()) | 632 if (download->IsPersisted()) |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 609 // When SavePackage downloads MHTML to GData (see | 667 // When SavePackage downloads MHTML to GData (see |
| 610 // SavePackageFilePickerChromeOS), GData calls MaybeCompleteDownload() like it | 668 // SavePackageFilePickerChromeOS), GData calls MaybeCompleteDownload() like it |
| 611 // does for non-SavePackage downloads, but SavePackage downloads never satisfy | 669 // does for non-SavePackage downloads, but SavePackage downloads never satisfy |
| 612 // IsDownloadReadyForCompletion(). GDataDownloadObserver manually calls | 670 // IsDownloadReadyForCompletion(). GDataDownloadObserver manually calls |
| 613 // DownloadItem::UpdateObservers() when the upload completes so that SavePackage | 671 // DownloadItem::UpdateObservers() when the upload completes so that SavePackage |
| 614 // notices that the upload has completed and runs its normal Finish() pathway. | 672 // notices that the upload has completed and runs its normal Finish() pathway. |
| 615 // MaybeCompleteDownload() is never the mechanism by which SavePackage completes | 673 // MaybeCompleteDownload() is never the mechanism by which SavePackage completes |
| 616 // downloads. SavePackage always uses its own Finish() to mark downloads | 674 // downloads. SavePackage always uses its own Finish() to mark downloads |
| 617 // complete. | 675 // complete. |
| 618 | 676 |
| 619 void DownloadManagerImpl::MaybeCompleteDownload( | 677 void DownloadManagerImpl::MaybeCompleteDownload(int32 download_id) { |
| 620 DownloadItemImpl* download) { | |
| 621 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 678 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 679 | |
| 680 // This can be called from |DownloadItemImpl::OnDownloadedFileRemoved()|, | |
| 681 // without the download being active. | |
| 682 DCHECK(ContainsKey(downloads_, download_id)); | |
| 683 if (!ContainsKey(active_downloads_, download_id)) | |
| 684 return; | |
| 685 DownloadItemImpl* download = active_downloads_[download_id]; | |
| 686 | |
| 622 VLOG(20) << __FUNCTION__ << "()" << " download = " | 687 VLOG(20) << __FUNCTION__ << "()" << " download = " |
| 623 << download->DebugString(false); | 688 << download->DebugString(true); |
| 624 | 689 |
| 625 if (!IsDownloadReadyForCompletion(download)) | 690 if (!IsDownloadReadyForCompletion(download)) |
| 626 return; | 691 return; |
| 627 | 692 |
| 628 // TODO(rdsmith): DCHECK that we only pass through this point | 693 // TODO(rdsmith): DCHECK that we only pass through this point |
| 629 // once per download. The natural way to do this is by a state | 694 // once per download. The natural way to do this is by a state |
| 630 // transition on the DownloadItem. | 695 // transition on the DownloadItem. |
| 631 | 696 |
| 632 // Confirm we're in the proper set of states to be here; | 697 // Confirm we're in the proper set of states to be here; |
| 633 // have all data, have a history handle, (validated or safe). | 698 // have all data, have a history handle, (validated or safe). |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 649 VLOG(20) << __FUNCTION__ << "()" << " executing: download = " | 714 VLOG(20) << __FUNCTION__ << "()" << " executing: download = " |
| 650 << download->DebugString(false); | 715 << download->DebugString(false); |
| 651 | 716 |
| 652 if (delegate_) | 717 if (delegate_) |
| 653 delegate_->UpdateItemInPersistentStore(download); | 718 delegate_->UpdateItemInPersistentStore(download); |
| 654 download->OnDownloadCompleting(); | 719 download->OnDownloadCompleting(); |
| 655 } | 720 } |
| 656 | 721 |
| 657 void DownloadManagerImpl::MaybeCompleteDownloadById(int download_id) { | 722 void DownloadManagerImpl::MaybeCompleteDownloadById(int download_id) { |
| 658 if (ContainsKey(active_downloads_, download_id)) | 723 if (ContainsKey(active_downloads_, download_id)) |
| 659 MaybeCompleteDownload(active_downloads_[download_id]); | 724 MaybeCompleteDownload(download_id); |
| 660 } | 725 } |
| 661 | 726 |
| 662 void DownloadManagerImpl::DownloadCompleted(DownloadItemImpl* download) { | 727 void DownloadManagerImpl::DownloadCompleted(DownloadItemImpl* download) { |
| 663 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 728 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 664 DCHECK(download); | 729 DCHECK(download); |
| 665 if (delegate_) | 730 if (delegate_) |
| 666 delegate_->UpdateItemInPersistentStore(download); | 731 delegate_->UpdateItemInPersistentStore(download); |
| 667 active_downloads_.erase(download->GetId()); | 732 active_downloads_.erase(download->GetId()); |
| 668 AssertStateConsistent(download); | 733 AssertStateConsistent(download); |
| 669 } | 734 } |
| 670 | 735 |
| 671 void DownloadManagerImpl::CancelDownload(int32 download_id) { | 736 void DownloadManagerImpl::CancelDownload(int32 download_id) { |
| 737 DownloadItem* download = GetActiveDownload(download_id); | |
| 672 // A cancel at the right time could remove the download from the | 738 // A cancel at the right time could remove the download from the |
| 673 // |active_downloads_| map before we get here. | 739 // |active_downloads_| map before we get here. |
| 674 if (ContainsKey(active_downloads_, download_id)) | 740 if (!download) |
| 675 active_downloads_[download_id]->Cancel(true); | 741 return; |
| 742 | |
| 743 download->Cancel(true); | |
| 676 } | 744 } |
| 677 | 745 |
| 678 void DownloadManagerImpl::DownloadStopped(DownloadItemImpl* download) { | 746 void DownloadManagerImpl::DownloadStopped(DownloadItemImpl* download) { |
| 679 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 747 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 680 | 748 |
| 681 VLOG(20) << __FUNCTION__ << "()" | 749 VLOG(20) << __FUNCTION__ << "()" |
| 682 << " download = " << download->DebugString(true); | 750 << " download = " << download->DebugString(true); |
| 683 | 751 |
| 684 RemoveFromActiveList(download); | 752 RemoveFromActiveList(download); |
| 685 // This function is called from the DownloadItem, so DI state | 753 // This function is called from the DownloadItem, so DI state |
| 686 // should already have been updated. | 754 // should already have been updated. |
| 687 AssertStateConsistent(download); | 755 AssertStateConsistent(download); |
| 688 | 756 |
| 689 DCHECK(file_manager_); | 757 DCHECK(file_manager_); |
| 690 download->OffThreadCancel(); | 758 |
| 759 if (download->IsInterrupted()) | |
| 760 download->OffThreadInterrupt(); | |
| 761 else | |
| 762 download->OffThreadCancel(); | |
| 691 } | 763 } |
| 692 | 764 |
| 693 void DownloadManagerImpl::OnDownloadInterrupted( | 765 void DownloadManagerImpl::OnDownloadInterrupted( |
| 694 int32 download_id, | 766 int32 download_id, |
| 695 content::DownloadInterruptReason reason) { | 767 content::DownloadInterruptReason reason) { |
| 696 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 768 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 697 | 769 |
| 698 if (!ContainsKey(active_downloads_, download_id)) | 770 if (!ContainsKey(active_downloads_, download_id)) |
| 699 return; | 771 return; |
| 772 | |
| 773 VLOG(20) << __FUNCTION__ << "()" | |
| 774 << " reason " << InterruptReasonDebugString(reason) | |
| 775 << " download = " | |
| 776 << active_downloads_[download_id]->DebugString(true); | |
| 777 | |
| 700 active_downloads_[download_id]->Interrupt(reason); | 778 active_downloads_[download_id]->Interrupt(reason); |
| 701 } | 779 } |
| 702 | 780 |
| 781 // Resume a download of a specific URL. We send the request to the | |
| 782 // ResourceDispatcherHost, and let it send us responses like a regular | |
| 783 // download. | |
| 784 void DownloadManagerImpl::RestartInterruptedDownload( | |
| 785 DownloadItemImpl* download, | |
| 786 const content::DownloadUrlParameters::OnStartedCallback& callback) { | |
|
Randy Smith (Not in Mondays)
2012/10/15 00:36:08
If we've already got a download item, let's not us
| |
| 787 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 788 // Handle the case of clicking 'Resume' in the download shelf. | |
| 789 DCHECK(download); | |
| 790 DCHECK(download->IsInterrupted()); | |
| 791 | |
| 792 DVLOG(20) << __FUNCTION__ << "()" | |
| 793 << " download = " << download->DebugString(true); | |
| 794 | |
| 795 // Restart the download. | |
| 796 WebContents* contents = GetWebContents(download); | |
| 797 if (!contents) { | |
| 798 if (!callback.is_null()) | |
| 799 callback.Run(download, net::ERR_ACCESS_DENIED); | |
| 800 return; | |
| 801 } | |
| 802 | |
| 803 content::DownloadSaveInfo save_info; | |
| 804 save_info.file_path = download->GetFullPath(); | |
| 805 save_info.offset = download->GetReceivedBytes(); | |
| 806 save_info.hash_state = download->GetHashState(); | |
| 807 | |
| 808 content::DownloadUrlParameters* download_params = | |
| 809 new content::DownloadUrlParameters( | |
| 810 download->GetOriginalUrl(), | |
| 811 contents->GetRenderProcessHost()->GetID(), | |
| 812 contents->GetRenderViewHost()->GetRoutingID(), | |
| 813 contents->GetBrowserContext()->GetResourceContext(), | |
| 814 save_info); | |
| 815 | |
| 816 content::Referrer referrer(download->GetReferrerUrl(), | |
| 817 WebKit::WebReferrerPolicyDefault); | |
| 818 download_params->set_referrer(referrer); | |
| 819 download_params->set_last_modified(download->GetLastModifiedTime()); | |
| 820 download_params->set_etag(download->GetETag()); | |
| 821 download_params->set_callback(callback); | |
| 822 | |
| 823 BrowserThread::PostTask( | |
| 824 BrowserThread::IO, | |
| 825 FROM_HERE, | |
| 826 base::Bind( | |
| 827 &BeginDownload, | |
| 828 base::Owned(download_params), | |
| 829 download->GetGlobalId())); | |
| 830 } | |
| 831 | |
| 832 DownloadItem* DownloadManagerImpl::GetActiveDownload(int32 download_id) { | |
| 833 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 834 DownloadMap::iterator it = active_downloads_.find(download_id); | |
| 835 if (it == active_downloads_.end()) | |
| 836 return NULL; | |
| 837 | |
| 838 DownloadItem* download = it->second; | |
| 839 | |
| 840 DCHECK(download); | |
| 841 DCHECK_EQ(download_id, download->GetId()); | |
| 842 | |
| 843 return download; | |
| 844 } | |
| 845 | |
| 703 void DownloadManagerImpl::RemoveFromActiveList(DownloadItemImpl* download) { | 846 void DownloadManagerImpl::RemoveFromActiveList(DownloadItemImpl* download) { |
| 704 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 847 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 705 DCHECK(download); | 848 DCHECK(download); |
| 706 | 849 |
| 707 // Clean up will happen when the history system create callback runs if we | 850 // Clean up will happen when the history system create callback runs if we |
| 708 // don't have a valid db_handle yet. | 851 // don't have a valid db_handle yet. |
| 709 if (download->IsPersisted()) { | 852 if (download->IsPersisted()) { |
| 710 active_downloads_.erase(download->GetId()); | 853 active_downloads_.erase(download->GetId()); |
| 711 if (delegate_) | 854 if (delegate_) |
| 712 delegate_->UpdateItemInPersistentStore(download); | 855 delegate_->UpdateItemInPersistentStore(download); |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 784 return num_deleted; | 927 return num_deleted; |
| 785 } | 928 } |
| 786 | 929 |
| 787 void DownloadManagerImpl::DownloadUrl( | 930 void DownloadManagerImpl::DownloadUrl( |
| 788 scoped_ptr<content::DownloadUrlParameters> params) { | 931 scoped_ptr<content::DownloadUrlParameters> params) { |
| 789 if (params->post_id() >= 0) { | 932 if (params->post_id() >= 0) { |
| 790 // Check this here so that the traceback is more useful. | 933 // Check this here so that the traceback is more useful. |
| 791 DCHECK(params->prefer_cache()); | 934 DCHECK(params->prefer_cache()); |
| 792 DCHECK(params->method() == "POST"); | 935 DCHECK(params->method() == "POST"); |
| 793 } | 936 } |
| 794 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind( | 937 BrowserThread::PostTask( |
| 795 &BeginDownload, base::Owned(params.release()))); | 938 BrowserThread::IO, FROM_HERE, |
| 939 base::Bind( | |
| 940 &BeginDownload, | |
| 941 base::Owned(params.release()), | |
| 942 DownloadId())); | |
| 796 } | 943 } |
| 797 | 944 |
| 798 void DownloadManagerImpl::AddObserver(Observer* observer) { | 945 void DownloadManagerImpl::AddObserver(Observer* observer) { |
| 799 observers_.AddObserver(observer); | 946 observers_.AddObserver(observer); |
| 800 // TODO: It is the responsibility of the observers to query the | 947 // TODO: It is the responsibility of the observers to query the |
| 801 // DownloadManager. Remove the following call from here and update all | 948 // DownloadManager. Remove the following call from here and update all |
| 802 // observers. | 949 // observers. |
| 803 observer->ModelChanged(this); | 950 observer->ModelChanged(this); |
| 804 } | 951 } |
| 805 | 952 |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 882 << " download = " << item->DebugString(true); | 1029 << " download = " << item->DebugString(true); |
| 883 | 1030 |
| 884 // If the download is still in progress, try to complete it. | 1031 // If the download is still in progress, try to complete it. |
| 885 // | 1032 // |
| 886 // Otherwise, download has been cancelled or interrupted before we've | 1033 // Otherwise, download has been cancelled or interrupted before we've |
| 887 // received the DB handle. We post one final message to the history | 1034 // received the DB handle. We post one final message to the history |
| 888 // service so that it can be properly in sync with the DownloadItem's | 1035 // service so that it can be properly in sync with the DownloadItem's |
| 889 // completion status, and also inform any observers so that they get | 1036 // completion status, and also inform any observers so that they get |
| 890 // more than just the start notification. | 1037 // more than just the start notification. |
| 891 if (item->IsInProgress()) { | 1038 if (item->IsInProgress()) { |
| 892 MaybeCompleteDownload(item); | 1039 MaybeCompleteDownload(item->GetId()); |
| 893 } else { | 1040 } else { |
| 894 DCHECK(item->IsCancelled()); | 1041 DCHECK(item->IsCancelled() || item->IsInterrupted()) |
| 1042 << " download = " << item->DebugString(true); | |
| 895 active_downloads_.erase(item->GetId()); | 1043 active_downloads_.erase(item->GetId()); |
| 896 if (delegate_) | 1044 if (delegate_) |
| 897 delegate_->UpdateItemInPersistentStore(item); | 1045 delegate_->UpdateItemInPersistentStore(item); |
| 898 item->UpdateObservers(); | 1046 item->UpdateObservers(); |
| 899 } | 1047 } |
| 900 } | 1048 } |
| 901 | 1049 |
| 902 void DownloadManagerImpl::ShowDownloadInBrowser(DownloadItemImpl* download) { | 1050 void DownloadManagerImpl::ShowDownloadInBrowser(DownloadItemImpl* download) { |
| 903 // The 'contents' may no longer exist if the user closed the contents before | 1051 // The 'contents' may no longer exist if the user closed the contents before |
| 904 // we get this start completion event. | 1052 // we get this start completion event. |
| 905 WebContents* content = download->GetWebContents(); | 1053 WebContents* content = GetWebContents(download); |
| 906 | |
| 907 // If the contents no longer exists, we ask the embedder to suggest another | |
| 908 // contents. | |
| 909 if (!content && delegate_) | |
| 910 content = delegate_->GetAlternativeWebContentsToNotifyForDownload(); | |
| 911 | 1054 |
| 912 if (content && content->GetDelegate()) | 1055 if (content && content->GetDelegate()) |
| 913 content->GetDelegate()->OnStartDownload(content, download); | 1056 content->GetDelegate()->OnStartDownload(content, download); |
| 914 } | 1057 } |
| 915 | 1058 |
| 916 int DownloadManagerImpl::InProgressCount() const { | 1059 int DownloadManagerImpl::InProgressCount() const { |
| 917 // Don't use active_downloads_.count() because Cancel() leaves items in | 1060 // Don't use active_downloads_.count() because Cancel() leaves items in |
| 918 // active_downloads_ if they haven't made it into the persistent store yet. | 1061 // active_downloads_ if they haven't made it into the persistent store yet. |
| 919 // Need to actually look at each item's state. | 1062 // Need to actually look at each item's state. |
| 920 int count = 0; | 1063 int count = 0; |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1039 void DownloadManagerImpl::DownloadRenamedToFinalName( | 1182 void DownloadManagerImpl::DownloadRenamedToFinalName( |
| 1040 DownloadItemImpl* download) { | 1183 DownloadItemImpl* download) { |
| 1041 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1184 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 1042 // If the rename failed, we receive an OnDownloadInterrupted() call before we | 1185 // If the rename failed, we receive an OnDownloadInterrupted() call before we |
| 1043 // receive the DownloadRenamedToFinalName() call. | 1186 // receive the DownloadRenamedToFinalName() call. |
| 1044 if (delegate_) { | 1187 if (delegate_) { |
| 1045 delegate_->UpdatePathForItemInPersistentStore( | 1188 delegate_->UpdatePathForItemInPersistentStore( |
| 1046 download, download->GetFullPath()); | 1189 download, download->GetFullPath()); |
| 1047 } | 1190 } |
| 1048 } | 1191 } |
| 1192 | |
| 1193 WebContents* DownloadManagerImpl::GetWebContents(const DownloadItem* download) { | |
| 1194 WebContents* web_contents = download->GetWebContents(); | |
| 1195 // If the original download_id was created from the history DB, its | |
| 1196 // |DownloadRequestHandle| will not be valid, and we won't get a proper | |
| 1197 // |WebContents| pointer from it. | |
| 1198 if (!web_contents) | |
| 1199 web_contents = delegate_->GetAlternativeWebContentsToNotifyForDownload(); | |
| 1200 | |
| 1201 return web_contents; | |
| 1202 } | |
| OLD | NEW |