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