• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
GetInternalPluginsDirectory(base::FilePath * result)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 
PathProvider(int key,base::FilePath * result)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.
RegisterPathProvider()596 void RegisterPathProvider() {
597   PathService::RegisterProvider(PathProvider, PATH_START, PATH_END);
598 }
599 
SetInvalidSpecifiedUserDataDir(const base::FilePath & user_data_dir)600 void SetInvalidSpecifiedUserDataDir(const base::FilePath& user_data_dir) {
601   g_invalid_specified_user_data_dir.Get() = user_data_dir;
602 }
603 
GetInvalidSpecifiedUserDataDir()604 const base::FilePath& GetInvalidSpecifiedUserDataDir() {
605   return g_invalid_specified_user_data_dir.Get();
606 }
607 
608 }  // namespace chrome
609