1 // Copyright 2013 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/chromeos/file_manager/path_util.h" 6 7 #include "base/files/file_path.h" 8 #include "base/logging.h" 9 #include "base/sys_info.h" 10 #include "chrome/browser/chromeos/drive/file_system_util.h" 11 #include "chrome/browser/chromeos/profiles/profile_helper.h" 12 #include "chrome/browser/download/download_prefs.h" 13 #include "chrome/browser/profiles/profile.h" 14 #include "components/user_manager/user.h" 15 #include "components/user_manager/user_manager.h" 16 #include "net/base/escape.h" 17 18 namespace file_manager { 19 namespace util { 20 21 namespace { 22 23 const char kDownloadsFolderName[] = "Downloads"; 24 const base::FilePath::CharType kOldDownloadsFolderPath[] = 25 FILE_PATH_LITERAL("/home/chronos/user/Downloads"); 26 const base::FilePath::CharType kOldDriveFolderPath[] = 27 FILE_PATH_LITERAL("/special/drive"); 28 // Unintended path introduced in crbug.com/363026. 29 const base::FilePath::CharType kBuggyDriveFolderPath[] = 30 FILE_PATH_LITERAL("/special/drive-user"); 31 32 } // namespace 33 34 base::FilePath GetDownloadsFolderForProfile(Profile* profile) { 35 // On non-ChromeOS system (test+development), the primary profile uses 36 // $HOME/Downloads for ease for accessing local files for debugging. 37 if (!base::SysInfo::IsRunningOnChromeOS() && 38 user_manager::UserManager::IsInitialized()) { 39 const user_manager::User* const user = 40 chromeos::ProfileHelper::Get()->GetUserByProfile( 41 profile->GetOriginalProfile()); 42 const user_manager::User* const primary_user = 43 user_manager::UserManager::Get()->GetPrimaryUser(); 44 if (user == primary_user) 45 return DownloadPrefs::GetDefaultDownloadDirectory(); 46 } 47 return profile->GetPath().AppendASCII(kDownloadsFolderName); 48 } 49 50 bool MigratePathFromOldFormat(Profile* profile, 51 const base::FilePath& old_path, 52 base::FilePath* new_path) { 53 // M34: 54 // /home/chronos/user/Downloads/xxx => /home/chronos/u-hash/Downloads/xxx 55 // /special/drive => /special/drive-xxx 56 // 57 // Old path format comes either from stored old settings or from the initial 58 // default value set in DownloadPrefs::RegisterProfilePrefs in profile-unaware 59 // code location. In the former case it is "/home/chronos/user/Downloads", 60 // and in the latter case it is DownloadPrefs::GetDefaultDownloadDirectory(). 61 // Those two paths coincides as long as $HOME=/home/chronos/user, but the 62 // environment variable is phasing out (crbug.com/333031) so we care both. 63 64 const base::FilePath downloads = GetDownloadsFolderForProfile(profile); 65 const base::FilePath drive = drive::util::GetDriveMountPointPath(profile); 66 67 std::vector<std::pair<base::FilePath, base::FilePath> > bases; 68 bases.push_back(std::make_pair(base::FilePath(kOldDownloadsFolderPath), 69 downloads)); 70 bases.push_back(std::make_pair(DownloadPrefs::GetDefaultDownloadDirectory(), 71 downloads)); 72 bases.push_back(std::make_pair(base::FilePath(kOldDriveFolderPath), drive)); 73 bases.push_back(std::make_pair(base::FilePath(kBuggyDriveFolderPath), drive)); 74 75 // Trying migrating u-<hash>/Downloads to the current download path. This is 76 // no-op when multi-profile is enabled. This is necessary for (1) back 77 // migration when multi-profile flag is enabled and then disabled, or (2) in 78 // some edge cases (crbug.com/356322) that u-<hash> path is temporarily used. 79 if (user_manager::UserManager::IsInitialized()) { 80 const user_manager::User* const user = 81 chromeos::ProfileHelper::Get()->GetUserByProfile(profile); 82 if (user) { 83 const base::FilePath hashed_downloads = 84 chromeos::ProfileHelper::GetProfilePathByUserIdHash( 85 user->username_hash()).AppendASCII(kDownloadsFolderName); 86 bases.push_back(std::make_pair(hashed_downloads, downloads)); 87 } 88 } 89 90 for (size_t i = 0; i < bases.size(); ++i) { 91 const base::FilePath& old_base = bases[i].first; 92 const base::FilePath& new_base = bases[i].second; 93 base::FilePath relative; 94 if (old_path == old_base || 95 old_base.AppendRelativePath(old_path, &relative)) { 96 *new_path = new_base.Append(relative); 97 return old_path != *new_path; 98 } 99 } 100 101 return false; 102 } 103 104 std::string GetDownloadsMountPointName(Profile* profile) { 105 // To distinguish profiles in multi-profile session, we append user name hash 106 // to "Downloads". Note that some profiles (like login or test profiles) 107 // are not associated with an user account. In that case, no suffix is added 108 // because such a profile never belongs to a multi-profile session. 109 user_manager::User* const user = 110 user_manager::UserManager::IsInitialized() 111 ? chromeos::ProfileHelper::Get()->GetUserByProfile( 112 profile->GetOriginalProfile()) 113 : NULL; 114 const std::string id = user ? "-" + user->username_hash() : ""; 115 return net::EscapeQueryParamValue(kDownloadsFolderName + id, false); 116 } 117 118 } // namespace util 119 } // namespace file_manager 120