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