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

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 14 matching lines...) Expand all
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 "webkit/glue/webkit_glue.h" 43 #include "webkit/glue/webkit_glue.h"
45 44
46 using content::BrowserThread; 45 using content::BrowserThread;
47 using content::DownloadId; 46 using content::DownloadId;
48 using content::DownloadItem; 47 using content::DownloadItem;
49 using content::DownloadPersistentStoreInfo;
50 using content::ResourceDispatcherHostImpl; 48 using content::ResourceDispatcherHostImpl;
51 using content::WebContents; 49 using content::WebContents;
52 50
53 namespace { 51 namespace {
54 52
55 // This is just used to remember which DownloadItems come from SavePage. 53 // This is just used to remember which DownloadItems come from SavePage.
56 class SavePageData : public base::SupportsUserData::Data { 54 class SavePageData : public base::SupportsUserData::Data {
57 public: 55 public:
58 // A spoonful of syntactic sugar. 56 // A spoonful of syntactic sugar.
59 static bool Get(DownloadItem* item) { 57 static bool Get(DownloadItem* item) {
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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.
479 DownloadItemImpl* item = download_iter->second;
480 item->OnDownloadTargetDetermined(
481 target_path, disposition, danger_type, intermediate_path);
482 ShowDownloadInBrowser(item);
483 NotifyModelChanged();
484 if (!SavePageData::Get(item)) {
485 MaybeCompleteDownload(item);
469 } 486 }
470 } 487 }
471 488
472 void DownloadManagerImpl::CheckForHistoryFilesRemoval() { 489 void DownloadManagerImpl::CheckForHistoryFilesRemoval() {
473 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 490 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
474 for (DownloadMap::iterator it = downloads_.begin(); 491 for (DownloadMap::iterator it = downloads_.begin();
475 it != downloads_.end(); ++it) { 492 it != downloads_.end(); ++it) {
476 DownloadItemImpl* item = it->second; 493 DownloadItemImpl* item = it->second;
477 if (item->IsPersisted()) 494 CheckForFileRemoval(item);
478 CheckForFileRemoval(item);
479 } 495 }
480 } 496 }
481 497
482 void DownloadManagerImpl::CheckForFileRemoval(DownloadItemImpl* download_item) { 498 void DownloadManagerImpl::CheckForFileRemoval(DownloadItemImpl* download_item) {
483 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 499 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
484 if (download_item->IsComplete() && 500 if (download_item->IsComplete() &&
485 !download_item->GetFileExternallyRemoved()) { 501 !download_item->GetFileExternallyRemoved()) {
486 BrowserThread::PostTask( 502 BrowserThread::PostTask(
487 BrowserThread::FILE, FROM_HERE, 503 BrowserThread::FILE, FROM_HERE,
488 base::Bind(&DownloadManagerImpl::CheckForFileRemovalOnFileThread, 504 base::Bind(&DownloadManagerImpl::CheckForFileRemovalOnFileThread,
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
536 return bound_net_log; 552 return bound_net_log;
537 } 553 }
538 554
539 DownloadItemImpl* DownloadManagerImpl::CreateSavePackageDownloadItem( 555 DownloadItemImpl* DownloadManagerImpl::CreateSavePackageDownloadItem(
540 const FilePath& main_file_path, 556 const FilePath& main_file_path,
541 const GURL& page_url, 557 const GURL& page_url,
542 const std::string& mime_type, 558 const std::string& mime_type,
543 DownloadItem::Observer* observer) { 559 DownloadItem::Observer* observer) {
544 net::BoundNetLog bound_net_log = 560 net::BoundNetLog bound_net_log =
545 net::BoundNetLog::Make(net_log_, net::NetLog::SOURCE_DOWNLOAD); 561 net::BoundNetLog::Make(net_log_, net::NetLog::SOURCE_DOWNLOAD);
546 DownloadItemImpl* download = factory_->CreateSavePageItem( 562 DownloadItemImpl* download_item = factory_->CreateSavePageItem(
547 this, 563 this,
548 main_file_path, 564 main_file_path,
549 page_url, 565 page_url,
550 GetNextId(), 566 GetNextId(),
551 mime_type, 567 mime_type,
552 bound_net_log); 568 bound_net_log);
553 569 download_item->AddObserver(observer);
554 download->AddObserver(observer); 570 DCHECK(!ContainsKey(downloads_, download_item->GetId()));
555 571 downloads_[download_item->GetId()] = download_item;
556 DCHECK(!ContainsKey(downloads_, download->GetId())); 572 DCHECK(!SavePageData::Get(download_item));
557 downloads_[download->GetId()] = download; 573 new SavePageData(download_item);
558 DCHECK(!SavePageData::Get(download)); 574 DCHECK(SavePageData::Get(download_item));
559 new SavePageData(download); 575 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadCreated(
560 DCHECK(SavePageData::Get(download)); 576 this, download_item));
561 577 OnDownloadTargetDetermined(
562 // TODO(benjhayden): Fire OnDownloadCreated for SavePackage downloads when 578 download_item->GetId(),
563 // we're comfortable with the user interacting with them. 579 main_file_path,
564 // FOR_EACH_OBSERVER(Observer, observers_, OnDownloadCreated(this, download)); 580 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
565 581 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
566 // Will notify the observer in the callback. 582 main_file_path);
567 if (delegate_) 583 return download_item;
568 delegate_->AddItemToPersistentStore(download);
569
570 return download;
571 } 584 }
572 585
573 void DownloadManagerImpl::UpdateDownload(int32 download_id, 586 void DownloadManagerImpl::UpdateDownload(int32 download_id,
574 int64 bytes_so_far, 587 int64 bytes_so_far,
575 int64 bytes_per_sec, 588 int64 bytes_per_sec,
576 const std::string& hash_state) { 589 const std::string& hash_state) {
577 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 590 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
578 DownloadMap::iterator it = active_downloads_.find(download_id); 591 DownloadMap::iterator it = active_downloads_.find(download_id);
579 if (it != active_downloads_.end()) { 592 if (it != active_downloads_.end()) {
580 DownloadItemImpl* download = it->second; 593 DownloadItemImpl* download = it->second;
581 if (download->IsInProgress()) { 594 if (download->IsInProgress()) {
582 download->UpdateProgress(bytes_so_far, bytes_per_sec, hash_state); 595 download->UpdateProgress(bytes_so_far, bytes_per_sec, hash_state);
583 if (delegate_)
584 delegate_->UpdateItemInPersistentStore(download);
585 } 596 }
586 } 597 }
587 } 598 }
588 599
589 void DownloadManagerImpl::OnResponseCompleted(int32 download_id, 600 void DownloadManagerImpl::OnResponseCompleted(int32 download_id,
590 int64 size, 601 int64 size,
591 const std::string& hash) { 602 const std::string& hash) {
592 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 603 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
593 VLOG(20) << __FUNCTION__ << "()" << " download_id = " << download_id 604 VLOG(20) << __FUNCTION__ << "()" << " download_id = " << download_id
594 << " size = " << size; 605 << " size = " << size;
595 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 606 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
596 607
597 // If it's not in active_downloads_, that means it was cancelled; just 608 // If it's not in active_downloads_, that means it was cancelled; just
598 // ignore the notification. 609 // ignore the notification.
599 if (active_downloads_.count(download_id) == 0) 610 if (active_downloads_.count(download_id) == 0)
600 return; 611 return;
601 612
602 DownloadItemImpl* download = active_downloads_[download_id]; 613 DownloadItemImpl* download = active_downloads_[download_id];
603 download->OnAllDataSaved(size, hash); 614 download->OnAllDataSaved(size, hash);
604 MaybeCompleteDownload(download); 615 MaybeCompleteDownload(download);
605 } 616 }
606 617
607 void DownloadManagerImpl::AssertStateConsistent( 618 void DownloadManagerImpl::AssertStateConsistent(
608 DownloadItemImpl* download) const { 619 DownloadItemImpl* download) const {
609 CHECK(ContainsKey(downloads_, download->GetId())); 620 CHECK(ContainsKey(downloads_, download->GetId()));
610 621
611 int64 state = download->GetState(); 622 int64 state = download->GetState();
612 base::debug::Alias(&state); 623 base::debug::Alias(&state);
613 if (ContainsKey(active_downloads_, download->GetId())) {
614 if (download->IsPersisted())
615 CHECK_EQ(DownloadItem::IN_PROGRESS, download->GetState());
616 if (DownloadItem::IN_PROGRESS != download->GetState())
617 CHECK_EQ(DownloadItem::kUninitializedHandle, download->GetDbHandle());
618 }
619 if (DownloadItem::IN_PROGRESS == download->GetState()) 624 if (DownloadItem::IN_PROGRESS == download->GetState())
620 CHECK(ContainsKey(active_downloads_, download->GetId())); 625 CHECK(ContainsKey(active_downloads_, download->GetId()));
621 } 626 }
622 627
623 bool DownloadManagerImpl::IsDownloadReadyForCompletion( 628 bool DownloadManagerImpl::IsDownloadReadyForCompletion(
624 DownloadItemImpl* download) { 629 DownloadItemImpl* download) {
625 // If we don't have all the data, the download is not ready for 630 // If we don't have all the data, the download is not ready for
626 // completion. 631 // completion.
627 if (!download->AllDataSaved()) 632 if (!download->AllDataSaved())
628 return false; 633 return false;
629 634
630 // If the download is dangerous, but not yet validated, it's not ready for 635 // If the download is dangerous, but not yet validated, it's not ready for
631 // completion. 636 // completion.
632 if (download->GetSafetyState() == DownloadItem::DANGEROUS) 637 if (download->GetSafetyState() == DownloadItem::DANGEROUS)
633 return false; 638 return false;
634 639
635 // If the download isn't active (e.g. has been cancelled) it's not 640 // If the download isn't active (e.g. has been cancelled) it's not
636 // ready for completion. 641 // ready for completion.
637 if (active_downloads_.count(download->GetId()) == 0) 642 if (active_downloads_.count(download->GetId()) == 0)
638 return false; 643 return false;
639 644
640 // If the download hasn't been inserted into the history system 645 if (download->GetTargetFilePath().DirName() !=
641 // (which occurs strictly after file name determination, intermediate 646 download->GetFullPath().DirName())
642 // file rename, and UI display) then it's not ready for completion. 647 return false;
643 if (!download->IsPersisted()) 648 if (download->GetTargetName().empty())
644 return false; 649 return false;
645 650
646 return true; 651 return true;
647 } 652 }
648 653
649 // When SavePackage downloads MHTML to GData (see 654 // When SavePackage downloads MHTML to GData (see
650 // SavePackageFilePickerChromeOS), GData calls MaybeCompleteDownload() like it 655 // SavePackageFilePickerChromeOS), GData calls MaybeCompleteDownload() like it
651 // does for non-SavePackage downloads, but SavePackage downloads never satisfy 656 // does for non-SavePackage downloads, but SavePackage downloads never satisfy
652 // IsDownloadReadyForCompletion(). GDataDownloadObserver manually calls 657 // IsDownloadReadyForCompletion(). GDataDownloadObserver manually calls
653 // DownloadItem::UpdateObservers() when the upload completes so that SavePackage 658 // DownloadItem::UpdateObservers() when the upload completes so that SavePackage
(...skipping 13 matching lines...) Expand all
667 672
668 // TODO(rdsmith): DCHECK that we only pass through this point 673 // TODO(rdsmith): DCHECK that we only pass through this point
669 // once per download. The natural way to do this is by a state 674 // once per download. The natural way to do this is by a state
670 // transition on the DownloadItem. 675 // transition on the DownloadItem.
671 676
672 // Confirm we're in the proper set of states to be here; 677 // Confirm we're in the proper set of states to be here;
673 // have all data, have a history handle, (validated or safe). 678 // have all data, have a history handle, (validated or safe).
674 DCHECK(download->IsInProgress()); 679 DCHECK(download->IsInProgress());
675 DCHECK_NE(DownloadItem::DANGEROUS, download->GetSafetyState()); 680 DCHECK_NE(DownloadItem::DANGEROUS, download->GetSafetyState());
676 DCHECK(download->AllDataSaved()); 681 DCHECK(download->AllDataSaved());
677 DCHECK(download->IsPersisted());
678 682
679 // Give the delegate a chance to override. It's ok to keep re-setting the 683 // Give the delegate a chance to override. It's ok to keep re-setting the
680 // delegate's |complete_callback| cb as long as there isn't another call-point 684 // delegate's |complete_callback| cb as long as there isn't another call-point
681 // trying to set it to a different cb. TODO(benjhayden): Change the callback 685 // trying to set it to a different cb. TODO(benjhayden): Change the callback
682 // to point directly to the item instead of |this| when DownloadItem supports 686 // to point directly to the item instead of |this| when DownloadItem supports
683 // weak-ptrs. 687 // weak-ptrs.
684 if (delegate_ && !delegate_->ShouldCompleteDownload(download, base::Bind( 688 if (delegate_ && !delegate_->ShouldCompleteDownload(download, base::Bind(
685 &DownloadManagerImpl::MaybeCompleteDownloadById, 689 &DownloadManagerImpl::MaybeCompleteDownloadById,
686 this, download->GetId()))) 690 this, download->GetId())))
687 return; 691 return;
688 692
689 VLOG(20) << __FUNCTION__ << "()" << " executing: download = " 693 VLOG(20) << __FUNCTION__ << "()" << " executing: download = "
690 << download->DebugString(false); 694 << download->DebugString(false);
691 695
692 if (delegate_)
693 delegate_->UpdateItemInPersistentStore(download);
694 download->OnDownloadCompleting(); 696 download->OnDownloadCompleting();
695 } 697 }
696 698
697 void DownloadManagerImpl::MaybeCompleteDownloadById(int download_id) { 699 void DownloadManagerImpl::MaybeCompleteDownloadById(int download_id) {
698 if (ContainsKey(active_downloads_, download_id)) 700 if (ContainsKey(active_downloads_, download_id))
699 MaybeCompleteDownload(active_downloads_[download_id]); 701 MaybeCompleteDownload(active_downloads_[download_id]);
700 } 702 }
701 703
702 void DownloadManagerImpl::DownloadCompleted(DownloadItemImpl* download) { 704 void DownloadManagerImpl::DownloadCompleted(DownloadItemImpl* download) {
703 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 705 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
704 DCHECK(download); 706 DCHECK(download);
705 if (delegate_)
706 delegate_->UpdateItemInPersistentStore(download);
707 active_downloads_.erase(download->GetId()); 707 active_downloads_.erase(download->GetId());
708 AssertStateConsistent(download); 708 AssertStateConsistent(download);
709 } 709 }
710 710
711 void DownloadManagerImpl::CancelDownload(int32 download_id) { 711 void DownloadManagerImpl::CancelDownload(int32 download_id) {
712 // A cancel at the right time could remove the download from the 712 // A cancel at the right time could remove the download from the
713 // |active_downloads_| map before we get here. 713 // |active_downloads_| map before we get here.
714 if (ContainsKey(active_downloads_, download_id)) 714 if (ContainsKey(active_downloads_, download_id))
715 active_downloads_[download_id]->Cancel(true); 715 active_downloads_[download_id]->Cancel(true);
716 } 716 }
(...skipping 19 matching lines...) Expand all
736 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 736 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
737 737
738 if (!ContainsKey(active_downloads_, download_id)) 738 if (!ContainsKey(active_downloads_, download_id))
739 return; 739 return;
740 active_downloads_[download_id]->Interrupt(reason); 740 active_downloads_[download_id]->Interrupt(reason);
741 } 741 }
742 742
743 void DownloadManagerImpl::RemoveFromActiveList(DownloadItemImpl* download) { 743 void DownloadManagerImpl::RemoveFromActiveList(DownloadItemImpl* download) {
744 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 744 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
745 DCHECK(download); 745 DCHECK(download);
746 746 active_downloads_.erase(download->GetId());
747 // Clean up will happen when the history system create callback runs if we
748 // don't have a valid db_handle yet.
749 if (download->IsPersisted()) {
750 active_downloads_.erase(download->GetId());
751 if (delegate_)
752 delegate_->UpdateItemInPersistentStore(download);
753 }
754 } 747 }
755 748
756 bool DownloadManagerImpl::GenerateFileHash() { 749 bool DownloadManagerImpl::GenerateFileHash() {
757 return delegate_ && delegate_->GenerateFileHash(); 750 return delegate_ && delegate_->GenerateFileHash();
758 } 751 }
759 752
760 int DownloadManagerImpl::RemoveDownloadItems( 753 int DownloadManagerImpl::RemoveDownloadItems(
761 const DownloadItemImplVector& pending_deletes) { 754 const DownloadItemImplVector& pending_deletes) {
762 if (pending_deletes.empty()) 755 if (pending_deletes.empty())
763 return 0; 756 return 0;
(...skipping 10 matching lines...) Expand all
774 } 767 }
775 NotifyModelChanged(); 768 NotifyModelChanged();
776 return static_cast<int>(pending_deletes.size()); 769 return static_cast<int>(pending_deletes.size());
777 } 770 }
778 771
779 void DownloadManagerImpl::DownloadRemoved(DownloadItemImpl* download) { 772 void DownloadManagerImpl::DownloadRemoved(DownloadItemImpl* download) {
780 if (!download || 773 if (!download ||
781 downloads_.find(download->GetId()) == downloads_.end()) 774 downloads_.find(download->GetId()) == downloads_.end())
782 return; 775 return;
783 776
784 // TODO(benjhayden,rdsmith): Remove this.
785 if (!download->IsPersisted())
786 return;
787
788 // Make history update.
789 if (delegate_)
790 delegate_->RemoveItemFromPersistentStore(download);
791
792 // Remove from our tables and delete. 777 // Remove from our tables and delete.
793 int downloads_count = 778 int downloads_count =
794 RemoveDownloadItems(DownloadItemImplVector(1, download)); 779 RemoveDownloadItems(DownloadItemImplVector(1, download));
795 DCHECK_EQ(1, downloads_count); 780 DCHECK_EQ(1, downloads_count);
796 } 781 }
797 782
798 int DownloadManagerImpl::RemoveDownloadsBetween(base::Time remove_begin, 783 int DownloadManagerImpl::RemoveDownloadsBetween(base::Time remove_begin,
799 base::Time remove_end) { 784 base::Time remove_end) {
800 if (delegate_)
801 delegate_->RemoveItemsFromPersistentStoreBetween(remove_begin, remove_end);
802
803 DownloadItemImplVector pending_deletes; 785 DownloadItemImplVector pending_deletes;
804 for (DownloadMap::const_iterator it = downloads_.begin(); 786 for (DownloadMap::const_iterator it = downloads_.begin();
805 it != downloads_.end(); 787 it != downloads_.end();
806 ++it) { 788 ++it) {
807 DownloadItemImpl* download = it->second; 789 DownloadItemImpl* download = it->second;
808 if (download->IsPersisted() && 790 if (download->GetStartTime() >= remove_begin &&
809 download->GetStartTime() >= remove_begin &&
810 (remove_end.is_null() || download->GetStartTime() < remove_end) && 791 (remove_end.is_null() || download->GetStartTime() < remove_end) &&
811 (download->IsComplete() || download->IsCancelled())) { 792 (download->IsComplete() || download->IsCancelled())) {
812 AssertStateConsistent(download); 793 AssertStateConsistent(download);
813 download->NotifyRemoved(); 794 download->NotifyRemoved();
814 pending_deletes.push_back(download); 795 pending_deletes.push_back(download);
815 } 796 }
816 } 797 }
817 return RemoveDownloadItems(pending_deletes); 798 return RemoveDownloadItems(pending_deletes);
818 } 799 }
819 800
(...skipping 26 matching lines...) Expand all
846 // observers. 827 // observers.
847 observer->ModelChanged(this); 828 observer->ModelChanged(this);
848 } 829 }
849 830
850 void DownloadManagerImpl::RemoveObserver(Observer* observer) { 831 void DownloadManagerImpl::RemoveObserver(Observer* observer) {
851 observers_.RemoveObserver(observer); 832 observers_.RemoveObserver(observer);
852 } 833 }
853 834
854 // Operations posted to us from the history service ---------------------------- 835 // Operations posted to us from the history service ----------------------------
855 836
856 // The history service has retrieved all download entries. 'entries' contains 837 DownloadItem* DownloadManagerImpl::CreateDownloadItem(
857 // 'DownloadPersistentStoreInfo's in sorted order (by ascending start_time). 838 const FilePath& path,
858 void DownloadManagerImpl::OnPersistentStoreQueryComplete( 839 const GURL& url,
859 std::vector<DownloadPersistentStoreInfo>* entries) { 840 const GURL& referrer_url,
860 history_size_ = entries->size(); 841 const base::Time& start_time,
861 for (size_t i = 0; i < entries->size(); ++i) { 842 const base::Time& end_time,
862 int64 db_handle = entries->at(i).db_handle; 843 int64 received_bytes,
863 base::debug::Alias(&db_handle); 844 int64 total_bytes,
864 845 DownloadItem::DownloadState state,
865 net::BoundNetLog bound_net_log = 846 bool opened) {
866 net::BoundNetLog::Make(net_log_, net::NetLog::SOURCE_DOWNLOAD); 847 DownloadItemImpl* item = factory_->CreatePersistedItem(
867 DownloadItemImpl* download = factory_->CreatePersistedItem( 848 this,
868 this, GetNextId(), entries->at(i), bound_net_log); 849 GetNextId(),
869 DCHECK(!ContainsKey(downloads_, download->GetId())); 850 path,
870 downloads_[download->GetId()] = download; 851 url,
871 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadCreated(this, download)); 852 referrer_url,
872 VLOG(20) << __FUNCTION__ << "()" << i << ">" 853 start_time,
873 << " download = " << download->DebugString(true); 854 end_time,
874 } 855 received_bytes,
856 total_bytes,
857 state,
858 opened,
859 net::BoundNetLog::Make(net_log_, net::NetLog::SOURCE_DOWNLOAD));
860 DCHECK(!ContainsKey(downloads_, item->GetId()));
861 downloads_[item->GetId()] = item;
862 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadCreated(this, item));
863 VLOG(20) << __FUNCTION__ << "() download = " << item->DebugString(true);
875 NotifyModelChanged(); 864 NotifyModelChanged();
876 CheckForHistoryFilesRemoval(); 865 return item;
877 }
878
879 void DownloadManagerImpl::AddDownloadItemToHistory(DownloadItemImpl* download,
880 int64 db_handle) {
881 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
882 DCHECK_NE(DownloadItem::kUninitializedHandle, db_handle);
883 DCHECK(!download->IsPersisted());
884 download->SetDbHandle(db_handle);
885 download->SetIsPersisted();
886
887 download_stats::RecordHistorySize(history_size_);
888 // Not counting |download|.
889 ++history_size_;
890
891 // Show in the appropriate browser UI.
892 // This includes buttons to save or cancel, for a dangerous download.
893 ShowDownloadInBrowser(download);
894
895 // Inform interested objects about the new download.
896 NotifyModelChanged();
897 }
898
899
900 void DownloadManagerImpl::OnItemAddedToPersistentStore(int32 download_id,
901 int64 db_handle) {
902 // It's valid that we don't find a matching item, i.e. on shutdown.
903 if (!ContainsKey(downloads_, download_id))
904 return;
905
906 DownloadItemImpl* item = downloads_[download_id];
907 AddDownloadItemToHistory(item, db_handle);
908 if (SavePageData::Get(item)) {
909 OnSavePageItemAddedToPersistentStore(item);
910 } else {
911 OnDownloadItemAddedToPersistentStore(item);
912 }
913 }
914
915 // Once the new DownloadItem has been committed to the persistent store,
916 // associate it with its db_handle (TODO(benjhayden) merge db_handle with id),
917 // show it in the browser (TODO(benjhayden) the ui should observe us instead),
918 // and notify observers (TODO(benjhayden) observers should be able to see the
919 // item when it's created so they can observe it directly. Are there any
920 // clients that actually need to know when the item is added to the history?).
921 void DownloadManagerImpl::OnDownloadItemAddedToPersistentStore(
922 DownloadItemImpl* item) {
923 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
924 VLOG(20) << __FUNCTION__ << "()" << " db_handle = " << item->GetDbHandle()
925 << " download_id = " << item->GetId()
926 << " download = " << item->DebugString(true);
927
928 // If the download is still in progress, try to complete it.
929 //
930 // Otherwise, download has been cancelled or interrupted before we've
931 // received the DB handle. We post one final message to the history
932 // service so that it can be properly in sync with the DownloadItem's
933 // completion status, and also inform any observers so that they get
934 // more than just the start notification.
935 if (item->IsInProgress()) {
936 MaybeCompleteDownload(item);
937 } else {
938 DCHECK(item->IsCancelled());
939 active_downloads_.erase(item->GetId());
940 if (delegate_)
941 delegate_->UpdateItemInPersistentStore(item);
942 item->UpdateObservers();
943 }
944 } 866 }
945 867
946 void DownloadManagerImpl::ShowDownloadInBrowser(DownloadItemImpl* download) { 868 void DownloadManagerImpl::ShowDownloadInBrowser(DownloadItemImpl* download) {
947 // The 'contents' may no longer exist if the user closed the contents before 869 // The 'contents' may no longer exist if the user closed the contents before
948 // we get this start completion event. 870 // we get this start completion event.
949 WebContents* content = download->GetWebContents(); 871 WebContents* content = download->GetWebContents();
950 872
951 // If the contents no longer exists, we ask the embedder to suggest another 873 // If the contents no longer exists, we ask the embedder to suggest another
952 // contents. 874 // contents.
953 if (!content && delegate_) 875 if (!content && delegate_)
(...skipping 15 matching lines...) Expand all
969 ++count; 891 ++count;
970 } 892 }
971 return count; 893 return count;
972 } 894 }
973 895
974 void DownloadManagerImpl::NotifyModelChanged() { 896 void DownloadManagerImpl::NotifyModelChanged() {
975 FOR_EACH_OBSERVER(Observer, observers_, ModelChanged(this)); 897 FOR_EACH_OBSERVER(Observer, observers_, ModelChanged(this));
976 } 898 }
977 899
978 DownloadItem* DownloadManagerImpl::GetDownloadItem(int download_id) { 900 DownloadItem* DownloadManagerImpl::GetDownloadItem(int download_id) {
979 DownloadItem* download = GetDownload(download_id); 901 return GetDownload(download_id);
980 return (download && download->IsPersisted()) ? download : NULL;
981 } 902 }
982 903
983 DownloadItem* DownloadManagerImpl::GetDownload(int download_id) { 904 DownloadItem* DownloadManagerImpl::GetDownload(int download_id) {
984 return ContainsKey(downloads_, download_id) ? downloads_[download_id] : NULL; 905 return ContainsKey(downloads_, download_id) ? downloads_[download_id] : NULL;
985 } 906 }
986 907
987 DownloadItem* DownloadManagerImpl::GetActiveDownloadItem(int download_id) { 908 DownloadItem* DownloadManagerImpl::GetActiveDownloadItem(int download_id) {
988 if (ContainsKey(active_downloads_, download_id)) 909 if (ContainsKey(active_downloads_, download_id))
989 return active_downloads_[download_id]; 910 return active_downloads_[download_id];
990 return NULL; 911 return NULL;
(...skipping 26 matching lines...) Expand all
1017 DownloadSet remainder; 938 DownloadSet remainder;
1018 std::insert_iterator<DownloadSet> insert_it(remainder, remainder.begin()); 939 std::insert_iterator<DownloadSet> insert_it(remainder, remainder.begin());
1019 std::set_difference(all_sets[i]->begin(), all_sets[i]->end(), 940 std::set_difference(all_sets[i]->begin(), all_sets[i]->end(),
1020 all_downloads.begin(), all_downloads.end(), 941 all_downloads.begin(), all_downloads.end(),
1021 insert_it); 942 insert_it);
1022 DCHECK(remainder.empty()); 943 DCHECK(remainder.empty());
1023 } 944 }
1024 #endif 945 #endif
1025 } 946 }
1026 947
1027 // SavePackage will call SavePageDownloadFinished upon completion/cancellation.
1028 // The history callback will call OnSavePageItemAddedToPersistentStore.
1029 // If the download finishes before the history callback,
1030 // OnSavePageItemAddedToPersistentStore calls SavePageDownloadFinished, ensuring
1031 // that the history event is update regardless of the order in which these two
1032 // events complete.
1033 // If something removes the download item from the download manager (Remove,
1034 // Shutdown) the result will be that the SavePage system will not be able to
1035 // properly update the download item (which no longer exists) or the download
1036 // history, but the action will complete properly anyway. This may lead to the
1037 // history entry being wrong on a reload of chrome (specifically in the case of
1038 // Initiation -> History Callback -> Removal -> Completion), but there's no way
1039 // to solve that without canceling on Remove (which would then update the DB).
1040
1041 void DownloadManagerImpl::OnSavePageItemAddedToPersistentStore(
1042 DownloadItemImpl* item) {
1043 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1044
1045 // Finalize this download if it finished before the history callback.
1046 if (!item->IsInProgress())
1047 SavePageDownloadFinished(item);
1048 }
1049
1050 void DownloadManagerImpl::SavePageDownloadFinished( 948 void DownloadManagerImpl::SavePageDownloadFinished(
1051 content::DownloadItem* download) { 949 content::DownloadItem* download) {
1052 if (download->IsPersisted()) { 950 if (download->IsComplete())
1053 if (delegate_) 951 content::NotificationService::current()->Notify(
1054 delegate_->UpdateItemInPersistentStore(download); 952 content::NOTIFICATION_SAVE_PACKAGE_SUCCESSFULLY_FINISHED,
1055 if (download->IsComplete()) 953 content::Source<DownloadManager>(this),
1056 content::NotificationService::current()->Notify( 954 content::Details<DownloadItem>(download));
1057 content::NOTIFICATION_SAVE_PACKAGE_SUCCESSFULLY_FINISHED,
1058 content::Source<DownloadManager>(this),
1059 content::Details<DownloadItem>(download));
1060 }
1061 } 955 }
1062 956
1063 void DownloadManagerImpl::DownloadOpened(DownloadItemImpl* download) { 957 void DownloadManagerImpl::DownloadOpened(DownloadItemImpl* download) {
1064 if (delegate_)
1065 delegate_->UpdateItemInPersistentStore(download);
1066 int num_unopened = 0; 958 int num_unopened = 0;
1067 for (DownloadMap::iterator it = downloads_.begin(); 959 for (DownloadMap::iterator it = downloads_.begin();
1068 it != downloads_.end(); ++it) { 960 it != downloads_.end(); ++it) {
1069 DownloadItemImpl* item = it->second; 961 DownloadItemImpl* item = it->second;
1070 if (item->IsComplete() && 962 if (item->IsComplete() &&
1071 !item->GetOpened()) 963 !item->GetOpened())
1072 ++num_unopened; 964 ++num_unopened;
1073 } 965 }
1074 download_stats::RecordOpensOutstanding(num_unopened); 966 download_stats::RecordOpensOutstanding(num_unopened);
1075 } 967 }
1076 968
969 // TODO(benjhayden) this should be a method on DI
1077 void DownloadManagerImpl::DownloadRenamedToIntermediateName( 970 void DownloadManagerImpl::DownloadRenamedToIntermediateName(
1078 DownloadItemImpl* download) { 971 DownloadItemImpl* download) {
1079 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 972 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1080 // download->GetFullPath() is only expected to be meaningful after this 973 download->UpdateObservers();
1081 // callback is received. Therefore we can now add the download to a persistent 974 MaybeCompleteDownload(download);
1082 // store. If the rename failed, we receive an OnDownloadInterrupted() call
1083 // before we receive the DownloadRenamedToIntermediateName() call.
1084 if (delegate_) {
1085 delegate_->AddItemToPersistentStore(download);
1086 } else {
1087 OnItemAddedToPersistentStore(download->GetId(),
1088 DownloadItem::kUninitializedHandle);
1089 }
1090 } 975 }
1091 976
977 // TODO(benjhayden) this should be a method on DI
1092 void DownloadManagerImpl::DownloadRenamedToFinalName( 978 void DownloadManagerImpl::DownloadRenamedToFinalName(
1093 DownloadItemImpl* download) { 979 DownloadItemImpl* download) {
1094 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 980 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1095 // If the rename failed, we receive an OnDownloadInterrupted() call before we 981 // If the rename failed, we receive an OnDownloadInterrupted() call before we
1096 // receive the DownloadRenamedToFinalName() call. 982 // receive the DownloadRenamedToFinalName() call.
1097 if (delegate_) { 983 download->UpdateObservers();
1098 delegate_->UpdatePathForItemInPersistentStore(
1099 download, download->GetFullPath());
1100 }
1101 } 984 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698