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