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

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

Issue 10704052: Download filename determination refactor (3/3) (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Merge with r148594 to and resolve conflicts with r148576 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 226 matching lines...) Expand 10 before | Expand all | Expand 10 after
237 if (delegate_) 237 if (delegate_)
238 id = delegate_->GetNextId(); 238 id = delegate_->GetNextId();
239 if (!id.IsValid()) { 239 if (!id.IsValid()) {
240 static int next_id; 240 static int next_id;
241 id = DownloadId(browser_context_, ++next_id); 241 id = DownloadId(browser_context_, ++next_id);
242 } 242 }
243 243
244 return id; 244 return id;
245 } 245 }
246 246
247 DownloadFileManager* DownloadManagerImpl::GetDownloadFileManager() {
248 return file_manager_;
249 }
250
247 bool DownloadManagerImpl::ShouldOpenDownload(DownloadItemImpl* item) { 251 bool DownloadManagerImpl::ShouldOpenDownload(DownloadItemImpl* item) {
248 if (!delegate_) 252 if (!delegate_)
249 return true; 253 return true;
250 254
251 return delegate_->ShouldOpenDownload(item); 255 return delegate_->ShouldOpenDownload(item);
252 } 256 }
253 257
254 bool DownloadManagerImpl::ShouldOpenFileBasedOnExtension(const FilePath& path) { 258 bool DownloadManagerImpl::ShouldOpenFileBasedOnExtension(const FilePath& path) {
255 if (!delegate_) 259 if (!delegate_)
256 return false; 260 return false;
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
324 328
325 active_downloads_.clear(); 329 active_downloads_.clear();
326 STLDeleteValues(&downloads_to_delete); 330 STLDeleteValues(&downloads_to_delete);
327 331
328 // We'll have nothing more to report to the observers after this point. 332 // We'll have nothing more to report to the observers after this point.
329 observers_.Clear(); 333 observers_.Clear();
330 334
331 file_manager_ = NULL; 335 file_manager_ = NULL;
332 if (delegate_) 336 if (delegate_)
333 delegate_->Shutdown(); 337 delegate_->Shutdown();
338 delegate_ = NULL;
334 } 339 }
335 340
336 void DownloadManagerImpl::GetTemporaryDownloads( 341 void DownloadManagerImpl::GetTemporaryDownloads(
337 const FilePath& dir_path, DownloadVector* result) { 342 const FilePath& dir_path, DownloadVector* result) {
338 DCHECK(result); 343 DCHECK(result);
339 344
340 for (DownloadMap::iterator it = downloads_.begin(); 345 for (DownloadMap::iterator it = downloads_.begin();
341 it != downloads_.end(); ++it) { 346 it != downloads_.end(); ++it) {
342 DownloadItemImpl* item = it->second; 347 DownloadItemImpl* item = it->second;
343 // TODO(benjhayden): Don't check IsPersisted(). 348 // TODO(benjhayden): Don't check IsPersisted().
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
431 OnDownloadInterrupted(download_id, reason); 436 OnDownloadInterrupted(download_id, reason);
432 // TODO(rdsmith): It makes no sense to continue along the 437 // TODO(rdsmith): It makes no sense to continue along the
433 // regular download path after we've gotten an error. But it's 438 // regular download path after we've gotten an error. But it's
434 // the way the code has historically worked, and this allows us 439 // the way the code has historically worked, and this allows us
435 // to get the download persisted and observers of the download manager 440 // to get the download persisted and observers of the download manager
436 // notified, so tests work. When we execute all side effects of cancel 441 // notified, so tests work. When we execute all side effects of cancel
437 // (including queue removal) immedately rather than waiting for 442 // (including queue removal) immedately rather than waiting for
438 // persistence we should replace this comment with a "return;". 443 // persistence we should replace this comment with a "return;".
439 } 444 }
440 445
441 if (!delegate_ || delegate_->ShouldStartDownload(download_id)) 446 DownloadMap::iterator download_iter = active_downloads_.find(download_id);
442 RestartDownload(download_id); 447 if (download_iter == active_downloads_.end())
448 return;
449
450 DownloadItemImpl* download = download_iter->second;
451 content::DownloadTargetCallback callback =
452 base::Bind(&DownloadManagerImpl::OnDownloadTargetDetermined,
453 this, download_id);
454 if (!delegate_ || !delegate_->DetermineDownloadTarget(download, callback)) {
455 FilePath target_path = download->GetForcedFilePath();
456 // TODO(asanka): Determine a useful path if |target_path| is empty.
457 callback.Run(target_path,
458 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
459 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
460 target_path);
461 }
462 }
463
464 void DownloadManagerImpl::OnDownloadTargetDetermined(
465 int32 download_id,
466 const FilePath& target_path,
467 DownloadItem::TargetDisposition disposition,
468 content::DownloadDangerType danger_type,
469 const FilePath& intermediate_path) {
470 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
471 DownloadMap::iterator download_iter = active_downloads_.find(download_id);
472 if (download_iter != active_downloads_.end()) {
473 // Once DownloadItem::OnDownloadTargetDetermined() is called, we expect a
474 // DownloadRenamedToIntermediateName() callback. This is necessary for the
475 // download to proceed.
476 download_iter->second->OnDownloadTargetDetermined(
477 target_path, disposition, danger_type, intermediate_path);
478 }
443 } 479 }
444 480
445 void DownloadManagerImpl::CheckForHistoryFilesRemoval() { 481 void DownloadManagerImpl::CheckForHistoryFilesRemoval() {
446 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 482 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
447 for (DownloadMap::iterator it = downloads_.begin(); 483 for (DownloadMap::iterator it = downloads_.begin();
448 it != downloads_.end(); ++it) { 484 it != downloads_.end(); ++it) {
449 DownloadItemImpl* item = it->second; 485 DownloadItemImpl* item = it->second;
450 if (item->IsPersisted()) 486 if (item->IsPersisted())
451 CheckForFileRemoval(item); 487 CheckForFileRemoval(item);
452 } 488 }
(...skipping 22 matching lines...) Expand all
475 download_id)); 511 download_id));
476 } 512 }
477 } 513 }
478 514
479 void DownloadManagerImpl::OnFileRemovalDetected(int32 download_id) { 515 void DownloadManagerImpl::OnFileRemovalDetected(int32 download_id) {
480 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 516 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
481 if (ContainsKey(downloads_, download_id)) 517 if (ContainsKey(downloads_, download_id))
482 downloads_[download_id]->OnDownloadedFileRemoved(); 518 downloads_[download_id]->OnDownloadedFileRemoved();
483 } 519 }
484 520
485 void DownloadManagerImpl::RestartDownload(int32 download_id) {
486 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
487
488 if (!ContainsKey(active_downloads_, download_id))
489 return;
490 DownloadItemImpl* download = active_downloads_[download_id];
491
492 VLOG(20) << __FUNCTION__ << "()"
493 << " download = " << download->DebugString(true);
494
495 if (download->GetTargetDisposition() ==
496 DownloadItem::TARGET_DISPOSITION_PROMPT) {
497 // We must ask the user for the place to put the download.
498 if (delegate_) {
499 delegate_->ChooseDownloadPath(download);
500 FOR_EACH_OBSERVER(Observer, observers_,
501 SelectFileDialogDisplayed(this, download_id));
502 } else {
503 FileSelectionCanceled(download_id);
504 }
505 } else {
506 // No prompting for download, just continue with the current target path.
507 OnTargetPathAvailable(download);
508 }
509 }
510
511 content::BrowserContext* DownloadManagerImpl::GetBrowserContext() const { 521 content::BrowserContext* DownloadManagerImpl::GetBrowserContext() const {
512 return browser_context_; 522 return browser_context_;
513 } 523 }
514 524
515 FilePath DownloadManagerImpl::LastDownloadPath() {
516 return last_download_path_;
517 }
518
519 net::BoundNetLog DownloadManagerImpl::CreateDownloadItem( 525 net::BoundNetLog DownloadManagerImpl::CreateDownloadItem(
520 DownloadCreateInfo* info) { 526 DownloadCreateInfo* info) {
521 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 527 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
522 528
523 net::BoundNetLog bound_net_log = 529 net::BoundNetLog bound_net_log =
524 net::BoundNetLog::Make(net_log_, net::NetLog::SOURCE_DOWNLOAD); 530 net::BoundNetLog::Make(net_log_, net::NetLog::SOURCE_DOWNLOAD);
525 if (!info->download_id.IsValid()) 531 if (!info->download_id.IsValid())
526 info->download_id = GetNextId(); 532 info->download_id = GetNextId();
527 DownloadItemImpl* download = factory_->CreateActiveItem( 533 DownloadItemImpl* download = factory_->CreateActiveItem(
528 this, *info, 534 this, *info,
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
568 // we're comfortable with the user interacting with them. 574 // we're comfortable with the user interacting with them.
569 // FOR_EACH_OBSERVER(Observer, observers_, OnDownloadCreated(this, download)); 575 // FOR_EACH_OBSERVER(Observer, observers_, OnDownloadCreated(this, download));
570 576
571 // Will notify the observer in the callback. 577 // Will notify the observer in the callback.
572 if (delegate_) 578 if (delegate_)
573 delegate_->AddItemToPersistentStore(download); 579 delegate_->AddItemToPersistentStore(download);
574 580
575 return download; 581 return download;
576 } 582 }
577 583
578 // The target path for the download item is now valid. We proceed with the
579 // determination of an intermediate path.
580 void DownloadManagerImpl::OnTargetPathAvailable(DownloadItemImpl* download) {
581 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
582 DCHECK(download);
583 DCHECK(ContainsKey(downloads_, download->GetId()));
584 DCHECK(ContainsKey(active_downloads_, download->GetId()));
585
586 VLOG(20) << __FUNCTION__ << "()"
587 << " download = " << download->DebugString(true);
588
589 // Rename to intermediate name.
590 // TODO(asanka): Skip this rename if download->AllDataSaved() is true. This
591 // avoids a spurious rename when we can just rename to the final
592 // filename. Unnecessary renames may cause bugs like
593 // http://crbug.com/74187.
594 FilePath intermediate_path;
595 if (delegate_)
596 intermediate_path = delegate_->GetIntermediatePath(*download);
597 else
598 intermediate_path = download->GetTargetFilePath();
599
600 // We want the intermediate and target paths to refer to the same directory so
601 // that they are both on the same device and subject to same
602 // space/permission/availability constraints.
603 DCHECK(intermediate_path.DirName() ==
604 download->GetTargetFilePath().DirName());
605 download->OnIntermediatePathDetermined(file_manager_, intermediate_path);
606 }
607
608 void DownloadManagerImpl::UpdateDownload(int32 download_id, 584 void DownloadManagerImpl::UpdateDownload(int32 download_id,
609 int64 bytes_so_far, 585 int64 bytes_so_far,
610 int64 bytes_per_sec, 586 int64 bytes_per_sec,
611 const std::string& hash_state) { 587 const std::string& hash_state) {
612 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 588 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
613 DownloadMap::iterator it = active_downloads_.find(download_id); 589 DownloadMap::iterator it = active_downloads_.find(download_id);
614 if (it != active_downloads_.end()) { 590 if (it != active_downloads_.end()) {
615 DownloadItemImpl* download = it->second; 591 DownloadItemImpl* download = it->second;
616 if (download->IsInProgress()) { 592 if (download->IsInProgress()) {
617 download->UpdateProgress(bytes_so_far, bytes_per_sec, hash_state); 593 download->UpdateProgress(bytes_so_far, bytes_per_sec, hash_state);
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
726 if (delegate_ && !delegate_->ShouldCompleteDownload(download, base::Bind( 702 if (delegate_ && !delegate_->ShouldCompleteDownload(download, base::Bind(
727 &DownloadManagerImpl::MaybeCompleteDownloadById, 703 &DownloadManagerImpl::MaybeCompleteDownloadById,
728 this, download->GetId()))) 704 this, download->GetId())))
729 return; 705 return;
730 706
731 VLOG(20) << __FUNCTION__ << "()" << " executing: download = " 707 VLOG(20) << __FUNCTION__ << "()" << " executing: download = "
732 << download->DebugString(false); 708 << download->DebugString(false);
733 709
734 if (delegate_) 710 if (delegate_)
735 delegate_->UpdateItemInPersistentStore(download); 711 delegate_->UpdateItemInPersistentStore(download);
736 download->OnDownloadCompleting(file_manager_); 712 download->OnDownloadCompleting();
737 } 713 }
738 714
739 void DownloadManagerImpl::MaybeCompleteDownloadById(int download_id) { 715 void DownloadManagerImpl::MaybeCompleteDownloadById(int download_id) {
740 if (ContainsKey(active_downloads_, download_id)) 716 if (ContainsKey(active_downloads_, download_id))
741 MaybeCompleteDownload(active_downloads_[download_id]); 717 MaybeCompleteDownload(active_downloads_[download_id]);
742 } 718 }
743 719
744 void DownloadManagerImpl::DownloadCompleted(DownloadItemImpl* download) { 720 void DownloadManagerImpl::DownloadCompleted(DownloadItemImpl* download) {
745 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 721 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
746 DCHECK(download); 722 DCHECK(download);
(...skipping 15 matching lines...) Expand all
762 738
763 VLOG(20) << __FUNCTION__ << "()" 739 VLOG(20) << __FUNCTION__ << "()"
764 << " download = " << download->DebugString(true); 740 << " download = " << download->DebugString(true);
765 741
766 RemoveFromActiveList(download); 742 RemoveFromActiveList(download);
767 // This function is called from the DownloadItem, so DI state 743 // This function is called from the DownloadItem, so DI state
768 // should already have been updated. 744 // should already have been updated.
769 AssertStateConsistent(download); 745 AssertStateConsistent(download);
770 746
771 DCHECK(file_manager_); 747 DCHECK(file_manager_);
772 download->OffThreadCancel(file_manager_); 748 download->OffThreadCancel();
773 } 749 }
774 750
775 void DownloadManagerImpl::OnDownloadInterrupted( 751 void DownloadManagerImpl::OnDownloadInterrupted(
776 int32 download_id, 752 int32 download_id,
777 content::DownloadInterruptReason reason) { 753 content::DownloadInterruptReason reason) {
778 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 754 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
779 755
780 if (!ContainsKey(active_downloads_, download_id)) 756 if (!ContainsKey(active_downloads_, download_id))
781 return; 757 return;
782 active_downloads_[download_id]->Interrupt(reason); 758 active_downloads_[download_id]->Interrupt(reason);
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
891 // TODO: It is the responsibility of the observers to query the 867 // TODO: It is the responsibility of the observers to query the
892 // DownloadManager. Remove the following call from here and update all 868 // DownloadManager. Remove the following call from here and update all
893 // observers. 869 // observers.
894 observer->ModelChanged(this); 870 observer->ModelChanged(this);
895 } 871 }
896 872
897 void DownloadManagerImpl::RemoveObserver(Observer* observer) { 873 void DownloadManagerImpl::RemoveObserver(Observer* observer) {
898 observers_.RemoveObserver(observer); 874 observers_.RemoveObserver(observer);
899 } 875 }
900 876
901 void DownloadManagerImpl::FileSelected(const FilePath& path,
902 int32 download_id) {
903 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
904 DCHECK(!path.empty());
905
906 if (!ContainsKey(active_downloads_, download_id))
907 return;
908 DownloadItemImpl* download = active_downloads_[download_id];
909
910 VLOG(20) << __FUNCTION__ << "()" << " path = \"" << path.value() << "\""
911 << " download = " << download->DebugString(true);
912
913 // Retain the last directory. Exclude temporary downloads since the path
914 // likely points at the location of a temporary file.
915 if (!download->IsTemporary())
916 last_download_path_ = path.DirName();
917
918 // Make sure the initial file name is set only once.
919 download->OnTargetPathSelected(path);
920 OnTargetPathAvailable(download);
921 }
922
923 void DownloadManagerImpl::FileSelectionCanceled(int32 download_id) {
924 // The user didn't pick a place to save the file, so need to cancel the
925 // download that's already in progress to the temporary location.
926 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
927
928 if (!ContainsKey(active_downloads_, download_id))
929 return;
930 DownloadItemImpl* download = active_downloads_[download_id];
931
932 VLOG(20) << __FUNCTION__ << "()"
933 << " download = " << download->DebugString(true);
934
935 download->Cancel(true);
936 }
937
938 // Operations posted to us from the history service ---------------------------- 877 // Operations posted to us from the history service ----------------------------
939 878
940 // The history service has retrieved all download entries. 'entries' contains 879 // The history service has retrieved all download entries. 'entries' contains
941 // 'DownloadPersistentStoreInfo's in sorted order (by ascending start_time). 880 // 'DownloadPersistentStoreInfo's in sorted order (by ascending start_time).
942 void DownloadManagerImpl::OnPersistentStoreQueryComplete( 881 void DownloadManagerImpl::OnPersistentStoreQueryComplete(
943 std::vector<DownloadPersistentStoreInfo>* entries) { 882 std::vector<DownloadPersistentStoreInfo>* entries) {
944 history_size_ = entries->size(); 883 history_size_ = entries->size();
945 for (size_t i = 0; i < entries->size(); ++i) { 884 for (size_t i = 0; i < entries->size(); ++i) {
946 int64 db_handle = entries->at(i).db_handle; 885 int64 db_handle = entries->at(i).db_handle;
947 base::debug::Alias(&db_handle); 886 base::debug::Alias(&db_handle);
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
1048 int count = 0; 987 int count = 0;
1049 for (DownloadMap::const_iterator it = active_downloads_.begin(); 988 for (DownloadMap::const_iterator it = active_downloads_.begin();
1050 it != active_downloads_.end(); ++it) { 989 it != active_downloads_.end(); ++it) {
1051 DownloadItemImpl* item = it->second; 990 DownloadItemImpl* item = it->second;
1052 if (item->IsInProgress()) 991 if (item->IsInProgress())
1053 ++count; 992 ++count;
1054 } 993 }
1055 return count; 994 return count;
1056 } 995 }
1057 996
1058 // Clears the last download path, used to initialize "save as" dialogs.
1059 void DownloadManagerImpl::ClearLastDownloadPath() {
1060 last_download_path_ = FilePath();
1061 }
1062
1063 void DownloadManagerImpl::NotifyModelChanged() { 997 void DownloadManagerImpl::NotifyModelChanged() {
1064 FOR_EACH_OBSERVER(Observer, observers_, ModelChanged(this)); 998 FOR_EACH_OBSERVER(Observer, observers_, ModelChanged(this));
1065 } 999 }
1066 1000
1067 DownloadItem* DownloadManagerImpl::GetDownloadItem(int download_id) { 1001 DownloadItem* DownloadManagerImpl::GetDownloadItem(int download_id) {
1068 DownloadItem* download = GetDownload(download_id); 1002 DownloadItem* download = GetDownload(download_id);
1069 return (download && download->IsPersisted()) ? download : NULL; 1003 return (download && download->IsPersisted()) ? download : NULL;
1070 } 1004 }
1071 1005
1072 DownloadItem* DownloadManagerImpl::GetDownload(int download_id) { 1006 DownloadItem* DownloadManagerImpl::GetDownload(int download_id) {
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
1159 if (item->IsComplete() && 1093 if (item->IsComplete() &&
1160 !item->GetOpened()) 1094 !item->GetOpened())
1161 ++num_unopened; 1095 ++num_unopened;
1162 } 1096 }
1163 download_stats::RecordOpensOutstanding(num_unopened); 1097 download_stats::RecordOpensOutstanding(num_unopened);
1164 } 1098 }
1165 1099
1166 void DownloadManagerImpl::DownloadRenamedToIntermediateName( 1100 void DownloadManagerImpl::DownloadRenamedToIntermediateName(
1167 DownloadItemImpl* download) { 1101 DownloadItemImpl* download) {
1168 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1102 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1169 // If the rename failed, we receive an OnDownloadInterrupted() call before we 1103 // download->GetFullPath() is only expected to be meaningful after this
1170 // receive the DownloadRenamedToIntermediateName() call. 1104 // callback is received. Therefore we can now add the download to a persistent
1171 if (delegate_) 1105 // store. If the rename failed, we receive an OnDownloadInterrupted() call
1106 // before we receive the DownloadRenamedToIntermediateName() call.
1107 if (delegate_) {
1172 delegate_->AddItemToPersistentStore(download); 1108 delegate_->AddItemToPersistentStore(download);
1109 } else {
1110 OnItemAddedToPersistentStore(download->GetId(),
1111 DownloadItem::kUninitializedHandle);
1112 }
1173 } 1113 }
1174 1114
1175 void DownloadManagerImpl::DownloadRenamedToFinalName( 1115 void DownloadManagerImpl::DownloadRenamedToFinalName(
1176 DownloadItemImpl* download) { 1116 DownloadItemImpl* download) {
1177 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1117 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1178 // If the rename failed, we receive an OnDownloadInterrupted() call before we 1118 // If the rename failed, we receive an OnDownloadInterrupted() call before we
1179 // receive the DownloadRenamedToFinalName() call. 1119 // receive the DownloadRenamedToFinalName() call.
1180 if (delegate_) { 1120 if (delegate_) {
1181 delegate_->UpdatePathForItemInPersistentStore( 1121 delegate_->UpdatePathForItemInPersistentStore(
1182 download, download->GetFullPath()); 1122 download, download->GetFullPath());
1183 } 1123 }
1184 } 1124 }
OLDNEW
« no previous file with comments | « content/browser/download/download_manager_impl.h ('k') | content/browser/download/download_manager_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698