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