1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/download/download_prefs.h"
6
7 #include "base/file_util.h"
8 #include "base/string_split.h"
9 #include "base/string_util.h"
10 #include "base/sys_string_conversions.h"
11 #include "base/utf_string_conversions.h"
12 #include "chrome/browser/download/download_extensions.h"
13 #include "chrome/browser/download/download_util.h"
14 #include "chrome/browser/download/save_package.h"
15 #include "chrome/browser/prefs/pref_service.h"
16 #include "chrome/common/pref_names.h"
17 #include "content/browser/browser_thread.h"
18
DownloadPrefs(PrefService * prefs)19 DownloadPrefs::DownloadPrefs(PrefService* prefs) : prefs_(prefs) {
20 prompt_for_download_.Init(prefs::kPromptForDownload, prefs, NULL);
21 download_path_.Init(prefs::kDownloadDefaultDirectory, prefs, NULL);
22 save_file_type_.Init(prefs::kSaveFileType, prefs, NULL);
23
24 // We store any file extension that should be opened automatically at
25 // download completion in this pref.
26 std::string extensions_to_open =
27 prefs->GetString(prefs::kDownloadExtensionsToOpen);
28 std::vector<std::string> extensions;
29 base::SplitString(extensions_to_open, ':', &extensions);
30
31 for (size_t i = 0; i < extensions.size(); ++i) {
32 #if defined(OS_POSIX)
33 FilePath path(extensions[i]);
34 #elif defined(OS_WIN)
35 FilePath path(UTF8ToWide(extensions[i]));
36 #endif
37 if (!extensions[i].empty() && download_util::IsFileSafe(path))
38 auto_open_.insert(path.value());
39 }
40 }
41
~DownloadPrefs()42 DownloadPrefs::~DownloadPrefs() {
43 SaveAutoOpenState();
44 }
45
46 // static
RegisterUserPrefs(PrefService * prefs)47 void DownloadPrefs::RegisterUserPrefs(PrefService* prefs) {
48 prefs->RegisterBooleanPref(prefs::kPromptForDownload, false);
49 prefs->RegisterStringPref(prefs::kDownloadExtensionsToOpen, "");
50 prefs->RegisterBooleanPref(prefs::kDownloadDirUpgraded, false);
51 prefs->RegisterIntegerPref(prefs::kSaveFileType,
52 SavePackage::SAVE_AS_COMPLETE_HTML);
53
54 // The default download path is userprofile\download.
55 const FilePath& default_download_path =
56 download_util::GetDefaultDownloadDirectory();
57 prefs->RegisterFilePathPref(prefs::kDownloadDefaultDirectory,
58 default_download_path);
59
60 #if defined(OS_CHROMEOS)
61 // Ensure that the download directory specified in the preferences exists.
62 BrowserThread::PostTask(
63 BrowserThread::FILE, FROM_HERE,
64 NewRunnableFunction(&file_util::CreateDirectory, default_download_path));
65 #endif // defined(OS_CHROMEOS)
66
67 // If the download path is dangerous we forcefully reset it. But if we do
68 // so we set a flag to make sure we only do it once, to avoid fighting
69 // the user if he really wants it on an unsafe place such as the desktop.
70 if (!prefs->GetBoolean(prefs::kDownloadDirUpgraded)) {
71 FilePath current_download_dir = prefs->GetFilePath(
72 prefs::kDownloadDefaultDirectory);
73 if (download_util::DownloadPathIsDangerous(current_download_dir)) {
74 prefs->SetFilePath(prefs::kDownloadDefaultDirectory,
75 default_download_path);
76 }
77 prefs->SetBoolean(prefs::kDownloadDirUpgraded, true);
78 }
79 }
80
PromptForDownload() const81 bool DownloadPrefs::PromptForDownload() const {
82 return *prompt_for_download_ && !download_path_.IsManaged();
83 }
84
IsDownloadPathManaged() const85 bool DownloadPrefs::IsDownloadPathManaged() const {
86 return download_path_.IsManaged();
87 }
88
IsAutoOpenUsed() const89 bool DownloadPrefs::IsAutoOpenUsed() const {
90 return !auto_open_.empty();
91 }
92
IsAutoOpenEnabledForExtension(const FilePath::StringType & extension) const93 bool DownloadPrefs::IsAutoOpenEnabledForExtension(
94 const FilePath::StringType& extension) const {
95 return auto_open_.find(extension) != auto_open_.end();
96 }
97
EnableAutoOpenBasedOnExtension(const FilePath & file_name)98 bool DownloadPrefs::EnableAutoOpenBasedOnExtension(const FilePath& file_name) {
99 FilePath::StringType extension = file_name.Extension();
100 if (extension.empty())
101 return false;
102 DCHECK(extension[0] == FilePath::kExtensionSeparator);
103 extension.erase(0, 1);
104
105 auto_open_.insert(extension);
106 SaveAutoOpenState();
107 return true;
108 }
109
DisableAutoOpenBasedOnExtension(const FilePath & file_name)110 void DownloadPrefs::DisableAutoOpenBasedOnExtension(const FilePath& file_name) {
111 FilePath::StringType extension = file_name.Extension();
112 if (extension.empty())
113 return;
114 DCHECK(extension[0] == FilePath::kExtensionSeparator);
115 extension.erase(0, 1);
116 auto_open_.erase(extension);
117 SaveAutoOpenState();
118 }
119
ResetToDefaults()120 void DownloadPrefs::ResetToDefaults() {
121 // TODO(phajdan.jr): Should we reset rest of prefs here?
122 ResetAutoOpen();
123 }
124
ResetAutoOpen()125 void DownloadPrefs::ResetAutoOpen() {
126 auto_open_.clear();
127 SaveAutoOpenState();
128 }
129
SaveAutoOpenState()130 void DownloadPrefs::SaveAutoOpenState() {
131 std::string extensions;
132 for (AutoOpenSet::iterator it = auto_open_.begin();
133 it != auto_open_.end(); ++it) {
134 #if defined(OS_POSIX)
135 std::string this_extension = *it;
136 #elif defined(OS_WIN)
137 // TODO(phajdan.jr): Why we're using Sys conversion here, but not in ctor?
138 std::string this_extension = base::SysWideToUTF8(*it);
139 #endif
140 extensions += this_extension + ":";
141 }
142 if (!extensions.empty())
143 extensions.erase(extensions.size() - 1);
144
145 prefs_->SetString(prefs::kDownloadExtensionsToOpen, extensions);
146 }
147
operator ()(const FilePath::StringType & a,const FilePath::StringType & b) const148 bool DownloadPrefs::AutoOpenCompareFunctor::operator()(
149 const FilePath::StringType& a,
150 const FilePath::StringType& b) const {
151 return FilePath::CompareLessIgnoreCase(a, b);
152 }
153