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

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: @r177662 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 467 matching lines...) Expand 10 before | Expand all | Expand 10 after
663 chrome::NOTIFICATION_CRX_INSTALLER_DONE, 658 chrome::NOTIFICATION_CRX_INSTALLER_DONE,
664 source); 659 source);
665 660
666 scoped_refptr<extensions::CrxInstaller> installer = 661 scoped_refptr<extensions::CrxInstaller> installer =
667 content::Source<extensions::CrxInstaller>(source).ptr(); 662 content::Source<extensions::CrxInstaller>(source).ptr();
668 content::DownloadOpenDelayedCallback callback = crx_installers_[installer]; 663 content::DownloadOpenDelayedCallback callback = crx_installers_[installer];
669 crx_installers_.erase(installer.get()); 664 crx_installers_.erase(installer.get());
670 callback.Run(installer->did_handle_successfully()); 665 callback.Run(installer->did_handle_successfully());
671 } 666 }
672 667
668 struct ChromeDownloadManagerDelegate::ContinueFilenameDeterminationInfo {
669 ContinueFilenameDeterminationInfo();
670 ~ContinueFilenameDeterminationInfo();
671
672 int32 download_id;
673 content::DownloadTargetCallback callback;
674 content::DownloadDangerType danger_type;
675 bool visited_referrer_before;
676 bool should_prompt;
677 };
678
679 ChromeDownloadManagerDelegate::ContinueFilenameDeterminationInfo::
680 ContinueFilenameDeterminationInfo() {}
681 ChromeDownloadManagerDelegate::ContinueFilenameDeterminationInfo::
682 ~ContinueFilenameDeterminationInfo() {}
683
673 void ChromeDownloadManagerDelegate::CheckVisitedReferrerBeforeDone( 684 void ChromeDownloadManagerDelegate::CheckVisitedReferrerBeforeDone(
674 int32 download_id, 685 int32 download_id,
675 const content::DownloadTargetCallback& callback, 686 const content::DownloadTargetCallback& callback,
676 content::DownloadDangerType danger_type, 687 content::DownloadDangerType danger_type,
677 bool visited_referrer_before) { 688 bool visited_referrer_before) {
678 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 689 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
679 690
680 DownloadItem* download = 691 DownloadItem* download =
681 download_manager_->GetDownload(download_id); 692 download_manager_->GetDownload(download_id);
682 if (!download || (download->GetState() != DownloadItem::IN_PROGRESS)) 693 if (!download || (download->GetState() != DownloadItem::IN_PROGRESS))
683 return; 694 return;
684 695
685 bool should_prompt = (download->GetTargetDisposition() == 696 bool should_prompt = (download->GetTargetDisposition() ==
686 DownloadItem::TARGET_DISPOSITION_PROMPT); 697 DownloadItem::TARGET_DISPOSITION_PROMPT);
687 bool is_forced_path = !download->GetForcedFilePath().empty(); 698 bool is_forced_path = !download->GetForcedFilePath().empty();
699 FilePath generated_name;
688 FilePath suggested_path; 700 FilePath suggested_path;
689 701
690 // Check whether this download is for an extension install or not. 702 // Check whether this download is for an extension install or not.
691 // Allow extensions to be explicitly saved. 703 // Allow extensions to be explicitly saved.
692 if (!is_forced_path) { 704 if (!is_forced_path) {
693 FilePath generated_name;
694 GenerateFileNameFromRequest( 705 GenerateFileNameFromRequest(
695 *download, 706 *download,
696 &generated_name, 707 &generated_name,
697 profile_->GetPrefs()->GetString(prefs::kDefaultCharset)); 708 profile_->GetPrefs()->GetString(prefs::kDefaultCharset));
698 709
699 // Freeze the user's preference for showing a Save As dialog. We're going 710 // Freeze the user's preference for showing a Save As dialog. We're going
700 // to bounce around a bunch of threads and we don't want to worry about race 711 // to bounce around a bunch of threads and we don't want to worry about race
701 // conditions where the user changes this pref out from under us. 712 // conditions where the user changes this pref out from under us.
702 if (download_prefs_->PromptForDownload()) { 713 if (download_prefs_->PromptForDownload()) {
703 // But ignore the user's preference for the following scenarios: 714 // But ignore the user's preference for the following scenarios:
(...skipping 24 matching lines...) Expand all
728 } 739 }
729 740
730 // If we will open the file with a web intents dispatch, 741 // If we will open the file with a web intents dispatch,
731 // give it a name that will not allow the OS to open it using usual 742 // give it a name that will not allow the OS to open it using usual
732 // associated apps. 743 // associated apps.
733 if (ShouldOpenWithWebIntents(download)) { 744 if (ShouldOpenWithWebIntents(download)) {
734 download->SetDisplayName(suggested_path.BaseName()); 745 download->SetDisplayName(suggested_path.BaseName());
735 suggested_path = suggested_path.AddExtension(kWebIntentsFileExtension); 746 suggested_path = suggested_path.AddExtension(kWebIntentsFileExtension);
736 } 747 }
737 748
749 ContinueFilenameDeterminationInfo continue_info;
750 continue_info.download_id = download_id;
751 continue_info.callback = callback;
752 continue_info.danger_type = danger_type;
753 continue_info.visited_referrer_before = visited_referrer_before;
754 continue_info.should_prompt = should_prompt;
755
756 base::Closure filename_determined = base::Bind(
757 &ChromeDownloadManagerDelegate::OnExtensionsDeterminedFilename,
758 this,
759 continue_info,
760 suggested_path,
761 is_forced_path);
762 #if !defined(OS_ANDROID)
763 if (is_forced_path ||
764 ShouldOpenWithWebIntents(download) ||
765 !DownloadServiceFactory::GetForProfile(profile_)
766 ->GetExtensionEventRouter()) {
767 filename_determined.Run();
768 } else {
769 DownloadServiceFactory::GetForProfile(profile_)->GetExtensionEventRouter()
770 ->OnDownloadFilenameDetermined(
771 download,
772 generated_name,
773 filename_determined,
774 base::Bind(&ChromeDownloadManagerDelegate::OnExtensionsChangingFilename,
775 this, continue_info));
776 }
777 #else
778 filename_determined.Run();
779 #endif
780 }
781
782 void ChromeDownloadManagerDelegate::OnExtensionsChangingFilename(
783 const ContinueFilenameDeterminationInfo& continue_info,
784 const FilePath& changed_filename,
785 bool overwrite) {
786 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
787 DownloadItem* download =
788 download_manager_->GetDownload(continue_info.download_id);
789 if (!download || (download->GetState() != DownloadItem::IN_PROGRESS))
790 return;
791 // If an extension overrides the filename, then the target directory will be
792 // forced to download_prefs_->DownloadPath() since extensions cannot place
793 // downloaded files anywhere except there. This prevents subdirectories from
794 // accumulating: if an extension is allowed to say that a file should go in
795 // last_download_path/music/foo.mp3, then last_download_path will accumulate
796 // the subdirectory /music/ so that the next download may end up in
797 // last_download_path/music/music/bar.mp3.
798 FilePath temp_filename(download_prefs_->DownloadPath().Append(
799 changed_filename));
800 net::GenerateSafeFileName(download->GetMimeType(), false, &temp_filename);
801 // If |is_forced_path| were true, then extensions would not have been
802 // consulted, so use |overwrite| instead of |is_forced_path|. This does NOT
803 // set DownloadItem::GetForcedFilePath()!
804 OnExtensionsDeterminedFilename(continue_info, temp_filename, overwrite);
805 }
806
807 void ChromeDownloadManagerDelegate::OnExtensionsDeterminedFilename(
808 const ContinueFilenameDeterminationInfo& continue_info,
809 const FilePath& suggested_path,
810 bool is_forced_path) {
811 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
812 int32 download_id = continue_info.download_id;
813 const content::DownloadTargetCallback& callback = continue_info.callback;
814 content::DownloadDangerType danger_type = continue_info.danger_type;
815 bool visited_referrer_before = continue_info.visited_referrer_before;
816 bool should_prompt = continue_info.should_prompt;
817 DownloadItem* download =
818 download_manager_->GetDownload(download_id);
819 if (!download || (download->GetState() != DownloadItem::IN_PROGRESS))
820 return;
821
738 // If the download hasn't already been marked dangerous (could be 822 // If the download hasn't already been marked dangerous (could be
739 // DANGEROUS_URL), check if it is a dangerous file. 823 // DANGEROUS_URL), check if it is a dangerous file.
740 if (danger_type == content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS) { 824 if (danger_type == content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS) {
741 if (!should_prompt && !is_forced_path && 825 if (!should_prompt && !is_forced_path &&
742 IsDangerousFile(*download, suggested_path, visited_referrer_before)) { 826 IsDangerousFile(*download, suggested_path, visited_referrer_before)) {
743 danger_type = content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE; 827 danger_type = content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE;
744 } 828 }
745 829
746 #if defined(FULL_SAFE_BROWSING) 830 #if defined(FULL_SAFE_BROWSING)
747 DownloadProtectionService* service = GetDownloadProtectionService(); 831 DownloadProtectionService* service = GetDownloadProtectionService();
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
855 // TODO(asanka): This logic is a hack. DownloadFilePicker should give us a 939 // TODO(asanka): This logic is a hack. DownloadFilePicker should give us a
856 // directory to persist. Or perhaps, if the Drive path 940 // directory to persist. Or perhaps, if the Drive path
857 // substitution logic is moved here, then we would have a 941 // substitution logic is moved here, then we would have a
858 // persistable path after the DownloadFilePicker is done. 942 // persistable path after the DownloadFilePicker is done.
859 if (disposition == DownloadItem::TARGET_DISPOSITION_PROMPT && 943 if (disposition == DownloadItem::TARGET_DISPOSITION_PROMPT &&
860 !download->IsTemporary()) 944 !download->IsTemporary())
861 last_download_path_ = target_path.DirName(); 945 last_download_path_ = target_path.DirName();
862 } 946 }
863 callback.Run(target_path, disposition, danger_type, intermediate_path); 947 callback.Run(target_path, disposition, danger_type, intermediate_path);
864 } 948 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698