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

Side by Side Diff: chrome/browser/download/chrome_download_manager_delegate.cc

Issue 11574006: Implement chrome.downloads.onDeterminingFilename() (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: @r177190 Created 7 years, 11 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 "chrome/browser/download/chrome_download_manager_delegate.h" 5 #include "chrome/browser/download/chrome_download_manager_delegate.h"
6 6
7 #include <string> 7 #include <string>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/bind_helpers.h" 10 #include "base/bind_helpers.h"
11 #include "base/callback.h" 11 #include "base/callback.h"
12 #include "base/file_util.h" 12 #include "base/file_util.h"
13 #include "base/prefs/public/pref_member.h" 13 #include "base/prefs/public/pref_member.h"
14 #include "base/rand_util.h" 14 #include "base/rand_util.h"
15 #include "base/stringprintf.h" 15 #include "base/stringprintf.h"
16 #include "base/time.h" 16 #include "base/time.h"
17 #include "base/utf_string_conversions.h" 17 #include "base/utf_string_conversions.h"
18 #include "chrome/browser/browser_process.h" 18 #include "chrome/browser/browser_process.h"
19 #include "chrome/browser/download/download_completion_blocker.h" 19 #include "chrome/browser/download/download_completion_blocker.h"
20 #include "chrome/browser/download/download_crx_util.h" 20 #include "chrome/browser/download/download_crx_util.h"
21 #include "chrome/browser/download/download_extensions.h" 21 #include "chrome/browser/download/download_extensions.h"
22 #include "chrome/browser/download/download_file_picker.h" 22 #include "chrome/browser/download/download_file_picker.h"
23 #include "chrome/browser/download/download_history.h" 23 #include "chrome/browser/download/download_history.h"
24 #include "chrome/browser/download/download_path_reservation_tracker.h" 24 #include "chrome/browser/download/download_path_reservation_tracker.h"
25 #include "chrome/browser/download/download_prefs.h" 25 #include "chrome/browser/download/download_prefs.h"
26 #include "chrome/browser/download/download_service.h"
27 #include "chrome/browser/download/download_service_factory.h"
26 #include "chrome/browser/download/download_status_updater.h" 28 #include "chrome/browser/download/download_status_updater.h"
27 #include "chrome/browser/download/download_util.h" 29 #include "chrome/browser/download/download_util.h"
28 #include "chrome/browser/download/save_package_file_picker.h" 30 #include "chrome/browser/download/save_package_file_picker.h"
29 #include "chrome/browser/extensions/api/downloads/downloads_api.h" 31 #include "chrome/browser/extensions/api/downloads/downloads_api.h"
30 #include "chrome/browser/extensions/crx_installer.h" 32 #include "chrome/browser/extensions/crx_installer.h"
31 #include "chrome/browser/extensions/extension_service.h" 33 #include "chrome/browser/extensions/extension_service.h"
32 #include "chrome/browser/extensions/extension_system.h" 34 #include "chrome/browser/extensions/extension_system.h"
33 #include "chrome/browser/history/history.h" 35 #include "chrome/browser/history/history.h"
34 #include "chrome/browser/history/history_service_factory.h" 36 #include "chrome/browser/history/history_service_factory.h"
35 #include "chrome/browser/intents/web_intents_util.h" 37 #include "chrome/browser/intents/web_intents_util.h"
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
165 : profile_(profile), 167 : profile_(profile),
166 next_download_id_(0), 168 next_download_id_(0),
167 download_prefs_(new DownloadPrefs(profile)) { 169 download_prefs_(new DownloadPrefs(profile)) {
168 } 170 }
169 171
170 ChromeDownloadManagerDelegate::~ChromeDownloadManagerDelegate() { 172 ChromeDownloadManagerDelegate::~ChromeDownloadManagerDelegate() {
171 } 173 }
172 174
173 void ChromeDownloadManagerDelegate::SetDownloadManager(DownloadManager* dm) { 175 void ChromeDownloadManagerDelegate::SetDownloadManager(DownloadManager* dm) {
174 download_manager_ = dm; 176 download_manager_ = dm;
175 #if !defined(OS_ANDROID)
176 extension_event_router_.reset(new ExtensionDownloadsEventRouter(
177 profile_, download_manager_));
178 #endif
179 } 177 }
180 178
181 void ChromeDownloadManagerDelegate::Shutdown() { 179 void ChromeDownloadManagerDelegate::Shutdown() {
182 download_prefs_.reset(); 180 download_prefs_.reset();
183 #if !defined(OS_ANDROID)
184 extension_event_router_.reset();
185 #endif
186 } 181 }
187 182
188 DownloadId ChromeDownloadManagerDelegate::GetNextId() { 183 DownloadId ChromeDownloadManagerDelegate::GetNextId() {
189 if (!profile_->IsOffTheRecord()) 184 if (!profile_->IsOffTheRecord())
190 return DownloadId(this, next_download_id_++); 185 return DownloadId(this, next_download_id_++);
191 186
192 return BrowserContext::GetDownloadManager(profile_->GetOriginalProfile())-> 187 return BrowserContext::GetDownloadManager(profile_->GetOriginalProfile())->
193 GetDelegate()->GetNextId(); 188 GetDelegate()->GetNextId();
194 } 189 }
195 190
(...skipping 465 matching lines...) Expand 10 before | Expand all | Expand 10 after
661 chrome::NOTIFICATION_CRX_INSTALLER_DONE, 656 chrome::NOTIFICATION_CRX_INSTALLER_DONE,
662 source); 657 source);
663 658
664 scoped_refptr<extensions::CrxInstaller> installer = 659 scoped_refptr<extensions::CrxInstaller> installer =
665 content::Source<extensions::CrxInstaller>(source).ptr(); 660 content::Source<extensions::CrxInstaller>(source).ptr();
666 content::DownloadOpenDelayedCallback callback = crx_installers_[installer]; 661 content::DownloadOpenDelayedCallback callback = crx_installers_[installer];
667 crx_installers_.erase(installer.get()); 662 crx_installers_.erase(installer.get());
668 callback.Run(installer->did_handle_successfully()); 663 callback.Run(installer->did_handle_successfully());
669 } 664 }
670 665
666 struct ChromeDownloadManagerDelegate::ContinueFilenameDeterminationInfo {
667 ContinueFilenameDeterminationInfo();
668 ~ContinueFilenameDeterminationInfo();
669
670 int32 download_id;
671 content::DownloadTargetCallback callback;
672 content::DownloadDangerType danger_type;
673 bool visited_referrer_before;
674 bool should_prompt;
675 };
676
677 ChromeDownloadManagerDelegate::ContinueFilenameDeterminationInfo::
678 ContinueFilenameDeterminationInfo() {}
679 ChromeDownloadManagerDelegate::ContinueFilenameDeterminationInfo::
680 ~ContinueFilenameDeterminationInfo() {}
681
671 void ChromeDownloadManagerDelegate::CheckVisitedReferrerBeforeDone( 682 void ChromeDownloadManagerDelegate::CheckVisitedReferrerBeforeDone(
672 int32 download_id, 683 int32 download_id,
673 const content::DownloadTargetCallback& callback, 684 const content::DownloadTargetCallback& callback,
674 content::DownloadDangerType danger_type, 685 content::DownloadDangerType danger_type,
675 bool visited_referrer_before) { 686 bool visited_referrer_before) {
676 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 687 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
677 688
678 DownloadItem* download = 689 DownloadItem* download =
679 download_manager_->GetDownload(download_id); 690 download_manager_->GetDownload(download_id);
680 if (!download || (download->GetState() != DownloadItem::IN_PROGRESS)) 691 if (!download || (download->GetState() != DownloadItem::IN_PROGRESS))
681 return; 692 return;
682 693
683 bool should_prompt = (download->GetTargetDisposition() == 694 bool should_prompt = (download->GetTargetDisposition() ==
684 DownloadItem::TARGET_DISPOSITION_PROMPT); 695 DownloadItem::TARGET_DISPOSITION_PROMPT);
685 bool is_forced_path = !download->GetForcedFilePath().empty(); 696 bool is_forced_path = !download->GetForcedFilePath().empty();
697 FilePath generated_name;
686 FilePath suggested_path; 698 FilePath suggested_path;
687 699
688 // Check whether this download is for an extension install or not. 700 // Check whether this download is for an extension install or not.
689 // Allow extensions to be explicitly saved. 701 // Allow extensions to be explicitly saved.
690 if (!is_forced_path) { 702 if (!is_forced_path) {
691 FilePath generated_name;
692 GenerateFileNameFromRequest( 703 GenerateFileNameFromRequest(
693 *download, 704 *download,
694 &generated_name, 705 &generated_name,
695 profile_->GetPrefs()->GetString(prefs::kDefaultCharset)); 706 profile_->GetPrefs()->GetString(prefs::kDefaultCharset));
696 707
697 // Freeze the user's preference for showing a Save As dialog. We're going 708 // Freeze the user's preference for showing a Save As dialog. We're going
698 // to bounce around a bunch of threads and we don't want to worry about race 709 // to bounce around a bunch of threads and we don't want to worry about race
699 // conditions where the user changes this pref out from under us. 710 // conditions where the user changes this pref out from under us.
700 if (download_prefs_->PromptForDownload()) { 711 if (download_prefs_->PromptForDownload()) {
701 // But ignore the user's preference for the following scenarios: 712 // But ignore the user's preference for the following scenarios:
(...skipping 24 matching lines...) Expand all
726 } 737 }
727 738
728 // If we will open the file with a web intents dispatch, 739 // If we will open the file with a web intents dispatch,
729 // give it a name that will not allow the OS to open it using usual 740 // give it a name that will not allow the OS to open it using usual
730 // associated apps. 741 // associated apps.
731 if (ShouldOpenWithWebIntents(download)) { 742 if (ShouldOpenWithWebIntents(download)) {
732 download->SetDisplayName(suggested_path.BaseName()); 743 download->SetDisplayName(suggested_path.BaseName());
733 suggested_path = suggested_path.AddExtension(kWebIntentsFileExtension); 744 suggested_path = suggested_path.AddExtension(kWebIntentsFileExtension);
734 } 745 }
735 746
747 ContinueFilenameDeterminationInfo continue_info;
748 continue_info.download_id = download_id;
749 continue_info.callback = callback;
750 continue_info.danger_type = danger_type;
751 continue_info.visited_referrer_before = visited_referrer_before;
752 continue_info.should_prompt = should_prompt;
753
754 base::Closure filename_determined = base::Bind(
755 &ChromeDownloadManagerDelegate::OnExtensionsDeterminedFilename,
756 this,
757 continue_info,
758 suggested_path,
759 is_forced_path);
760 #if !defined(OS_ANDROID)
761 if (is_forced_path ||
762 ShouldOpenWithWebIntents(download) ||
763 !DownloadServiceFactory::GetForProfile(profile_)
764 ->GetExtensionEventRouter()) {
765 filename_determined.Run();
766 } else {
767 DownloadServiceFactory::GetForProfile(profile_)->GetExtensionEventRouter()
768 ->OnDownloadFilenameDetermined(
769 download,
770 generated_name,
771 filename_determined,
772 base::Bind(&ChromeDownloadManagerDelegate::OnExtensionsChangingFilename,
773 this, continue_info));
774 }
775 #else
776 filename_determined.Run();
777 #endif
778 }
779
780 void ChromeDownloadManagerDelegate::OnExtensionsChangingFilename(
781 const ContinueFilenameDeterminationInfo& continue_info,
782 const FilePath& changed_filename,
783 bool overwrite) {
784 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
785 DownloadItem* download =
786 download_manager_->GetDownload(continue_info.download_id);
787 if (!download || (download->GetState() != DownloadItem::IN_PROGRESS))
788 return;
789 // If an extension overrides the filename, then the target directory will be
790 // forced to download_prefs_->DownloadPath() since extensions cannot place
791 // downloaded files anywhere except there. This prevents subdirectories from
792 // accumulating: if an extension is allowed to say that a file should go in
793 // last_download_path/music/foo.mp3, then last_download_path will accumulate
794 // the subdirectory /music/ so that the next download may end up in
795 // last_download_path/music/music/bar.mp3.
796 FilePath temp_filename(download_prefs_->DownloadPath().Append(
797 changed_filename));
798 net::GenerateSafeFileName(download->GetMimeType(), false, &temp_filename);
799 // If |is_forced_path| were true, then extensions would not have been
800 // consulted, so use |overwrite| instead of |is_forced_path|. This does NOT
801 // set DownloadItem::GetForcedFilePath()!
802 OnExtensionsDeterminedFilename(continue_info, temp_filename, overwrite);
803 }
804
805 void ChromeDownloadManagerDelegate::OnExtensionsDeterminedFilename(
806 const ContinueFilenameDeterminationInfo& continue_info,
807 const FilePath& suggested_path,
808 bool is_forced_path) {
809 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
810 int32 download_id = continue_info.download_id;
811 const content::DownloadTargetCallback& callback = continue_info.callback;
812 content::DownloadDangerType danger_type = continue_info.danger_type;
813 bool visited_referrer_before = continue_info.visited_referrer_before;
814 bool should_prompt = continue_info.should_prompt;
815 DownloadItem* download =
816 download_manager_->GetDownload(download_id);
817 if (!download || (download->GetState() != DownloadItem::IN_PROGRESS))
818 return;
819
736 // If the download hasn't already been marked dangerous (could be 820 // If the download hasn't already been marked dangerous (could be
737 // DANGEROUS_URL), check if it is a dangerous file. 821 // DANGEROUS_URL), check if it is a dangerous file.
738 if (danger_type == content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS) { 822 if (danger_type == content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS) {
739 if (!should_prompt && !is_forced_path && 823 if (!should_prompt && !is_forced_path &&
740 IsDangerousFile(*download, suggested_path, visited_referrer_before)) { 824 IsDangerousFile(*download, suggested_path, visited_referrer_before)) {
741 danger_type = content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE; 825 danger_type = content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE;
742 } 826 }
743 827
744 #if defined(FULL_SAFE_BROWSING) 828 #if defined(FULL_SAFE_BROWSING)
745 DownloadProtectionService* service = GetDownloadProtectionService(); 829 DownloadProtectionService* service = GetDownloadProtectionService();
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
853 // TODO(asanka): This logic is a hack. DownloadFilePicker should give us a 937 // TODO(asanka): This logic is a hack. DownloadFilePicker should give us a
854 // directory to persist. Or perhaps, if the Drive path 938 // directory to persist. Or perhaps, if the Drive path
855 // substitution logic is moved here, then we would have a 939 // substitution logic is moved here, then we would have a
856 // persistable path after the DownloadFilePicker is done. 940 // persistable path after the DownloadFilePicker is done.
857 if (disposition == DownloadItem::TARGET_DISPOSITION_PROMPT && 941 if (disposition == DownloadItem::TARGET_DISPOSITION_PROMPT &&
858 !download->IsTemporary()) 942 !download->IsTemporary())
859 last_download_path_ = target_path.DirName(); 943 last_download_path_ = target_path.DirName();
860 } 944 }
861 callback.Run(target_path, disposition, danger_type, intermediate_path); 945 callback.Run(target_path, disposition, danger_type, intermediate_path);
862 } 946 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698