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/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