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