Home | History | Annotate | Download | only in download
      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
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/download/download_prefs.h"
      6 
      7 #include <string>
      8 #include <vector>
      9 
     10 #include "base/bind.h"
     11 #include "base/bind_helpers.h"
     12 #include "base/file_util.h"
     13 #include "base/logging.h"
     14 #include "base/prefs/pref_service.h"
     15 #include "base/strings/string_split.h"
     16 #include "base/strings/string_util.h"
     17 #include "base/strings/sys_string_conversions.h"
     18 #include "base/strings/utf_string_conversions.h"
     19 #include "chrome/browser/download/chrome_download_manager_delegate.h"
     20 #include "chrome/browser/download/download_extensions.h"
     21 #include "chrome/browser/download/download_service.h"
     22 #include "chrome/browser/download/download_service_factory.h"
     23 #include "chrome/browser/download/download_util.h"
     24 #include "chrome/browser/profiles/profile.h"
     25 #include "chrome/browser/profiles/profile_manager.h"
     26 #include "chrome/common/pref_names.h"
     27 #include "components/user_prefs/pref_registry_syncable.h"
     28 #include "content/public/browser/browser_thread.h"
     29 #include "content/public/browser/download_manager.h"
     30 #include "content/public/browser/save_page_type.h"
     31 
     32 #if defined(OS_CHROMEOS)
     33 #include "chrome/browser/chromeos/drive/drive_integration_service.h"
     34 #include "chrome/browser/chromeos/drive/file_system_util.h"
     35 #endif
     36 
     37 using content::BrowserContext;
     38 using content::BrowserThread;
     39 using content::DownloadManager;
     40 
     41 DownloadPrefs::DownloadPrefs(Profile* profile) : profile_(profile) {
     42   PrefService* prefs = profile->GetPrefs();
     43 
     44   // If the download path is dangerous we forcefully reset it. But if we do
     45   // so we set a flag to make sure we only do it once, to avoid fighting
     46   // the user if he really wants it on an unsafe place such as the desktop.
     47   if (!prefs->GetBoolean(prefs::kDownloadDirUpgraded)) {
     48     base::FilePath current_download_dir = prefs->GetFilePath(
     49         prefs::kDownloadDefaultDirectory);
     50     if (download_util::DownloadPathIsDangerous(current_download_dir)) {
     51       prefs->SetFilePath(prefs::kDownloadDefaultDirectory,
     52                          download_util::GetDefaultDownloadDirectory());
     53     }
     54     prefs->SetBoolean(prefs::kDownloadDirUpgraded, true);
     55   }
     56 
     57   prompt_for_download_.Init(prefs::kPromptForDownload, prefs);
     58   download_path_.Init(prefs::kDownloadDefaultDirectory, prefs);
     59   save_file_path_.Init(prefs::kSaveFileDefaultDirectory, prefs);
     60   save_file_type_.Init(prefs::kSaveFileType, prefs);
     61 
     62   // We store any file extension that should be opened automatically at
     63   // download completion in this pref.
     64   std::string extensions_to_open =
     65       prefs->GetString(prefs::kDownloadExtensionsToOpen);
     66   std::vector<std::string> extensions;
     67   base::SplitString(extensions_to_open, ':', &extensions);
     68 
     69   for (size_t i = 0; i < extensions.size(); ++i) {
     70 #if defined(OS_POSIX)
     71     base::FilePath path(extensions[i]);
     72 #elif defined(OS_WIN)
     73     base::FilePath path(UTF8ToWide(extensions[i]));
     74 #endif
     75     if (!extensions[i].empty() &&
     76         download_util::GetFileDangerLevel(path) == download_util::NOT_DANGEROUS)
     77       auto_open_.insert(path.value());
     78   }
     79 }
     80 
     81 DownloadPrefs::~DownloadPrefs() {
     82 }
     83 
     84 // static
     85 void DownloadPrefs::RegisterProfilePrefs(
     86     user_prefs::PrefRegistrySyncable* registry) {
     87   registry->RegisterBooleanPref(
     88       prefs::kPromptForDownload,
     89       false,
     90       user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
     91   registry->RegisterStringPref(
     92       prefs::kDownloadExtensionsToOpen,
     93       std::string(),
     94       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
     95   registry->RegisterBooleanPref(
     96       prefs::kDownloadDirUpgraded,
     97       false,
     98       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
     99   registry->RegisterIntegerPref(
    100       prefs::kSaveFileType,
    101       content::SAVE_PAGE_TYPE_AS_COMPLETE_HTML,
    102       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
    103 
    104   // The default download path is userprofile\download.
    105   const base::FilePath& default_download_path =
    106       download_util::GetDefaultDownloadDirectory();
    107   registry->RegisterFilePathPref(
    108       prefs::kDownloadDefaultDirectory,
    109       default_download_path,
    110       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
    111   registry->RegisterFilePathPref(
    112       prefs::kSaveFileDefaultDirectory,
    113       default_download_path,
    114       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
    115 
    116 #if defined(OS_CHROMEOS)
    117   // Ensure that the download directory specified in the preferences exists.
    118   BrowserThread::PostTask(
    119       BrowserThread::FILE, FROM_HERE,
    120       base::Bind(base::IgnoreResult(&file_util::CreateDirectory),
    121                  default_download_path));
    122 #endif  // defined(OS_CHROMEOS)
    123 }
    124 
    125 // static
    126 DownloadPrefs* DownloadPrefs::FromDownloadManager(
    127     DownloadManager* download_manager) {
    128   ChromeDownloadManagerDelegate* delegate =
    129       static_cast<ChromeDownloadManagerDelegate*>(
    130           download_manager->GetDelegate());
    131   return delegate->download_prefs();
    132 }
    133 
    134 // static
    135 DownloadPrefs* DownloadPrefs::FromBrowserContext(
    136     content::BrowserContext* context) {
    137   return FromDownloadManager(BrowserContext::GetDownloadManager(context));
    138 }
    139 
    140 base::FilePath DownloadPrefs::DownloadPath() const {
    141 #if defined(OS_CHROMEOS)
    142   // If the download path is under /drive, and DriveIntegrationService isn't
    143   // available (which it isn't for incognito mode, for instance), use the
    144   // default download directory (/Downloads).
    145   if (drive::util::IsUnderDriveMountPoint(*download_path_) &&
    146       !drive::DriveIntegrationServiceFactory::GetForProfile(profile_))
    147     return download_util::GetDefaultDownloadDirectory();
    148 #endif
    149   return *download_path_;
    150 }
    151 
    152 void DownloadPrefs::SetDownloadPath(const base::FilePath& path) {
    153   download_path_.SetValue(path);
    154   SetSaveFilePath(path);
    155 }
    156 
    157 base::FilePath DownloadPrefs::SaveFilePath() const {
    158   return *save_file_path_;
    159 }
    160 
    161 void DownloadPrefs::SetSaveFilePath(const base::FilePath& path) {
    162   save_file_path_.SetValue(path);
    163 }
    164 
    165 void DownloadPrefs::SetSaveFileType(int type) {
    166   save_file_type_.SetValue(type);
    167 }
    168 
    169 bool DownloadPrefs::PromptForDownload() const {
    170   // If the DownloadDirectory policy is set, then |prompt_for_download_| should
    171   // always be false.
    172   DCHECK(!download_path_.IsManaged() || !prompt_for_download_.GetValue());
    173   return *prompt_for_download_;
    174 }
    175 
    176 bool DownloadPrefs::IsDownloadPathManaged() const {
    177   return download_path_.IsManaged();
    178 }
    179 
    180 bool DownloadPrefs::IsAutoOpenUsed() const {
    181   return !auto_open_.empty();
    182 }
    183 
    184 bool DownloadPrefs::IsAutoOpenEnabledBasedOnExtension(
    185     const base::FilePath& path) const {
    186   base::FilePath::StringType extension = path.Extension();
    187   if (extension.empty())
    188     return false;
    189   DCHECK(extension[0] == base::FilePath::kExtensionSeparator);
    190   extension.erase(0, 1);
    191   return auto_open_.find(extension) != auto_open_.end();
    192 }
    193 
    194 bool DownloadPrefs::EnableAutoOpenBasedOnExtension(
    195     const base::FilePath& file_name) {
    196   base::FilePath::StringType extension = file_name.Extension();
    197   if (extension.empty())
    198     return false;
    199   DCHECK(extension[0] == base::FilePath::kExtensionSeparator);
    200   extension.erase(0, 1);
    201 
    202   auto_open_.insert(extension);
    203   SaveAutoOpenState();
    204   return true;
    205 }
    206 
    207 void DownloadPrefs::DisableAutoOpenBasedOnExtension(
    208     const base::FilePath& file_name) {
    209   base::FilePath::StringType extension = file_name.Extension();
    210   if (extension.empty())
    211     return;
    212   DCHECK(extension[0] == base::FilePath::kExtensionSeparator);
    213   extension.erase(0, 1);
    214   auto_open_.erase(extension);
    215   SaveAutoOpenState();
    216 }
    217 
    218 void DownloadPrefs::ResetAutoOpen() {
    219   auto_open_.clear();
    220   SaveAutoOpenState();
    221 }
    222 
    223 void DownloadPrefs::SaveAutoOpenState() {
    224   std::string extensions;
    225   for (AutoOpenSet::iterator it = auto_open_.begin();
    226        it != auto_open_.end(); ++it) {
    227 #if defined(OS_POSIX)
    228     std::string this_extension = *it;
    229 #elif defined(OS_WIN)
    230     // TODO(phajdan.jr): Why we're using Sys conversion here, but not in ctor?
    231     std::string this_extension = base::SysWideToUTF8(*it);
    232 #endif
    233     extensions += this_extension + ":";
    234   }
    235   if (!extensions.empty())
    236     extensions.erase(extensions.size() - 1);
    237 
    238   profile_->GetPrefs()->SetString(prefs::kDownloadExtensionsToOpen, extensions);
    239 }
    240 
    241 bool DownloadPrefs::AutoOpenCompareFunctor::operator()(
    242     const base::FilePath::StringType& a,
    243     const base::FilePath::StringType& b) const {
    244   return base::FilePath::CompareLessIgnoreCase(a, b);
    245 }
    246