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.
5 #include "chrome/browser/chromeos/file_manager/path_util.h"
7 #include "base/files/file_path.h"
8 #include "base/logging.h"
9 #include "base/path_service.h"
10 #include "base/sys_info.h"
11 #include "chrome/browser/chromeos/drive/file_system_util.h"
12 #include "chrome/browser/chromeos/login/user.h"
13 #include "chrome/browser/chromeos/login/user_manager.h"
14 #include "chrome/browser/download/download_prefs.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "content/public/browser/browser_context.h"
17 #include "net/base/escape.h"
18 #include "webkit/browser/fileapi/external_mount_points.h"
20 namespace file_manager {
25 const char kDownloadsFolderName[] = "Downloads";
26 const base::FilePath::CharType kOldDownloadsFolderPath[] =
27 FILE_PATH_LITERAL("/home/chronos/user/Downloads");
31 base::FilePath GetDownloadsFolderForProfile(Profile* profile) {
32 if (!base::SysInfo::IsRunningOnChromeOS() &&
33 !chromeos::UserManager::IsMultipleProfilesAllowed()) {
34 // On the developer run on Linux desktop build, if multiple profiles are
35 // not enabled, use $HOME/Downloads for ease for accessing local files for
38 CHECK(PathService::Get(base::DIR_HOME, &path));
39 return path.AppendASCII(kDownloadsFolderName);
42 return profile->GetPath().AppendASCII(kDownloadsFolderName);
45 bool MigratePathFromOldFormat(Profile* profile,
46 const base::FilePath& old_path,
47 base::FilePath* new_path) {
49 // /home/chronos/user/Downloads/xxx => /home/chronos/u-hash/Downloads/xxx
51 // Old path format comes either from stored old settings or from the initial
52 // default value set in DownloadPrefs::RegisterProfilePrefs in profile-unaware
53 // code location. In the former case it is "/home/chronos/user/Downloads",
54 // and in the latter case it is DownloadPrefs::GetDefaultDownloadDirectory().
55 // Those two paths coincides as long as $HOME=/home/chronos/user, but the
56 // environment variable is phasing out (crbug.com/333031) so we care both.
57 const base::FilePath old_bases[] = {
58 base::FilePath(kOldDownloadsFolderPath),
59 DownloadPrefs::GetDefaultDownloadDirectory(),
61 for (size_t i = 0; i < arraysize(old_bases); ++i) {
62 const base::FilePath& old_base = old_bases[i];
63 base::FilePath relative;
64 if (old_path == old_base ||
65 old_base.AppendRelativePath(old_path, &relative)) {
66 const base::FilePath new_base = GetDownloadsFolderForProfile(profile);
67 *new_path = new_base.Append(relative);
68 return old_path != *new_path;
75 std::string GetDownloadsMountPointName(Profile* profile) {
76 // To distinguish profiles in multi-profile session, we append user name hash
77 // to "Downloads". Note that some profiles (like login or test profiles)
78 // are not associated with an user account. In that case, no suffix is added
79 // because such a profile never belongs to a multi-profile session.
80 chromeos::User* const user =
81 chromeos::UserManager::IsInitialized() ?
82 chromeos::UserManager::Get()->GetUserByProfile(
83 profile->GetOriginalProfile()) : NULL;
84 const std::string id = user ? "-" + user->username_hash() : "";
85 return net::EscapePath(kDownloadsFolderName + id);
88 bool RegisterDownloadsMountPoint(Profile* profile, const base::FilePath& path) {
89 // Although we show only profile's own "Downloads" folder in Files.app,
90 // in the backend we need to mount all profile's download directory globally.
91 // Otherwise, Files.app cannot support cross-profile file copies, etc.
92 // For this reason, we need to register to the global GetSystemInstance().
93 const std::string mount_point_name = GetDownloadsMountPointName(profile);
94 fileapi::ExternalMountPoints* const mount_points =
95 fileapi::ExternalMountPoints::GetSystemInstance();
97 // In some tests we want to override existing Downloads mount point, so we
98 // first revoke the existing mount point (if any).
99 mount_points->RevokeFileSystem(mount_point_name);
100 return mount_points->RegisterFileSystem(
101 mount_point_name, fileapi::kFileSystemTypeNativeLocal,
102 fileapi::FileSystemMountOption(), path);
105 bool FindDownloadsMountPointPath(Profile* profile, base::FilePath* path) {
106 const std::string mount_point_name = GetDownloadsMountPointName(profile);
107 fileapi::ExternalMountPoints* const mount_points =
108 fileapi::ExternalMountPoints::GetSystemInstance();
110 return mount_points->GetRegisteredPath(mount_point_name, path);
114 } // namespace file_manager