summaryrefslogtreecommitdiffstats
path: root/chrome/common/chrome_paths_win.cc
blob: c9afb7a2ea9a32fb005e3654842fe0bb811a33f9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/common/chrome_paths_internal.h"

#include <windows.h>
#include <knownfolders.h>
#include <shellapi.h>
#include <shlobj.h>
#include <shobjidl.h>

#include "base/file_path.h"
#include "base/path_service.h"
#include "base/win/metro.h"
#include "base/win/scoped_co_mem.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/installer/util/browser_distribution.h"
#include "content/public/common/content_switches.h"

namespace chrome {

namespace {

// Gets the default user data directory for either the current environment
// (desktop or metro) or for the other one (metro or desktop).
bool GetUserDataDirectoryForEnvironment(bool current, FilePath* result) {
  if (!PathService::Get(base::DIR_LOCAL_APP_DATA, result))
    return false;
  BrowserDistribution* dist = BrowserDistribution::GetDistribution();
  *result = result->Append(dist->GetInstallSubDir());
  if (base::win::IsMetroProcess() ? current : !current)
    *result = result->Append(kMetroChromeUserDataSubDir);
  *result = result->Append(chrome::kUserDataDirname);
  return true;
}

}  // namespace

bool GetDefaultUserDataDirectory(FilePath* result) {
  return GetUserDataDirectoryForEnvironment(true, result);
}

bool GetAlternateUserDataDirectory(FilePath *result) {
  return GetUserDataDirectoryForEnvironment(false, result);
}

bool GetChromeFrameUserDataDirectory(FilePath* result) {
  if (!PathService::Get(base::DIR_LOCAL_APP_DATA, result))
    return false;
  BrowserDistribution* dist = BrowserDistribution::GetSpecificDistribution(
      BrowserDistribution::CHROME_FRAME);
  *result = result->Append(dist->GetInstallSubDir());
  *result = result->Append(chrome::kUserDataDirname);
  return true;
}

void GetUserCacheDirectory(const FilePath& profile_dir, FilePath* result) {
  // This function does more complicated things on Mac/Linux.
  *result = profile_dir;
}

bool GetUserDocumentsDirectory(FilePath* result) {
  wchar_t path_buf[MAX_PATH];
  if (FAILED(SHGetFolderPath(NULL, CSIDL_MYDOCUMENTS, NULL,
                             SHGFP_TYPE_CURRENT, path_buf)))
    return false;
  *result = FilePath(path_buf);
  return true;
}

// Return a default path for downloads that is safe.
// We just use 'Downloads' under DIR_USER_DOCUMENTS. Localizing
// 'downloads' is not a good idea because Chrome's UI language
// can be changed.
bool GetUserDownloadsDirectorySafe(FilePath* result) {
  if (!GetUserDocumentsDirectory(result))
    return false;

  *result = result->Append(L"Downloads");
  return true;
}

// On Vista and higher, use the downloads known folder. Since it can be
// relocated to point to a "dangerous" folder, callers should validate that the
// returned path is not dangerous before using it.
bool GetUserDownloadsDirectory(FilePath* result) {
  typedef HRESULT (WINAPI *GetKnownFolderPath)(
      REFKNOWNFOLDERID, DWORD, HANDLE, PWSTR*);
  GetKnownFolderPath f = reinterpret_cast<GetKnownFolderPath>(
      GetProcAddress(GetModuleHandle(L"shell32.dll"), "SHGetKnownFolderPath"));
  base::win::ScopedCoMem<wchar_t> path_buf;
  if (f && SUCCEEDED(f(FOLDERID_Downloads, 0, NULL, &path_buf))) {
    *result = FilePath(std::wstring(path_buf));
    return true;
  }
  return GetUserDownloadsDirectorySafe(result);
}

bool GetUserPicturesDirectory(FilePath* result) {
  wchar_t path_buf[MAX_PATH];
  if (FAILED(SHGetFolderPath(NULL, CSIDL_MYPICTURES, NULL,
                             SHGFP_TYPE_CURRENT, path_buf))) {
    return false;
  }
  *result = FilePath(path_buf);
  return true;
}

bool GetUserDesktop(FilePath* result) {
  // We need to go compute the value. It would be nice to support paths
  // with names longer than MAX_PATH, but the system functions don't seem
  // to be designed for it either, with the exception of GetTempPath
  // (but other things will surely break if the temp path is too long,
  // so we don't bother handling it.
  wchar_t system_buffer[MAX_PATH];
  system_buffer[0] = 0;
  if (FAILED(SHGetFolderPath(NULL, CSIDL_DESKTOPDIRECTORY, NULL,
                             SHGFP_TYPE_CURRENT, system_buffer))) {
    return false;
  }
  *result = FilePath(system_buffer);
  return true;
}

bool ProcessNeedsProfileDir(const std::string& process_type) {
  // On windows we don't want subprocesses other than the browser process and
  // service processes to be able to use the profile directory because if it
  // lies on a network share the sandbox will prevent us from accessing it.
  // TODO(pastarmovj): For now gpu and plugin broker processes are whitelisted
  // too because they do use the profile dir in some way but this must be
  // investigated and fixed if possible.
  return process_type.empty() ||
         process_type == switches::kServiceProcess ||
         process_type == switches::kGpuProcess ||
         process_type == switches::kNaClBrokerProcess ||
         process_type == switches::kNaClLoaderProcess ||
         process_type == switches::kPpapiBrokerProcess;
}

}  // namespace chrome