Home | History | Annotate | Download | only in common
      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