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