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. 4 5 #include "chrome/common/chrome_paths.h" 6 7 #include "base/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" 20 21 #if defined(OS_ANDROID) 22 #include "base/android/path_utils.h" 23 #endif 24 25 #if defined(OS_MACOSX) 26 #include "base/mac/foundation_util.h" 27 #endif 28 29 #include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR. 30 31 namespace { 32 33 // File name of the internal Flash plugin on different platforms. 34 const base::FilePath::CharType kInternalFlashPluginFileName[] = 35 #if defined(OS_MACOSX) 36 FILE_PATH_LITERAL("Flash Player Plugin for Chrome.plugin"); 37 #elif defined(OS_WIN) 38 FILE_PATH_LITERAL("gcswf32.dll"); 39 #else // OS_LINUX, etc. 40 FILE_PATH_LITERAL("libgcflashplayer.so"); 41 #endif 42 43 // The Pepper Flash plugins are in a directory with this name. 44 const base::FilePath::CharType kPepperFlashBaseDirectory[] = 45 FILE_PATH_LITERAL("PepperFlash"); 46 47 #if defined(OS_WIN) 48 const base::FilePath::CharType kPepperFlashDebuggerBaseDirectory[] = 49 FILE_PATH_LITERAL("Macromed\\Flash"); 50 #endif 51 52 // File name of the internal PDF plugin on different platforms. 53 const base::FilePath::CharType kInternalPDFPluginFileName[] = 54 #if defined(OS_WIN) 55 FILE_PATH_LITERAL("pdf.dll"); 56 #elif defined(OS_MACOSX) 57 FILE_PATH_LITERAL("PDF.plugin"); 58 #else // Linux and Chrome OS 59 FILE_PATH_LITERAL("libpdf.so"); 60 #endif 61 62 // File name of the internal NaCl plugin on different platforms. 63 const base::FilePath::CharType kInternalNaClPluginFileName[] = 64 #if defined(OS_WIN) 65 FILE_PATH_LITERAL("ppGoogleNaClPluginChrome.dll"); 66 #elif defined(OS_MACOSX) 67 // TODO(noelallen) Please verify this extention name is correct. 68 FILE_PATH_LITERAL("ppGoogleNaClPluginChrome.plugin"); 69 #else // Linux and Chrome OS 70 FILE_PATH_LITERAL("libppGoogleNaClPluginChrome.so"); 71 #endif 72 73 const base::FilePath::CharType kEffectsPluginFileName[] = 74 #if defined(OS_WIN) 75 FILE_PATH_LITERAL("pepper/libppeffects.dll"); 76 #elif defined(OS_MACOSX) 77 FILE_PATH_LITERAL("pepper/libppeffects.plugin"); 78 #else // Linux and Chrome OS 79 FILE_PATH_LITERAL("pepper/libppeffects.so"); 80 #endif 81 82 #if defined(OS_POSIX) && !defined(OS_MACOSX) 83 84 const base::FilePath::CharType kO1DPluginFileName[] = 85 FILE_PATH_LITERAL("pepper/libppo1d.so"); 86 87 const base::FilePath::CharType kGTalkPluginFileName[] = 88 FILE_PATH_LITERAL("pepper/libppgoogletalk.so"); 89 90 #endif // defined(OS_POSIX) && !defined(OS_MACOSX) 91 92 #if defined(OS_LINUX) 93 // The path to the external extension <id>.json files. 94 // /usr/share seems like a good choice, see: http://www.pathname.com/fhs/ 95 const base::FilePath::CharType kFilepathSinglePrefExtensions[] = 96 #if defined(GOOGLE_CHROME_BUILD) 97 FILE_PATH_LITERAL("/usr/share/google-chrome/extensions"); 98 #else 99 FILE_PATH_LITERAL("/usr/share/chromium/extensions"); 100 #endif // defined(GOOGLE_CHROME_BUILD) 101 #endif // defined(OS_LINUX) 102 103 static base::LazyInstance<base::FilePath> 104 g_invalid_specified_user_data_dir = LAZY_INSTANCE_INITIALIZER; 105 106 // Gets the path for internal plugins. 107 bool GetInternalPluginsDirectory(base::FilePath* result) { 108 #if defined(OS_MACOSX) && !defined(OS_IOS) 109 // If called from Chrome, get internal plugins from a subdirectory of the 110 // framework. 111 if (base::mac::AmIBundled()) { 112 *result = chrome::GetFrameworkBundlePath(); 113 DCHECK(!result->empty()); 114 *result = result->Append("Internet Plug-Ins"); 115 return true; 116 } 117 // In tests, just look in the module directory (below). 118 #endif 119 120 // The rest of the world expects plugins in the module directory. 121 return PathService::Get(base::DIR_MODULE, result); 122 } 123 124 } // namespace 125 126 namespace chrome { 127 128 bool PathProvider(int key, base::FilePath* result) { 129 // Some keys are just aliases... 130 switch (key) { 131 case chrome::DIR_APP: 132 return PathService::Get(base::DIR_MODULE, result); 133 case chrome::DIR_LOGS: 134 #ifdef NDEBUG 135 // Release builds write to the data dir 136 return PathService::Get(chrome::DIR_USER_DATA, result); 137 #else 138 // Debug builds write next to the binary (in the build tree) 139 #if defined(OS_MACOSX) 140 if (!PathService::Get(base::DIR_EXE, result)) 141 return false; 142 if (base::mac::AmIBundled()) { 143 // If we're called from chrome, dump it beside the app (outside the 144 // app bundle), if we're called from a unittest, we'll already 145 // outside the bundle so use the exe dir. 146 // exe_dir gave us .../Chromium.app/Contents/MacOS/Chromium. 147 *result = result->DirName(); 148 *result = result->DirName(); 149 *result = result->DirName(); 150 } 151 return true; 152 #else 153 return PathService::Get(base::DIR_EXE, result); 154 #endif // defined(OS_MACOSX) 155 #endif // NDEBUG 156 case chrome::FILE_RESOURCE_MODULE: 157 return PathService::Get(base::FILE_MODULE, result); 158 } 159 160 // Assume that we will not need to create the directory if it does not exist. 161 // This flag can be set to true for the cases where we want to create it. 162 bool create_dir = false; 163 164 base::FilePath cur; 165 switch (key) { 166 case chrome::DIR_USER_DATA: 167 if (!GetDefaultUserDataDirectory(&cur)) { 168 NOTREACHED(); 169 return false; 170 } 171 create_dir = true; 172 break; 173 case chrome::DIR_USER_DOCUMENTS: 174 if (!GetUserDocumentsDirectory(&cur)) 175 return false; 176 create_dir = true; 177 break; 178 case chrome::DIR_USER_MUSIC: 179 if (!GetUserMusicDirectory(&cur)) 180 return false; 181 break; 182 case chrome::DIR_USER_PICTURES: 183 if (!GetUserPicturesDirectory(&cur)) 184 return false; 185 break; 186 case chrome::DIR_USER_VIDEOS: 187 if (!GetUserVideosDirectory(&cur)) 188 return false; 189 break; 190 case chrome::DIR_DEFAULT_DOWNLOADS_SAFE: 191 #if defined(OS_WIN) || defined(OS_LINUX) 192 if (!GetUserDownloadsDirectorySafe(&cur)) 193 return false; 194 break; 195 #else 196 // Fall through for all other platforms. 197 #endif 198 case chrome::DIR_DEFAULT_DOWNLOADS: 199 #if defined(OS_ANDROID) 200 if (!base::android::GetDownloadsDirectory(&cur)) 201 return false; 202 #else 203 if (!GetUserDownloadsDirectory(&cur)) 204 return false; 205 // Do not create the download directory here, we have done it twice now 206 // and annoyed a lot of users. 207 #endif 208 break; 209 case chrome::DIR_CRASH_DUMPS: 210 #if defined(OS_CHROMEOS) 211 // ChromeOS uses a separate directory. See http://crosbug.com/25089 212 cur = base::FilePath("/var/log/chrome"); 213 #elif defined(OS_ANDROID) 214 if (!base::android::GetCacheDirectory(&cur)) 215 return false; 216 #else 217 // The crash reports are always stored relative to the default user data 218 // directory. This avoids the problem of having to re-initialize the 219 // exception handler after parsing command line options, which may 220 // override the location of the app's profile directory. 221 if (!GetDefaultUserDataDirectory(&cur)) 222 return false; 223 #endif 224 cur = cur.Append(FILE_PATH_LITERAL("Crash Reports")); 225 create_dir = true; 226 break; 227 case chrome::DIR_RESOURCES: 228 #if defined(OS_MACOSX) 229 cur = base::mac::FrameworkBundlePath(); 230 cur = cur.Append(FILE_PATH_LITERAL("Resources")); 231 #else 232 if (!PathService::Get(chrome::DIR_APP, &cur)) 233 return false; 234 cur = cur.Append(FILE_PATH_LITERAL("resources")); 235 #endif 236 break; 237 case chrome::DIR_INSPECTOR: 238 if (!PathService::Get(chrome::DIR_RESOURCES, &cur)) 239 return false; 240 cur = cur.Append(FILE_PATH_LITERAL("inspector")); 241 break; 242 case chrome::DIR_APP_DICTIONARIES: 243 #if defined(OS_POSIX) 244 // We can't write into the EXE dir on Linux, so keep dictionaries 245 // alongside the safe browsing database in the user data dir. 246 // And we don't want to write into the bundle on the Mac, so push 247 // it to the user data dir there also. 248 if (!PathService::Get(chrome::DIR_USER_DATA, &cur)) 249 return false; 250 #else 251 if (!PathService::Get(base::DIR_EXE, &cur)) 252 return false; 253 #endif 254 cur = cur.Append(FILE_PATH_LITERAL("Dictionaries")); 255 create_dir = true; 256 break; 257 case chrome::DIR_INTERNAL_PLUGINS: 258 if (!GetInternalPluginsDirectory(&cur)) 259 return false; 260 break; 261 case chrome::DIR_PEPPER_FLASH_PLUGIN: 262 if (!GetInternalPluginsDirectory(&cur)) 263 return false; 264 cur = cur.Append(kPepperFlashBaseDirectory); 265 break; 266 case chrome::DIR_COMPONENT_UPDATED_PEPPER_FLASH_PLUGIN: 267 if (!PathService::Get(chrome::DIR_USER_DATA, &cur)) 268 return false; 269 cur = cur.Append(kPepperFlashBaseDirectory); 270 break; 271 case chrome::DIR_PEPPER_FLASH_DEBUGGER_PLUGIN: 272 #if defined(OS_WIN) 273 if (!PathService::Get(base::DIR_SYSTEM, &cur)) 274 return false; 275 cur = cur.Append(kPepperFlashDebuggerBaseDirectory); 276 #elif defined(OS_MACOSX) 277 // TODO(luken): finalize Mac OS directory paths, current consensus is 278 // around /Library/Internet Plug-Ins/PepperFlashPlayer/ 279 return false; 280 #else 281 return false; 282 #endif 283 break; 284 case chrome::FILE_LOCAL_STATE: 285 if (!PathService::Get(chrome::DIR_USER_DATA, &cur)) 286 return false; 287 cur = cur.Append(chrome::kLocalStateFilename); 288 break; 289 case chrome::FILE_RECORDED_SCRIPT: 290 if (!PathService::Get(chrome::DIR_USER_DATA, &cur)) 291 return false; 292 cur = cur.Append(FILE_PATH_LITERAL("script.log")); 293 break; 294 case chrome::FILE_FLASH_PLUGIN: 295 if (!GetInternalPluginsDirectory(&cur)) 296 return false; 297 cur = cur.Append(kInternalFlashPluginFileName); 298 break; 299 case chrome::FILE_PEPPER_FLASH_PLUGIN: 300 if (!PathService::Get(chrome::DIR_PEPPER_FLASH_PLUGIN, &cur)) 301 return false; 302 cur = cur.Append(chrome::kPepperFlashPluginFilename); 303 break; 304 case chrome::FILE_PDF_PLUGIN: 305 if (!GetInternalPluginsDirectory(&cur)) 306 return false; 307 cur = cur.Append(kInternalPDFPluginFileName); 308 break; 309 case chrome::FILE_EFFECTS_PLUGIN: 310 if (!GetInternalPluginsDirectory(&cur)) 311 return false; 312 cur = cur.Append(kEffectsPluginFileName); 313 break; 314 case chrome::FILE_NACL_PLUGIN: 315 if (!GetInternalPluginsDirectory(&cur)) 316 return false; 317 cur = cur.Append(kInternalNaClPluginFileName); 318 break; 319 // PNaCl is currenly installable via the component updater or by being 320 // simply built-in. DIR_PNACL_BASE is used as the base directory for 321 // installation via component updater. DIR_PNACL_COMPONENT will be 322 // the final location of pnacl, which is a subdir of DIR_PNACL_BASE. 323 case chrome::DIR_PNACL_BASE: 324 if (!PathService::Get(chrome::DIR_USER_DATA, &cur)) 325 return false; 326 cur = cur.Append(FILE_PATH_LITERAL("pnacl")); 327 break; 328 // Where PNaCl files are ultimately located. The default finds the files 329 // inside the InternalPluginsDirectory / build directory, as if it 330 // was shipped along with chrome. The value can be overridden 331 // if it is installed via component updater. 332 case chrome::DIR_PNACL_COMPONENT: 333 #if defined(OS_MACOSX) 334 // PNaCl really belongs in the InternalPluginsDirectory but actually 335 // copying it there would result in the files also being shipped, which 336 // we don't want yet. So for now, just find them in the directory where 337 // they get built. 338 if (!PathService::Get(base::DIR_EXE, &cur)) 339 return false; 340 if (base::mac::AmIBundled()) { 341 // If we're called from chrome, it's beside the app (outside the 342 // app bundle), if we're called from a unittest, we'll already be 343 // outside the bundle so use the exe dir. 344 // exe_dir gave us .../Chromium.app/Contents/MacOS/Chromium. 345 cur = cur.DirName(); 346 cur = cur.DirName(); 347 cur = cur.DirName(); 348 } 349 #else 350 if (!GetInternalPluginsDirectory(&cur)) 351 return false; 352 #endif 353 cur = cur.Append(FILE_PATH_LITERAL("pnacl")); 354 break; 355 case chrome::DIR_RECOVERY_BASE: 356 if (!PathService::Get(chrome::DIR_USER_DATA, &cur)) 357 return false; 358 cur = cur.Append(FILE_PATH_LITERAL("recovery")); 359 create_dir = true; 360 break; 361 #if defined(OS_POSIX) && !defined(OS_MACOSX) 362 case chrome::FILE_O1D_PLUGIN: 363 if (!PathService::Get(base::DIR_MODULE, &cur)) 364 return false; 365 cur = cur.Append(kO1DPluginFileName); 366 break; 367 case chrome::FILE_GTALK_PLUGIN: 368 if (!PathService::Get(base::DIR_MODULE, &cur)) 369 return false; 370 cur = cur.Append(kGTalkPluginFileName); 371 break; 372 #endif 373 case chrome::DIR_COMPONENT_CLD2: 374 if (!PathService::Get(chrome::DIR_USER_DATA, &cur)) 375 return false; 376 cur = cur.Append(FILE_PATH_LITERAL("CLD")); 377 break; 378 #if defined(WIDEVINE_CDM_AVAILABLE) && defined(ENABLE_PEPPER_CDMS) 379 #if defined(WIDEVINE_CDM_IS_COMPONENT) 380 case chrome::DIR_COMPONENT_WIDEVINE_CDM: 381 if (!PathService::Get(chrome::DIR_USER_DATA, &cur)) 382 return false; 383 cur = cur.Append(kWidevineCdmBaseDirectory); 384 break; 385 #endif // defined(WIDEVINE_CDM_IS_COMPONENT) 386 // TODO(xhwang): FILE_WIDEVINE_CDM_ADAPTER has different meanings. 387 // In the component case, this is the source adapter. Otherwise, it is the 388 // actual Pepper module that gets loaded. 389 case chrome::FILE_WIDEVINE_CDM_ADAPTER: 390 if (!GetInternalPluginsDirectory(&cur)) 391 return false; 392 cur = cur.AppendASCII(kWidevineCdmAdapterFileName); 393 break; 394 #endif // defined(WIDEVINE_CDM_AVAILABLE) && defined(ENABLE_PEPPER_CDMS) 395 case chrome::FILE_RESOURCES_PACK: 396 #if defined(OS_MACOSX) && !defined(OS_IOS) 397 if (base::mac::AmIBundled()) { 398 cur = base::mac::FrameworkBundlePath(); 399 cur = cur.Append(FILE_PATH_LITERAL("Resources")) 400 .Append(FILE_PATH_LITERAL("resources.pak")); 401 break; 402 } 403 #elif defined(OS_ANDROID) 404 if (!PathService::Get(ui::DIR_RESOURCE_PAKS_ANDROID, &cur)) 405 return false; 406 #else 407 // If we're not bundled on mac or Android, resources.pak should be next 408 // to the binary (e.g., for unit tests). 409 if (!PathService::Get(base::DIR_MODULE, &cur)) 410 return false; 411 #endif 412 cur = cur.Append(FILE_PATH_LITERAL("resources.pak")); 413 break; 414 case chrome::DIR_RESOURCES_EXTENSION: 415 if (!PathService::Get(base::DIR_MODULE, &cur)) 416 return false; 417 cur = cur.Append(FILE_PATH_LITERAL("resources")) 418 .Append(FILE_PATH_LITERAL("extension")); 419 break; 420 #if defined(OS_CHROMEOS) 421 case chrome::DIR_CHROMEOS_WALLPAPERS: 422 if (!PathService::Get(chrome::DIR_USER_DATA, &cur)) 423 return false; 424 cur = cur.Append(FILE_PATH_LITERAL("wallpapers")); 425 break; 426 case chrome::DIR_CHROMEOS_WALLPAPER_THUMBNAILS: 427 if (!PathService::Get(chrome::DIR_USER_DATA, &cur)) 428 return false; 429 cur = cur.Append(FILE_PATH_LITERAL("wallpaper_thumbnails")); 430 break; 431 case chrome::DIR_CHROMEOS_CUSTOM_WALLPAPERS: 432 if (!PathService::Get(chrome::DIR_USER_DATA, &cur)) 433 return false; 434 cur = cur.Append(FILE_PATH_LITERAL("custom_wallpapers")); 435 break; 436 #endif 437 #if defined(OS_LINUX) && defined(ENABLE_MANAGED_USERS) 438 case chrome::DIR_SUPERVISED_USERS_DEFAULT_APPS: 439 if (!PathService::Get(chrome::DIR_STANDALONE_EXTERNAL_EXTENSIONS, &cur)) 440 return false; 441 cur = cur.Append(FILE_PATH_LITERAL("managed_users")); 442 break; 443 #endif 444 // The following are only valid in the development environment, and 445 // will fail if executed from an installed executable (because the 446 // generated path won't exist). 447 case chrome::DIR_GEN_TEST_DATA: 448 if (!PathService::Get(base::DIR_MODULE, &cur)) 449 return false; 450 cur = cur.Append(FILE_PATH_LITERAL("test_data")); 451 if (!base::PathExists(cur)) // We don't want to create this. 452 return false; 453 break; 454 case chrome::DIR_TEST_DATA: 455 if (!PathService::Get(base::DIR_SOURCE_ROOT, &cur)) 456 return false; 457 cur = cur.Append(FILE_PATH_LITERAL("chrome")); 458 cur = cur.Append(FILE_PATH_LITERAL("test")); 459 cur = cur.Append(FILE_PATH_LITERAL("data")); 460 if (!base::PathExists(cur)) // We don't want to create this. 461 return false; 462 break; 463 case chrome::DIR_TEST_TOOLS: 464 if (!PathService::Get(base::DIR_SOURCE_ROOT, &cur)) 465 return false; 466 cur = cur.Append(FILE_PATH_LITERAL("chrome")); 467 cur = cur.Append(FILE_PATH_LITERAL("tools")); 468 cur = cur.Append(FILE_PATH_LITERAL("test")); 469 if (!base::PathExists(cur)) // We don't want to create this 470 return false; 471 break; 472 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD) 473 case chrome::DIR_POLICY_FILES: { 474 #if defined(GOOGLE_CHROME_BUILD) 475 cur = base::FilePath(FILE_PATH_LITERAL("/etc/opt/chrome/policies")); 476 #else 477 cur = base::FilePath(FILE_PATH_LITERAL("/etc/chromium/policies")); 478 #endif 479 break; 480 } 481 #endif 482 #if defined(OS_MACOSX) && !defined(OS_IOS) 483 case chrome::DIR_MANAGED_PREFS: { 484 if (!GetLocalLibraryDirectory(&cur)) 485 return false; 486 cur = cur.Append(FILE_PATH_LITERAL("Managed Preferences")); 487 char* login = getlogin(); 488 if (!login) 489 return false; 490 cur = cur.AppendASCII(login); 491 if (!base::PathExists(cur)) // We don't want to create this. 492 return false; 493 break; 494 } 495 case chrome::DIR_USER_LIBRARY: { 496 if (!GetUserLibraryDirectory(&cur)) 497 return false; 498 if (!base::PathExists(cur)) // We don't want to create this. 499 return false; 500 break; 501 } 502 case chrome::DIR_USER_APPLICATIONS: { 503 if (!GetUserApplicationsDirectory(&cur)) 504 return false; 505 if (!base::PathExists(cur)) // We don't want to create this. 506 return false; 507 break; 508 } 509 #endif 510 #if defined(OS_CHROMEOS) || (defined(OS_MACOSX) && !defined(OS_IOS)) 511 case chrome::DIR_USER_EXTERNAL_EXTENSIONS: { 512 if (!PathService::Get(chrome::DIR_USER_DATA, &cur)) 513 return false; 514 cur = cur.Append(FILE_PATH_LITERAL("External Extensions")); 515 break; 516 } 517 #endif 518 #if defined(OS_LINUX) 519 case chrome::DIR_STANDALONE_EXTERNAL_EXTENSIONS: { 520 cur = base::FilePath(kFilepathSinglePrefExtensions); 521 break; 522 } 523 #endif 524 case chrome::DIR_EXTERNAL_EXTENSIONS: 525 #if defined(OS_MACOSX) && !defined(OS_IOS) 526 if (!chrome::GetGlobalApplicationSupportDirectory(&cur)) 527 return false; 528 529 cur = cur.Append(FILE_PATH_LITERAL("Google")) 530 .Append(FILE_PATH_LITERAL("Chrome")) 531 .Append(FILE_PATH_LITERAL("External Extensions")); 532 create_dir = false; 533 #else 534 if (!PathService::Get(base::DIR_MODULE, &cur)) 535 return false; 536 537 cur = cur.Append(FILE_PATH_LITERAL("extensions")); 538 create_dir = true; 539 #endif 540 break; 541 542 case chrome::DIR_DEFAULT_APPS: 543 #if defined(OS_MACOSX) 544 cur = base::mac::FrameworkBundlePath(); 545 cur = cur.Append(FILE_PATH_LITERAL("Default Apps")); 546 #else 547 if (!PathService::Get(chrome::DIR_APP, &cur)) 548 return false; 549 cur = cur.Append(FILE_PATH_LITERAL("default_apps")); 550 #endif 551 break; 552 553 #if defined(OS_LINUX) || (defined(OS_MACOSX) && !defined(OS_IOS)) 554 case chrome::DIR_NATIVE_MESSAGING: 555 #if defined(OS_MACOSX) 556 #if defined(GOOGLE_CHROME_BUILD) 557 cur = base::FilePath(FILE_PATH_LITERAL( 558 "/Library/Google/Chrome/NativeMessagingHosts")); 559 #else 560 cur = base::FilePath(FILE_PATH_LITERAL( 561 "/Library/Application Support/Chromium/NativeMessagingHosts")); 562 #endif 563 #else // defined(OS_MACOSX) 564 #if defined(GOOGLE_CHROME_BUILD) 565 cur = base::FilePath(FILE_PATH_LITERAL( 566 "/etc/opt/chrome/native-messaging-hosts")); 567 #else 568 cur = base::FilePath(FILE_PATH_LITERAL( 569 "/etc/chromium/native-messaging-hosts")); 570 #endif 571 #endif // !defined(OS_MACOSX) 572 break; 573 574 case chrome::DIR_USER_NATIVE_MESSAGING: 575 if (!PathService::Get(chrome::DIR_USER_DATA, &cur)) 576 return false; 577 cur = cur.Append(FILE_PATH_LITERAL("NativeMessagingHosts")); 578 break; 579 #endif // defined(OS_LINUX) || (defined(OS_MACOSX) && !defined(OS_IOS)) 580 #if !defined(OS_ANDROID) 581 case chrome::DIR_GLOBAL_GCM_STORE: 582 if (!PathService::Get(chrome::DIR_USER_DATA, &cur)) 583 return false; 584 cur = cur.Append(kGCMStoreDirname); 585 break; 586 #endif // !defined(OS_ANDROID) 587 588 default: 589 return false; 590 } 591 592 // TODO(bauerb): http://crbug.com/259796 593 base::ThreadRestrictions::ScopedAllowIO allow_io; 594 if (create_dir && !base::PathExists(cur) && 595 !base::CreateDirectory(cur)) 596 return false; 597 598 *result = cur; 599 return true; 600 } 601 602 // This cannot be done as a static initializer sadly since Visual Studio will 603 // eliminate this object file if there is no direct entry point into it. 604 void RegisterPathProvider() { 605 PathService::RegisterProvider(PathProvider, PATH_START, PATH_END); 606 } 607 608 void SetInvalidSpecifiedUserDataDir(const base::FilePath& user_data_dir) { 609 g_invalid_specified_user_data_dir.Get() = user_data_dir; 610 } 611 612 const base::FilePath& GetInvalidSpecifiedUserDataDir() { 613 return g_invalid_specified_user_data_dir.Get(); 614 } 615 616 } // namespace chrome 617