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

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: @r183850 Created 7 years, 10 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/pref_service.h" 13 #include "base/prefs/pref_service.h"
14 #include "base/prefs/public/pref_member.h" 14 #include "base/prefs/public/pref_member.h"
15 #include "base/rand_util.h" 15 #include "base/rand_util.h"
16 #include "base/stringprintf.h" 16 #include "base/stringprintf.h"
17 #include "base/time.h" 17 #include "base/time.h"
18 #include "base/utf_string_conversions.h" 18 #include "base/utf_string_conversions.h"
19 #include "chrome/browser/browser_process.h" 19 #include "chrome/browser/browser_process.h"
20 #include "chrome/browser/download/download_completion_blocker.h" 20 #include "chrome/browser/download/download_completion_blocker.h"
21 #include "chrome/browser/download/download_crx_util.h" 21 #include "chrome/browser/download/download_crx_util.h"
22 #include "chrome/browser/download/download_extensions.h" 22 #include "chrome/browser/download/download_extensions.h"
23 #include "chrome/browser/download/download_file_picker.h" 23 #include "chrome/browser/download/download_file_picker.h"
24 #include "chrome/browser/download/download_history.h" 24 #include "chrome/browser/download/download_history.h"
25 #include "chrome/browser/download/download_path_reservation_tracker.h" 25 #include "chrome/browser/download/download_path_reservation_tracker.h"
26 #include "chrome/browser/download/download_prefs.h" 26 #include "chrome/browser/download/download_prefs.h"
27 #include "chrome/browser/download/download_service.h"
28 #include "chrome/browser/download/download_service_factory.h"
27 #include "chrome/browser/download/download_status_updater.h" 29 #include "chrome/browser/download/download_status_updater.h"
28 #include "chrome/browser/download/download_util.h" 30 #include "chrome/browser/download/download_util.h"
29 #include "chrome/browser/download/save_package_file_picker.h" 31 #include "chrome/browser/download/save_package_file_picker.h"
30 #include "chrome/browser/extensions/api/downloads/downloads_api.h" 32 #include "chrome/browser/extensions/api/downloads/downloads_api.h"
31 #include "chrome/browser/extensions/crx_installer.h" 33 #include "chrome/browser/extensions/crx_installer.h"
32 #include "chrome/browser/extensions/extension_service.h" 34 #include "chrome/browser/extensions/extension_service.h"
33 #include "chrome/browser/extensions/extension_system.h" 35 #include "chrome/browser/extensions/extension_system.h"
34 #include "chrome/browser/history/history_service.h" 36 #include "chrome/browser/history/history_service.h"
35 #include "chrome/browser/history/history_service_factory.h" 37 #include "chrome/browser/history/history_service_factory.h"
36 #include "chrome/browser/platform_util.h" 38 #include "chrome/browser/platform_util.h"
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
201 : profile_(profile), 203 : profile_(profile),
202 next_download_id_(0), 204 next_download_id_(0),
203 download_prefs_(new DownloadPrefs(profile)) { 205 download_prefs_(new DownloadPrefs(profile)) {
204 } 206 }
205 207
206 ChromeDownloadManagerDelegate::~ChromeDownloadManagerDelegate() { 208 ChromeDownloadManagerDelegate::~ChromeDownloadManagerDelegate() {
207 } 209 }
208 210
209 void ChromeDownloadManagerDelegate::SetDownloadManager(DownloadManager* dm) { 211 void ChromeDownloadManagerDelegate::SetDownloadManager(DownloadManager* dm) {
210 download_manager_ = dm; 212 download_manager_ = dm;
211 #if !defined(OS_ANDROID)
212 extension_event_router_.reset(new ExtensionDownloadsEventRouter(
213 profile_, download_manager_));
214 #endif
215 } 213 }
216 214
217 void ChromeDownloadManagerDelegate::Shutdown() { 215 void ChromeDownloadManagerDelegate::Shutdown() {
218 download_prefs_.reset(); 216 download_prefs_.reset();
219 #if !defined(OS_ANDROID)
220 extension_event_router_.reset();
221 #endif
222 } 217 }
223 218
224 DownloadId ChromeDownloadManagerDelegate::GetNextId() { 219 DownloadId ChromeDownloadManagerDelegate::GetNextId() {
225 if (!profile_->IsOffTheRecord()) 220 if (!profile_->IsOffTheRecord())
226 return DownloadId(this, next_download_id_++); 221 return DownloadId(this, next_download_id_++);
227 222
228 return BrowserContext::GetDownloadManager(profile_->GetOriginalProfile())-> 223 return BrowserContext::GetDownloadManager(profile_->GetOriginalProfile())->
229 GetDelegate()->GetNextId(); 224 GetDelegate()->GetNextId();
230 } 225 }
231 226
(...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after
614 chrome::NOTIFICATION_CRX_INSTALLER_DONE, 609 chrome::NOTIFICATION_CRX_INSTALLER_DONE,
615 source); 610 source);
616 611
617 scoped_refptr<extensions::CrxInstaller> installer = 612 scoped_refptr<extensions::CrxInstaller> installer =
618 content::Source<extensions::CrxInstaller>(source).ptr(); 613 content::Source<extensions::CrxInstaller>(source).ptr();
619 content::DownloadOpenDelayedCallback callback = crx_installers_[installer]; 614 content::DownloadOpenDelayedCallback callback = crx_installers_[installer];
620 crx_installers_.erase(installer.get()); 615 crx_installers_.erase(installer.get());
621 callback.Run(installer->did_handle_successfully()); 616 callback.Run(installer->did_handle_successfully());
622 } 617 }
623 618
619 struct ChromeDownloadManagerDelegate::ContinueFilenameDeterminationInfo {
asanka 2013/02/22 18:55:48 Shall we move this to the top of the source file?
benjhayden 2013/02/22 20:43:23 You mean to the anonymous namespace? Can't do -- i
620 ContinueFilenameDeterminationInfo();
621 ~ContinueFilenameDeterminationInfo();
622
623 int32 download_id;
624 content::DownloadTargetCallback callback;
625 content::DownloadDangerType danger_type;
626 bool visited_referrer_before;
627 bool should_prompt;
628 };
629
630 ChromeDownloadManagerDelegate::ContinueFilenameDeterminationInfo::
631 ContinueFilenameDeterminationInfo() {}
632 ChromeDownloadManagerDelegate::ContinueFilenameDeterminationInfo::
633 ~ContinueFilenameDeterminationInfo() {}
634
624 void ChromeDownloadManagerDelegate::CheckVisitedReferrerBeforeDone( 635 void ChromeDownloadManagerDelegate::CheckVisitedReferrerBeforeDone(
625 int32 download_id, 636 int32 download_id,
626 const content::DownloadTargetCallback& callback, 637 const content::DownloadTargetCallback& callback,
627 content::DownloadDangerType danger_type, 638 content::DownloadDangerType danger_type,
628 bool visited_referrer_before) { 639 bool visited_referrer_before) {
629 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 640 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
630 641
631 DownloadItem* download = 642 DownloadItem* download =
632 download_manager_->GetDownload(download_id); 643 download_manager_->GetDownload(download_id);
633 if (!download || (download->GetState() != DownloadItem::IN_PROGRESS)) 644 if (!download || (download->GetState() != DownloadItem::IN_PROGRESS))
634 return; 645 return;
635 646
636 bool should_prompt = (download->GetTargetDisposition() == 647 bool should_prompt = (download->GetTargetDisposition() ==
637 DownloadItem::TARGET_DISPOSITION_PROMPT); 648 DownloadItem::TARGET_DISPOSITION_PROMPT);
638 bool is_forced_path = !download->GetForcedFilePath().empty(); 649 bool is_forced_path = !download->GetForcedFilePath().empty();
650 base::FilePath generated_name;
639 base::FilePath suggested_path; 651 base::FilePath suggested_path;
640 652
641 // Check whether this download is for an extension install or not. 653 // Check whether this download is for an extension install or not.
642 // Allow extensions to be explicitly saved. 654 // Allow extensions to be explicitly saved.
643 if (!is_forced_path) { 655 if (!is_forced_path) {
644 base::FilePath generated_name;
645 GenerateFileNameFromRequest( 656 GenerateFileNameFromRequest(
646 *download, 657 *download,
647 &generated_name, 658 &generated_name,
648 profile_->GetPrefs()->GetString(prefs::kDefaultCharset)); 659 profile_->GetPrefs()->GetString(prefs::kDefaultCharset));
649 660
650 // Freeze the user's preference for showing a Save As dialog. We're going 661 // Freeze the user's preference for showing a Save As dialog. We're going
651 // to bounce around a bunch of threads and we don't want to worry about race 662 // to bounce around a bunch of threads and we don't want to worry about race
652 // conditions where the user changes this pref out from under us. 663 // conditions where the user changes this pref out from under us.
653 if (download_prefs_->PromptForDownload()) { 664 if (download_prefs_->PromptForDownload()) {
654 // But ignore the user's preference for the following scenarios: 665 // But ignore the user's preference for the following scenarios:
(...skipping 16 matching lines...) Expand all
671 if (should_prompt && !last_download_path_.empty()) 682 if (should_prompt && !last_download_path_.empty())
672 target_directory = last_download_path_; 683 target_directory = last_download_path_;
673 else 684 else
674 target_directory = download_prefs_->DownloadPath(); 685 target_directory = download_prefs_->DownloadPath();
675 suggested_path = target_directory.Append(generated_name); 686 suggested_path = target_directory.Append(generated_name);
676 } else { 687 } else {
677 DCHECK(!should_prompt); 688 DCHECK(!should_prompt);
678 suggested_path = download->GetForcedFilePath(); 689 suggested_path = download->GetForcedFilePath();
679 } 690 }
680 691
692 ContinueFilenameDeterminationInfo continue_info;
693 continue_info.download_id = download_id;
694 continue_info.callback = callback;
695 continue_info.danger_type = danger_type;
696 continue_info.visited_referrer_before = visited_referrer_before;
697 continue_info.should_prompt = should_prompt;
698
699 base::Closure filename_determined = base::Bind(
700 &ChromeDownloadManagerDelegate::ContinueDeterminingFilename,
701 this, continue_info, suggested_path, is_forced_path);
702 #if !defined(OS_ANDROID)
703 if (is_forced_path ||
704 !DownloadServiceFactory::GetForProfile(profile_)
705 ->GetExtensionEventRouter()) {
706 filename_determined.Run();
707 } else {
708 DownloadService* service = DownloadServiceFactory::GetForProfile(profile_);
709 ExtensionDownloadsEventRouter* router = service->GetExtensionEventRouter();
710 ExtensionDownloadsEventRouter::FilenameChangedCallback overriding =
711 base::Bind(&ChromeDownloadManagerDelegate::OnExtensionOverridingFilename,
712 this, continue_info);
713 router->OnDeterminingFilename(
714 download, generated_name, filename_determined, overriding);
715 }
716 #else // defined(OS_ANDROID)
717 filename_determined.Run();
718 #endif // defined(OS_ANDROID)
719 }
720
721 void ChromeDownloadManagerDelegate::OnExtensionOverridingFilename(
722 const ContinueFilenameDeterminationInfo& continue_info,
723 const base::FilePath& changed_filename,
724 bool overwrite) {
725 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
726 DownloadItem* download =
727 download_manager_->GetDownload(continue_info.download_id);
728 if (!download || (download->GetState() != DownloadItem::IN_PROGRESS))
729 return;
730 // If an extension overrides the filename, then the target directory will be
731 // forced to download_prefs_->DownloadPath() since extensions cannot place
732 // downloaded files anywhere except there. This prevents subdirectories from
733 // accumulating: if an extension is allowed to say that a file should go in
734 // last_download_path/music/foo.mp3, then last_download_path will accumulate
735 // the subdirectory /music/ so that the next download may end up in
736 // Downloads/music/music/music/bar.mp3.
737 base::FilePath temp_filename(download_prefs_->DownloadPath().Append(
738 changed_filename));
asanka 2013/02/22 18:55:48 Also normalize path separators. Or we might end up
benjhayden 2013/02/22 20:43:23 Done.
739 net::GenerateSafeFileName(download->GetMimeType(), false, &temp_filename);
asanka 2013/02/22 18:55:48 This could prevent the extension from setting a fi
benjhayden 2013/02/22 20:43:23 Done.
740 // If |is_forced_path| were true, then extensions would not have been
741 // consulted, so use |overwrite| instead of |is_forced_path|. This does NOT
742 // set DownloadItem::GetForcedFilePath()!
743 ContinueDeterminingFilename(continue_info, temp_filename, overwrite);
744 }
745
746 void ChromeDownloadManagerDelegate::ContinueDeterminingFilename(
747 const ContinueFilenameDeterminationInfo& continue_info,
748 const base::FilePath& suggested_path,
749 bool is_forced_path) {
750 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
751 int32 download_id = continue_info.download_id;
752 const content::DownloadTargetCallback& callback = continue_info.callback;
753 content::DownloadDangerType danger_type = continue_info.danger_type;
754 bool visited_referrer_before = continue_info.visited_referrer_before;
755 bool should_prompt = continue_info.should_prompt;
756 DownloadItem* download =
757 download_manager_->GetDownload(download_id);
758 if (!download || (download->GetState() != DownloadItem::IN_PROGRESS))
759 return;
760
681 // If the download hasn't already been marked dangerous (could be 761 // If the download hasn't already been marked dangerous (could be
682 // DANGEROUS_URL), check if it is a dangerous file. 762 // DANGEROUS_URL), check if it is a dangerous file.
683 if (danger_type == content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS) { 763 if (danger_type == content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS) {
684 if (!should_prompt && !is_forced_path && 764 if (!should_prompt && !is_forced_path &&
685 IsDangerousFile(*download, suggested_path, visited_referrer_before)) { 765 IsDangerousFile(*download, suggested_path, visited_referrer_before)) {
686 danger_type = content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE; 766 danger_type = content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE;
687 } 767 }
688 768
689 #if defined(FULL_SAFE_BROWSING) 769 #if defined(FULL_SAFE_BROWSING)
690 DownloadProtectionService* service = GetDownloadProtectionService(); 770 DownloadProtectionService* service = GetDownloadProtectionService();
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
812 // TODO(asanka): This logic is a hack. DownloadFilePicker should give us a 892 // TODO(asanka): This logic is a hack. DownloadFilePicker should give us a
813 // directory to persist. Or perhaps, if the Drive path 893 // directory to persist. Or perhaps, if the Drive path
814 // substitution logic is moved here, then we would have a 894 // substitution logic is moved here, then we would have a
815 // persistable path after the DownloadFilePicker is done. 895 // persistable path after the DownloadFilePicker is done.
816 if (disposition == DownloadItem::TARGET_DISPOSITION_PROMPT && 896 if (disposition == DownloadItem::TARGET_DISPOSITION_PROMPT &&
817 !download->IsTemporary()) 897 !download->IsTemporary())
818 last_download_path_ = target_path.DirName(); 898 last_download_path_ = target_path.DirName();
819 } 899 }
820 callback.Run(target_path, disposition, danger_type, intermediate_path); 900 callback.Run(target_path, disposition, danger_type, intermediate_path);
821 } 901 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698