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

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

Powered by Google App Engine
This is Rietveld 408576698