1 // Copyright (c) 2011 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/common/chrome_paths.h"
6
7 #include "base/command_line.h"
8 #include "base/file_util.h"
9 #include "base/logging.h"
10 #include "base/path_service.h"
11 #include "base/string_util.h"
12 #include "base/sys_info.h"
13 #include "chrome/common/chrome_constants.h"
14 #include "chrome/common/chrome_paths_internal.h"
15 #include "chrome/common/chrome_switches.h"
16
17 #if defined(OS_MACOSX)
18 #include "base/mac/mac_util.h"
19 #endif
20
21 namespace {
22
23 // File name of the internal Flash plugin on different platforms.
24 const FilePath::CharType kInternalFlashPluginFileName[] =
25 #if defined(OS_MACOSX)
26 FILE_PATH_LITERAL("Flash Player Plugin for Chrome.plugin");
27 #elif defined(OS_WIN)
28 FILE_PATH_LITERAL("gcswf32.dll");
29 #else // OS_LINUX, etc.
30 FILE_PATH_LITERAL("libgcflashplayer.so");
31 #endif
32
33 // File name of the internal PDF plugin on different platforms.
34 const FilePath::CharType kInternalPDFPluginFileName[] =
35 #if defined(OS_WIN)
36 FILE_PATH_LITERAL("pdf.dll");
37 #elif defined(OS_MACOSX)
38 FILE_PATH_LITERAL("PDF.plugin");
39 #else // Linux and Chrome OS
40 FILE_PATH_LITERAL("libpdf.so");
41 #endif
42
43 // File name of the internal NaCl plugin on different platforms.
44 const FilePath::CharType kInternalNaClPluginFileName[] =
45 #if defined(OS_WIN)
46 FILE_PATH_LITERAL("ppGoogleNaClPluginChrome.dll");
47 #elif defined(OS_MACOSX)
48 // TODO(noelallen) Please verify this extention name is correct.
49 FILE_PATH_LITERAL("ppGoogleNaClPluginChrome.plugin");
50 #else // Linux and Chrome OS
51 FILE_PATH_LITERAL("libppGoogleNaClPluginChrome.so");
52 #endif
53
54 } // namespace
55
56 namespace chrome {
57
58 // Gets the path for internal plugins.
GetInternalPluginsDirectory(FilePath * result)59 bool GetInternalPluginsDirectory(FilePath* result) {
60 #if defined(OS_MACOSX)
61 // If called from Chrome, get internal plugins from a subdirectory of the
62 // framework.
63 if (base::mac::AmIBundled()) {
64 *result = chrome::GetFrameworkBundlePath();
65 DCHECK(!result->empty());
66 *result = result->Append("Internet Plug-Ins");
67 return true;
68 }
69 // In tests, just look in the module directory (below).
70 #endif
71
72 // The rest of the world expects plugins in the module directory.
73 return PathService::Get(base::DIR_MODULE, result);
74 }
75
PathProvider(int key,FilePath * result)76 bool PathProvider(int key, FilePath* result) {
77 // Some keys are just aliases...
78 switch (key) {
79 case chrome::DIR_APP:
80 return PathService::Get(base::DIR_MODULE, result);
81 case chrome::DIR_LOGS:
82 #ifdef NDEBUG
83 // Release builds write to the data dir
84 return PathService::Get(chrome::DIR_USER_DATA, result);
85 #else
86 // Debug builds write next to the binary (in the build tree)
87 #if defined(OS_MACOSX)
88 if (!PathService::Get(base::DIR_EXE, result))
89 return false;
90 if (base::mac::AmIBundled()) {
91 // If we're called from chrome, dump it beside the app (outside the
92 // app bundle), if we're called from a unittest, we'll already
93 // outside the bundle so use the exe dir.
94 // exe_dir gave us .../Chromium.app/Contents/MacOS/Chromium.
95 *result = result->DirName();
96 *result = result->DirName();
97 *result = result->DirName();
98 }
99 return true;
100 #else
101 return PathService::Get(base::DIR_EXE, result);
102 #endif // defined(OS_MACOSX)
103 #endif // NDEBUG
104 case chrome::FILE_RESOURCE_MODULE:
105 return PathService::Get(base::FILE_MODULE, result);
106 }
107
108 // Assume that we will not need to create the directory if it does not exist.
109 // This flag can be set to true for the cases where we want to create it.
110 bool create_dir = false;
111
112 FilePath cur;
113 switch (key) {
114 case chrome::DIR_USER_DATA:
115 if (!GetDefaultUserDataDirectory(&cur)) {
116 NOTREACHED();
117 return false;
118 }
119 create_dir = true;
120 break;
121 case chrome::DIR_USER_DOCUMENTS:
122 if (!GetUserDocumentsDirectory(&cur))
123 return false;
124 create_dir = true;
125 break;
126 case chrome::DIR_DEFAULT_DOWNLOADS_SAFE:
127 #if defined(OS_WIN)
128 if (!GetUserDownloadsDirectorySafe(&cur))
129 return false;
130 break;
131 #else
132 // Fall through for all other platforms.
133 #endif
134 case chrome::DIR_DEFAULT_DOWNLOADS:
135 if (!GetUserDownloadsDirectory(&cur))
136 return false;
137 // Do not create the download directory here, we have done it twice now
138 // and annoyed a lot of users.
139 break;
140 case chrome::DIR_CRASH_DUMPS:
141 // The crash reports are always stored relative to the default user data
142 // directory. This avoids the problem of having to re-initialize the
143 // exception handler after parsing command line options, which may
144 // override the location of the app's profile directory.
145 if (!GetDefaultUserDataDirectory(&cur))
146 return false;
147 cur = cur.Append(FILE_PATH_LITERAL("Crash Reports"));
148 create_dir = true;
149 break;
150 case chrome::DIR_USER_DESKTOP:
151 if (!GetUserDesktop(&cur))
152 return false;
153 break;
154 case chrome::DIR_RESOURCES:
155 #if defined(OS_MACOSX)
156 cur = base::mac::MainAppBundlePath();
157 cur = cur.Append(FILE_PATH_LITERAL("Resources"));
158 #else
159 if (!PathService::Get(chrome::DIR_APP, &cur))
160 return false;
161 cur = cur.Append(FILE_PATH_LITERAL("resources"));
162 #endif
163 break;
164 case chrome::DIR_SHARED_RESOURCES:
165 if (!PathService::Get(chrome::DIR_RESOURCES, &cur))
166 return false;
167 cur = cur.Append(FILE_PATH_LITERAL("shared"));
168 break;
169 case chrome::DIR_INSPECTOR:
170 if (!PathService::Get(chrome::DIR_RESOURCES, &cur))
171 return false;
172 cur = cur.Append(FILE_PATH_LITERAL("inspector"));
173 break;
174 case chrome::DIR_APP_DICTIONARIES:
175 #if defined(OS_LINUX) || defined(OS_MACOSX)
176 // We can't write into the EXE dir on Linux, so keep dictionaries
177 // alongside the safe browsing database in the user data dir.
178 // And we don't want to write into the bundle on the Mac, so push
179 // it to the user data dir there also.
180 if (!PathService::Get(chrome::DIR_USER_DATA, &cur))
181 return false;
182 #else
183 if (!PathService::Get(base::DIR_EXE, &cur))
184 return false;
185 #endif
186 cur = cur.Append(FILE_PATH_LITERAL("Dictionaries"));
187 create_dir = true;
188 break;
189 case chrome::DIR_USER_DATA_TEMP:
190 if (!PathService::Get(chrome::DIR_USER_DATA, &cur))
191 return false;
192 cur = cur.Append(FILE_PATH_LITERAL("Temp"));
193 break;
194 case chrome::DIR_INTERNAL_PLUGINS:
195 if (!GetInternalPluginsDirectory(&cur))
196 return false;
197 break;
198 case chrome::DIR_MEDIA_LIBS:
199 #if defined(OS_MACOSX)
200 *result = base::mac::MainAppBundlePath();
201 *result = result->Append("Libraries");
202 return true;
203 #else
204 return PathService::Get(chrome::DIR_APP, result);
205 #endif
206 case chrome::FILE_LOCAL_STATE:
207 if (!PathService::Get(chrome::DIR_USER_DATA, &cur))
208 return false;
209 cur = cur.Append(chrome::kLocalStateFilename);
210 break;
211 case chrome::FILE_RECORDED_SCRIPT:
212 if (!PathService::Get(chrome::DIR_USER_DATA, &cur))
213 return false;
214 cur = cur.Append(FILE_PATH_LITERAL("script.log"));
215 break;
216 case chrome::FILE_FLASH_PLUGIN:
217 if (!GetInternalPluginsDirectory(&cur))
218 return false;
219 cur = cur.Append(kInternalFlashPluginFileName);
220 if (!file_util::PathExists(cur))
221 return false;
222 break;
223 case chrome::FILE_PDF_PLUGIN:
224 if (!GetInternalPluginsDirectory(&cur))
225 return false;
226 cur = cur.Append(kInternalPDFPluginFileName);
227 break;
228 case chrome::FILE_NACL_PLUGIN:
229 if (!GetInternalPluginsDirectory(&cur))
230 return false;
231 cur = cur.Append(kInternalNaClPluginFileName);
232 break;
233 case chrome::FILE_RESOURCES_PACK:
234 #if defined(OS_MACOSX)
235 if (base::mac::AmIBundled()) {
236 cur = base::mac::MainAppBundlePath();
237 cur = cur.Append(FILE_PATH_LITERAL("Resources"))
238 .Append(FILE_PATH_LITERAL("resources.pak"));
239 break;
240 }
241 // If we're not bundled on mac, resources.pak should be next to the
242 // binary (e.g., for unit tests).
243 #endif
244 if (!PathService::Get(base::DIR_MODULE, &cur))
245 return false;
246 cur = cur.Append(FILE_PATH_LITERAL("resources.pak"));
247 break;
248 #if defined(OS_CHROMEOS)
249 case chrome::FILE_CHROMEOS_API:
250 if (!PathService::Get(base::DIR_MODULE, &cur))
251 return false;
252 cur = cur.Append(FILE_PATH_LITERAL("chromeos"));
253 cur = cur.Append(FILE_PATH_LITERAL("libcros.so"));
254 break;
255 #endif
256 // The following are only valid in the development environment, and
257 // will fail if executed from an installed executable (because the
258 // generated path won't exist).
259 case chrome::DIR_TEST_DATA:
260 if (!PathService::Get(base::DIR_SOURCE_ROOT, &cur))
261 return false;
262 cur = cur.Append(FILE_PATH_LITERAL("chrome"));
263 cur = cur.Append(FILE_PATH_LITERAL("test"));
264 cur = cur.Append(FILE_PATH_LITERAL("data"));
265 if (!file_util::PathExists(cur)) // we don't want to create this
266 return false;
267 break;
268 case chrome::DIR_TEST_TOOLS:
269 if (!PathService::Get(base::DIR_SOURCE_ROOT, &cur))
270 return false;
271 cur = cur.Append(FILE_PATH_LITERAL("chrome"));
272 cur = cur.Append(FILE_PATH_LITERAL("tools"));
273 cur = cur.Append(FILE_PATH_LITERAL("test"));
274 if (!file_util::PathExists(cur)) // we don't want to create this
275 return false;
276 break;
277 #if defined(OS_POSIX) && !defined(OS_MACOSX)
278 case chrome::DIR_POLICY_FILES: {
279 #if defined(GOOGLE_CHROME_BUILD)
280 cur = FilePath(FILE_PATH_LITERAL("/etc/opt/chrome/policies"));
281 #else
282 cur = FilePath(FILE_PATH_LITERAL("/etc/chromium/policies"));
283 #endif
284 if (!file_util::PathExists(cur)) // we don't want to create this
285 return false;
286 break;
287 }
288 #endif
289 #if defined(OS_MACOSX)
290 case chrome::DIR_MANAGED_PREFS: {
291 if (!GetLocalLibraryDirectory(&cur))
292 return false;
293 cur = cur.Append(FILE_PATH_LITERAL("Managed Preferences"));
294 char* login = getlogin();
295 if (!login)
296 return false;
297 cur = cur.AppendASCII(login);
298 if (!file_util::PathExists(cur)) // we don't want to create this
299 return false;
300 break;
301 }
302 #endif
303 #if defined(OS_CHROMEOS)
304 case chrome::DIR_USER_EXTERNAL_EXTENSIONS: {
305 if (!PathService::Get(chrome::DIR_USER_DATA, &cur))
306 return false;
307 cur = cur.Append(FILE_PATH_LITERAL("External Extensions"));
308 break;
309 }
310 #endif
311 default:
312 return false;
313 }
314
315 if (create_dir && !file_util::PathExists(cur) &&
316 !file_util::CreateDirectory(cur))
317 return false;
318
319 *result = cur;
320 return true;
321 }
322
323 // This cannot be done as a static initializer sadly since Visual Studio will
324 // eliminate this object file if there is no direct entry point into it.
RegisterPathProvider()325 void RegisterPathProvider() {
326 PathService::RegisterProvider(PathProvider, PATH_START, PATH_END);
327 }
328
329 } // namespace chrome
330