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