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 14 matching lines...) Expand all Loading... | |
| 25 #include "content/browser/download/download_item_impl.h" | 25 #include "content/browser/download/download_item_impl.h" |
| 26 #include "content/browser/download/download_stats.h" | 26 #include "content/browser/download/download_stats.h" |
| 27 #include "content/browser/renderer_host/render_view_host_impl.h" | 27 #include "content/browser/renderer_host/render_view_host_impl.h" |
| 28 #include "content/browser/renderer_host/resource_dispatcher_host_impl.h" | 28 #include "content/browser/renderer_host/resource_dispatcher_host_impl.h" |
| 29 #include "content/browser/web_contents/web_contents_impl.h" | 29 #include "content/browser/web_contents/web_contents_impl.h" |
| 30 #include "content/public/browser/browser_context.h" | 30 #include "content/public/browser/browser_context.h" |
| 31 #include "content/public/browser/browser_thread.h" | 31 #include "content/public/browser/browser_thread.h" |
| 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" | |
| 36 #include "content/public/browser/download_url_parameters.h" | 35 #include "content/public/browser/download_url_parameters.h" |
| 37 #include "content/public/browser/notification_service.h" | 36 #include "content/public/browser/notification_service.h" |
| 38 #include "content/public/browser/notification_types.h" | 37 #include "content/public/browser/notification_types.h" |
| 39 #include "content/public/browser/render_process_host.h" | 38 #include "content/public/browser/render_process_host.h" |
| 40 #include "content/public/browser/resource_context.h" | 39 #include "content/public/browser/resource_context.h" |
| 41 #include "content/public/browser/web_contents_delegate.h" | 40 #include "content/public/browser/web_contents_delegate.h" |
| 42 #include "net/base/load_flags.h" | 41 #include "net/base/load_flags.h" |
| 43 #include "net/base/upload_data.h" | 42 #include "net/base/upload_data.h" |
| 44 #include "net/url_request/url_request_context.h" | 43 #include "net/url_request/url_request_context.h" |
| 45 #include "webkit/glue/webkit_glue.h" | 44 #include "webkit/glue/webkit_glue.h" |
| 46 | 45 |
| 47 using content::BrowserThread; | 46 using content::BrowserThread; |
| 48 using content::DownloadId; | 47 using content::DownloadId; |
| 49 using content::DownloadItem; | 48 using content::DownloadItem; |
| 50 using content::DownloadPersistentStoreInfo; | |
| 51 using content::ResourceDispatcherHostImpl; | 49 using content::ResourceDispatcherHostImpl; |
| 52 using content::WebContents; | 50 using content::WebContents; |
| 53 | 51 |
| 54 namespace { | 52 namespace { |
| 55 | 53 |
| 56 // This is just used to remember which DownloadItems come from SavePage. | 54 // This is just used to remember which DownloadItems come from SavePage. |
| 57 class SavePageData : public base::SupportsUserData::Data { | 55 class SavePageData : public base::SupportsUserData::Data { |
| 58 public: | 56 public: |
| 59 // A spoonful of syntactic sugar. | 57 // A spoonful of syntactic sugar. |
| 60 static bool Get(DownloadItem* item) { | 58 static bool Get(DownloadItem* item) { |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 162 } | 160 } |
| 163 | 161 |
| 164 class DownloadItemFactoryImpl : public content::DownloadItemFactory { | 162 class DownloadItemFactoryImpl : public content::DownloadItemFactory { |
| 165 public: | 163 public: |
| 166 DownloadItemFactoryImpl() {} | 164 DownloadItemFactoryImpl() {} |
| 167 virtual ~DownloadItemFactoryImpl() {} | 165 virtual ~DownloadItemFactoryImpl() {} |
| 168 | 166 |
| 169 virtual DownloadItemImpl* CreatePersistedItem( | 167 virtual DownloadItemImpl* CreatePersistedItem( |
| 170 DownloadItemImplDelegate* delegate, | 168 DownloadItemImplDelegate* delegate, |
| 171 content::DownloadId download_id, | 169 content::DownloadId download_id, |
| 172 const content::DownloadPersistentStoreInfo& info, | 170 const FilePath& path, |
| 171 const GURL& url, | |
| 172 const GURL& referrer_url, | |
| 173 const base::Time& start_time, | |
| 174 const base::Time& end_time, | |
| 175 int64 received_bytes, | |
| 176 int64 total_bytes, | |
| 177 DownloadItem::DownloadState state, | |
| 178 bool opened, | |
| 173 const net::BoundNetLog& bound_net_log) OVERRIDE { | 179 const net::BoundNetLog& bound_net_log) OVERRIDE { |
| 174 return new DownloadItemImpl(delegate, download_id, info, bound_net_log); | 180 return new DownloadItemImpl( |
| 181 delegate, | |
| 182 download_id, | |
| 183 path, | |
| 184 url, | |
| 185 referrer_url, | |
| 186 start_time, | |
| 187 end_time, | |
| 188 received_bytes, | |
| 189 total_bytes, | |
| 190 state, | |
| 191 opened, | |
| 192 bound_net_log); | |
| 175 } | 193 } |
| 176 | 194 |
| 177 virtual DownloadItemImpl* CreateActiveItem( | 195 virtual DownloadItemImpl* CreateActiveItem( |
| 178 DownloadItemImplDelegate* delegate, | 196 DownloadItemImplDelegate* delegate, |
| 179 const DownloadCreateInfo& info, | 197 const DownloadCreateInfo& info, |
| 180 scoped_ptr<DownloadRequestHandleInterface> request_handle, | 198 scoped_ptr<DownloadRequestHandleInterface> request_handle, |
| 181 const net::BoundNetLog& bound_net_log) OVERRIDE { | 199 const net::BoundNetLog& bound_net_log) OVERRIDE { |
| 182 return new DownloadItemImpl(delegate, info, request_handle.Pass(), | 200 return new DownloadItemImpl(delegate, info, request_handle.Pass(), |
| 183 bound_net_log); | 201 bound_net_log); |
| 184 } | 202 } |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 304 // from the disk. This may or may not result in it being | 322 // from the disk. This may or may not result in it being |
| 305 // removed from the DownloadManager queues and deleted | 323 // removed from the DownloadManager queues and deleted |
| 306 // (specifically, DownloadManager::DownloadRemoved only | 324 // (specifically, DownloadManager::DownloadRemoved only |
| 307 // removes and deletes it if it's known to the history service) | 325 // removes and deletes it if it's known to the history service) |
| 308 // so the only thing we know after calling this function is that | 326 // so the only thing we know after calling this function is that |
| 309 // the download was deleted if-and-only-if it was removed | 327 // the download was deleted if-and-only-if it was removed |
| 310 // from all queues. | 328 // from all queues. |
| 311 download->Delete(DownloadItem::DELETE_DUE_TO_BROWSER_SHUTDOWN); | 329 download->Delete(DownloadItem::DELETE_DUE_TO_BROWSER_SHUTDOWN); |
| 312 } else if (download->IsPartialDownload()) { | 330 } else if (download->IsPartialDownload()) { |
| 313 download->Cancel(false); | 331 download->Cancel(false); |
| 314 if (delegate_) | |
| 315 delegate_->UpdateItemInPersistentStore(download); | |
| 316 } | 332 } |
| 317 } | 333 } |
| 318 | 334 |
| 319 // At this point, all dangerous downloads have had their files removed | 335 // At this point, all dangerous downloads have had their files removed |
| 320 // and all in progress downloads have been cancelled. We can now delete | 336 // and all in progress downloads have been cancelled. We can now delete |
| 321 // anything left. | 337 // anything left. |
| 322 | 338 |
| 323 active_downloads_.clear(); | 339 active_downloads_.clear(); |
| 324 STLDeleteValues(&downloads_); | 340 STLDeleteValues(&downloads_); |
| 325 downloads_.clear(); | 341 downloads_.clear(); |
| 326 | 342 |
| 327 // We'll have nothing more to report to the observers after this point. | 343 // We'll have nothing more to report to the observers after this point. |
| 328 observers_.Clear(); | 344 observers_.Clear(); |
| 329 | 345 |
| 330 file_manager_ = NULL; | 346 file_manager_ = NULL; |
| 331 if (delegate_) | 347 if (delegate_) |
| 332 delegate_->Shutdown(); | 348 delegate_->Shutdown(); |
| 333 delegate_ = NULL; | 349 delegate_ = NULL; |
| 334 } | 350 } |
| 335 | 351 |
| 336 void DownloadManagerImpl::GetTemporaryDownloads( | 352 void DownloadManagerImpl::GetTemporaryDownloads( |
| 337 const FilePath& dir_path, DownloadVector* result) { | 353 const FilePath& dir_path, DownloadVector* result) { |
| 338 DCHECK(result); | 354 DCHECK(result); |
| 339 | 355 |
| 340 for (DownloadMap::iterator it = downloads_.begin(); | 356 for (DownloadMap::iterator it = downloads_.begin(); |
| 341 it != downloads_.end(); ++it) { | 357 it != downloads_.end(); ++it) { |
| 342 DownloadItemImpl* item = it->second; | 358 DownloadItemImpl* item = it->second; |
| 343 // TODO(benjhayden): Don't check IsPersisted(). | |
| 344 if (item->IsTemporary() && | 359 if (item->IsTemporary() && |
| 345 item->IsPersisted() && | |
| 346 (dir_path.empty() || | 360 (dir_path.empty() || |
| 347 item->GetTargetFilePath().DirName() == dir_path)) | 361 item->GetTargetFilePath().DirName() == dir_path)) |
| 348 result->push_back(item); | 362 result->push_back(item); |
| 349 } | 363 } |
| 350 } | 364 } |
| 351 | 365 |
| 352 void DownloadManagerImpl::GetAllDownloads( | 366 void DownloadManagerImpl::GetAllDownloads( |
| 353 const FilePath& dir_path, DownloadVector* result) { | 367 const FilePath& dir_path, DownloadVector* result) { |
| 354 DCHECK(result); | 368 DCHECK(result); |
| 355 | 369 |
| 356 for (DownloadMap::iterator it = downloads_.begin(); | 370 for (DownloadMap::iterator it = downloads_.begin(); |
| 357 it != downloads_.end(); ++it) { | 371 it != downloads_.end(); ++it) { |
| 358 DownloadItemImpl* item = it->second; | 372 DownloadItemImpl* item = it->second; |
| 359 // TODO(benjhayden): Don't check IsPersisted(). | |
| 360 if (!item->IsTemporary() && | 373 if (!item->IsTemporary() && |
| 361 item->IsPersisted() && | |
| 362 (dir_path.empty() || | 374 (dir_path.empty() || |
| 363 item->GetTargetFilePath().DirName() == dir_path)) | 375 item->GetTargetFilePath().DirName() == dir_path)) |
| 364 result->push_back(item); | 376 result->push_back(item); |
| 365 } | 377 } |
| 366 } | 378 } |
| 367 | 379 |
| 368 void DownloadManagerImpl::SearchDownloads(const string16& query, | 380 void DownloadManagerImpl::SearchDownloads(const string16& query, |
| 369 DownloadVector* result) { | 381 DownloadVector* result) { |
| 370 string16 query_lower(base::i18n::ToLower(query)); | 382 string16 query_lower(base::i18n::ToLower(query)); |
| 371 | 383 |
| 372 for (DownloadMap::iterator it = downloads_.begin(); | 384 for (DownloadMap::iterator it = downloads_.begin(); |
| 373 it != downloads_.end(); ++it) { | 385 it != downloads_.end(); ++it) { |
| 374 DownloadItemImpl* download_item = it->second; | 386 DownloadItemImpl* download_item = it->second; |
| 375 // TODO(benjhayden): Don't check IsPersisted(). | |
| 376 if (!download_item->IsTemporary() && | 387 if (!download_item->IsTemporary() && |
| 377 download_item->IsPersisted() && | |
| 378 download_item->MatchesQuery(query_lower)) { | 388 download_item->MatchesQuery(query_lower)) { |
| 379 result->push_back(download_item); | 389 result->push_back(download_item); |
| 380 } | 390 } |
| 381 } | 391 } |
| 382 } | 392 } |
| 383 | 393 |
| 384 bool DownloadManagerImpl::Init(content::BrowserContext* browser_context) { | 394 bool DownloadManagerImpl::Init(content::BrowserContext* browser_context) { |
| 385 DCHECK(browser_context); | 395 DCHECK(browser_context); |
| 386 DCHECK(!shutdown_needed_) << "DownloadManager already initialized."; | 396 DCHECK(!shutdown_needed_) << "DownloadManager already initialized."; |
| 387 shutdown_needed_ = true; | 397 shutdown_needed_ = true; |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 452 } | 462 } |
| 453 } | 463 } |
| 454 | 464 |
| 455 void DownloadManagerImpl::OnDownloadTargetDetermined( | 465 void DownloadManagerImpl::OnDownloadTargetDetermined( |
| 456 int32 download_id, | 466 int32 download_id, |
| 457 const FilePath& target_path, | 467 const FilePath& target_path, |
| 458 DownloadItem::TargetDisposition disposition, | 468 DownloadItem::TargetDisposition disposition, |
| 459 content::DownloadDangerType danger_type, | 469 content::DownloadDangerType danger_type, |
| 460 const FilePath& intermediate_path) { | 470 const FilePath& intermediate_path) { |
| 461 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 471 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 462 DownloadMap::iterator download_iter = active_downloads_.find(download_id); | 472 DownloadMap::iterator download_iter = downloads_.find(download_id); |
| 463 if (download_iter != active_downloads_.end()) { | 473 if (download_iter == downloads_.end()) |
| 464 // Once DownloadItem::OnDownloadTargetDetermined() is called, we expect a | 474 return; |
| 465 // DownloadRenamedToIntermediateName() callback. This is necessary for the | 475 |
| 466 // download to proceed. | 476 // Once DownloadItem::OnDownloadTargetDetermined() is called, we expect a |
| 467 download_iter->second->OnDownloadTargetDetermined( | 477 // DownloadRenamedToIntermediateName() callback. This is necessary for the |
| 468 target_path, disposition, danger_type, intermediate_path); | 478 // download to proceed. |
| 469 } | 479 DownloadItemImpl* item = download_iter->second; |
| 480 item->OnDownloadTargetDetermined( | |
| 481 target_path, disposition, danger_type, intermediate_path); | |
| 482 ShowDownloadInBrowser(item); | |
| 483 NotifyModelChanged(); | |
| 470 } | 484 } |
| 471 | 485 |
| 472 void DownloadManagerImpl::CheckForHistoryFilesRemoval() { | 486 void DownloadManagerImpl::CheckForHistoryFilesRemoval() { |
| 473 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 487 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 474 for (DownloadMap::iterator it = downloads_.begin(); | 488 for (DownloadMap::iterator it = downloads_.begin(); |
| 475 it != downloads_.end(); ++it) { | 489 it != downloads_.end(); ++it) { |
| 476 DownloadItemImpl* item = it->second; | 490 DownloadItemImpl* item = it->second; |
| 477 if (item->IsPersisted()) | 491 CheckForFileRemoval(item); |
| 478 CheckForFileRemoval(item); | |
| 479 } | 492 } |
| 480 } | 493 } |
| 481 | 494 |
| 482 void DownloadManagerImpl::CheckForFileRemoval(DownloadItemImpl* download_item) { | 495 void DownloadManagerImpl::CheckForFileRemoval(DownloadItemImpl* download_item) { |
| 483 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 496 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 484 if (download_item->IsComplete() && | 497 if (download_item->IsComplete() && |
| 485 !download_item->GetFileExternallyRemoved()) { | 498 !download_item->GetFileExternallyRemoved()) { |
| 486 BrowserThread::PostTask( | 499 BrowserThread::PostTask( |
| 487 BrowserThread::FILE, FROM_HERE, | 500 BrowserThread::FILE, FROM_HERE, |
| 488 base::Bind(&DownloadManagerImpl::CheckForFileRemovalOnFileThread, | 501 base::Bind(&DownloadManagerImpl::CheckForFileRemovalOnFileThread, |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 536 return bound_net_log; | 549 return bound_net_log; |
| 537 } | 550 } |
| 538 | 551 |
| 539 DownloadItemImpl* DownloadManagerImpl::CreateSavePackageDownloadItem( | 552 DownloadItemImpl* DownloadManagerImpl::CreateSavePackageDownloadItem( |
| 540 const FilePath& main_file_path, | 553 const FilePath& main_file_path, |
| 541 const GURL& page_url, | 554 const GURL& page_url, |
| 542 const std::string& mime_type, | 555 const std::string& mime_type, |
| 543 DownloadItem::Observer* observer) { | 556 DownloadItem::Observer* observer) { |
| 544 net::BoundNetLog bound_net_log = | 557 net::BoundNetLog bound_net_log = |
| 545 net::BoundNetLog::Make(net_log_, net::NetLog::SOURCE_DOWNLOAD); | 558 net::BoundNetLog::Make(net_log_, net::NetLog::SOURCE_DOWNLOAD); |
| 546 DownloadItemImpl* download = factory_->CreateSavePageItem( | 559 DownloadItemImpl* download_item = factory_->CreateSavePageItem( |
| 547 this, | 560 this, |
| 548 main_file_path, | 561 main_file_path, |
| 549 page_url, | 562 page_url, |
| 550 GetNextId(), | 563 GetNextId(), |
| 551 mime_type, | 564 mime_type, |
| 552 bound_net_log); | 565 bound_net_log); |
| 553 | 566 download_item->AddObserver(observer); |
| 554 download->AddObserver(observer); | 567 DCHECK(!ContainsKey(downloads_, download_item->GetId())); |
| 555 | 568 downloads_[download_item->GetId()] = download_item; |
| 556 DCHECK(!ContainsKey(downloads_, download->GetId())); | 569 DCHECK(!SavePageData::Get(download_item)); |
| 557 downloads_[download->GetId()] = download; | 570 new SavePageData(download_item); |
| 558 DCHECK(!SavePageData::Get(download)); | 571 DCHECK(SavePageData::Get(download_item)); |
| 559 new SavePageData(download); | 572 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadCreated( |
| 560 DCHECK(SavePageData::Get(download)); | 573 this, download_item)); |
| 561 | 574 OnDownloadTargetDetermined( |
|
Randy Smith (Not in Mondays)
2012/09/11 18:36:53
I don't follow where this came from; it doesn't lo
| |
| 562 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadCreated(this, download)); | 575 download_item->GetId(), |
| 563 | 576 main_file_path, |
| 564 // Will notify the observer in the callback. | 577 DownloadItem::TARGET_DISPOSITION_OVERWRITE, |
| 565 if (delegate_) | 578 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, |
| 566 delegate_->AddItemToPersistentStore(download); | 579 main_file_path); |
| 567 | 580 return download_item; |
| 568 return download; | |
| 569 } | 581 } |
| 570 | 582 |
| 571 void DownloadManagerImpl::UpdateDownload(int32 download_id, | 583 void DownloadManagerImpl::UpdateDownload(int32 download_id, |
| 572 int64 bytes_so_far, | 584 int64 bytes_so_far, |
| 573 int64 bytes_per_sec, | 585 int64 bytes_per_sec, |
| 574 const std::string& hash_state) { | 586 const std::string& hash_state) { |
| 575 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 587 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 576 DownloadMap::iterator it = active_downloads_.find(download_id); | 588 DownloadMap::iterator it = active_downloads_.find(download_id); |
| 577 if (it != active_downloads_.end()) { | 589 if (it != active_downloads_.end()) { |
| 578 DownloadItemImpl* download = it->second; | 590 DownloadItemImpl* download = it->second; |
| 579 if (download->IsInProgress()) { | 591 if (download->IsInProgress()) { |
| 580 download->UpdateProgress(bytes_so_far, bytes_per_sec, hash_state); | 592 download->UpdateProgress(bytes_so_far, bytes_per_sec, hash_state); |
| 581 if (delegate_) | |
| 582 delegate_->UpdateItemInPersistentStore(download); | |
| 583 } | 593 } |
| 584 } | 594 } |
| 585 } | 595 } |
| 586 | 596 |
| 587 void DownloadManagerImpl::OnResponseCompleted(int32 download_id, | 597 void DownloadManagerImpl::OnResponseCompleted(int32 download_id, |
| 588 int64 size, | 598 int64 size, |
| 589 const std::string& hash) { | 599 const std::string& hash) { |
| 590 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 600 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 591 VLOG(20) << __FUNCTION__ << "()" << " download_id = " << download_id | 601 VLOG(20) << __FUNCTION__ << "()" << " download_id = " << download_id |
| 592 << " size = " << size; | 602 << " size = " << size; |
| 593 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 603 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 594 | 604 |
| 595 // If it's not in active_downloads_, that means it was cancelled; just | 605 // If it's not in active_downloads_, that means it was cancelled; just |
| 596 // ignore the notification. | 606 // ignore the notification. |
| 597 if (active_downloads_.count(download_id) == 0) | 607 if (active_downloads_.count(download_id) == 0) |
| 598 return; | 608 return; |
| 599 | 609 |
| 600 DownloadItemImpl* download = active_downloads_[download_id]; | 610 DownloadItemImpl* download = active_downloads_[download_id]; |
| 601 download->OnAllDataSaved(size, hash); | 611 download->OnAllDataSaved(size, hash); |
| 602 MaybeCompleteDownload(download); | 612 MaybeCompleteDownload(download); |
| 603 } | 613 } |
| 604 | 614 |
| 605 void DownloadManagerImpl::AssertStateConsistent( | 615 void DownloadManagerImpl::AssertStateConsistent( |
| 606 DownloadItemImpl* download) const { | 616 DownloadItemImpl* download) const { |
| 607 CHECK(ContainsKey(downloads_, download->GetId())); | 617 CHECK(ContainsKey(downloads_, download->GetId())); |
| 608 | 618 |
| 609 int64 state = download->GetState(); | 619 int64 state = download->GetState(); |
| 610 base::debug::Alias(&state); | 620 base::debug::Alias(&state); |
| 611 if (ContainsKey(active_downloads_, download->GetId())) { | |
| 612 if (download->IsPersisted()) | |
| 613 CHECK_EQ(DownloadItem::IN_PROGRESS, download->GetState()); | |
| 614 if (DownloadItem::IN_PROGRESS != download->GetState()) | |
| 615 CHECK_EQ(DownloadItem::kUninitializedHandle, download->GetDbHandle()); | |
| 616 } | |
| 617 if (DownloadItem::IN_PROGRESS == download->GetState()) | 621 if (DownloadItem::IN_PROGRESS == download->GetState()) |
| 618 CHECK(ContainsKey(active_downloads_, download->GetId())); | 622 CHECK(ContainsKey(active_downloads_, download->GetId())); |
| 619 } | 623 } |
| 620 | 624 |
| 621 bool DownloadManagerImpl::IsDownloadReadyForCompletion( | 625 bool DownloadManagerImpl::IsDownloadReadyForCompletion( |
| 622 DownloadItemImpl* download) { | 626 DownloadItemImpl* download) { |
| 623 // If we don't have all the data, the download is not ready for | 627 // If we don't have all the data, the download is not ready for |
| 624 // completion. | 628 // completion. |
| 625 if (!download->AllDataSaved()) | 629 if (!download->AllDataSaved()) |
| 626 return false; | 630 return false; |
| 627 | 631 |
| 628 // If the download is dangerous, but not yet validated, it's not ready for | 632 // If the download is dangerous, but not yet validated, it's not ready for |
| 629 // completion. | 633 // completion. |
| 630 if (download->GetSafetyState() == DownloadItem::DANGEROUS) | 634 if (download->GetSafetyState() == DownloadItem::DANGEROUS) |
| 631 return false; | 635 return false; |
| 632 | 636 |
| 633 // If the download isn't active (e.g. has been cancelled) it's not | 637 // If the download isn't active (e.g. has been cancelled) it's not |
| 634 // ready for completion. | 638 // ready for completion. |
| 635 if (active_downloads_.count(download->GetId()) == 0) | 639 if (active_downloads_.count(download->GetId()) == 0) |
| 636 return false; | 640 return false; |
| 637 | 641 |
| 638 // If the download hasn't been inserted into the history system | 642 if (download->GetTargetFilePath().DirName() != |
|
Randy Smith (Not in Mondays)
2012/09/11 18:36:53
Could you comment this test? Something like "If t
benjhayden
2012/09/13 15:18:16
Done.
| |
| 639 // (which occurs strictly after file name determination, intermediate | 643 download->GetFullPath().DirName()) |
| 640 // file rename, and UI display) then it's not ready for completion. | 644 return false; |
| 641 if (!download->IsPersisted()) | 645 if (download->GetTargetName().empty()) |
| 642 return false; | 646 return false; |
| 643 | 647 |
| 644 return true; | 648 return true; |
| 645 } | 649 } |
| 646 | 650 |
| 647 // When SavePackage downloads MHTML to GData (see | 651 // When SavePackage downloads MHTML to GData (see |
| 648 // SavePackageFilePickerChromeOS), GData calls MaybeCompleteDownload() like it | 652 // SavePackageFilePickerChromeOS), GData calls MaybeCompleteDownload() like it |
| 649 // does for non-SavePackage downloads, but SavePackage downloads never satisfy | 653 // does for non-SavePackage downloads, but SavePackage downloads never satisfy |
| 650 // IsDownloadReadyForCompletion(). GDataDownloadObserver manually calls | 654 // IsDownloadReadyForCompletion(). GDataDownloadObserver manually calls |
| 651 // DownloadItem::UpdateObservers() when the upload completes so that SavePackage | 655 // DownloadItem::UpdateObservers() when the upload completes so that SavePackage |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 665 | 669 |
| 666 // TODO(rdsmith): DCHECK that we only pass through this point | 670 // TODO(rdsmith): DCHECK that we only pass through this point |
| 667 // once per download. The natural way to do this is by a state | 671 // once per download. The natural way to do this is by a state |
| 668 // transition on the DownloadItem. | 672 // transition on the DownloadItem. |
| 669 | 673 |
| 670 // Confirm we're in the proper set of states to be here; | 674 // Confirm we're in the proper set of states to be here; |
| 671 // have all data, have a history handle, (validated or safe). | 675 // have all data, have a history handle, (validated or safe). |
| 672 DCHECK(download->IsInProgress()); | 676 DCHECK(download->IsInProgress()); |
| 673 DCHECK_NE(DownloadItem::DANGEROUS, download->GetSafetyState()); | 677 DCHECK_NE(DownloadItem::DANGEROUS, download->GetSafetyState()); |
| 674 DCHECK(download->AllDataSaved()); | 678 DCHECK(download->AllDataSaved()); |
| 675 DCHECK(download->IsPersisted()); | |
| 676 | 679 |
| 677 // Give the delegate a chance to override. It's ok to keep re-setting the | 680 // Give the delegate a chance to override. It's ok to keep re-setting the |
| 678 // delegate's |complete_callback| cb as long as there isn't another call-point | 681 // delegate's |complete_callback| cb as long as there isn't another call-point |
| 679 // trying to set it to a different cb. TODO(benjhayden): Change the callback | 682 // trying to set it to a different cb. TODO(benjhayden): Change the callback |
| 680 // to point directly to the item instead of |this| when DownloadItem supports | 683 // to point directly to the item instead of |this| when DownloadItem supports |
| 681 // weak-ptrs. | 684 // weak-ptrs. |
| 682 if (delegate_ && !delegate_->ShouldCompleteDownload(download, base::Bind( | 685 if (delegate_ && !delegate_->ShouldCompleteDownload(download, base::Bind( |
| 683 &DownloadManagerImpl::MaybeCompleteDownloadById, | 686 &DownloadManagerImpl::MaybeCompleteDownloadById, |
| 684 this, download->GetId()))) | 687 this, download->GetId()))) |
| 685 return; | 688 return; |
| 686 | 689 |
| 687 VLOG(20) << __FUNCTION__ << "()" << " executing: download = " | 690 VLOG(20) << __FUNCTION__ << "()" << " executing: download = " |
| 688 << download->DebugString(false); | 691 << download->DebugString(false); |
| 689 | 692 |
| 690 if (delegate_) | |
| 691 delegate_->UpdateItemInPersistentStore(download); | |
| 692 download->OnDownloadCompleting(); | 693 download->OnDownloadCompleting(); |
| 693 } | 694 } |
| 694 | 695 |
| 695 void DownloadManagerImpl::MaybeCompleteDownloadById(int download_id) { | 696 void DownloadManagerImpl::MaybeCompleteDownloadById(int download_id) { |
| 696 if (ContainsKey(active_downloads_, download_id)) | 697 if (ContainsKey(active_downloads_, download_id)) |
| 697 MaybeCompleteDownload(active_downloads_[download_id]); | 698 MaybeCompleteDownload(active_downloads_[download_id]); |
| 698 } | 699 } |
| 699 | 700 |
| 700 void DownloadManagerImpl::DownloadCompleted(DownloadItemImpl* download) { | 701 void DownloadManagerImpl::DownloadCompleted(DownloadItemImpl* download) { |
| 701 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 702 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 702 DCHECK(download); | 703 DCHECK(download); |
| 703 if (delegate_) | |
| 704 delegate_->UpdateItemInPersistentStore(download); | |
| 705 active_downloads_.erase(download->GetId()); | 704 active_downloads_.erase(download->GetId()); |
| 706 AssertStateConsistent(download); | 705 AssertStateConsistent(download); |
| 707 } | 706 } |
| 708 | 707 |
| 709 void DownloadManagerImpl::CancelDownload(int32 download_id) { | 708 void DownloadManagerImpl::CancelDownload(int32 download_id) { |
| 710 // A cancel at the right time could remove the download from the | 709 // A cancel at the right time could remove the download from the |
| 711 // |active_downloads_| map before we get here. | 710 // |active_downloads_| map before we get here. |
| 712 if (ContainsKey(active_downloads_, download_id)) | 711 if (ContainsKey(active_downloads_, download_id)) |
| 713 active_downloads_[download_id]->Cancel(true); | 712 active_downloads_[download_id]->Cancel(true); |
| 714 } | 713 } |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 734 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 733 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 735 | 734 |
| 736 if (!ContainsKey(active_downloads_, download_id)) | 735 if (!ContainsKey(active_downloads_, download_id)) |
| 737 return; | 736 return; |
| 738 active_downloads_[download_id]->Interrupt(reason); | 737 active_downloads_[download_id]->Interrupt(reason); |
| 739 } | 738 } |
| 740 | 739 |
| 741 void DownloadManagerImpl::RemoveFromActiveList(DownloadItemImpl* download) { | 740 void DownloadManagerImpl::RemoveFromActiveList(DownloadItemImpl* download) { |
| 742 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 741 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 743 DCHECK(download); | 742 DCHECK(download); |
| 744 | 743 active_downloads_.erase(download->GetId()); |
| 745 // Clean up will happen when the history system create callback runs if we | |
| 746 // don't have a valid db_handle yet. | |
| 747 if (download->IsPersisted()) { | |
| 748 active_downloads_.erase(download->GetId()); | |
| 749 if (delegate_) | |
| 750 delegate_->UpdateItemInPersistentStore(download); | |
| 751 } | |
| 752 } | 744 } |
| 753 | 745 |
| 754 bool DownloadManagerImpl::GenerateFileHash() { | 746 bool DownloadManagerImpl::GenerateFileHash() { |
| 755 return delegate_ && delegate_->GenerateFileHash(); | 747 return delegate_ && delegate_->GenerateFileHash(); |
| 756 } | 748 } |
| 757 | 749 |
| 758 int DownloadManagerImpl::RemoveDownloadItems( | 750 int DownloadManagerImpl::RemoveDownloadItems( |
| 759 const DownloadItemImplVector& pending_deletes) { | 751 const DownloadItemImplVector& pending_deletes) { |
| 760 if (pending_deletes.empty()) | 752 if (pending_deletes.empty()) |
| 761 return 0; | 753 return 0; |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 772 } | 764 } |
| 773 NotifyModelChanged(); | 765 NotifyModelChanged(); |
| 774 return static_cast<int>(pending_deletes.size()); | 766 return static_cast<int>(pending_deletes.size()); |
| 775 } | 767 } |
| 776 | 768 |
| 777 void DownloadManagerImpl::DownloadRemoved(DownloadItemImpl* download) { | 769 void DownloadManagerImpl::DownloadRemoved(DownloadItemImpl* download) { |
| 778 if (!download || | 770 if (!download || |
| 779 downloads_.find(download->GetId()) == downloads_.end()) | 771 downloads_.find(download->GetId()) == downloads_.end()) |
| 780 return; | 772 return; |
| 781 | 773 |
| 782 // TODO(benjhayden,rdsmith): Remove this. | |
| 783 if (!download->IsPersisted()) | |
| 784 return; | |
| 785 | |
| 786 // Make history update. | |
| 787 if (delegate_) | |
| 788 delegate_->RemoveItemFromPersistentStore(download); | |
| 789 | |
| 790 // Remove from our tables and delete. | 774 // Remove from our tables and delete. |
| 791 int downloads_count = | 775 int downloads_count = |
| 792 RemoveDownloadItems(DownloadItemImplVector(1, download)); | 776 RemoveDownloadItems(DownloadItemImplVector(1, download)); |
| 793 DCHECK_EQ(1, downloads_count); | 777 DCHECK_EQ(1, downloads_count); |
| 794 } | 778 } |
| 795 | 779 |
| 796 int DownloadManagerImpl::RemoveDownloadsBetween(base::Time remove_begin, | 780 int DownloadManagerImpl::RemoveDownloadsBetween(base::Time remove_begin, |
| 797 base::Time remove_end) { | 781 base::Time remove_end) { |
| 798 if (delegate_) | |
| 799 delegate_->RemoveItemsFromPersistentStoreBetween(remove_begin, remove_end); | |
| 800 | |
| 801 DownloadItemImplVector pending_deletes; | 782 DownloadItemImplVector pending_deletes; |
| 802 for (DownloadMap::const_iterator it = downloads_.begin(); | 783 for (DownloadMap::const_iterator it = downloads_.begin(); |
| 803 it != downloads_.end(); | 784 it != downloads_.end(); |
| 804 ++it) { | 785 ++it) { |
| 805 DownloadItemImpl* download = it->second; | 786 DownloadItemImpl* download = it->second; |
| 806 if (download->IsPersisted() && | 787 if (download->GetStartTime() >= remove_begin && |
| 807 download->GetStartTime() >= remove_begin && | |
| 808 (remove_end.is_null() || download->GetStartTime() < remove_end) && | 788 (remove_end.is_null() || download->GetStartTime() < remove_end) && |
| 809 (download->IsComplete() || download->IsCancelled())) { | 789 (download->IsComplete() || download->IsCancelled())) { |
| 810 AssertStateConsistent(download); | 790 AssertStateConsistent(download); |
| 811 download->NotifyRemoved(); | 791 download->NotifyRemoved(); |
| 812 pending_deletes.push_back(download); | 792 pending_deletes.push_back(download); |
| 813 } | 793 } |
| 814 } | 794 } |
| 815 return RemoveDownloadItems(pending_deletes); | 795 return RemoveDownloadItems(pending_deletes); |
| 816 } | 796 } |
| 817 | 797 |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 844 // observers. | 824 // observers. |
| 845 observer->ModelChanged(this); | 825 observer->ModelChanged(this); |
| 846 } | 826 } |
| 847 | 827 |
| 848 void DownloadManagerImpl::RemoveObserver(Observer* observer) { | 828 void DownloadManagerImpl::RemoveObserver(Observer* observer) { |
| 849 observers_.RemoveObserver(observer); | 829 observers_.RemoveObserver(observer); |
| 850 } | 830 } |
| 851 | 831 |
| 852 // Operations posted to us from the history service ---------------------------- | 832 // Operations posted to us from the history service ---------------------------- |
| 853 | 833 |
| 854 // The history service has retrieved all download entries. 'entries' contains | 834 DownloadItem* DownloadManagerImpl::CreateDownloadItem( |
| 855 // 'DownloadPersistentStoreInfo's in sorted order (by ascending start_time). | 835 const FilePath& path, |
| 856 void DownloadManagerImpl::OnPersistentStoreQueryComplete( | 836 const GURL& url, |
| 857 std::vector<DownloadPersistentStoreInfo>* entries) { | 837 const GURL& referrer_url, |
| 858 history_size_ = entries->size(); | 838 const base::Time& start_time, |
| 859 for (size_t i = 0; i < entries->size(); ++i) { | 839 const base::Time& end_time, |
| 860 int64 db_handle = entries->at(i).db_handle; | 840 int64 received_bytes, |
| 861 base::debug::Alias(&db_handle); | 841 int64 total_bytes, |
| 862 | 842 DownloadItem::DownloadState state, |
| 863 net::BoundNetLog bound_net_log = | 843 bool opened) { |
| 864 net::BoundNetLog::Make(net_log_, net::NetLog::SOURCE_DOWNLOAD); | 844 DownloadItemImpl* item = factory_->CreatePersistedItem( |
| 865 DownloadItemImpl* download = factory_->CreatePersistedItem( | 845 this, |
| 866 this, GetNextId(), entries->at(i), bound_net_log); | 846 GetNextId(), |
| 867 DCHECK(!ContainsKey(downloads_, download->GetId())); | 847 path, |
| 868 downloads_[download->GetId()] = download; | 848 url, |
| 869 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadCreated(this, download)); | 849 referrer_url, |
| 870 VLOG(20) << __FUNCTION__ << "()" << i << ">" | 850 start_time, |
| 871 << " download = " << download->DebugString(true); | 851 end_time, |
| 872 } | 852 received_bytes, |
| 853 total_bytes, | |
| 854 state, | |
| 855 opened, | |
| 856 net::BoundNetLog::Make(net_log_, net::NetLog::SOURCE_DOWNLOAD)); | |
| 857 DCHECK(!ContainsKey(downloads_, item->GetId())); | |
| 858 downloads_[item->GetId()] = item; | |
| 859 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadCreated(this, item)); | |
| 860 VLOG(20) << __FUNCTION__ << "() download = " << item->DebugString(true); | |
| 873 NotifyModelChanged(); | 861 NotifyModelChanged(); |
| 874 CheckForHistoryFilesRemoval(); | 862 return item; |
| 875 } | |
| 876 | |
| 877 void DownloadManagerImpl::AddDownloadItemToHistory(DownloadItemImpl* download, | |
| 878 int64 db_handle) { | |
| 879 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 880 DCHECK_NE(DownloadItem::kUninitializedHandle, db_handle); | |
| 881 DCHECK(!download->IsPersisted()); | |
| 882 download->SetDbHandle(db_handle); | |
| 883 download->SetIsPersisted(); | |
| 884 | |
| 885 download_stats::RecordHistorySize(history_size_); | |
| 886 // Not counting |download|. | |
| 887 ++history_size_; | |
| 888 | |
| 889 // Show in the appropriate browser UI. | |
| 890 // This includes buttons to save or cancel, for a dangerous download. | |
| 891 ShowDownloadInBrowser(download); | |
| 892 | |
| 893 // Inform interested objects about the new download. | |
| 894 NotifyModelChanged(); | |
| 895 } | |
| 896 | |
| 897 | |
| 898 void DownloadManagerImpl::OnItemAddedToPersistentStore(int32 download_id, | |
| 899 int64 db_handle) { | |
| 900 // It's valid that we don't find a matching item, i.e. on shutdown. | |
| 901 if (!ContainsKey(downloads_, download_id)) | |
| 902 return; | |
| 903 | |
| 904 DownloadItemImpl* item = downloads_[download_id]; | |
| 905 AddDownloadItemToHistory(item, db_handle); | |
| 906 if (SavePageData::Get(item)) { | |
| 907 OnSavePageItemAddedToPersistentStore(item); | |
| 908 } else { | |
| 909 OnDownloadItemAddedToPersistentStore(item); | |
| 910 } | |
| 911 } | |
| 912 | |
| 913 // Once the new DownloadItem has been committed to the persistent store, | |
| 914 // associate it with its db_handle (TODO(benjhayden) merge db_handle with id), | |
| 915 // show it in the browser (TODO(benjhayden) the ui should observe us instead), | |
| 916 // and notify observers (TODO(benjhayden) observers should be able to see the | |
| 917 // item when it's created so they can observe it directly. Are there any | |
| 918 // clients that actually need to know when the item is added to the history?). | |
| 919 void DownloadManagerImpl::OnDownloadItemAddedToPersistentStore( | |
| 920 DownloadItemImpl* item) { | |
| 921 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 922 VLOG(20) << __FUNCTION__ << "()" << " db_handle = " << item->GetDbHandle() | |
| 923 << " download_id = " << item->GetId() | |
| 924 << " download = " << item->DebugString(true); | |
| 925 | |
| 926 // If the download is still in progress, try to complete it. | |
| 927 // | |
| 928 // Otherwise, download has been cancelled or interrupted before we've | |
| 929 // received the DB handle. We post one final message to the history | |
| 930 // service so that it can be properly in sync with the DownloadItem's | |
| 931 // completion status, and also inform any observers so that they get | |
| 932 // more than just the start notification. | |
| 933 if (item->IsInProgress()) { | |
| 934 MaybeCompleteDownload(item); | |
| 935 } else { | |
| 936 DCHECK(item->IsCancelled()); | |
| 937 active_downloads_.erase(item->GetId()); | |
| 938 if (delegate_) | |
| 939 delegate_->UpdateItemInPersistentStore(item); | |
| 940 item->UpdateObservers(); | |
| 941 } | |
| 942 } | 863 } |
| 943 | 864 |
| 944 void DownloadManagerImpl::ShowDownloadInBrowser(DownloadItemImpl* download) { | 865 void DownloadManagerImpl::ShowDownloadInBrowser(DownloadItemImpl* download) { |
| 945 // The 'contents' may no longer exist if the user closed the contents before | 866 // The 'contents' may no longer exist if the user closed the contents before |
| 946 // we get this start completion event. | 867 // we get this start completion event. |
| 947 WebContents* content = download->GetWebContents(); | 868 WebContents* content = download->GetWebContents(); |
| 948 | 869 |
| 949 // If the contents no longer exists, we ask the embedder to suggest another | 870 // If the contents no longer exists, we ask the embedder to suggest another |
| 950 // contents. | 871 // contents. |
| 951 if (!content && delegate_) | 872 if (!content && delegate_) |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 967 ++count; | 888 ++count; |
| 968 } | 889 } |
| 969 return count; | 890 return count; |
| 970 } | 891 } |
| 971 | 892 |
| 972 void DownloadManagerImpl::NotifyModelChanged() { | 893 void DownloadManagerImpl::NotifyModelChanged() { |
| 973 FOR_EACH_OBSERVER(Observer, observers_, ModelChanged(this)); | 894 FOR_EACH_OBSERVER(Observer, observers_, ModelChanged(this)); |
| 974 } | 895 } |
| 975 | 896 |
| 976 DownloadItem* DownloadManagerImpl::GetDownloadItem(int download_id) { | 897 DownloadItem* DownloadManagerImpl::GetDownloadItem(int download_id) { |
| 977 DownloadItem* download = GetDownload(download_id); | 898 return GetDownload(download_id); |
| 978 return (download && download->IsPersisted()) ? download : NULL; | |
| 979 } | 899 } |
| 980 | 900 |
| 981 DownloadItem* DownloadManagerImpl::GetDownload(int download_id) { | 901 DownloadItem* DownloadManagerImpl::GetDownload(int download_id) { |
| 982 return ContainsKey(downloads_, download_id) ? downloads_[download_id] : NULL; | 902 return ContainsKey(downloads_, download_id) ? downloads_[download_id] : NULL; |
| 983 } | 903 } |
| 984 | 904 |
| 985 DownloadItem* DownloadManagerImpl::GetActiveDownloadItem(int download_id) { | 905 DownloadItem* DownloadManagerImpl::GetActiveDownloadItem(int download_id) { |
| 986 if (ContainsKey(active_downloads_, download_id)) | 906 if (ContainsKey(active_downloads_, download_id)) |
| 987 return active_downloads_[download_id]; | 907 return active_downloads_[download_id]; |
| 988 return NULL; | 908 return NULL; |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 1015 DownloadSet remainder; | 935 DownloadSet remainder; |
| 1016 std::insert_iterator<DownloadSet> insert_it(remainder, remainder.begin()); | 936 std::insert_iterator<DownloadSet> insert_it(remainder, remainder.begin()); |
| 1017 std::set_difference(all_sets[i]->begin(), all_sets[i]->end(), | 937 std::set_difference(all_sets[i]->begin(), all_sets[i]->end(), |
| 1018 all_downloads.begin(), all_downloads.end(), | 938 all_downloads.begin(), all_downloads.end(), |
| 1019 insert_it); | 939 insert_it); |
| 1020 DCHECK(remainder.empty()); | 940 DCHECK(remainder.empty()); |
| 1021 } | 941 } |
| 1022 #endif | 942 #endif |
| 1023 } | 943 } |
| 1024 | 944 |
| 1025 // SavePackage will call SavePageDownloadFinished upon completion/cancellation. | |
| 1026 // The history callback will call OnSavePageItemAddedToPersistentStore. | |
| 1027 // If the download finishes before the history callback, | |
| 1028 // OnSavePageItemAddedToPersistentStore calls SavePageDownloadFinished, ensuring | |
| 1029 // that the history event is update regardless of the order in which these two | |
| 1030 // events complete. | |
| 1031 // If something removes the download item from the download manager (Remove, | |
| 1032 // Shutdown) the result will be that the SavePage system will not be able to | |
| 1033 // properly update the download item (which no longer exists) or the download | |
| 1034 // history, but the action will complete properly anyway. This may lead to the | |
| 1035 // history entry being wrong on a reload of chrome (specifically in the case of | |
| 1036 // Initiation -> History Callback -> Removal -> Completion), but there's no way | |
| 1037 // to solve that without canceling on Remove (which would then update the DB). | |
| 1038 | |
| 1039 void DownloadManagerImpl::OnSavePageItemAddedToPersistentStore( | |
| 1040 DownloadItemImpl* item) { | |
| 1041 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 1042 | |
| 1043 // Finalize this download if it finished before the history callback. | |
| 1044 if (!item->IsInProgress()) | |
| 1045 SavePageDownloadFinished(item); | |
| 1046 } | |
| 1047 | |
| 1048 void DownloadManagerImpl::SavePageDownloadFinished( | 945 void DownloadManagerImpl::SavePageDownloadFinished( |
| 1049 content::DownloadItem* download) { | 946 content::DownloadItem* download) { |
| 1050 if (download->IsPersisted()) { | 947 if (download->IsComplete()) |
| 1051 if (delegate_) | 948 content::NotificationService::current()->Notify( |
| 1052 delegate_->UpdateItemInPersistentStore(download); | 949 content::NOTIFICATION_SAVE_PACKAGE_SUCCESSFULLY_FINISHED, |
| 1053 if (download->IsComplete()) | 950 content::Source<DownloadManager>(this), |
| 1054 content::NotificationService::current()->Notify( | 951 content::Details<DownloadItem>(download)); |
| 1055 content::NOTIFICATION_SAVE_PACKAGE_SUCCESSFULLY_FINISHED, | |
| 1056 content::Source<DownloadManager>(this), | |
| 1057 content::Details<DownloadItem>(download)); | |
| 1058 } | |
| 1059 } | 952 } |
| 1060 | 953 |
| 1061 void DownloadManagerImpl::DownloadOpened(DownloadItemImpl* download) { | 954 void DownloadManagerImpl::DownloadOpened(DownloadItemImpl* download) { |
| 1062 if (delegate_) | |
| 1063 delegate_->UpdateItemInPersistentStore(download); | |
| 1064 int num_unopened = 0; | 955 int num_unopened = 0; |
| 1065 for (DownloadMap::iterator it = downloads_.begin(); | 956 for (DownloadMap::iterator it = downloads_.begin(); |
| 1066 it != downloads_.end(); ++it) { | 957 it != downloads_.end(); ++it) { |
| 1067 DownloadItemImpl* item = it->second; | 958 DownloadItemImpl* item = it->second; |
| 1068 if (item->IsComplete() && | 959 if (item->IsComplete() && |
| 1069 !item->GetOpened()) | 960 !item->GetOpened()) |
| 1070 ++num_unopened; | 961 ++num_unopened; |
| 1071 } | 962 } |
| 1072 download_stats::RecordOpensOutstanding(num_unopened); | 963 download_stats::RecordOpensOutstanding(num_unopened); |
| 1073 } | 964 } |
| 1074 | 965 |
| 966 // TODO(benjhayden) this should be a method on DI | |
|
Randy Smith (Not in Mondays)
2012/09/11 18:36:53
I'm confused by this comment. It is a method on t
benjhayden
2012/09/13 15:18:16
Clarified the comment.
| |
| 1075 void DownloadManagerImpl::DownloadRenamedToIntermediateName( | 967 void DownloadManagerImpl::DownloadRenamedToIntermediateName( |
| 1076 DownloadItemImpl* download) { | 968 DownloadItemImpl* download) { |
| 1077 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 969 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 1078 // download->GetFullPath() is only expected to be meaningful after this | 970 download->UpdateObservers(); |
| 1079 // callback is received. Therefore we can now add the download to a persistent | 971 MaybeCompleteDownload(download); |
| 1080 // store. If the rename failed, we receive an OnDownloadInterrupted() call | |
| 1081 // before we receive the DownloadRenamedToIntermediateName() call. | |
| 1082 if (delegate_) { | |
| 1083 delegate_->AddItemToPersistentStore(download); | |
| 1084 } else { | |
| 1085 OnItemAddedToPersistentStore(download->GetId(), | |
| 1086 DownloadItem::kUninitializedHandle); | |
| 1087 } | |
| 1088 } | 972 } |
| 1089 | 973 |
| 974 // TODO(benjhayden) this should be a method on DI | |
|
Randy Smith (Not in Mondays)
2012/09/11 18:36:53
Same comment as above, with the twist that given t
benjhayden
2012/09/13 15:18:16
Done.
| |
| 1090 void DownloadManagerImpl::DownloadRenamedToFinalName( | 975 void DownloadManagerImpl::DownloadRenamedToFinalName( |
| 1091 DownloadItemImpl* download) { | 976 DownloadItemImpl* download) { |
| 1092 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 977 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 1093 // If the rename failed, we receive an OnDownloadInterrupted() call before we | 978 // If the rename failed, we receive an OnDownloadInterrupted() call before we |
| 1094 // receive the DownloadRenamedToFinalName() call. | 979 // receive the DownloadRenamedToFinalName() call. |
| 1095 if (delegate_) { | 980 download->UpdateObservers(); |
| 1096 delegate_->UpdatePathForItemInPersistentStore( | |
| 1097 download, download->GetFullPath()); | |
| 1098 } | |
| 1099 } | 981 } |
| OLD | NEW |