1 // Copyright (c) 2012 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/common/chrome_paths.h"
7 #include "base/files/file_util.h"
8 #include "base/lazy_instance.h"
9 #include "base/logging.h"
10 #include "base/mac/bundle_locations.h"
11 #include "base/path_service.h"
12 #include "base/strings/string_util.h"
13 #include "base/sys_info.h"
14 #include "base/threading/thread_restrictions.h"
15 #include "base/version.h"
16 #include "chrome/common/chrome_constants.h"
17 #include "chrome/common/chrome_paths_internal.h"
18 #include "chrome/common/widevine_cdm_constants.h"
19 #include "ui/base/ui_base_paths.h"
21 #if defined(OS_ANDROID)
22 #include "base/android/path_utils.h"
23 #include "base/base_paths_android.h"
26 #if defined(OS_MACOSX)
27 #include "base/mac/foundation_util.h"
31 #include "base/win/registry.h"
34 #include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR.
38 // The Pepper Flash plugins are in a directory with this name.
39 const base::FilePath::CharType kPepperFlashBaseDirectory
[] =
40 FILE_PATH_LITERAL("PepperFlash");
42 #if defined(OS_MACOSX) && !defined(OS_IOS)
43 const base::FilePath::CharType kPepperFlashSystemBaseDirectory
[] =
44 FILE_PATH_LITERAL("Internet Plug-Ins/PepperFlashPlayer");
45 const base::FilePath::CharType kFlashSystemBaseDirectory
[] =
46 FILE_PATH_LITERAL("Internet Plug-Ins");
47 const base::FilePath::CharType kFlashSystemPluginName
[] =
48 FILE_PATH_LITERAL("Flash Player.plugin");
51 const base::FilePath::CharType kInternalNaClPluginFileName
[] =
52 FILE_PATH_LITERAL("internal-nacl-plugin");
55 // The path to the external extension <id>.json files.
56 // /usr/share seems like a good choice, see: http://www.pathname.com/fhs/
57 const base::FilePath::CharType kFilepathSinglePrefExtensions
[] =
58 #if defined(GOOGLE_CHROME_BUILD)
59 FILE_PATH_LITERAL("/usr/share/google-chrome/extensions");
61 FILE_PATH_LITERAL("/usr/share/chromium/extensions");
62 #endif // defined(GOOGLE_CHROME_BUILD)
64 // The path to the hint file that tells the pepper plugin loader
65 // where it can find the latest component updated flash.
66 const base::FilePath::CharType kComponentUpdatedFlashHint
[] =
67 FILE_PATH_LITERAL("latest-component-updated-flash");
68 #endif // defined(OS_LINUX)
70 static base::LazyInstance
<base::FilePath
>
71 g_invalid_specified_user_data_dir
= LAZY_INSTANCE_INITIALIZER
;
73 // Gets the path for internal plugins.
74 bool GetInternalPluginsDirectory(base::FilePath
* result
) {
75 #if defined(OS_MACOSX) && !defined(OS_IOS)
76 // If called from Chrome, get internal plugins from a subdirectory of the
78 if (base::mac::AmIBundled()) {
79 *result
= chrome::GetFrameworkBundlePath();
80 DCHECK(!result
->empty());
81 *result
= result
->Append("Internet Plug-Ins");
84 // In tests, just look in the module directory (below).
87 // The rest of the world expects plugins in the module directory.
88 return PathService::Get(base::DIR_MODULE
, result
);
92 // Gets the Flash path if installed on the system. |is_npapi| determines whether
93 // to return the NPAPI of the PPAPI version of the system plugin.
94 bool GetSystemFlashFilename(base::FilePath
* out_path
, bool is_npapi
) {
95 const wchar_t kNpapiFlashRegistryRoot
[] =
96 L
"SOFTWARE\\Macromedia\\FlashPlayerPlugin";
97 const wchar_t kPepperFlashRegistryRoot
[] =
98 L
"SOFTWARE\\Macromedia\\FlashPlayerPepper";
99 const wchar_t kFlashPlayerPathValueName
[] = L
"PlayerPath";
101 base::win::RegKey
path_key(
103 is_npapi
? kNpapiFlashRegistryRoot
: kPepperFlashRegistryRoot
, KEY_READ
);
104 base::string16 path_str
;
105 if (FAILED(path_key
.ReadValue(kFlashPlayerPathValueName
, &path_str
)))
108 *out_path
= base::FilePath(path_str
);
117 bool PathProvider(int key
, base::FilePath
* result
) {
118 // Some keys are just aliases...
120 case chrome::DIR_APP
:
121 return PathService::Get(base::DIR_MODULE
, result
);
122 case chrome::DIR_LOGS
:
124 // Release builds write to the data dir
125 return PathService::Get(chrome::DIR_USER_DATA
, result
);
127 // Debug builds write next to the binary (in the build tree)
128 #if defined(OS_MACOSX)
129 if (!PathService::Get(base::DIR_EXE
, result
))
131 if (base::mac::AmIBundled()) {
132 // If we're called from chrome, dump it beside the app (outside the
133 // app bundle), if we're called from a unittest, we'll already
134 // outside the bundle so use the exe dir.
135 // exe_dir gave us .../Chromium.app/Contents/MacOS/Chromium.
136 *result
= result
->DirName();
137 *result
= result
->DirName();
138 *result
= result
->DirName();
142 return PathService::Get(base::DIR_EXE
, result
);
143 #endif // defined(OS_MACOSX)
145 case chrome::FILE_RESOURCE_MODULE
:
146 return PathService::Get(base::FILE_MODULE
, result
);
149 // Assume that we will not need to create the directory if it does not exist.
150 // This flag can be set to true for the cases where we want to create it.
151 bool create_dir
= false;
155 case chrome::DIR_USER_DATA
:
156 if (!GetDefaultUserDataDirectory(&cur
)) {
162 case chrome::DIR_USER_DOCUMENTS
:
163 if (!GetUserDocumentsDirectory(&cur
))
167 case chrome::DIR_USER_MUSIC
:
168 if (!GetUserMusicDirectory(&cur
))
171 case chrome::DIR_USER_PICTURES
:
172 if (!GetUserPicturesDirectory(&cur
))
175 case chrome::DIR_USER_VIDEOS
:
176 if (!GetUserVideosDirectory(&cur
))
179 case chrome::DIR_DEFAULT_DOWNLOADS_SAFE
:
180 #if defined(OS_WIN) || defined(OS_LINUX)
181 if (!GetUserDownloadsDirectorySafe(&cur
))
185 // Fall through for all other platforms.
187 case chrome::DIR_DEFAULT_DOWNLOADS
:
188 #if defined(OS_ANDROID)
189 if (!base::android::GetDownloadsDirectory(&cur
))
192 if (!GetUserDownloadsDirectory(&cur
))
194 // Do not create the download directory here, we have done it twice now
195 // and annoyed a lot of users.
198 case chrome::DIR_CRASH_DUMPS
:
199 #if defined(OS_CHROMEOS)
200 // ChromeOS uses a separate directory. See http://crosbug.com/25089
201 cur
= base::FilePath("/var/log/chrome");
202 #elif defined(OS_ANDROID)
203 if (!base::android::GetCacheDirectory(&cur
))
206 // The crash reports are always stored relative to the default user data
207 // directory. This avoids the problem of having to re-initialize the
208 // exception handler after parsing command line options, which may
209 // override the location of the app's profile directory.
210 if (!GetDefaultUserDataDirectory(&cur
))
213 #if defined(OS_MACOSX)
214 cur
= cur
.Append(FILE_PATH_LITERAL("Crashpad"));
216 cur
= cur
.Append(FILE_PATH_LITERAL("Crash Reports"));
221 case chrome::DIR_WATCHER_DATA
:
222 // The watcher data is always stored relative to the default user data
223 // directory. This allows the watcher to be initialized before
224 // command-line options have been parsed.
225 if (!GetDefaultUserDataDirectory(&cur
))
227 cur
= cur
.Append(FILE_PATH_LITERAL("Diagnostics"));
230 case chrome::DIR_RESOURCES
:
231 #if defined(OS_MACOSX)
232 cur
= base::mac::FrameworkBundlePath();
233 cur
= cur
.Append(FILE_PATH_LITERAL("Resources"));
235 if (!PathService::Get(chrome::DIR_APP
, &cur
))
237 cur
= cur
.Append(FILE_PATH_LITERAL("resources"));
240 case chrome::DIR_INSPECTOR
:
241 if (!PathService::Get(chrome::DIR_RESOURCES
, &cur
))
243 cur
= cur
.Append(FILE_PATH_LITERAL("inspector"));
245 case chrome::DIR_APP_DICTIONARIES
:
246 #if defined(OS_POSIX)
247 // We can't write into the EXE dir on Linux, so keep dictionaries
248 // alongside the safe browsing database in the user data dir.
249 // And we don't want to write into the bundle on the Mac, so push
250 // it to the user data dir there also.
251 if (!PathService::Get(chrome::DIR_USER_DATA
, &cur
))
254 if (!PathService::Get(base::DIR_EXE
, &cur
))
257 cur
= cur
.Append(FILE_PATH_LITERAL("Dictionaries"));
260 case chrome::DIR_INTERNAL_PLUGINS
:
261 if (!GetInternalPluginsDirectory(&cur
))
264 case chrome::DIR_PEPPER_FLASH_PLUGIN
:
265 if (!GetInternalPluginsDirectory(&cur
))
267 cur
= cur
.Append(kPepperFlashBaseDirectory
);
269 case chrome::DIR_COMPONENT_UPDATED_PEPPER_FLASH_PLUGIN
:
270 if (!PathService::Get(chrome::DIR_USER_DATA
, &cur
))
272 cur
= cur
.Append(kPepperFlashBaseDirectory
);
274 case chrome::FILE_PEPPER_FLASH_SYSTEM_PLUGIN
:
276 if (!GetSystemFlashFilename(&cur
, false))
278 #elif defined(OS_MACOSX) && !defined(OS_IOS)
279 if (!GetLocalLibraryDirectory(&cur
))
281 cur
= cur
.Append(kPepperFlashSystemBaseDirectory
);
282 cur
= cur
.Append(chrome::kPepperFlashPluginFilename
);
284 // Chrome on iOS does not supports PPAPI binaries, return false.
285 // TODO(wfh): If Adobe release PPAPI binaries for Linux, add support here.
289 case chrome::FILE_FLASH_SYSTEM_PLUGIN
:
291 if (!GetSystemFlashFilename(&cur
, true))
293 #elif defined(OS_MACOSX) && !defined(OS_IOS)
294 if (!GetLocalLibraryDirectory(&cur
))
296 cur
= cur
.Append(kFlashSystemBaseDirectory
);
297 cur
= cur
.Append(kFlashSystemPluginName
);
299 // Chrome on other platforms does not supports system NPAPI binaries.
303 case chrome::FILE_LOCAL_STATE
:
304 if (!PathService::Get(chrome::DIR_USER_DATA
, &cur
))
306 cur
= cur
.Append(chrome::kLocalStateFilename
);
308 case chrome::FILE_RECORDED_SCRIPT
:
309 if (!PathService::Get(chrome::DIR_USER_DATA
, &cur
))
311 cur
= cur
.Append(FILE_PATH_LITERAL("script.log"));
313 case chrome::FILE_PEPPER_FLASH_PLUGIN
:
314 if (!PathService::Get(chrome::DIR_PEPPER_FLASH_PLUGIN
, &cur
))
316 cur
= cur
.Append(chrome::kPepperFlashPluginFilename
);
318 // TODO(teravest): Remove this case once the internal NaCl plugin is gone.
319 // We currently need a path here to look up whether the plugin is disabled
320 // and what its permissions are.
321 case chrome::FILE_NACL_PLUGIN
:
322 if (!GetInternalPluginsDirectory(&cur
))
324 cur
= cur
.Append(kInternalNaClPluginFileName
);
326 // PNaCl is currenly installable via the component updater or by being
327 // simply built-in. DIR_PNACL_BASE is used as the base directory for
328 // installation via component updater. DIR_PNACL_COMPONENT will be
329 // the final location of pnacl, which is a subdir of DIR_PNACL_BASE.
330 case chrome::DIR_PNACL_BASE
:
331 if (!PathService::Get(chrome::DIR_USER_DATA
, &cur
))
333 cur
= cur
.Append(FILE_PATH_LITERAL("pnacl"));
335 // Where PNaCl files are ultimately located. The default finds the files
336 // inside the InternalPluginsDirectory / build directory, as if it
337 // was shipped along with chrome. The value can be overridden
338 // if it is installed via component updater.
339 case chrome::DIR_PNACL_COMPONENT
:
340 #if defined(OS_MACOSX)
341 // PNaCl really belongs in the InternalPluginsDirectory but actually
342 // copying it there would result in the files also being shipped, which
343 // we don't want yet. So for now, just find them in the directory where
345 if (!PathService::Get(base::DIR_EXE
, &cur
))
347 if (base::mac::AmIBundled()) {
348 // If we're called from chrome, it's beside the app (outside the
349 // app bundle), if we're called from a unittest, we'll already be
350 // outside the bundle so use the exe dir.
351 // exe_dir gave us .../Chromium.app/Contents/MacOS/Chromium.
357 if (!GetInternalPluginsDirectory(&cur
))
360 cur
= cur
.Append(FILE_PATH_LITERAL("pnacl"));
362 #if defined(WIDEVINE_CDM_AVAILABLE) && defined(ENABLE_PEPPER_CDMS)
363 #if defined(WIDEVINE_CDM_IS_COMPONENT)
364 case chrome::DIR_COMPONENT_WIDEVINE_CDM
:
365 if (!PathService::Get(chrome::DIR_USER_DATA
, &cur
))
367 cur
= cur
.Append(kWidevineCdmBaseDirectory
);
369 #endif // defined(WIDEVINE_CDM_IS_COMPONENT)
370 // TODO(xhwang): FILE_WIDEVINE_CDM_ADAPTER has different meanings.
371 // In the component case, this is the source adapter. Otherwise, it is the
372 // actual Pepper module that gets loaded.
373 case chrome::FILE_WIDEVINE_CDM_ADAPTER
:
374 if (!GetInternalPluginsDirectory(&cur
))
376 cur
= cur
.AppendASCII(kWidevineCdmAdapterFileName
);
378 #endif // defined(WIDEVINE_CDM_AVAILABLE) && defined(ENABLE_PEPPER_CDMS)
379 case chrome::FILE_RESOURCES_PACK
:
380 #if defined(OS_MACOSX) && !defined(OS_IOS)
381 if (base::mac::AmIBundled()) {
382 cur
= base::mac::FrameworkBundlePath();
383 cur
= cur
.Append(FILE_PATH_LITERAL("Resources"))
384 .Append(FILE_PATH_LITERAL("resources.pak"));
387 #elif defined(OS_ANDROID)
388 if (!PathService::Get(ui::DIR_RESOURCE_PAKS_ANDROID
, &cur
))
391 // If we're not bundled on mac or Android, resources.pak should be next
392 // to the binary (e.g., for unit tests).
393 if (!PathService::Get(base::DIR_MODULE
, &cur
))
396 cur
= cur
.Append(FILE_PATH_LITERAL("resources.pak"));
398 case chrome::DIR_RESOURCES_EXTENSION
:
399 if (!PathService::Get(base::DIR_MODULE
, &cur
))
401 cur
= cur
.Append(FILE_PATH_LITERAL("resources"))
402 .Append(FILE_PATH_LITERAL("extension"));
404 #if defined(OS_CHROMEOS)
405 case chrome::DIR_CHROMEOS_WALLPAPERS
:
406 if (!PathService::Get(chrome::DIR_USER_DATA
, &cur
))
408 cur
= cur
.Append(FILE_PATH_LITERAL("wallpapers"));
410 case chrome::DIR_CHROMEOS_WALLPAPER_THUMBNAILS
:
411 if (!PathService::Get(chrome::DIR_USER_DATA
, &cur
))
413 cur
= cur
.Append(FILE_PATH_LITERAL("wallpaper_thumbnails"));
415 case chrome::DIR_CHROMEOS_CUSTOM_WALLPAPERS
:
416 if (!PathService::Get(chrome::DIR_USER_DATA
, &cur
))
418 cur
= cur
.Append(FILE_PATH_LITERAL("custom_wallpapers"));
421 #if defined(OS_LINUX) && defined(ENABLE_SUPERVISED_USERS)
422 case chrome::DIR_SUPERVISED_USERS_DEFAULT_APPS
:
423 if (!PathService::Get(chrome::DIR_STANDALONE_EXTERNAL_EXTENSIONS
, &cur
))
425 cur
= cur
.Append(FILE_PATH_LITERAL("managed_users"));
428 // The following are only valid in the development environment, and
429 // will fail if executed from an installed executable (because the
430 // generated path won't exist).
431 case chrome::DIR_GEN_TEST_DATA
:
432 #if defined(OS_ANDROID)
433 // On Android, our tests don't have permission to write to DIR_MODULE.
434 // gtest/test_runner.py pushes data to external storage.
435 if (!PathService::Get(base::DIR_ANDROID_EXTERNAL_STORAGE
, &cur
))
438 if (!PathService::Get(base::DIR_MODULE
, &cur
))
441 cur
= cur
.Append(FILE_PATH_LITERAL("test_data"));
442 if (!base::PathExists(cur
)) // We don't want to create this.
445 case chrome::DIR_TEST_DATA
:
446 if (!PathService::Get(base::DIR_SOURCE_ROOT
, &cur
))
448 cur
= cur
.Append(FILE_PATH_LITERAL("chrome"));
449 cur
= cur
.Append(FILE_PATH_LITERAL("test"));
450 cur
= cur
.Append(FILE_PATH_LITERAL("data"));
451 if (!base::PathExists(cur
)) // We don't want to create this.
454 case chrome::DIR_TEST_TOOLS
:
455 if (!PathService::Get(base::DIR_SOURCE_ROOT
, &cur
))
457 cur
= cur
.Append(FILE_PATH_LITERAL("chrome"));
458 cur
= cur
.Append(FILE_PATH_LITERAL("tools"));
459 cur
= cur
.Append(FILE_PATH_LITERAL("test"));
460 if (!base::PathExists(cur
)) // We don't want to create this
463 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD)
464 case chrome::DIR_POLICY_FILES
: {
465 #if defined(GOOGLE_CHROME_BUILD)
466 cur
= base::FilePath(FILE_PATH_LITERAL("/etc/opt/chrome/policies"));
468 cur
= base::FilePath(FILE_PATH_LITERAL("/etc/chromium/policies"));
473 #if defined(OS_MACOSX) && !defined(OS_IOS)
474 case chrome::DIR_USER_LIBRARY
: {
475 if (!GetUserLibraryDirectory(&cur
))
477 if (!base::PathExists(cur
)) // We don't want to create this.
481 case chrome::DIR_USER_APPLICATIONS
: {
482 if (!GetUserApplicationsDirectory(&cur
))
484 if (!base::PathExists(cur
)) // We don't want to create this.
489 #if defined(OS_CHROMEOS) || (defined(OS_LINUX) && defined(CHROMIUM_BUILD)) || \
490 (defined(OS_MACOSX) && !defined(OS_IOS))
491 case chrome::DIR_USER_EXTERNAL_EXTENSIONS
: {
492 if (!PathService::Get(chrome::DIR_USER_DATA
, &cur
))
494 cur
= cur
.Append(FILE_PATH_LITERAL("External Extensions"));
498 #if defined(OS_LINUX)
499 case chrome::DIR_STANDALONE_EXTERNAL_EXTENSIONS
: {
500 cur
= base::FilePath(kFilepathSinglePrefExtensions
);
504 case chrome::DIR_EXTERNAL_EXTENSIONS
:
505 #if defined(OS_MACOSX) && !defined(OS_IOS)
506 if (!chrome::GetGlobalApplicationSupportDirectory(&cur
))
509 cur
= cur
.Append(FILE_PATH_LITERAL("Google"))
510 .Append(FILE_PATH_LITERAL("Chrome"))
511 .Append(FILE_PATH_LITERAL("External Extensions"));
514 if (!PathService::Get(base::DIR_MODULE
, &cur
))
517 cur
= cur
.Append(FILE_PATH_LITERAL("extensions"));
522 case chrome::DIR_DEFAULT_APPS
:
523 #if defined(OS_MACOSX)
524 cur
= base::mac::FrameworkBundlePath();
525 cur
= cur
.Append(FILE_PATH_LITERAL("Default Apps"));
527 if (!PathService::Get(chrome::DIR_APP
, &cur
))
529 cur
= cur
.Append(FILE_PATH_LITERAL("default_apps"));
533 #if defined(OS_LINUX) || (defined(OS_MACOSX) && !defined(OS_IOS))
534 case chrome::DIR_NATIVE_MESSAGING
:
535 #if defined(OS_MACOSX)
536 #if defined(GOOGLE_CHROME_BUILD)
537 cur
= base::FilePath(FILE_PATH_LITERAL(
538 "/Library/Google/Chrome/NativeMessagingHosts"));
540 cur
= base::FilePath(FILE_PATH_LITERAL(
541 "/Library/Application Support/Chromium/NativeMessagingHosts"));
543 #else // defined(OS_MACOSX)
544 #if defined(GOOGLE_CHROME_BUILD)
545 cur
= base::FilePath(FILE_PATH_LITERAL(
546 "/etc/opt/chrome/native-messaging-hosts"));
548 cur
= base::FilePath(FILE_PATH_LITERAL(
549 "/etc/chromium/native-messaging-hosts"));
551 #endif // !defined(OS_MACOSX)
554 case chrome::DIR_USER_NATIVE_MESSAGING
:
555 if (!PathService::Get(chrome::DIR_USER_DATA
, &cur
))
557 cur
= cur
.Append(FILE_PATH_LITERAL("NativeMessagingHosts"));
559 #endif // defined(OS_LINUX) || (defined(OS_MACOSX) && !defined(OS_IOS))
560 #if !defined(OS_ANDROID)
561 case chrome::DIR_GLOBAL_GCM_STORE
:
562 if (!PathService::Get(chrome::DIR_USER_DATA
, &cur
))
564 cur
= cur
.Append(kGCMStoreDirname
);
566 #endif // !defined(OS_ANDROID)
567 #if defined(OS_ANDROID)
568 case chrome::DIR_OFFLINE_PAGE_METADATA
:
569 if (!PathService::Get(chrome::DIR_USER_DATA
, &cur
))
571 cur
= cur
.Append(kOfflinePageMetadataDirname
);
573 #endif // defined(OS_ANDROID)
574 #if defined(OS_LINUX)
575 case chrome::FILE_COMPONENT_FLASH_HINT
:
576 if (!PathService::Get(chrome::DIR_COMPONENT_UPDATED_PEPPER_FLASH_PLUGIN
,
580 cur
= cur
.Append(kComponentUpdatedFlashHint
);
582 #endif // defined(OS_LINUX)
588 // TODO(bauerb): http://crbug.com/259796
589 base::ThreadRestrictions::ScopedAllowIO allow_io
;
590 if (create_dir
&& !base::PathExists(cur
) &&
591 !base::CreateDirectory(cur
))
598 // This cannot be done as a static initializer sadly since Visual Studio will
599 // eliminate this object file if there is no direct entry point into it.
600 void RegisterPathProvider() {
601 PathService::RegisterProvider(PathProvider
, PATH_START
, PATH_END
);
604 void SetInvalidSpecifiedUserDataDir(const base::FilePath
& user_data_dir
) {
605 g_invalid_specified_user_data_dir
.Get() = user_data_dir
;
608 const base::FilePath
& GetInvalidSpecifiedUserDataDir() {
609 return g_invalid_specified_user_data_dir
.Get();
612 } // namespace chrome