Home | History | Annotate | Download | only in common
      1 // Copyright (c) 2011 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/command_line.h"
      8 #include "base/file_util.h"
      9 #include "base/logging.h"
     10 #include "base/path_service.h"
     11 #include "base/string_util.h"
     12 #include "base/sys_info.h"
     13 #include "chrome/common/chrome_constants.h"
     14 #include "chrome/common/chrome_paths_internal.h"
     15 #include "chrome/common/chrome_switches.h"
     16 
     17 #if defined(OS_MACOSX)
     18 #include "base/mac/mac_util.h"
     19 #endif
     20 
     21 namespace {
     22 
     23 // File name of the internal Flash plugin on different platforms.
     24 const FilePath::CharType kInternalFlashPluginFileName[] =
     25 #if defined(OS_MACOSX)
     26     FILE_PATH_LITERAL("Flash Player Plugin for Chrome.plugin");
     27 #elif defined(OS_WIN)
     28     FILE_PATH_LITERAL("gcswf32.dll");
     29 #else  // OS_LINUX, etc.
     30     FILE_PATH_LITERAL("libgcflashplayer.so");
     31 #endif
     32 
     33 // File name of the internal PDF plugin on different platforms.
     34 const FilePath::CharType kInternalPDFPluginFileName[] =
     35 #if defined(OS_WIN)
     36     FILE_PATH_LITERAL("pdf.dll");
     37 #elif defined(OS_MACOSX)
     38     FILE_PATH_LITERAL("PDF.plugin");
     39 #else  // Linux and Chrome OS
     40     FILE_PATH_LITERAL("libpdf.so");
     41 #endif
     42 
     43 // File name of the internal NaCl plugin on different platforms.
     44 const FilePath::CharType kInternalNaClPluginFileName[] =
     45 #if defined(OS_WIN)
     46     FILE_PATH_LITERAL("ppGoogleNaClPluginChrome.dll");
     47 #elif defined(OS_MACOSX)
     48     // TODO(noelallen) Please verify this extention name is correct.
     49     FILE_PATH_LITERAL("ppGoogleNaClPluginChrome.plugin");
     50 #else  // Linux and Chrome OS
     51     FILE_PATH_LITERAL("libppGoogleNaClPluginChrome.so");
     52 #endif
     53 
     54 }  // namespace
     55 
     56 namespace chrome {
     57 
     58 // Gets the path for internal plugins.
     59 bool GetInternalPluginsDirectory(FilePath* result) {
     60 #if defined(OS_MACOSX)
     61   // If called from Chrome, get internal plugins from a subdirectory of the
     62   // framework.
     63   if (base::mac::AmIBundled()) {
     64     *result = chrome::GetFrameworkBundlePath();
     65     DCHECK(!result->empty());
     66     *result = result->Append("Internet Plug-Ins");
     67     return true;
     68   }
     69   // In tests, just look in the module directory (below).
     70 #endif
     71 
     72   // The rest of the world expects plugins in the module directory.
     73   return PathService::Get(base::DIR_MODULE, result);
     74 }
     75 
     76 bool PathProvider(int key, FilePath* result) {
     77   // Some keys are just aliases...
     78   switch (key) {
     79     case chrome::DIR_APP:
     80       return PathService::Get(base::DIR_MODULE, result);
     81     case chrome::DIR_LOGS:
     82 #ifdef NDEBUG
     83       // Release builds write to the data dir
     84       return PathService::Get(chrome::DIR_USER_DATA, result);
     85 #else
     86       // Debug builds write next to the binary (in the build tree)
     87 #if defined(OS_MACOSX)
     88       if (!PathService::Get(base::DIR_EXE, result))
     89         return false;
     90       if (base::mac::AmIBundled()) {
     91         // If we're called from chrome, dump it beside the app (outside the
     92         // app bundle), if we're called from a unittest, we'll already
     93         // outside the bundle so use the exe dir.
     94         // exe_dir gave us .../Chromium.app/Contents/MacOS/Chromium.
     95         *result = result->DirName();
     96         *result = result->DirName();
     97         *result = result->DirName();
     98       }
     99       return true;
    100 #else
    101       return PathService::Get(base::DIR_EXE, result);
    102 #endif  // defined(OS_MACOSX)
    103 #endif  // NDEBUG
    104     case chrome::FILE_RESOURCE_MODULE:
    105       return PathService::Get(base::FILE_MODULE, result);
    106   }
    107 
    108   // Assume that we will not need to create the directory if it does not exist.
    109   // This flag can be set to true for the cases where we want to create it.
    110   bool create_dir = false;
    111 
    112   FilePath cur;
    113   switch (key) {
    114     case chrome::DIR_USER_DATA:
    115       if (!GetDefaultUserDataDirectory(&cur)) {
    116         NOTREACHED();
    117         return false;
    118       }
    119       create_dir = true;
    120       break;
    121     case chrome::DIR_USER_DOCUMENTS:
    122       if (!GetUserDocumentsDirectory(&cur))
    123         return false;
    124       create_dir = true;
    125       break;
    126     case chrome::DIR_DEFAULT_DOWNLOADS_SAFE:
    127 #if defined(OS_WIN)
    128       if (!GetUserDownloadsDirectorySafe(&cur))
    129         return false;
    130       break;
    131 #else
    132       // Fall through for all other platforms.
    133 #endif
    134     case chrome::DIR_DEFAULT_DOWNLOADS:
    135       if (!GetUserDownloadsDirectory(&cur))
    136         return false;
    137       // Do not create the download directory here, we have done it twice now
    138       // and annoyed a lot of users.
    139       break;
    140     case chrome::DIR_CRASH_DUMPS:
    141       // The crash reports are always stored relative to the default user data
    142       // directory.  This avoids the problem of having to re-initialize the
    143       // exception handler after parsing command line options, which may
    144       // override the location of the app's profile directory.
    145       if (!GetDefaultUserDataDirectory(&cur))
    146         return false;
    147       cur = cur.Append(FILE_PATH_LITERAL("Crash Reports"));
    148       create_dir = true;
    149       break;
    150     case chrome::DIR_USER_DESKTOP:
    151       if (!GetUserDesktop(&cur))
    152         return false;
    153       break;
    154     case chrome::DIR_RESOURCES:
    155 #if defined(OS_MACOSX)
    156       cur = base::mac::MainAppBundlePath();
    157       cur = cur.Append(FILE_PATH_LITERAL("Resources"));
    158 #else
    159       if (!PathService::Get(chrome::DIR_APP, &cur))
    160         return false;
    161       cur = cur.Append(FILE_PATH_LITERAL("resources"));
    162 #endif
    163       break;
    164     case chrome::DIR_SHARED_RESOURCES:
    165       if (!PathService::Get(chrome::DIR_RESOURCES, &cur))
    166         return false;
    167       cur = cur.Append(FILE_PATH_LITERAL("shared"));
    168       break;
    169     case chrome::DIR_INSPECTOR:
    170       if (!PathService::Get(chrome::DIR_RESOURCES, &cur))
    171         return false;
    172       cur = cur.Append(FILE_PATH_LITERAL("inspector"));
    173       break;
    174     case chrome::DIR_APP_DICTIONARIES:
    175 #if defined(OS_LINUX) || defined(OS_MACOSX)
    176       // We can't write into the EXE dir on Linux, so keep dictionaries
    177       // alongside the safe browsing database in the user data dir.
    178       // And we don't want to write into the bundle on the Mac, so push
    179       // it to the user data dir there also.
    180       if (!PathService::Get(chrome::DIR_USER_DATA, &cur))
    181         return false;
    182 #else
    183       if (!PathService::Get(base::DIR_EXE, &cur))
    184         return false;
    185 #endif
    186       cur = cur.Append(FILE_PATH_LITERAL("Dictionaries"));
    187       create_dir = true;
    188       break;
    189     case chrome::DIR_USER_DATA_TEMP:
    190       if (!PathService::Get(chrome::DIR_USER_DATA, &cur))
    191         return false;
    192       cur = cur.Append(FILE_PATH_LITERAL("Temp"));
    193       break;
    194     case chrome::DIR_INTERNAL_PLUGINS:
    195       if (!GetInternalPluginsDirectory(&cur))
    196         return false;
    197       break;
    198     case chrome::DIR_MEDIA_LIBS:
    199 #if defined(OS_MACOSX)
    200       *result = base::mac::MainAppBundlePath();
    201       *result = result->Append("Libraries");
    202       return true;
    203 #else
    204       return PathService::Get(chrome::DIR_APP, result);
    205 #endif
    206     case chrome::FILE_LOCAL_STATE:
    207       if (!PathService::Get(chrome::DIR_USER_DATA, &cur))
    208         return false;
    209       cur = cur.Append(chrome::kLocalStateFilename);
    210       break;
    211     case chrome::FILE_RECORDED_SCRIPT:
    212       if (!PathService::Get(chrome::DIR_USER_DATA, &cur))
    213         return false;
    214       cur = cur.Append(FILE_PATH_LITERAL("script.log"));
    215       break;
    216     case chrome::FILE_FLASH_PLUGIN:
    217       if (!GetInternalPluginsDirectory(&cur))
    218         return false;
    219       cur = cur.Append(kInternalFlashPluginFileName);
    220       if (!file_util::PathExists(cur))
    221         return false;
    222       break;
    223     case chrome::FILE_PDF_PLUGIN:
    224       if (!GetInternalPluginsDirectory(&cur))
    225         return false;
    226       cur = cur.Append(kInternalPDFPluginFileName);
    227       break;
    228     case chrome::FILE_NACL_PLUGIN:
    229       if (!GetInternalPluginsDirectory(&cur))
    230         return false;
    231       cur = cur.Append(kInternalNaClPluginFileName);
    232       break;
    233     case chrome::FILE_RESOURCES_PACK:
    234 #if defined(OS_MACOSX)
    235       if (base::mac::AmIBundled()) {
    236         cur = base::mac::MainAppBundlePath();
    237         cur = cur.Append(FILE_PATH_LITERAL("Resources"))
    238                  .Append(FILE_PATH_LITERAL("resources.pak"));
    239         break;
    240       }
    241       // If we're not bundled on mac, resources.pak should be next to the
    242       // binary (e.g., for unit tests).
    243 #endif
    244       if (!PathService::Get(base::DIR_MODULE, &cur))
    245         return false;
    246       cur = cur.Append(FILE_PATH_LITERAL("resources.pak"));
    247       break;
    248 #if defined(OS_CHROMEOS)
    249     case chrome::FILE_CHROMEOS_API:
    250       if (!PathService::Get(base::DIR_MODULE, &cur))
    251         return false;
    252       cur = cur.Append(FILE_PATH_LITERAL("chromeos"));
    253       cur = cur.Append(FILE_PATH_LITERAL("libcros.so"));
    254       break;
    255 #endif
    256     // The following are only valid in the development environment, and
    257     // will fail if executed from an installed executable (because the
    258     // generated path won't exist).
    259     case chrome::DIR_TEST_DATA:
    260       if (!PathService::Get(base::DIR_SOURCE_ROOT, &cur))
    261         return false;
    262       cur = cur.Append(FILE_PATH_LITERAL("chrome"));
    263       cur = cur.Append(FILE_PATH_LITERAL("test"));
    264       cur = cur.Append(FILE_PATH_LITERAL("data"));
    265       if (!file_util::PathExists(cur))  // we don't want to create this
    266         return false;
    267       break;
    268     case chrome::DIR_TEST_TOOLS:
    269       if (!PathService::Get(base::DIR_SOURCE_ROOT, &cur))
    270         return false;
    271       cur = cur.Append(FILE_PATH_LITERAL("chrome"));
    272       cur = cur.Append(FILE_PATH_LITERAL("tools"));
    273       cur = cur.Append(FILE_PATH_LITERAL("test"));
    274       if (!file_util::PathExists(cur))  // we don't want to create this
    275         return false;
    276       break;
    277 #if defined(OS_POSIX) && !defined(OS_MACOSX)
    278     case chrome::DIR_POLICY_FILES: {
    279 #if defined(GOOGLE_CHROME_BUILD)
    280       cur = FilePath(FILE_PATH_LITERAL("/etc/opt/chrome/policies"));
    281 #else
    282       cur = FilePath(FILE_PATH_LITERAL("/etc/chromium/policies"));
    283 #endif
    284       if (!file_util::PathExists(cur))  // we don't want to create this
    285         return false;
    286       break;
    287     }
    288 #endif
    289 #if defined(OS_MACOSX)
    290     case chrome::DIR_MANAGED_PREFS: {
    291       if (!GetLocalLibraryDirectory(&cur))
    292         return false;
    293       cur = cur.Append(FILE_PATH_LITERAL("Managed Preferences"));
    294       char* login = getlogin();
    295       if (!login)
    296         return false;
    297       cur = cur.AppendASCII(login);
    298       if (!file_util::PathExists(cur))  // we don't want to create this
    299         return false;
    300       break;
    301     }
    302 #endif
    303 #if defined(OS_CHROMEOS)
    304     case chrome::DIR_USER_EXTERNAL_EXTENSIONS: {
    305       if (!PathService::Get(chrome::DIR_USER_DATA, &cur))
    306         return false;
    307       cur = cur.Append(FILE_PATH_LITERAL("External Extensions"));
    308       break;
    309     }
    310 #endif
    311     default:
    312       return false;
    313   }
    314 
    315   if (create_dir && !file_util::PathExists(cur) &&
    316       !file_util::CreateDirectory(cur))
    317     return false;
    318 
    319   *result = cur;
    320   return true;
    321 }
    322 
    323 // This cannot be done as a static initializer sadly since Visual Studio will
    324 // eliminate this object file if there is no direct entry point into it.
    325 void RegisterPathProvider() {
    326   PathService::RegisterProvider(PathProvider, PATH_START, PATH_END);
    327 }
    328 
    329 }  // namespace chrome
    330