Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(109)

Side by Side Diff: content/browser/download/download_manager_impl.cc

Issue 10665049: Make DownloadHistory observe manager, items (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
45 using content::BrowserThread; 45 using content::BrowserThread;
46 using content::DownloadId; 46 using content::DownloadId;
47 using content::DownloadItem; 47 using content::DownloadItem;
48 using content::DownloadPersistentStoreInfo; 48 using content::DownloadPersistentStoreInfo;
49 using content::ResourceDispatcherHostImpl; 49 using content::ResourceDispatcherHostImpl;
50 using content::WebContents; 50 using content::WebContents;
51 51
52 namespace { 52 namespace {
53 53
54 // This is just used to remember which DownloadItems come from SavePage. 54 // This is just used to remember which DownloadItems come from SavePage.
55 class SavePageExternalData : public DownloadItem::ExternalData { 55 class SavePageData : public base::SupportsUserData::Data {
56 public: 56 public:
57 // A spoonful of syntactic sugar. 57 // A spoonful of syntactic sugar.
58 static bool Get(DownloadItem* item) { 58 static bool Get(DownloadItem* item) {
59 return item->GetExternalData(kKey) != NULL; 59 return item->GetUserData(kKey) != NULL;
60 } 60 }
61 61
62 explicit SavePageExternalData(DownloadItem* item) { 62 explicit SavePageData(DownloadItem* item) {
63 item->SetExternalData(kKey, this); 63 item->SetUserData(kKey, this);
64 } 64 }
65 65
66 virtual ~SavePageExternalData() {} 66 virtual ~SavePageData() {}
67 67
68 private: 68 private:
69 static const char kKey[]; 69 static const char kKey[];
70 70
71 DISALLOW_COPY_AND_ASSIGN(SavePageExternalData); 71 DISALLOW_COPY_AND_ASSIGN(SavePageData);
72 }; 72 };
73 73
74 const char SavePageExternalData::kKey[] = "DownloadItem SavePageExternalData"; 74 const char SavePageData::kKey[] = "DownloadItem SavePageData";
75 75
76 void BeginDownload(content::DownloadUrlParameters* params) { 76 void BeginDownload(content::DownloadUrlParameters* params) {
77 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 77 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
78 // ResourceDispatcherHost{Base} is-not-a URLRequest::Delegate, and 78 // ResourceDispatcherHost{Base} is-not-a URLRequest::Delegate, and
79 // DownloadUrlParameters can-not include resource_dispatcher_host_impl.h, so 79 // DownloadUrlParameters can-not include resource_dispatcher_host_impl.h, so
80 // we must down cast. RDHI is the only subclass of RDH as of 2012 May 4. 80 // we must down cast. RDHI is the only subclass of RDH as of 2012 May 4.
81 scoped_ptr<net::URLRequest> request(new net::URLRequest( 81 scoped_ptr<net::URLRequest> request(new net::URLRequest(
82 params->url(), 82 params->url(),
83 NULL, 83 NULL,
84 params->resource_context()->GetRequestContext())); 84 params->resource_context()->GetRequestContext()));
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after
305 // from the disk. This may or may not result in it being 305 // from the disk. This may or may not result in it being
306 // removed from the DownloadManager queues and deleted 306 // removed from the DownloadManager queues and deleted
307 // (specifically, DownloadManager::DownloadRemoved only 307 // (specifically, DownloadManager::DownloadRemoved only
308 // removes and deletes it if it's known to the history service) 308 // removes and deletes it if it's known to the history service)
309 // so the only thing we know after calling this function is that 309 // so the only thing we know after calling this function is that
310 // the download was deleted if-and-only-if it was removed 310 // the download was deleted if-and-only-if it was removed
311 // from all queues. 311 // from all queues.
312 download->Delete(DownloadItem::DELETE_DUE_TO_BROWSER_SHUTDOWN); 312 download->Delete(DownloadItem::DELETE_DUE_TO_BROWSER_SHUTDOWN);
313 } else if (download->IsPartialDownload()) { 313 } else if (download->IsPartialDownload()) {
314 download->Cancel(false); 314 download->Cancel(false);
315 if (delegate_)
316 delegate_->UpdateItemInPersistentStore(download);
317 } 315 }
318 } 316 }
319 317
320 // At this point, all dangerous downloads have had their files removed 318 // At this point, all dangerous downloads have had their files removed
321 // and all in progress downloads have been cancelled. We can now delete 319 // and all in progress downloads have been cancelled. We can now delete
322 // anything left. 320 // anything left.
323 321
324 // Copy downloads_ to separate container so as not to set off checks
325 // in DownloadItem destruction.
326 DownloadMap downloads_to_delete;
327 downloads_to_delete.swap(downloads_);
328
329 active_downloads_.clear(); 322 active_downloads_.clear();
330 STLDeleteValues(&downloads_to_delete); 323 STLDeleteValues(&downloads_);
324 downloads_.clear();
331 325
332 // We'll have nothing more to report to the observers after this point. 326 // We'll have nothing more to report to the observers after this point.
333 observers_.Clear(); 327 observers_.Clear();
334 328
335 file_manager_ = NULL; 329 file_manager_ = NULL;
336 if (delegate_) 330 if (delegate_)
337 delegate_->Shutdown(); 331 delegate_->Shutdown();
338 delegate_ = NULL; 332 delegate_ = NULL;
339 } 333 }
340 334
341 void DownloadManagerImpl::GetTemporaryDownloads( 335 void DownloadManagerImpl::GetTemporaryDownloads(
342 const FilePath& dir_path, DownloadVector* result) { 336 const FilePath& dir_path, DownloadVector* result) {
343 DCHECK(result); 337 DCHECK(result);
344 338
345 for (DownloadMap::iterator it = downloads_.begin(); 339 for (DownloadMap::iterator it = downloads_.begin();
346 it != downloads_.end(); ++it) { 340 it != downloads_.end(); ++it) {
347 DownloadItemImpl* item = it->second; 341 DownloadItemImpl* item = it->second;
348 // TODO(benjhayden): Don't check IsPersisted().
349 if (item->IsTemporary() && 342 if (item->IsTemporary() &&
350 item->IsPersisted() &&
351 (dir_path.empty() || 343 (dir_path.empty() ||
352 item->GetTargetFilePath().DirName() == dir_path)) 344 item->GetTargetFilePath().DirName() == dir_path))
353 result->push_back(item); 345 result->push_back(item);
354 } 346 }
355 } 347 }
356 348
357 void DownloadManagerImpl::GetAllDownloads( 349 void DownloadManagerImpl::GetAllDownloads(
358 const FilePath& dir_path, DownloadVector* result) { 350 const FilePath& dir_path, DownloadVector* result) {
359 DCHECK(result); 351 DCHECK(result);
360 352
361 for (DownloadMap::iterator it = downloads_.begin(); 353 for (DownloadMap::iterator it = downloads_.begin();
362 it != downloads_.end(); ++it) { 354 it != downloads_.end(); ++it) {
363 DownloadItemImpl* item = it->second; 355 DownloadItemImpl* item = it->second;
364 // TODO(benjhayden): Don't check IsPersisted().
365 if (!item->IsTemporary() && 356 if (!item->IsTemporary() &&
366 item->IsPersisted() &&
367 (dir_path.empty() || 357 (dir_path.empty() ||
368 item->GetTargetFilePath().DirName() == dir_path)) 358 item->GetTargetFilePath().DirName() == dir_path))
369 result->push_back(item); 359 result->push_back(item);
370 } 360 }
371 } 361 }
372 362
373 void DownloadManagerImpl::SearchDownloads(const string16& query, 363 void DownloadManagerImpl::SearchDownloads(const string16& query,
374 DownloadVector* result) { 364 DownloadVector* result) {
375 string16 query_lower(base::i18n::ToLower(query)); 365 string16 query_lower(base::i18n::ToLower(query));
376 366
377 for (DownloadMap::iterator it = downloads_.begin(); 367 for (DownloadMap::iterator it = downloads_.begin();
378 it != downloads_.end(); ++it) { 368 it != downloads_.end(); ++it) {
379 DownloadItemImpl* download_item = it->second; 369 DownloadItemImpl* download_item = it->second;
380 // Display Incognito downloads only in Incognito window, and vice versa. 370 // Display Incognito downloads only in Incognito window, and vice versa.
381 // The Incognito Downloads page will get the list of non-Incognito downloads 371 // The Incognito Downloads page will get the list of non-Incognito downloads
382 // from its parent profile. 372 // from its parent profile.
383 // TODO(benjhayden): Don't check IsPersisted().
384 if (!download_item->IsTemporary() && 373 if (!download_item->IsTemporary() &&
385 download_item->IsPersisted() &&
386 (browser_context_->IsOffTheRecord() == download_item->IsOtr()) && 374 (browser_context_->IsOffTheRecord() == download_item->IsOtr()) &&
387 download_item->MatchesQuery(query_lower)) { 375 download_item->MatchesQuery(query_lower)) {
388 result->push_back(download_item); 376 result->push_back(download_item);
389 } 377 }
390 } 378 }
391 } 379 }
392 380
393 bool DownloadManagerImpl::Init(content::BrowserContext* browser_context) { 381 bool DownloadManagerImpl::Init(content::BrowserContext* browser_context) {
394 DCHECK(browser_context); 382 DCHECK(browser_context);
395 DCHECK(!shutdown_needed_) << "DownloadManager already initialized."; 383 DCHECK(!shutdown_needed_) << "DownloadManager already initialized.";
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
461 } 449 }
462 } 450 }
463 451
464 void DownloadManagerImpl::OnDownloadTargetDetermined( 452 void DownloadManagerImpl::OnDownloadTargetDetermined(
465 int32 download_id, 453 int32 download_id,
466 const FilePath& target_path, 454 const FilePath& target_path,
467 DownloadItem::TargetDisposition disposition, 455 DownloadItem::TargetDisposition disposition,
468 content::DownloadDangerType danger_type, 456 content::DownloadDangerType danger_type,
469 const FilePath& intermediate_path) { 457 const FilePath& intermediate_path) {
470 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 458 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
471 DownloadMap::iterator download_iter = active_downloads_.find(download_id); 459 DownloadMap::iterator download_iter = downloads_.find(download_id);
472 if (download_iter != active_downloads_.end()) { 460 if (download_iter == downloads_.end())
473 // Once DownloadItem::OnDownloadTargetDetermined() is called, we expect a 461 return;
474 // DownloadRenamedToIntermediateName() callback. This is necessary for the 462
475 // download to proceed. 463 // Once DownloadItem::OnDownloadTargetDetermined() is called, we expect a
476 download_iter->second->OnDownloadTargetDetermined( 464 // DownloadRenamedToIntermediateName() callback. This is necessary for the
477 target_path, disposition, danger_type, intermediate_path); 465 // download to proceed.
466 DownloadItemImpl* item = download_iter->second;
467 item->OnDownloadTargetDetermined(
468 target_path, disposition, danger_type, intermediate_path);
469 ShowDownloadInBrowser(item);
470 NotifyModelChanged();
471 if (!SavePageData::Get(item)) {
472 MaybeCompleteDownload(item);
478 } 473 }
479 } 474 }
480 475
481 void DownloadManagerImpl::CheckForHistoryFilesRemoval() { 476 void DownloadManagerImpl::CheckForHistoryFilesRemoval() {
482 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 477 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
483 for (DownloadMap::iterator it = downloads_.begin(); 478 for (DownloadMap::iterator it = downloads_.begin();
484 it != downloads_.end(); ++it) { 479 it != downloads_.end(); ++it) {
485 DownloadItemImpl* item = it->second; 480 DownloadItemImpl* item = it->second;
486 if (item->IsPersisted()) 481 CheckForFileRemoval(item);
487 CheckForFileRemoval(item);
488 } 482 }
489 } 483 }
490 484
491 void DownloadManagerImpl::CheckForFileRemoval(DownloadItemImpl* download_item) { 485 void DownloadManagerImpl::CheckForFileRemoval(DownloadItemImpl* download_item) {
492 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 486 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
493 if (download_item->IsComplete() && 487 if (download_item->IsComplete() &&
494 !download_item->GetFileExternallyRemoved()) { 488 !download_item->GetFileExternallyRemoved()) {
495 BrowserThread::PostTask( 489 BrowserThread::PostTask(
496 BrowserThread::FILE, FROM_HERE, 490 BrowserThread::FILE, FROM_HERE,
497 base::Bind(&DownloadManagerImpl::CheckForFileRemovalOnFileThread, 491 base::Bind(&DownloadManagerImpl::CheckForFileRemovalOnFileThread,
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
546 } 540 }
547 541
548 DownloadItemImpl* DownloadManagerImpl::CreateSavePackageDownloadItem( 542 DownloadItemImpl* DownloadManagerImpl::CreateSavePackageDownloadItem(
549 const FilePath& main_file_path, 543 const FilePath& main_file_path,
550 const GURL& page_url, 544 const GURL& page_url,
551 bool is_otr, 545 bool is_otr,
552 const std::string& mime_type, 546 const std::string& mime_type,
553 DownloadItem::Observer* observer) { 547 DownloadItem::Observer* observer) {
554 net::BoundNetLog bound_net_log = 548 net::BoundNetLog bound_net_log =
555 net::BoundNetLog::Make(net_log_, net::NetLog::SOURCE_DOWNLOAD); 549 net::BoundNetLog::Make(net_log_, net::NetLog::SOURCE_DOWNLOAD);
556 DownloadItemImpl* download = factory_->CreateSavePageItem( 550 DownloadItemImpl* download_item = factory_->CreateSavePageItem(
557 this, 551 this,
558 main_file_path, 552 main_file_path,
559 page_url, 553 page_url,
560 is_otr, 554 is_otr,
561 GetNextId(), 555 GetNextId(),
562 mime_type, 556 mime_type,
563 bound_net_log); 557 bound_net_log);
564 558 download_item->AddObserver(observer);
565 download->AddObserver(observer); 559 DCHECK(!ContainsKey(downloads_, download_item->GetId()));
566 560 downloads_[download_item->GetId()] = download_item;
567 DCHECK(!ContainsKey(downloads_, download->GetId())); 561 DCHECK(!SavePageData::Get(download_item));
568 downloads_[download->GetId()] = download; 562 new SavePageData(download_item);
569 DCHECK(!SavePageExternalData::Get(download)); 563 DCHECK(SavePageData::Get(download_item));
570 new SavePageExternalData(download); 564 // TODO(benjhayden) XXX occam test showing SavePackage DownloadItems in ui
571 DCHECK(SavePageExternalData::Get(download)); 565 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadCreated(
572 566 this, download_item));
573 // TODO(benjhayden): Fire OnDownloadCreated for SavePackage downloads when 567 return download_item;
574 // we're comfortable with the user interacting with them.
575 // FOR_EACH_OBSERVER(Observer, observers_, OnDownloadCreated(this, download));
576
577 // Will notify the observer in the callback.
578 if (delegate_)
579 delegate_->AddItemToPersistentStore(download);
580
581 return download;
582 } 568 }
583 569
584 void DownloadManagerImpl::UpdateDownload(int32 download_id, 570 void DownloadManagerImpl::UpdateDownload(int32 download_id,
585 int64 bytes_so_far, 571 int64 bytes_so_far,
586 int64 bytes_per_sec, 572 int64 bytes_per_sec,
587 const std::string& hash_state) { 573 const std::string& hash_state) {
588 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 574 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
589 DownloadMap::iterator it = active_downloads_.find(download_id); 575 DownloadMap::iterator it = active_downloads_.find(download_id);
590 if (it != active_downloads_.end()) { 576 if (it != active_downloads_.end()) {
591 DownloadItemImpl* download = it->second; 577 DownloadItemImpl* download = it->second;
592 if (download->IsInProgress()) { 578 if (download->IsInProgress()) {
593 download->UpdateProgress(bytes_so_far, bytes_per_sec, hash_state); 579 download->UpdateProgress(bytes_so_far, bytes_per_sec, hash_state);
594 if (delegate_)
595 delegate_->UpdateItemInPersistentStore(download);
596 } 580 }
597 } 581 }
598 } 582 }
599 583
600 void DownloadManagerImpl::OnResponseCompleted(int32 download_id, 584 void DownloadManagerImpl::OnResponseCompleted(int32 download_id,
601 int64 size, 585 int64 size,
602 const std::string& hash) { 586 const std::string& hash) {
603 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 587 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
604 VLOG(20) << __FUNCTION__ << "()" << " download_id = " << download_id 588 VLOG(20) << __FUNCTION__ << "()" << " download_id = " << download_id
605 << " size = " << size; 589 << " size = " << size;
606 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 590 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
607 591
608 // If it's not in active_downloads_, that means it was cancelled; just 592 // If it's not in active_downloads_, that means it was cancelled; just
609 // ignore the notification. 593 // ignore the notification.
610 if (active_downloads_.count(download_id) == 0) 594 if (active_downloads_.count(download_id) == 0)
611 return; 595 return;
612 596
613 DownloadItemImpl* download = active_downloads_[download_id]; 597 DownloadItemImpl* download = active_downloads_[download_id];
614 download->OnAllDataSaved(size, hash); 598 download->OnAllDataSaved(size, hash);
615 MaybeCompleteDownload(download); 599 MaybeCompleteDownload(download);
616 } 600 }
617 601
618 void DownloadManagerImpl::AssertStateConsistent( 602 void DownloadManagerImpl::AssertStateConsistent(
619 DownloadItemImpl* download) const { 603 DownloadItemImpl* download) const {
620 if (download->GetState() == DownloadItem::REMOVING) {
621 DCHECK(!ContainsKey(downloads_, download->GetId()));
622 DCHECK(!ContainsKey(active_downloads_, download->GetId()));
623 return;
624 }
625
626 // Should be in downloads_ if we're not REMOVING.
627 CHECK(ContainsKey(downloads_, download->GetId())); 604 CHECK(ContainsKey(downloads_, download->GetId()));
628 605
629 int64 state = download->GetState(); 606 int64 state = download->GetState();
630 base::debug::Alias(&state); 607 base::debug::Alias(&state);
631 if (ContainsKey(active_downloads_, download->GetId())) {
632 if (download->IsPersisted())
633 CHECK_EQ(DownloadItem::IN_PROGRESS, download->GetState());
634 if (DownloadItem::IN_PROGRESS != download->GetState())
635 CHECK_EQ(DownloadItem::kUninitializedHandle, download->GetDbHandle());
636 }
637 if (DownloadItem::IN_PROGRESS == download->GetState()) 608 if (DownloadItem::IN_PROGRESS == download->GetState())
638 CHECK(ContainsKey(active_downloads_, download->GetId())); 609 CHECK(ContainsKey(active_downloads_, download->GetId()));
639 } 610 }
640 611
641 bool DownloadManagerImpl::IsDownloadReadyForCompletion( 612 bool DownloadManagerImpl::IsDownloadReadyForCompletion(
642 DownloadItemImpl* download) { 613 DownloadItemImpl* download) {
643 // If we don't have all the data, the download is not ready for 614 // If we don't have all the data, the download is not ready for
644 // completion. 615 // completion.
645 if (!download->AllDataSaved()) 616 if (!download->AllDataSaved())
646 return false; 617 return false;
647 618
648 // If the download is dangerous, but not yet validated, it's not ready for 619 // If the download is dangerous, but not yet validated, it's not ready for
649 // completion. 620 // completion.
650 if (download->GetSafetyState() == DownloadItem::DANGEROUS) 621 if (download->GetSafetyState() == DownloadItem::DANGEROUS)
651 return false; 622 return false;
652 623
653 // If the download isn't active (e.g. has been cancelled) it's not 624 // If the download isn't active (e.g. has been cancelled) it's not
654 // ready for completion. 625 // ready for completion.
655 if (active_downloads_.count(download->GetId()) == 0) 626 if (active_downloads_.count(download->GetId()) == 0)
656 return false; 627 return false;
657 628
658 // If the download hasn't been inserted into the history system
659 // (which occurs strictly after file name determination, intermediate
660 // file rename, and UI display) then it's not ready for completion.
661 if (!download->IsPersisted())
662 return false;
663
664 return true; 629 return true;
665 } 630 }
666 631
667 // When SavePackage downloads MHTML to GData (see 632 // When SavePackage downloads MHTML to GData (see
668 // SavePackageFilePickerChromeOS), GData calls MaybeCompleteDownload() like it 633 // SavePackageFilePickerChromeOS), GData calls MaybeCompleteDownload() like it
669 // does for non-SavePackage downloads, but SavePackage downloads never satisfy 634 // does for non-SavePackage downloads, but SavePackage downloads never satisfy
670 // IsDownloadReadyForCompletion(). GDataDownloadObserver manually calls 635 // IsDownloadReadyForCompletion(). GDataDownloadObserver manually calls
671 // DownloadItem::UpdateObservers() when the upload completes so that SavePackage 636 // DownloadItem::UpdateObservers() when the upload completes so that SavePackage
672 // notices that the upload has completed and runs its normal Finish() pathway. 637 // notices that the upload has completed and runs its normal Finish() pathway.
673 // MaybeCompleteDownload() is never the mechanism by which SavePackage completes 638 // MaybeCompleteDownload() is never the mechanism by which SavePackage completes
(...skipping 11 matching lines...) Expand all
685 650
686 // TODO(rdsmith): DCHECK that we only pass through this point 651 // TODO(rdsmith): DCHECK that we only pass through this point
687 // once per download. The natural way to do this is by a state 652 // once per download. The natural way to do this is by a state
688 // transition on the DownloadItem. 653 // transition on the DownloadItem.
689 654
690 // Confirm we're in the proper set of states to be here; 655 // Confirm we're in the proper set of states to be here;
691 // have all data, have a history handle, (validated or safe). 656 // have all data, have a history handle, (validated or safe).
692 DCHECK(download->IsInProgress()); 657 DCHECK(download->IsInProgress());
693 DCHECK_NE(DownloadItem::DANGEROUS, download->GetSafetyState()); 658 DCHECK_NE(DownloadItem::DANGEROUS, download->GetSafetyState());
694 DCHECK(download->AllDataSaved()); 659 DCHECK(download->AllDataSaved());
695 DCHECK(download->IsPersisted());
696 660
697 // Give the delegate a chance to override. It's ok to keep re-setting the 661 // Give the delegate a chance to override. It's ok to keep re-setting the
698 // delegate's |complete_callback| cb as long as there isn't another call-point 662 // delegate's |complete_callback| cb as long as there isn't another call-point
699 // trying to set it to a different cb. TODO(benjhayden): Change the callback 663 // trying to set it to a different cb. TODO(benjhayden): Change the callback
700 // to point directly to the item instead of |this| when DownloadItem supports 664 // to point directly to the item instead of |this| when DownloadItem supports
701 // weak-ptrs. 665 // weak-ptrs.
702 if (delegate_ && !delegate_->ShouldCompleteDownload(download, base::Bind( 666 if (delegate_ && !delegate_->ShouldCompleteDownload(download, base::Bind(
703 &DownloadManagerImpl::MaybeCompleteDownloadById, 667 &DownloadManagerImpl::MaybeCompleteDownloadById,
704 this, download->GetId()))) 668 this, download->GetId())))
705 return; 669 return;
706 670
707 VLOG(20) << __FUNCTION__ << "()" << " executing: download = " 671 VLOG(20) << __FUNCTION__ << "()" << " executing: download = "
708 << download->DebugString(false); 672 << download->DebugString(false);
709 673
710 if (delegate_)
711 delegate_->UpdateItemInPersistentStore(download);
712 download->OnDownloadCompleting(); 674 download->OnDownloadCompleting();
713 } 675 }
714 676
715 void DownloadManagerImpl::MaybeCompleteDownloadById(int download_id) { 677 void DownloadManagerImpl::MaybeCompleteDownloadById(int download_id) {
716 if (ContainsKey(active_downloads_, download_id)) 678 if (ContainsKey(active_downloads_, download_id))
717 MaybeCompleteDownload(active_downloads_[download_id]); 679 MaybeCompleteDownload(active_downloads_[download_id]);
718 } 680 }
719 681
720 void DownloadManagerImpl::DownloadCompleted(DownloadItemImpl* download) { 682 void DownloadManagerImpl::DownloadCompleted(DownloadItemImpl* download) {
721 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 683 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
722 DCHECK(download); 684 DCHECK(download);
723 if (delegate_)
724 delegate_->UpdateItemInPersistentStore(download);
725 active_downloads_.erase(download->GetId()); 685 active_downloads_.erase(download->GetId());
726 AssertStateConsistent(download); 686 AssertStateConsistent(download);
727 } 687 }
728 688
729 void DownloadManagerImpl::CancelDownload(int32 download_id) { 689 void DownloadManagerImpl::CancelDownload(int32 download_id) {
730 // A cancel at the right time could remove the download from the 690 // A cancel at the right time could remove the download from the
731 // |active_downloads_| map before we get here. 691 // |active_downloads_| map before we get here.
732 if (ContainsKey(active_downloads_, download_id)) 692 if (ContainsKey(active_downloads_, download_id))
733 active_downloads_[download_id]->Cancel(true); 693 active_downloads_[download_id]->Cancel(true);
734 } 694 }
(...skipping 19 matching lines...) Expand all
754 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 714 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
755 715
756 if (!ContainsKey(active_downloads_, download_id)) 716 if (!ContainsKey(active_downloads_, download_id))
757 return; 717 return;
758 active_downloads_[download_id]->Interrupt(reason); 718 active_downloads_[download_id]->Interrupt(reason);
759 } 719 }
760 720
761 void DownloadManagerImpl::RemoveFromActiveList(DownloadItemImpl* download) { 721 void DownloadManagerImpl::RemoveFromActiveList(DownloadItemImpl* download) {
762 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 722 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
763 DCHECK(download); 723 DCHECK(download);
764 724 active_downloads_.erase(download->GetId());
765 // Clean up will happen when the history system create callback runs if we
766 // don't have a valid db_handle yet.
767 if (download->IsPersisted()) {
768 active_downloads_.erase(download->GetId());
769 if (delegate_)
770 delegate_->UpdateItemInPersistentStore(download);
771 }
772 } 725 }
773 726
774 bool DownloadManagerImpl::GenerateFileHash() { 727 bool DownloadManagerImpl::GenerateFileHash() {
775 return delegate_ && delegate_->GenerateFileHash(); 728 return delegate_ && delegate_->GenerateFileHash();
776 } 729 }
777 730
778 int DownloadManagerImpl::RemoveDownloadItems( 731 int DownloadManagerImpl::RemoveDownloadItems(
779 const DownloadItemImplVector& pending_deletes) { 732 const DownloadItemImplVector& pending_deletes) {
780 if (pending_deletes.empty()) 733 if (pending_deletes.empty())
781 return 0; 734 return 0;
782 735
783 // Delete from internal maps. 736 // Delete from internal maps.
784 for (DownloadItemImplVector::const_iterator it = pending_deletes.begin(); 737 for (DownloadItemImplVector::const_iterator it = pending_deletes.begin();
785 it != pending_deletes.end(); 738 it != pending_deletes.end();
786 ++it) { 739 ++it) {
787 DownloadItemImpl* download = *it; 740 DownloadItemImpl* download = *it;
788 DCHECK(download); 741 DCHECK(download);
789 downloads_.erase(download->GetId()); 742 int32 download_id = download->GetId();
743 delete download;
744 downloads_.erase(download_id);
790 } 745 }
791
792 // Tell observers to refresh their views.
793 NotifyModelChanged(); 746 NotifyModelChanged();
794 747 return static_cast<int>(pending_deletes.size());
795 // Delete the download items themselves.
796 const int num_deleted = static_cast<int>(pending_deletes.size());
797 STLDeleteContainerPointers(pending_deletes.begin(), pending_deletes.end());
798 return num_deleted;
799 } 748 }
800 749
801 void DownloadManagerImpl::DownloadRemoved(DownloadItemImpl* download) { 750 void DownloadManagerImpl::DownloadRemoved(DownloadItemImpl* download) {
802 if (!download || 751 if (!download ||
803 downloads_.find(download->GetId()) == downloads_.end()) 752 downloads_.find(download->GetId()) == downloads_.end())
804 return; 753 return;
805 754
806 // TODO(benjhayden,rdsmith): Remove this.
807 if (!download->IsPersisted())
808 return;
809
810 // Make history update.
811 if (delegate_)
812 delegate_->RemoveItemFromPersistentStore(download);
813
814 // Remove from our tables and delete. 755 // Remove from our tables and delete.
815 int downloads_count = 756 int downloads_count =
816 RemoveDownloadItems(DownloadItemImplVector(1, download)); 757 RemoveDownloadItems(DownloadItemImplVector(1, download));
817 DCHECK_EQ(1, downloads_count); 758 DCHECK_EQ(1, downloads_count);
818 } 759 }
819 760
820 int DownloadManagerImpl::RemoveDownloadsBetween(base::Time remove_begin, 761 int DownloadManagerImpl::RemoveDownloadsBetween(base::Time remove_begin,
821 base::Time remove_end) { 762 base::Time remove_end) {
822 if (delegate_)
823 delegate_->RemoveItemsFromPersistentStoreBetween(remove_begin, remove_end);
824
825 // All downloads visible to the user will be in the history,
826 // so scan that map.
827 DownloadItemImplVector pending_deletes; 763 DownloadItemImplVector pending_deletes;
828 for (DownloadMap::const_iterator it = downloads_.begin(); 764 for (DownloadMap::const_iterator it = downloads_.begin();
829 it != downloads_.end(); 765 it != downloads_.end();
830 ++it) { 766 ++it) {
831 DownloadItemImpl* download = it->second; 767 DownloadItemImpl* download = it->second;
832 if (download->IsPersisted() && 768 if (download->GetStartTime() >= remove_begin &&
833 download->GetStartTime() >= remove_begin &&
834 (remove_end.is_null() || download->GetStartTime() < remove_end) && 769 (remove_end.is_null() || download->GetStartTime() < remove_end) &&
835 (download->IsComplete() || download->IsCancelled())) { 770 (download->IsComplete() || download->IsCancelled())) {
836 AssertStateConsistent(download); 771 AssertStateConsistent(download);
772 download->NotifyRemoved();
837 pending_deletes.push_back(download); 773 pending_deletes.push_back(download);
838 } 774 }
839 } 775 }
840 return RemoveDownloadItems(pending_deletes); 776 return RemoveDownloadItems(pending_deletes);
841 } 777 }
842 778
843 int DownloadManagerImpl::RemoveDownloads(base::Time remove_begin) { 779 int DownloadManagerImpl::RemoveDownloads(base::Time remove_begin) {
844 return RemoveDownloadsBetween(remove_begin, base::Time()); 780 return RemoveDownloadsBetween(remove_begin, base::Time());
845 } 781 }
846 782
(...skipping 28 matching lines...) Expand all
875 } 811 }
876 812
877 // Operations posted to us from the history service ---------------------------- 813 // Operations posted to us from the history service ----------------------------
878 814
879 // The history service has retrieved all download entries. 'entries' contains 815 // The history service has retrieved all download entries. 'entries' contains
880 // 'DownloadPersistentStoreInfo's in sorted order (by ascending start_time). 816 // 'DownloadPersistentStoreInfo's in sorted order (by ascending start_time).
881 void DownloadManagerImpl::OnPersistentStoreQueryComplete( 817 void DownloadManagerImpl::OnPersistentStoreQueryComplete(
882 std::vector<DownloadPersistentStoreInfo>* entries) { 818 std::vector<DownloadPersistentStoreInfo>* entries) {
883 history_size_ = entries->size(); 819 history_size_ = entries->size();
884 for (size_t i = 0; i < entries->size(); ++i) { 820 for (size_t i = 0; i < entries->size(); ++i) {
885 int64 db_handle = entries->at(i).db_handle;
886 base::debug::Alias(&db_handle);
887
888 net::BoundNetLog bound_net_log = 821 net::BoundNetLog bound_net_log =
889 net::BoundNetLog::Make(net_log_, net::NetLog::SOURCE_DOWNLOAD); 822 net::BoundNetLog::Make(net_log_, net::NetLog::SOURCE_DOWNLOAD);
890 DownloadItemImpl* download = factory_->CreatePersistedItem( 823 DownloadItemImpl* download = factory_->CreatePersistedItem(
891 this, GetNextId(), entries->at(i), bound_net_log); 824 this, GetNextId(), entries->at(i), bound_net_log);
892 DCHECK(!ContainsKey(downloads_, download->GetId())); 825 DCHECK(!ContainsKey(downloads_, download->GetId()));
893 downloads_[download->GetId()] = download; 826 downloads_[download->GetId()] = download;
894 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadCreated(this, download)); 827 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadCreated(this, download));
895 VLOG(20) << __FUNCTION__ << "()" << i << ">" 828 VLOG(20) << __FUNCTION__ << "()" << i << ">"
896 << " download = " << download->DebugString(true); 829 << " download = " << download->DebugString(true);
897 } 830 }
898 NotifyModelChanged(); 831 NotifyModelChanged();
899 CheckForHistoryFilesRemoval(); 832 CheckForHistoryFilesRemoval();
900 } 833 }
901 834
902 void DownloadManagerImpl::AddDownloadItemToHistory(DownloadItemImpl* download,
903 int64 db_handle) {
904 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
905 DCHECK_NE(DownloadItem::kUninitializedHandle, db_handle);
906 DCHECK(!download->IsPersisted());
907 download->SetDbHandle(db_handle);
908 download->SetIsPersisted();
909
910 download_stats::RecordHistorySize(history_size_);
911 // Not counting |download|.
912 ++history_size_;
913
914 // Show in the appropriate browser UI.
915 // This includes buttons to save or cancel, for a dangerous download.
916 ShowDownloadInBrowser(download);
917
918 // Inform interested objects about the new download.
919 NotifyModelChanged();
920 }
921
922
923 void DownloadManagerImpl::OnItemAddedToPersistentStore(int32 download_id,
924 int64 db_handle) {
925 // It's valid that we don't find a matching item, i.e. on shutdown.
926 if (!ContainsKey(downloads_, download_id))
927 return;
928
929 DownloadItemImpl* item = downloads_[download_id];
930 AddDownloadItemToHistory(item, db_handle);
931 if (SavePageExternalData::Get(item)) {
932 OnSavePageItemAddedToPersistentStore(item);
933 } else {
934 OnDownloadItemAddedToPersistentStore(item);
935 }
936 }
937
938 // Once the new DownloadItem has been committed to the persistent store,
939 // associate it with its db_handle (TODO(benjhayden) merge db_handle with id),
940 // show it in the browser (TODO(benjhayden) the ui should observe us instead),
941 // and notify observers (TODO(benjhayden) observers should be able to see the
942 // item when it's created so they can observe it directly. Are there any
943 // clients that actually need to know when the item is added to the history?).
944 void DownloadManagerImpl::OnDownloadItemAddedToPersistentStore(
945 DownloadItemImpl* item) {
946 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
947 VLOG(20) << __FUNCTION__ << "()" << " db_handle = " << item->GetDbHandle()
948 << " download_id = " << item->GetId()
949 << " download = " << item->DebugString(true);
950
951 // If the download is still in progress, try to complete it.
952 //
953 // Otherwise, download has been cancelled or interrupted before we've
954 // received the DB handle. We post one final message to the history
955 // service so that it can be properly in sync with the DownloadItem's
956 // completion status, and also inform any observers so that they get
957 // more than just the start notification.
958 if (item->IsInProgress()) {
959 MaybeCompleteDownload(item);
960 } else {
961 DCHECK(item->IsCancelled());
962 active_downloads_.erase(item->GetId());
963 if (delegate_)
964 delegate_->UpdateItemInPersistentStore(item);
965 item->UpdateObservers();
966 }
967 }
968
969 void DownloadManagerImpl::ShowDownloadInBrowser(DownloadItemImpl* download) { 835 void DownloadManagerImpl::ShowDownloadInBrowser(DownloadItemImpl* download) {
970 // The 'contents' may no longer exist if the user closed the contents before 836 // The 'contents' may no longer exist if the user closed the contents before
971 // we get this start completion event. 837 // we get this start completion event.
972 WebContents* content = download->GetWebContents(); 838 WebContents* content = download->GetWebContents();
973 839
974 // If the contents no longer exists, we ask the embedder to suggest another 840 // If the contents no longer exists, we ask the embedder to suggest another
975 // contents. 841 // contents.
976 if (!content && delegate_) 842 if (!content && delegate_)
977 content = delegate_->GetAlternativeWebContentsToNotifyForDownload(); 843 content = delegate_->GetAlternativeWebContentsToNotifyForDownload();
978 844
(...skipping 12 matching lines...) Expand all
991 if (item->IsInProgress()) 857 if (item->IsInProgress())
992 ++count; 858 ++count;
993 } 859 }
994 return count; 860 return count;
995 } 861 }
996 862
997 void DownloadManagerImpl::NotifyModelChanged() { 863 void DownloadManagerImpl::NotifyModelChanged() {
998 FOR_EACH_OBSERVER(Observer, observers_, ModelChanged(this)); 864 FOR_EACH_OBSERVER(Observer, observers_, ModelChanged(this));
999 } 865 }
1000 866
867 // TODO(benjhayden): Kill this method premailing XXX occam
1001 DownloadItem* DownloadManagerImpl::GetDownloadItem(int download_id) { 868 DownloadItem* DownloadManagerImpl::GetDownloadItem(int download_id) {
1002 DownloadItem* download = GetDownload(download_id); 869 return GetDownload(download_id);
1003 return (download && download->IsPersisted()) ? download : NULL;
1004 } 870 }
1005 871
1006 DownloadItem* DownloadManagerImpl::GetDownload(int download_id) { 872 DownloadItem* DownloadManagerImpl::GetDownload(int download_id) {
1007 return ContainsKey(downloads_, download_id) ? downloads_[download_id] : NULL; 873 return ContainsKey(downloads_, download_id) ? downloads_[download_id] : NULL;
1008 } 874 }
1009 875
1010 DownloadItem* DownloadManagerImpl::GetActiveDownloadItem(int download_id) { 876 DownloadItem* DownloadManagerImpl::GetActiveDownloadItem(int download_id) {
1011 if (ContainsKey(active_downloads_, download_id)) 877 if (ContainsKey(active_downloads_, download_id))
1012 return active_downloads_[download_id]; 878 return active_downloads_[download_id];
1013 return NULL; 879 return NULL;
(...skipping 26 matching lines...) Expand all
1040 DownloadSet remainder; 906 DownloadSet remainder;
1041 std::insert_iterator<DownloadSet> insert_it(remainder, remainder.begin()); 907 std::insert_iterator<DownloadSet> insert_it(remainder, remainder.begin());
1042 std::set_difference(all_sets[i]->begin(), all_sets[i]->end(), 908 std::set_difference(all_sets[i]->begin(), all_sets[i]->end(),
1043 all_downloads.begin(), all_downloads.end(), 909 all_downloads.begin(), all_downloads.end(),
1044 insert_it); 910 insert_it);
1045 DCHECK(remainder.empty()); 911 DCHECK(remainder.empty());
1046 } 912 }
1047 #endif 913 #endif
1048 } 914 }
1049 915
1050 // SavePackage will call SavePageDownloadFinished upon completion/cancellation.
1051 // The history callback will call OnSavePageItemAddedToPersistentStore.
1052 // If the download finishes before the history callback,
1053 // OnSavePageItemAddedToPersistentStore calls SavePageDownloadFinished, ensuring
1054 // that the history event is update regardless of the order in which these two
1055 // events complete.
1056 // If something removes the download item from the download manager (Remove,
1057 // Shutdown) the result will be that the SavePage system will not be able to
1058 // properly update the download item (which no longer exists) or the download
1059 // history, but the action will complete properly anyway. This may lead to the
1060 // history entry being wrong on a reload of chrome (specifically in the case of
1061 // Initiation -> History Callback -> Removal -> Completion), but there's no way
1062 // to solve that without canceling on Remove (which would then update the DB).
1063
1064 void DownloadManagerImpl::OnSavePageItemAddedToPersistentStore(
1065 DownloadItemImpl* item) {
1066 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1067
1068 // Finalize this download if it finished before the history callback.
1069 if (!item->IsInProgress())
1070 SavePageDownloadFinished(item);
1071 }
1072
1073 void DownloadManagerImpl::SavePageDownloadFinished( 916 void DownloadManagerImpl::SavePageDownloadFinished(
1074 content::DownloadItem* download) { 917 content::DownloadItem* download) {
1075 if (download->IsPersisted()) { 918 if (download->IsComplete())
1076 if (delegate_) 919 content::NotificationService::current()->Notify(
1077 delegate_->UpdateItemInPersistentStore(download); 920 content::NOTIFICATION_SAVE_PACKAGE_SUCCESSFULLY_FINISHED,
1078 if (download->IsComplete()) 921 content::Source<DownloadManager>(this),
1079 content::NotificationService::current()->Notify( 922 content::Details<DownloadItem>(download));
1080 content::NOTIFICATION_SAVE_PACKAGE_SUCCESSFULLY_FINISHED,
1081 content::Source<DownloadManager>(this),
1082 content::Details<DownloadItem>(download));
1083 }
1084 } 923 }
1085 924
1086 void DownloadManagerImpl::DownloadOpened(DownloadItemImpl* download) { 925 void DownloadManagerImpl::DownloadOpened(DownloadItemImpl* download) {
1087 if (delegate_)
1088 delegate_->UpdateItemInPersistentStore(download);
1089 int num_unopened = 0; 926 int num_unopened = 0;
1090 for (DownloadMap::iterator it = downloads_.begin(); 927 for (DownloadMap::iterator it = downloads_.begin();
1091 it != downloads_.end(); ++it) { 928 it != downloads_.end(); ++it) {
1092 DownloadItemImpl* item = it->second; 929 DownloadItemImpl* item = it->second;
1093 if (item->IsComplete() && 930 if (item->IsComplete() &&
1094 !item->GetOpened()) 931 !item->GetOpened())
1095 ++num_unopened; 932 ++num_unopened;
1096 } 933 }
1097 download_stats::RecordOpensOutstanding(num_unopened); 934 download_stats::RecordOpensOutstanding(num_unopened);
1098 } 935 }
1099 936
937 // TODO(benjhayden) this should be a method on DI
1100 void DownloadManagerImpl::DownloadRenamedToIntermediateName( 938 void DownloadManagerImpl::DownloadRenamedToIntermediateName(
1101 DownloadItemImpl* download) { 939 DownloadItemImpl* download) {
1102 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 940 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1103 // download->GetFullPath() is only expected to be meaningful after this 941 download->UpdateObservers();
1104 // callback is received. Therefore we can now add the download to a persistent
1105 // store. If the rename failed, we receive an OnDownloadInterrupted() call
1106 // before we receive the DownloadRenamedToIntermediateName() call.
1107 if (delegate_) {
1108 delegate_->AddItemToPersistentStore(download);
1109 } else {
1110 OnItemAddedToPersistentStore(download->GetId(),
1111 DownloadItem::kUninitializedHandle);
1112 }
1113 } 942 }
1114 943
944 // TODO(benjhayden) this should be a method on DI
1115 void DownloadManagerImpl::DownloadRenamedToFinalName( 945 void DownloadManagerImpl::DownloadRenamedToFinalName(
1116 DownloadItemImpl* download) { 946 DownloadItemImpl* download) {
1117 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 947 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1118 // If the rename failed, we receive an OnDownloadInterrupted() call before we 948 // If the rename failed, we receive an OnDownloadInterrupted() call before we
1119 // receive the DownloadRenamedToFinalName() call. 949 // receive the DownloadRenamedToFinalName() call.
1120 if (delegate_) { 950 download->UpdateObservers();
1121 delegate_->UpdatePathForItemInPersistentStore(
1122 download, download->GetFullPath());
1123 }
1124 } 951 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698