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

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

Issue 10915180: Make DownloadHistory observe manager, items (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 8 years, 3 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 "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
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::SearchDownloads(const string16& query, 352 void DownloadManagerImpl::SearchDownloads(const string16& query,
337 DownloadVector* result) { 353 DownloadVector* result) {
338 string16 query_lower(base::i18n::ToLower(query)); 354 string16 query_lower(base::i18n::ToLower(query));
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* download_item = it->second; 358 DownloadItemImpl* download_item = it->second;
343 // TODO(benjhayden): Don't check IsPersisted().
344 if (!download_item->IsTemporary() && 359 if (!download_item->IsTemporary() &&
345 download_item->IsPersisted() &&
346 download_item->MatchesQuery(query_lower)) { 360 download_item->MatchesQuery(query_lower)) {
347 result->push_back(download_item); 361 result->push_back(download_item);
348 } 362 }
349 } 363 }
350 } 364 }
351 365
352 bool DownloadManagerImpl::Init(content::BrowserContext* browser_context) { 366 bool DownloadManagerImpl::Init(content::BrowserContext* browser_context) {
353 DCHECK(browser_context); 367 DCHECK(browser_context);
354 DCHECK(!shutdown_needed_) << "DownloadManager already initialized."; 368 DCHECK(!shutdown_needed_) << "DownloadManager already initialized.";
355 shutdown_needed_ = true; 369 shutdown_needed_ = true;
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
419 } 433 }
420 } 434 }
421 435
422 void DownloadManagerImpl::OnDownloadTargetDetermined( 436 void DownloadManagerImpl::OnDownloadTargetDetermined(
423 int32 download_id, 437 int32 download_id,
424 const FilePath& target_path, 438 const FilePath& target_path,
425 DownloadItem::TargetDisposition disposition, 439 DownloadItem::TargetDisposition disposition,
426 content::DownloadDangerType danger_type, 440 content::DownloadDangerType danger_type,
427 const FilePath& intermediate_path) { 441 const FilePath& intermediate_path) {
428 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 442 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
429 DownloadMap::iterator download_iter = active_downloads_.find(download_id); 443 DownloadMap::iterator download_iter = downloads_.find(download_id);
430 if (download_iter != active_downloads_.end()) { 444 if (download_iter == downloads_.end())
431 // Once DownloadItem::OnDownloadTargetDetermined() is called, we expect a 445 return;
432 // DownloadRenamedToIntermediateName() callback. This is necessary for the 446
433 // download to proceed. 447 // Once DownloadItem::OnDownloadTargetDetermined() is called, we expect a
434 download_iter->second->OnDownloadTargetDetermined( 448 // DownloadRenamedToIntermediateName() callback. This is necessary for the
435 target_path, disposition, danger_type, intermediate_path); 449 // download to proceed.
436 } 450 DownloadItemImpl* item = download_iter->second;
451 item->OnDownloadTargetDetermined(
452 target_path, disposition, danger_type, intermediate_path);
453 ShowDownloadInBrowser(item);
454 NotifyModelChanged();
437 } 455 }
438 456
439 void DownloadManagerImpl::CheckForHistoryFilesRemoval() { 457 void DownloadManagerImpl::CheckForHistoryFilesRemoval() {
440 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 458 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
441 for (DownloadMap::iterator it = downloads_.begin(); 459 for (DownloadMap::iterator it = downloads_.begin();
442 it != downloads_.end(); ++it) { 460 it != downloads_.end(); ++it) {
443 DownloadItemImpl* item = it->second; 461 DownloadItemImpl* item = it->second;
444 if (item->IsPersisted()) 462 CheckForFileRemoval(item);
445 CheckForFileRemoval(item);
446 } 463 }
447 } 464 }
448 465
449 void DownloadManagerImpl::CheckForFileRemoval(DownloadItemImpl* download_item) { 466 void DownloadManagerImpl::CheckForFileRemoval(DownloadItemImpl* download_item) {
450 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 467 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
451 if (download_item->IsComplete() && 468 if (download_item->IsComplete() &&
452 !download_item->GetFileExternallyRemoved()) { 469 !download_item->GetFileExternallyRemoved()) {
453 BrowserThread::PostTask( 470 BrowserThread::PostTask(
454 BrowserThread::FILE, FROM_HERE, 471 BrowserThread::FILE, FROM_HERE,
455 base::Bind(&DownloadManagerImpl::CheckForFileRemovalOnFileThread, 472 base::Bind(&DownloadManagerImpl::CheckForFileRemovalOnFileThread,
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
503 return bound_net_log; 520 return bound_net_log;
504 } 521 }
505 522
506 DownloadItemImpl* DownloadManagerImpl::CreateSavePackageDownloadItem( 523 DownloadItemImpl* DownloadManagerImpl::CreateSavePackageDownloadItem(
507 const FilePath& main_file_path, 524 const FilePath& main_file_path,
508 const GURL& page_url, 525 const GURL& page_url,
509 const std::string& mime_type, 526 const std::string& mime_type,
510 DownloadItem::Observer* observer) { 527 DownloadItem::Observer* observer) {
511 net::BoundNetLog bound_net_log = 528 net::BoundNetLog bound_net_log =
512 net::BoundNetLog::Make(net_log_, net::NetLog::SOURCE_DOWNLOAD); 529 net::BoundNetLog::Make(net_log_, net::NetLog::SOURCE_DOWNLOAD);
513 DownloadItemImpl* download = factory_->CreateSavePageItem( 530 DownloadItemImpl* download_item = factory_->CreateSavePageItem(
514 this, 531 this,
515 main_file_path, 532 main_file_path,
516 page_url, 533 page_url,
517 GetNextId(), 534 GetNextId(),
518 mime_type, 535 mime_type,
519 bound_net_log); 536 bound_net_log);
520 537 download_item->AddObserver(observer);
521 download->AddObserver(observer); 538 DCHECK(!ContainsKey(downloads_, download_item->GetId()));
522 539 downloads_[download_item->GetId()] = download_item;
523 DCHECK(!ContainsKey(downloads_, download->GetId())); 540 DCHECK(!SavePageData::Get(download_item));
524 downloads_[download->GetId()] = download; 541 new SavePageData(download_item);
525 DCHECK(!SavePageData::Get(download)); 542 DCHECK(SavePageData::Get(download_item));
526 new SavePageData(download); 543 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadCreated(
527 DCHECK(SavePageData::Get(download)); 544 this, download_item));
528 545 OnDownloadTargetDetermined(
529 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadCreated(this, download)); 546 download_item->GetId(),
530 547 main_file_path,
531 // Will notify the observer in the callback. 548 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
532 if (delegate_) 549 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
533 delegate_->AddItemToPersistentStore(download); 550 main_file_path);
534 551 return download_item;
535 return download;
536 } 552 }
537 553
538 void DownloadManagerImpl::UpdateDownload(int32 download_id, 554 void DownloadManagerImpl::UpdateDownload(int32 download_id,
539 int64 bytes_so_far, 555 int64 bytes_so_far,
540 int64 bytes_per_sec, 556 int64 bytes_per_sec,
541 const std::string& hash_state) { 557 const std::string& hash_state) {
542 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 558 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
543 DownloadMap::iterator it = active_downloads_.find(download_id); 559 DownloadMap::iterator it = active_downloads_.find(download_id);
544 if (it != active_downloads_.end()) { 560 if (it != active_downloads_.end()) {
545 DownloadItemImpl* download = it->second; 561 DownloadItemImpl* download = it->second;
546 if (download->IsInProgress()) { 562 if (download->IsInProgress()) {
547 download->UpdateProgress(bytes_so_far, bytes_per_sec, hash_state); 563 download->UpdateProgress(bytes_so_far, bytes_per_sec, hash_state);
548 if (delegate_)
549 delegate_->UpdateItemInPersistentStore(download);
550 } 564 }
551 } 565 }
552 } 566 }
553 567
554 void DownloadManagerImpl::OnResponseCompleted(int32 download_id, 568 void DownloadManagerImpl::OnResponseCompleted(int32 download_id,
555 int64 size, 569 int64 size,
556 const std::string& hash) { 570 const std::string& hash) {
557 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 571 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
558 VLOG(20) << __FUNCTION__ << "()" << " download_id = " << download_id 572 VLOG(20) << __FUNCTION__ << "()" << " download_id = " << download_id
559 << " size = " << size; 573 << " size = " << size;
560 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 574 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
561 575
562 // If it's not in active_downloads_, that means it was cancelled; just 576 // If it's not in active_downloads_, that means it was cancelled; just
563 // ignore the notification. 577 // ignore the notification.
564 if (active_downloads_.count(download_id) == 0) 578 if (active_downloads_.count(download_id) == 0)
565 return; 579 return;
566 580
567 DownloadItemImpl* download = active_downloads_[download_id]; 581 DownloadItemImpl* download = active_downloads_[download_id];
568 download->OnAllDataSaved(size, hash); 582 download->OnAllDataSaved(size, hash);
569 MaybeCompleteDownload(download); 583 MaybeCompleteDownload(download);
570 } 584 }
571 585
572 void DownloadManagerImpl::AssertStateConsistent( 586 void DownloadManagerImpl::AssertStateConsistent(
573 DownloadItemImpl* download) const { 587 DownloadItemImpl* download) const {
574 CHECK(ContainsKey(downloads_, download->GetId())); 588 CHECK(ContainsKey(downloads_, download->GetId()));
575 589
576 int64 state = download->GetState(); 590 int64 state = download->GetState();
577 base::debug::Alias(&state); 591 base::debug::Alias(&state);
578 if (ContainsKey(active_downloads_, download->GetId())) {
579 if (download->IsPersisted())
580 CHECK_EQ(DownloadItem::IN_PROGRESS, download->GetState());
581 if (DownloadItem::IN_PROGRESS != download->GetState())
582 CHECK_EQ(DownloadItem::kUninitializedHandle, download->GetDbHandle());
583 }
584 if (DownloadItem::IN_PROGRESS == download->GetState()) 592 if (DownloadItem::IN_PROGRESS == download->GetState())
585 CHECK(ContainsKey(active_downloads_, download->GetId())); 593 CHECK(ContainsKey(active_downloads_, download->GetId()));
586 } 594 }
587 595
588 bool DownloadManagerImpl::IsDownloadReadyForCompletion( 596 bool DownloadManagerImpl::IsDownloadReadyForCompletion(
589 DownloadItemImpl* download) { 597 DownloadItemImpl* download) {
590 // If we don't have all the data, the download is not ready for 598 // If we don't have all the data, the download is not ready for
591 // completion. 599 // completion.
592 if (!download->AllDataSaved()) 600 if (!download->AllDataSaved())
593 return false; 601 return false;
594 602
595 // If the download is dangerous, but not yet validated, it's not ready for 603 // If the download is dangerous, but not yet validated, it's not ready for
596 // completion. 604 // completion.
597 if (download->GetSafetyState() == DownloadItem::DANGEROUS) 605 if (download->GetSafetyState() == DownloadItem::DANGEROUS)
598 return false; 606 return false;
599 607
600 // If the download isn't active (e.g. has been cancelled) it's not 608 // If the download isn't active (e.g. has been cancelled) it's not
601 // ready for completion. 609 // ready for completion.
602 if (active_downloads_.count(download->GetId()) == 0) 610 if (active_downloads_.count(download->GetId()) == 0)
603 return false; 611 return false;
604 612
605 // If the download hasn't been inserted into the history system 613 // If the intermediate filename rename hasn't occurred, don't complete the
606 // (which occurs strictly after file name determination, intermediate 614 // download.
607 // file rename, and UI display) then it's not ready for completion. 615 if (download->GetTargetFilePath().DirName() !=
608 if (!download->IsPersisted()) 616 download->GetFullPath().DirName())
617 return false;
618
619 // If the target filename hasn't been determined, don't complete the download.
Randy Smith (Not in Mondays) 2012/09/13 19:53:19 So this is an example of the issue we were talking
benjhayden 2012/09/21 20:45:46 Can I let you fix this when you put DownloadItem i
Randy Smith (Not in Mondays) 2012/09/24 18:03:25 Is there a reason why you can't just check to see
benjhayden 2012/11/02 17:21:36 This method moved into DII. I added comments there
Randy Smith (Not in Mondays) 2012/11/02 23:31:24 I'm ok with putting in a new state in another CL,
benjhayden 2012/11/06 20:01:13 I seem to remember that there is a rare case where
620 if (download->GetTargetName().empty())
609 return false; 621 return false;
610 622
611 return true; 623 return true;
612 } 624 }
613 625
614 // When SavePackage downloads MHTML to GData (see 626 // When SavePackage downloads MHTML to GData (see
615 // SavePackageFilePickerChromeOS), GData calls MaybeCompleteDownload() like it 627 // SavePackageFilePickerChromeOS), GData calls MaybeCompleteDownload() like it
616 // does for non-SavePackage downloads, but SavePackage downloads never satisfy 628 // does for non-SavePackage downloads, but SavePackage downloads never satisfy
617 // IsDownloadReadyForCompletion(). GDataDownloadObserver manually calls 629 // IsDownloadReadyForCompletion(). GDataDownloadObserver manually calls
618 // DownloadItem::UpdateObservers() when the upload completes so that SavePackage 630 // DownloadItem::UpdateObservers() when the upload completes so that SavePackage
(...skipping 13 matching lines...) Expand all
632 644
633 // TODO(rdsmith): DCHECK that we only pass through this point 645 // TODO(rdsmith): DCHECK that we only pass through this point
634 // once per download. The natural way to do this is by a state 646 // once per download. The natural way to do this is by a state
635 // transition on the DownloadItem. 647 // transition on the DownloadItem.
636 648
637 // Confirm we're in the proper set of states to be here; 649 // Confirm we're in the proper set of states to be here;
638 // have all data, have a history handle, (validated or safe). 650 // have all data, have a history handle, (validated or safe).
639 DCHECK(download->IsInProgress()); 651 DCHECK(download->IsInProgress());
640 DCHECK_NE(DownloadItem::DANGEROUS, download->GetSafetyState()); 652 DCHECK_NE(DownloadItem::DANGEROUS, download->GetSafetyState());
641 DCHECK(download->AllDataSaved()); 653 DCHECK(download->AllDataSaved());
642 DCHECK(download->IsPersisted());
643 654
644 // Give the delegate a chance to override. It's ok to keep re-setting the 655 // Give the delegate a chance to override. It's ok to keep re-setting the
645 // delegate's |complete_callback| cb as long as there isn't another call-point 656 // delegate's |complete_callback| cb as long as there isn't another call-point
646 // trying to set it to a different cb. TODO(benjhayden): Change the callback 657 // trying to set it to a different cb. TODO(benjhayden): Change the callback
647 // to point directly to the item instead of |this| when DownloadItem supports 658 // to point directly to the item instead of |this| when DownloadItem supports
648 // weak-ptrs. 659 // weak-ptrs.
649 if (delegate_ && !delegate_->ShouldCompleteDownload(download, base::Bind( 660 if (delegate_ && !delegate_->ShouldCompleteDownload(download, base::Bind(
650 &DownloadManagerImpl::MaybeCompleteDownloadById, 661 &DownloadManagerImpl::MaybeCompleteDownloadById,
651 this, download->GetId()))) 662 this, download->GetId())))
652 return; 663 return;
653 664
654 VLOG(20) << __FUNCTION__ << "()" << " executing: download = " 665 VLOG(20) << __FUNCTION__ << "()" << " executing: download = "
655 << download->DebugString(false); 666 << download->DebugString(false);
656 667
657 if (delegate_)
658 delegate_->UpdateItemInPersistentStore(download);
659 download->OnDownloadCompleting(); 668 download->OnDownloadCompleting();
660 } 669 }
661 670
662 void DownloadManagerImpl::MaybeCompleteDownloadById(int download_id) { 671 void DownloadManagerImpl::MaybeCompleteDownloadById(int download_id) {
663 if (ContainsKey(active_downloads_, download_id)) 672 if (ContainsKey(active_downloads_, download_id))
664 MaybeCompleteDownload(active_downloads_[download_id]); 673 MaybeCompleteDownload(active_downloads_[download_id]);
665 } 674 }
666 675
667 void DownloadManagerImpl::DownloadCompleted(DownloadItemImpl* download) { 676 void DownloadManagerImpl::DownloadCompleted(DownloadItemImpl* download) {
668 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 677 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
669 DCHECK(download); 678 DCHECK(download);
670 if (delegate_)
671 delegate_->UpdateItemInPersistentStore(download);
672 active_downloads_.erase(download->GetId()); 679 active_downloads_.erase(download->GetId());
673 AssertStateConsistent(download); 680 AssertStateConsistent(download);
674 } 681 }
675 682
676 void DownloadManagerImpl::CancelDownload(int32 download_id) { 683 void DownloadManagerImpl::CancelDownload(int32 download_id) {
677 // A cancel at the right time could remove the download from the 684 // A cancel at the right time could remove the download from the
678 // |active_downloads_| map before we get here. 685 // |active_downloads_| map before we get here.
679 if (ContainsKey(active_downloads_, download_id)) 686 if (ContainsKey(active_downloads_, download_id))
680 active_downloads_[download_id]->Cancel(true); 687 active_downloads_[download_id]->Cancel(true);
681 } 688 }
(...skipping 19 matching lines...) Expand all
701 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 708 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
702 709
703 if (!ContainsKey(active_downloads_, download_id)) 710 if (!ContainsKey(active_downloads_, download_id))
704 return; 711 return;
705 active_downloads_[download_id]->Interrupt(reason); 712 active_downloads_[download_id]->Interrupt(reason);
706 } 713 }
707 714
708 void DownloadManagerImpl::RemoveFromActiveList(DownloadItemImpl* download) { 715 void DownloadManagerImpl::RemoveFromActiveList(DownloadItemImpl* download) {
709 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 716 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
710 DCHECK(download); 717 DCHECK(download);
711 718 active_downloads_.erase(download->GetId());
712 // Clean up will happen when the history system create callback runs if we
713 // don't have a valid db_handle yet.
714 if (download->IsPersisted()) {
715 active_downloads_.erase(download->GetId());
716 if (delegate_)
717 delegate_->UpdateItemInPersistentStore(download);
718 }
719 } 719 }
720 720
721 int DownloadManagerImpl::RemoveDownloadItems( 721 int DownloadManagerImpl::RemoveDownloadItems(
722 const DownloadItemImplVector& pending_deletes) { 722 const DownloadItemImplVector& pending_deletes) {
723 if (pending_deletes.empty()) 723 if (pending_deletes.empty())
724 return 0; 724 return 0;
725 725
726 // Delete from internal maps. 726 // Delete from internal maps.
727 for (DownloadItemImplVector::const_iterator it = pending_deletes.begin(); 727 for (DownloadItemImplVector::const_iterator it = pending_deletes.begin();
728 it != pending_deletes.end(); 728 it != pending_deletes.end();
729 ++it) { 729 ++it) {
730 DownloadItemImpl* download = *it; 730 DownloadItemImpl* download = *it;
731 DCHECK(download); 731 DCHECK(download);
732 int32 download_id = download->GetId(); 732 int32 download_id = download->GetId();
733 delete download; 733 delete download;
734 downloads_.erase(download_id); 734 downloads_.erase(download_id);
735 } 735 }
736 NotifyModelChanged(); 736 NotifyModelChanged();
737 return static_cast<int>(pending_deletes.size()); 737 return static_cast<int>(pending_deletes.size());
738 } 738 }
739 739
740 void DownloadManagerImpl::DownloadRemoved(DownloadItemImpl* download) { 740 void DownloadManagerImpl::DownloadRemoved(DownloadItemImpl* download) {
741 if (!download || 741 if (!download ||
742 downloads_.find(download->GetId()) == downloads_.end()) 742 downloads_.find(download->GetId()) == downloads_.end())
743 return; 743 return;
744 744
745 // TODO(benjhayden,rdsmith): Remove this.
746 if (!download->IsPersisted())
747 return;
748
749 // Make history update.
750 if (delegate_)
751 delegate_->RemoveItemFromPersistentStore(download);
752
753 // Remove from our tables and delete. 745 // Remove from our tables and delete.
754 int downloads_count = 746 int downloads_count =
755 RemoveDownloadItems(DownloadItemImplVector(1, download)); 747 RemoveDownloadItems(DownloadItemImplVector(1, download));
756 DCHECK_EQ(1, downloads_count); 748 DCHECK_EQ(1, downloads_count);
757 } 749 }
758 750
759 int DownloadManagerImpl::RemoveDownloadsBetween(base::Time remove_begin, 751 int DownloadManagerImpl::RemoveDownloadsBetween(base::Time remove_begin,
760 base::Time remove_end) { 752 base::Time remove_end) {
761 if (delegate_)
762 delegate_->RemoveItemsFromPersistentStoreBetween(remove_begin, remove_end);
763
764 DownloadItemImplVector pending_deletes; 753 DownloadItemImplVector pending_deletes;
765 for (DownloadMap::const_iterator it = downloads_.begin(); 754 for (DownloadMap::const_iterator it = downloads_.begin();
766 it != downloads_.end(); 755 it != downloads_.end();
767 ++it) { 756 ++it) {
768 DownloadItemImpl* download = it->second; 757 DownloadItemImpl* download = it->second;
769 if (download->IsPersisted() && 758 if (download->GetStartTime() >= remove_begin &&
770 download->GetStartTime() >= remove_begin &&
771 (remove_end.is_null() || download->GetStartTime() < remove_end) && 759 (remove_end.is_null() || download->GetStartTime() < remove_end) &&
772 (download->IsComplete() || download->IsCancelled())) { 760 (download->IsComplete() || download->IsCancelled())) {
773 AssertStateConsistent(download); 761 AssertStateConsistent(download);
774 download->NotifyRemoved(); 762 download->NotifyRemoved();
775 pending_deletes.push_back(download); 763 pending_deletes.push_back(download);
776 } 764 }
777 } 765 }
778 return RemoveDownloadItems(pending_deletes); 766 return RemoveDownloadItems(pending_deletes);
779 } 767 }
780 768
(...skipping 26 matching lines...) Expand all
807 // observers. 795 // observers.
808 observer->ModelChanged(this); 796 observer->ModelChanged(this);
809 } 797 }
810 798
811 void DownloadManagerImpl::RemoveObserver(Observer* observer) { 799 void DownloadManagerImpl::RemoveObserver(Observer* observer) {
812 observers_.RemoveObserver(observer); 800 observers_.RemoveObserver(observer);
813 } 801 }
814 802
815 // Operations posted to us from the history service ---------------------------- 803 // Operations posted to us from the history service ----------------------------
816 804
817 // The history service has retrieved all download entries. 'entries' contains 805 DownloadItem* DownloadManagerImpl::CreateDownloadItem(
818 // 'DownloadPersistentStoreInfo's in sorted order (by ascending start_time). 806 const FilePath& path,
819 void DownloadManagerImpl::OnPersistentStoreQueryComplete( 807 const GURL& url,
820 std::vector<DownloadPersistentStoreInfo>* entries) { 808 const GURL& referrer_url,
821 history_size_ = entries->size(); 809 const base::Time& start_time,
822 for (size_t i = 0; i < entries->size(); ++i) { 810 const base::Time& end_time,
823 int64 db_handle = entries->at(i).db_handle; 811 int64 received_bytes,
824 base::debug::Alias(&db_handle); 812 int64 total_bytes,
825 813 DownloadItem::DownloadState state,
826 net::BoundNetLog bound_net_log = 814 bool opened) {
827 net::BoundNetLog::Make(net_log_, net::NetLog::SOURCE_DOWNLOAD); 815 DownloadItemImpl* item = factory_->CreatePersistedItem(
828 DownloadItemImpl* download = factory_->CreatePersistedItem( 816 this,
829 this, GetNextId(), entries->at(i), bound_net_log); 817 GetNextId(),
830 DCHECK(!ContainsKey(downloads_, download->GetId())); 818 path,
831 downloads_[download->GetId()] = download; 819 url,
832 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadCreated(this, download)); 820 referrer_url,
833 VLOG(20) << __FUNCTION__ << "()" << i << ">" 821 start_time,
834 << " download = " << download->DebugString(true); 822 end_time,
835 } 823 received_bytes,
824 total_bytes,
825 state,
826 opened,
827 net::BoundNetLog::Make(net_log_, net::NetLog::SOURCE_DOWNLOAD));
828 DCHECK(!ContainsKey(downloads_, item->GetId()));
829 downloads_[item->GetId()] = item;
830 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadCreated(this, item));
831 VLOG(20) << __FUNCTION__ << "() download = " << item->DebugString(true);
836 NotifyModelChanged(); 832 NotifyModelChanged();
837 CheckForHistoryFilesRemoval(); 833 return item;
838 }
839
840 void DownloadManagerImpl::AddDownloadItemToHistory(DownloadItemImpl* download,
841 int64 db_handle) {
842 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
843 DCHECK_NE(DownloadItem::kUninitializedHandle, db_handle);
844 DCHECK(!download->IsPersisted());
845 download->SetDbHandle(db_handle);
846 download->SetIsPersisted();
847
848 download_stats::RecordHistorySize(history_size_);
849 // Not counting |download|.
850 ++history_size_;
851
852 // Show in the appropriate browser UI.
853 // This includes buttons to save or cancel, for a dangerous download.
854 ShowDownloadInBrowser(download);
855
856 // Inform interested objects about the new download.
857 NotifyModelChanged();
858 }
859
860
861 void DownloadManagerImpl::OnItemAddedToPersistentStore(int32 download_id,
862 int64 db_handle) {
863 // It's valid that we don't find a matching item, i.e. on shutdown.
864 if (!ContainsKey(downloads_, download_id))
865 return;
866
867 DownloadItemImpl* item = downloads_[download_id];
868 AddDownloadItemToHistory(item, db_handle);
869 if (SavePageData::Get(item)) {
870 OnSavePageItemAddedToPersistentStore(item);
871 } else {
872 OnDownloadItemAddedToPersistentStore(item);
873 }
874 }
875
876 // Once the new DownloadItem has been committed to the persistent store,
877 // associate it with its db_handle (TODO(benjhayden) merge db_handle with id),
878 // show it in the browser (TODO(benjhayden) the ui should observe us instead),
879 // and notify observers (TODO(benjhayden) observers should be able to see the
880 // item when it's created so they can observe it directly. Are there any
881 // clients that actually need to know when the item is added to the history?).
882 void DownloadManagerImpl::OnDownloadItemAddedToPersistentStore(
883 DownloadItemImpl* item) {
884 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
885 VLOG(20) << __FUNCTION__ << "()" << " db_handle = " << item->GetDbHandle()
886 << " download_id = " << item->GetId()
887 << " download = " << item->DebugString(true);
888
889 // If the download is still in progress, try to complete it.
890 //
891 // Otherwise, download has been cancelled or interrupted before we've
892 // received the DB handle. We post one final message to the history
893 // service so that it can be properly in sync with the DownloadItem's
894 // completion status, and also inform any observers so that they get
895 // more than just the start notification.
896 if (item->IsInProgress()) {
897 MaybeCompleteDownload(item);
898 } else {
899 DCHECK(item->IsCancelled());
900 active_downloads_.erase(item->GetId());
901 if (delegate_)
902 delegate_->UpdateItemInPersistentStore(item);
903 item->UpdateObservers();
904 }
905 } 834 }
906 835
907 void DownloadManagerImpl::ShowDownloadInBrowser(DownloadItemImpl* download) { 836 void DownloadManagerImpl::ShowDownloadInBrowser(DownloadItemImpl* download) {
908 // The 'contents' may no longer exist if the user closed the contents before 837 // The 'contents' may no longer exist if the user closed the contents before
909 // we get this start completion event. 838 // we get this start completion event.
910 WebContents* content = download->GetWebContents(); 839 WebContents* content = download->GetWebContents();
911 840
912 // If the contents no longer exists, we ask the embedder to suggest another 841 // If the contents no longer exists, we ask the embedder to suggest another
913 // contents. 842 // contents.
914 if (!content && delegate_) 843 if (!content && delegate_)
(...skipping 15 matching lines...) Expand all
930 ++count; 859 ++count;
931 } 860 }
932 return count; 861 return count;
933 } 862 }
934 863
935 void DownloadManagerImpl::NotifyModelChanged() { 864 void DownloadManagerImpl::NotifyModelChanged() {
936 FOR_EACH_OBSERVER(Observer, observers_, ModelChanged(this)); 865 FOR_EACH_OBSERVER(Observer, observers_, ModelChanged(this));
937 } 866 }
938 867
939 DownloadItem* DownloadManagerImpl::GetDownloadItem(int download_id) { 868 DownloadItem* DownloadManagerImpl::GetDownloadItem(int download_id) {
940 DownloadItem* download = GetDownload(download_id); 869 return GetDownload(download_id);
941 return (download && download->IsPersisted()) ? download : NULL;
942 } 870 }
943 871
944 DownloadItem* DownloadManagerImpl::GetDownload(int download_id) { 872 DownloadItem* DownloadManagerImpl::GetDownload(int download_id) {
945 return ContainsKey(downloads_, download_id) ? downloads_[download_id] : NULL; 873 return ContainsKey(downloads_, download_id) ? downloads_[download_id] : NULL;
946 } 874 }
947 875
948 void DownloadManagerImpl::GetAllDownloads(DownloadVector* downloads) { 876 void DownloadManagerImpl::GetAllDownloads(DownloadVector* downloads) {
949 for (DownloadMap::iterator it = downloads_.begin(); 877 for (DownloadMap::iterator it = downloads_.begin();
950 it != downloads_.end(); ++it) { 878 it != downloads_.end(); ++it) {
951 downloads->push_back(it->second); 879 downloads->push_back(it->second);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
985 DownloadSet remainder; 913 DownloadSet remainder;
986 std::insert_iterator<DownloadSet> insert_it(remainder, remainder.begin()); 914 std::insert_iterator<DownloadSet> insert_it(remainder, remainder.begin());
987 std::set_difference(all_sets[i]->begin(), all_sets[i]->end(), 915 std::set_difference(all_sets[i]->begin(), all_sets[i]->end(),
988 all_downloads.begin(), all_downloads.end(), 916 all_downloads.begin(), all_downloads.end(),
989 insert_it); 917 insert_it);
990 DCHECK(remainder.empty()); 918 DCHECK(remainder.empty());
991 } 919 }
992 #endif 920 #endif
993 } 921 }
994 922
995 // SavePackage will call SavePageDownloadFinished upon completion/cancellation.
996 // The history callback will call OnSavePageItemAddedToPersistentStore.
997 // If the download finishes before the history callback,
998 // OnSavePageItemAddedToPersistentStore calls SavePageDownloadFinished, ensuring
999 // that the history event is update regardless of the order in which these two
1000 // events complete.
1001 // If something removes the download item from the download manager (Remove,
1002 // Shutdown) the result will be that the SavePage system will not be able to
1003 // properly update the download item (which no longer exists) or the download
1004 // history, but the action will complete properly anyway. This may lead to the
1005 // history entry being wrong on a reload of chrome (specifically in the case of
1006 // Initiation -> History Callback -> Removal -> Completion), but there's no way
1007 // to solve that without canceling on Remove (which would then update the DB).
1008
1009 void DownloadManagerImpl::OnSavePageItemAddedToPersistentStore(
1010 DownloadItemImpl* item) {
1011 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1012
1013 // Finalize this download if it finished before the history callback.
1014 if (!item->IsInProgress())
1015 SavePageDownloadFinished(item);
1016 }
1017
1018 void DownloadManagerImpl::SavePageDownloadFinished( 923 void DownloadManagerImpl::SavePageDownloadFinished(
1019 content::DownloadItem* download) { 924 content::DownloadItem* download) {
1020 if (download->IsPersisted()) { 925 if (download->IsComplete())
1021 if (delegate_) 926 content::NotificationService::current()->Notify(
1022 delegate_->UpdateItemInPersistentStore(download); 927 content::NOTIFICATION_SAVE_PACKAGE_SUCCESSFULLY_FINISHED,
1023 if (download->IsComplete()) 928 content::Source<DownloadManager>(this),
1024 content::NotificationService::current()->Notify( 929 content::Details<DownloadItem>(download));
1025 content::NOTIFICATION_SAVE_PACKAGE_SUCCESSFULLY_FINISHED,
1026 content::Source<DownloadManager>(this),
1027 content::Details<DownloadItem>(download));
1028 }
1029 } 930 }
1030 931
1031 void DownloadManagerImpl::DownloadOpened(DownloadItemImpl* download) { 932 void DownloadManagerImpl::DownloadOpened(DownloadItemImpl* download) {
1032 if (delegate_)
1033 delegate_->UpdateItemInPersistentStore(download);
1034 int num_unopened = 0; 933 int num_unopened = 0;
1035 for (DownloadMap::iterator it = downloads_.begin(); 934 for (DownloadMap::iterator it = downloads_.begin();
1036 it != downloads_.end(); ++it) { 935 it != downloads_.end(); ++it) {
1037 DownloadItemImpl* item = it->second; 936 DownloadItemImpl* item = it->second;
1038 if (item->IsComplete() && 937 if (item->IsComplete() &&
1039 !item->GetOpened()) 938 !item->GetOpened())
1040 ++num_unopened; 939 ++num_unopened;
1041 } 940 }
1042 download_stats::RecordOpensOutstanding(num_unopened); 941 download_stats::RecordOpensOutstanding(num_unopened);
1043 } 942 }
1044 943
944 // TODO(benjhayden) MaybeCompleteDownload should be moved into DownloadItemImpl.
1045 void DownloadManagerImpl::DownloadRenamedToIntermediateName( 945 void DownloadManagerImpl::DownloadRenamedToIntermediateName(
1046 DownloadItemImpl* download) { 946 DownloadItemImpl* download) {
1047 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 947 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1048 // download->GetFullPath() is only expected to be meaningful after this 948 download->UpdateObservers();
1049 // callback is received. Therefore we can now add the download to a persistent 949 MaybeCompleteDownload(download);
1050 // store. If the rename failed, we receive an OnDownloadInterrupted() call
1051 // before we receive the DownloadRenamedToIntermediateName() call.
1052 if (delegate_) {
1053 delegate_->AddItemToPersistentStore(download);
1054 } else {
1055 OnItemAddedToPersistentStore(download->GetId(),
1056 DownloadItem::kUninitializedHandle);
1057 }
1058 } 950 }
1059
1060 void DownloadManagerImpl::DownloadRenamedToFinalName(
1061 DownloadItemImpl* download) {
1062 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1063 // If the rename failed, we receive an OnDownloadInterrupted() call before we
1064 // receive the DownloadRenamedToFinalName() call.
1065 if (delegate_) {
1066 delegate_->UpdatePathForItemInPersistentStore(
1067 download, download->GetFullPath());
1068 }
1069 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698