Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / chrome / common / chrome_paths.cc
blobb48092b758a9cf0af129115c7164cce50a84e551
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.
5 #include "chrome/common/chrome_paths.h"
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"
21 #if defined(OS_ANDROID)
22 #include "base/android/path_utils.h"
23 #include "base/base_paths_android.h"
24 #endif
26 #if defined(OS_MACOSX)
27 #include "base/mac/foundation_util.h"
28 #endif
30 #if defined(OS_WIN)
31 #include "base/win/registry.h"
32 #endif
34 #include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR.
36 namespace {
38 #if defined(OS_WIN)
39 const wchar_t kFlashRegistryRoot[] = L"SOFTWARE\\Macromedia\\FlashPlayerPepper";
41 const wchar_t kFlashPlayerPathValueName[] = L"PlayerPath";
42 #endif
44 // File name of the internal Flash plugin on different platforms.
45 const base::FilePath::CharType kInternalFlashPluginFileName[] =
46 #if defined(OS_MACOSX)
47 FILE_PATH_LITERAL("Flash Player Plugin for Chrome.plugin");
48 #elif defined(OS_WIN)
49 FILE_PATH_LITERAL("gcswf32.dll");
50 #else // OS_LINUX, etc.
51 FILE_PATH_LITERAL("libgcflashplayer.so");
52 #endif
54 // The Pepper Flash plugins are in a directory with this name.
55 const base::FilePath::CharType kPepperFlashBaseDirectory[] =
56 FILE_PATH_LITERAL("PepperFlash");
58 #if defined(OS_MACOSX) && !defined(OS_IOS)
59 const base::FilePath::CharType kPepperFlashSystemBaseDirectory[] =
60 FILE_PATH_LITERAL("Internet Plug-Ins/PepperFlashPlayer");
61 #endif
63 const base::FilePath::CharType kInternalNaClPluginFileName[] =
64 FILE_PATH_LITERAL("internal-nacl-plugin");
66 #if defined(OS_LINUX)
67 // The path to the external extension <id>.json files.
68 // /usr/share seems like a good choice, see: http://www.pathname.com/fhs/
69 const base::FilePath::CharType kFilepathSinglePrefExtensions[] =
70 #if defined(GOOGLE_CHROME_BUILD)
71 FILE_PATH_LITERAL("/usr/share/google-chrome/extensions");
72 #else
73 FILE_PATH_LITERAL("/usr/share/chromium/extensions");
74 #endif // defined(GOOGLE_CHROME_BUILD)
75 #endif // defined(OS_LINUX)
77 static base::LazyInstance<base::FilePath>
78 g_invalid_specified_user_data_dir = LAZY_INSTANCE_INITIALIZER;
80 // Gets the path for internal plugins.
81 bool GetInternalPluginsDirectory(base::FilePath* result) {
82 #if defined(OS_MACOSX) && !defined(OS_IOS)
83 // If called from Chrome, get internal plugins from a subdirectory of the
84 // framework.
85 if (base::mac::AmIBundled()) {
86 *result = chrome::GetFrameworkBundlePath();
87 DCHECK(!result->empty());
88 *result = result->Append("Internet Plug-Ins");
89 return true;
91 // In tests, just look in the module directory (below).
92 #endif
94 // The rest of the world expects plugins in the module directory.
95 return PathService::Get(base::DIR_MODULE, result);
98 #if defined(OS_WIN)
99 // Gets the Flash path if installed on the system.
100 bool GetSystemFlashDirectory(base::FilePath* out_path) {
101 base::win::RegKey path_key(HKEY_LOCAL_MACHINE, kFlashRegistryRoot, KEY_READ);
102 base::string16 path_str;
103 if (FAILED(path_key.ReadValue(kFlashPlayerPathValueName, &path_str)))
104 return false;
105 base::FilePath plugin_path = base::FilePath(path_str).DirName();
107 *out_path = plugin_path;
108 return true;
110 #endif
112 } // namespace
114 namespace chrome {
116 bool PathProvider(int key, base::FilePath* result) {
117 // Some keys are just aliases...
118 switch (key) {
119 case chrome::DIR_APP:
120 return PathService::Get(base::DIR_MODULE, result);
121 case chrome::DIR_LOGS:
122 #ifdef NDEBUG
123 // Release builds write to the data dir
124 return PathService::Get(chrome::DIR_USER_DATA, result);
125 #else
126 // Debug builds write next to the binary (in the build tree)
127 #if defined(OS_MACOSX)
128 if (!PathService::Get(base::DIR_EXE, result))
129 return false;
130 if (base::mac::AmIBundled()) {
131 // If we're called from chrome, dump it beside the app (outside the
132 // app bundle), if we're called from a unittest, we'll already
133 // outside the bundle so use the exe dir.
134 // exe_dir gave us .../Chromium.app/Contents/MacOS/Chromium.
135 *result = result->DirName();
136 *result = result->DirName();
137 *result = result->DirName();
139 return true;
140 #else
141 return PathService::Get(base::DIR_EXE, result);
142 #endif // defined(OS_MACOSX)
143 #endif // NDEBUG
144 case chrome::FILE_RESOURCE_MODULE:
145 return PathService::Get(base::FILE_MODULE, result);
148 // Assume that we will not need to create the directory if it does not exist.
149 // This flag can be set to true for the cases where we want to create it.
150 bool create_dir = false;
152 base::FilePath cur;
153 switch (key) {
154 case chrome::DIR_USER_DATA:
155 if (!GetDefaultUserDataDirectory(&cur)) {
156 NOTREACHED();
157 return false;
159 create_dir = true;
160 break;
161 case chrome::DIR_USER_DOCUMENTS:
162 if (!GetUserDocumentsDirectory(&cur))
163 return false;
164 create_dir = true;
165 break;
166 case chrome::DIR_USER_MUSIC:
167 if (!GetUserMusicDirectory(&cur))
168 return false;
169 break;
170 case chrome::DIR_USER_PICTURES:
171 if (!GetUserPicturesDirectory(&cur))
172 return false;
173 break;
174 case chrome::DIR_USER_VIDEOS:
175 if (!GetUserVideosDirectory(&cur))
176 return false;
177 break;
178 case chrome::DIR_DEFAULT_DOWNLOADS_SAFE:
179 #if defined(OS_WIN) || defined(OS_LINUX)
180 if (!GetUserDownloadsDirectorySafe(&cur))
181 return false;
182 break;
183 #else
184 // Fall through for all other platforms.
185 #endif
186 case chrome::DIR_DEFAULT_DOWNLOADS:
187 #if defined(OS_ANDROID)
188 if (!base::android::GetDownloadsDirectory(&cur))
189 return false;
190 #else
191 if (!GetUserDownloadsDirectory(&cur))
192 return false;
193 // Do not create the download directory here, we have done it twice now
194 // and annoyed a lot of users.
195 #endif
196 break;
197 case chrome::DIR_CRASH_DUMPS:
198 #if defined(OS_CHROMEOS)
199 // ChromeOS uses a separate directory. See http://crosbug.com/25089
200 cur = base::FilePath("/var/log/chrome");
201 #elif defined(OS_ANDROID)
202 if (!base::android::GetCacheDirectory(&cur))
203 return false;
204 #else
205 // The crash reports are always stored relative to the default user data
206 // directory. This avoids the problem of having to re-initialize the
207 // exception handler after parsing command line options, which may
208 // override the location of the app's profile directory.
209 if (!GetDefaultUserDataDirectory(&cur))
210 return false;
211 #endif
212 #if defined(OS_MACOSX)
213 cur = cur.Append(FILE_PATH_LITERAL("Crashpad"));
214 #else
215 cur = cur.Append(FILE_PATH_LITERAL("Crash Reports"));
216 #endif
217 create_dir = true;
218 break;
219 #if defined(OS_WIN)
220 case chrome::DIR_WATCHER_DATA:
221 // The watcher data is always stored relative to the default user data
222 // directory. This allows the watcher to be initialized before
223 // command-line options have been parsed.
224 if (!GetDefaultUserDataDirectory(&cur))
225 return false;
226 cur = cur.Append(FILE_PATH_LITERAL("Diagnostics"));
227 break;
228 #endif
229 case chrome::DIR_RESOURCES:
230 #if defined(OS_MACOSX)
231 cur = base::mac::FrameworkBundlePath();
232 cur = cur.Append(FILE_PATH_LITERAL("Resources"));
233 #else
234 if (!PathService::Get(chrome::DIR_APP, &cur))
235 return false;
236 cur = cur.Append(FILE_PATH_LITERAL("resources"));
237 #endif
238 break;
239 case chrome::DIR_INSPECTOR:
240 if (!PathService::Get(chrome::DIR_RESOURCES, &cur))
241 return false;
242 cur = cur.Append(FILE_PATH_LITERAL("inspector"));
243 break;
244 case chrome::DIR_APP_DICTIONARIES:
245 #if defined(OS_POSIX)
246 // We can't write into the EXE dir on Linux, so keep dictionaries
247 // alongside the safe browsing database in the user data dir.
248 // And we don't want to write into the bundle on the Mac, so push
249 // it to the user data dir there also.
250 if (!PathService::Get(chrome::DIR_USER_DATA, &cur))
251 return false;
252 #else
253 if (!PathService::Get(base::DIR_EXE, &cur))
254 return false;
255 #endif
256 cur = cur.Append(FILE_PATH_LITERAL("Dictionaries"));
257 create_dir = true;
258 break;
259 case chrome::DIR_INTERNAL_PLUGINS:
260 if (!GetInternalPluginsDirectory(&cur))
261 return false;
262 break;
263 case chrome::DIR_PEPPER_FLASH_PLUGIN:
264 if (!GetInternalPluginsDirectory(&cur))
265 return false;
266 cur = cur.Append(kPepperFlashBaseDirectory);
267 break;
268 case chrome::DIR_COMPONENT_UPDATED_PEPPER_FLASH_PLUGIN:
269 if (!PathService::Get(chrome::DIR_USER_DATA, &cur))
270 return false;
271 cur = cur.Append(kPepperFlashBaseDirectory);
272 break;
273 case chrome::DIR_PEPPER_FLASH_SYSTEM_PLUGIN:
274 #if defined(OS_WIN)
275 if (!GetSystemFlashDirectory(&cur))
276 return false;
277 #elif defined(OS_MACOSX) && !defined(OS_IOS)
278 if (!GetLocalLibraryDirectory(&cur))
279 return false;
280 cur = cur.Append(kPepperFlashSystemBaseDirectory);
281 #else
282 // Chrome on iOS does not supports PPAPI binaries, return false.
283 // TODO(wfh): If Adobe release PPAPI binaries for Linux, add support here.
284 return false;
285 #endif
286 break;
287 case chrome::FILE_LOCAL_STATE:
288 if (!PathService::Get(chrome::DIR_USER_DATA, &cur))
289 return false;
290 cur = cur.Append(chrome::kLocalStateFilename);
291 break;
292 case chrome::FILE_RECORDED_SCRIPT:
293 if (!PathService::Get(chrome::DIR_USER_DATA, &cur))
294 return false;
295 cur = cur.Append(FILE_PATH_LITERAL("script.log"));
296 break;
297 case chrome::FILE_FLASH_PLUGIN:
298 if (!GetInternalPluginsDirectory(&cur))
299 return false;
300 cur = cur.Append(kInternalFlashPluginFileName);
301 break;
302 case chrome::FILE_PEPPER_FLASH_PLUGIN:
303 if (!PathService::Get(chrome::DIR_PEPPER_FLASH_PLUGIN, &cur))
304 return false;
305 cur = cur.Append(chrome::kPepperFlashPluginFilename);
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();
345 #else
346 if (!GetInternalPluginsDirectory(&cur))
347 return false;
348 #endif
349 cur = cur.Append(FILE_PATH_LITERAL("pnacl"));
350 break;
351 #if defined(WIDEVINE_CDM_AVAILABLE) && defined(ENABLE_PEPPER_CDMS)
352 #if defined(WIDEVINE_CDM_IS_COMPONENT)
353 case chrome::DIR_COMPONENT_WIDEVINE_CDM:
354 if (!PathService::Get(chrome::DIR_USER_DATA, &cur))
355 return false;
356 cur = cur.Append(kWidevineCdmBaseDirectory);
357 break;
358 #endif // defined(WIDEVINE_CDM_IS_COMPONENT)
359 // TODO(xhwang): FILE_WIDEVINE_CDM_ADAPTER has different meanings.
360 // In the component case, this is the source adapter. Otherwise, it is the
361 // actual Pepper module that gets loaded.
362 case chrome::FILE_WIDEVINE_CDM_ADAPTER:
363 if (!GetInternalPluginsDirectory(&cur))
364 return false;
365 cur = cur.AppendASCII(kWidevineCdmAdapterFileName);
366 break;
367 #endif // defined(WIDEVINE_CDM_AVAILABLE) && defined(ENABLE_PEPPER_CDMS)
368 case chrome::FILE_RESOURCES_PACK:
369 #if defined(OS_MACOSX) && !defined(OS_IOS)
370 if (base::mac::AmIBundled()) {
371 cur = base::mac::FrameworkBundlePath();
372 cur = cur.Append(FILE_PATH_LITERAL("Resources"))
373 .Append(FILE_PATH_LITERAL("resources.pak"));
374 break;
376 #elif defined(OS_ANDROID)
377 if (!PathService::Get(ui::DIR_RESOURCE_PAKS_ANDROID, &cur))
378 return false;
379 #else
380 // If we're not bundled on mac or Android, resources.pak should be next
381 // to the binary (e.g., for unit tests).
382 if (!PathService::Get(base::DIR_MODULE, &cur))
383 return false;
384 #endif
385 cur = cur.Append(FILE_PATH_LITERAL("resources.pak"));
386 break;
387 case chrome::DIR_RESOURCES_EXTENSION:
388 if (!PathService::Get(base::DIR_MODULE, &cur))
389 return false;
390 cur = cur.Append(FILE_PATH_LITERAL("resources"))
391 .Append(FILE_PATH_LITERAL("extension"));
392 break;
393 #if defined(OS_CHROMEOS)
394 case chrome::DIR_CHROMEOS_WALLPAPERS:
395 if (!PathService::Get(chrome::DIR_USER_DATA, &cur))
396 return false;
397 cur = cur.Append(FILE_PATH_LITERAL("wallpapers"));
398 break;
399 case chrome::DIR_CHROMEOS_WALLPAPER_THUMBNAILS:
400 if (!PathService::Get(chrome::DIR_USER_DATA, &cur))
401 return false;
402 cur = cur.Append(FILE_PATH_LITERAL("wallpaper_thumbnails"));
403 break;
404 case chrome::DIR_CHROMEOS_CUSTOM_WALLPAPERS:
405 if (!PathService::Get(chrome::DIR_USER_DATA, &cur))
406 return false;
407 cur = cur.Append(FILE_PATH_LITERAL("custom_wallpapers"));
408 break;
409 #endif
410 #if defined(OS_LINUX) && defined(ENABLE_SUPERVISED_USERS)
411 case chrome::DIR_SUPERVISED_USERS_DEFAULT_APPS:
412 if (!PathService::Get(chrome::DIR_STANDALONE_EXTERNAL_EXTENSIONS, &cur))
413 return false;
414 cur = cur.Append(FILE_PATH_LITERAL("managed_users"));
415 break;
416 #endif
417 // The following are only valid in the development environment, and
418 // will fail if executed from an installed executable (because the
419 // generated path won't exist).
420 case chrome::DIR_GEN_TEST_DATA:
421 #if defined(OS_ANDROID)
422 // On Android, our tests don't have permission to write to DIR_MODULE.
423 // gtest/test_runner.py pushes data to external storage.
424 if (!PathService::Get(base::DIR_ANDROID_EXTERNAL_STORAGE, &cur))
425 return false;
426 #else
427 if (!PathService::Get(base::DIR_MODULE, &cur))
428 return false;
429 #endif
430 cur = cur.Append(FILE_PATH_LITERAL("test_data"));
431 if (!base::PathExists(cur)) // We don't want to create this.
432 return false;
433 break;
434 case chrome::DIR_TEST_DATA:
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("test"));
439 cur = cur.Append(FILE_PATH_LITERAL("data"));
440 if (!base::PathExists(cur)) // We don't want to create this.
441 return false;
442 break;
443 case chrome::DIR_TEST_TOOLS:
444 if (!PathService::Get(base::DIR_SOURCE_ROOT, &cur))
445 return false;
446 cur = cur.Append(FILE_PATH_LITERAL("chrome"));
447 cur = cur.Append(FILE_PATH_LITERAL("tools"));
448 cur = cur.Append(FILE_PATH_LITERAL("test"));
449 if (!base::PathExists(cur)) // We don't want to create this
450 return false;
451 break;
452 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD)
453 case chrome::DIR_POLICY_FILES: {
454 #if defined(GOOGLE_CHROME_BUILD)
455 cur = base::FilePath(FILE_PATH_LITERAL("/etc/opt/chrome/policies"));
456 #else
457 cur = base::FilePath(FILE_PATH_LITERAL("/etc/chromium/policies"));
458 #endif
459 break;
461 #endif
462 #if defined(OS_MACOSX) && !defined(OS_IOS)
463 case chrome::DIR_USER_LIBRARY: {
464 if (!GetUserLibraryDirectory(&cur))
465 return false;
466 if (!base::PathExists(cur)) // We don't want to create this.
467 return false;
468 break;
470 case chrome::DIR_USER_APPLICATIONS: {
471 if (!GetUserApplicationsDirectory(&cur))
472 return false;
473 if (!base::PathExists(cur)) // We don't want to create this.
474 return false;
475 break;
477 #endif
478 #if defined(OS_CHROMEOS) || (defined(OS_MACOSX) && !defined(OS_IOS))
479 case chrome::DIR_USER_EXTERNAL_EXTENSIONS: {
480 if (!PathService::Get(chrome::DIR_USER_DATA, &cur))
481 return false;
482 cur = cur.Append(FILE_PATH_LITERAL("External Extensions"));
483 break;
485 #endif
486 #if defined(OS_LINUX)
487 case chrome::DIR_STANDALONE_EXTERNAL_EXTENSIONS: {
488 cur = base::FilePath(kFilepathSinglePrefExtensions);
489 break;
491 #endif
492 case chrome::DIR_EXTERNAL_EXTENSIONS:
493 #if defined(OS_MACOSX) && !defined(OS_IOS)
494 if (!chrome::GetGlobalApplicationSupportDirectory(&cur))
495 return false;
497 cur = cur.Append(FILE_PATH_LITERAL("Google"))
498 .Append(FILE_PATH_LITERAL("Chrome"))
499 .Append(FILE_PATH_LITERAL("External Extensions"));
500 create_dir = false;
501 #else
502 if (!PathService::Get(base::DIR_MODULE, &cur))
503 return false;
505 cur = cur.Append(FILE_PATH_LITERAL("extensions"));
506 create_dir = true;
507 #endif
508 break;
510 case chrome::DIR_DEFAULT_APPS:
511 #if defined(OS_MACOSX)
512 cur = base::mac::FrameworkBundlePath();
513 cur = cur.Append(FILE_PATH_LITERAL("Default Apps"));
514 #else
515 if (!PathService::Get(chrome::DIR_APP, &cur))
516 return false;
517 cur = cur.Append(FILE_PATH_LITERAL("default_apps"));
518 #endif
519 break;
521 #if defined(OS_LINUX) || (defined(OS_MACOSX) && !defined(OS_IOS))
522 case chrome::DIR_NATIVE_MESSAGING:
523 #if defined(OS_MACOSX)
524 #if defined(GOOGLE_CHROME_BUILD)
525 cur = base::FilePath(FILE_PATH_LITERAL(
526 "/Library/Google/Chrome/NativeMessagingHosts"));
527 #else
528 cur = base::FilePath(FILE_PATH_LITERAL(
529 "/Library/Application Support/Chromium/NativeMessagingHosts"));
530 #endif
531 #else // defined(OS_MACOSX)
532 #if defined(GOOGLE_CHROME_BUILD)
533 cur = base::FilePath(FILE_PATH_LITERAL(
534 "/etc/opt/chrome/native-messaging-hosts"));
535 #else
536 cur = base::FilePath(FILE_PATH_LITERAL(
537 "/etc/chromium/native-messaging-hosts"));
538 #endif
539 #endif // !defined(OS_MACOSX)
540 break;
542 case chrome::DIR_USER_NATIVE_MESSAGING:
543 if (!PathService::Get(chrome::DIR_USER_DATA, &cur))
544 return false;
545 cur = cur.Append(FILE_PATH_LITERAL("NativeMessagingHosts"));
546 break;
547 #endif // defined(OS_LINUX) || (defined(OS_MACOSX) && !defined(OS_IOS))
548 #if !defined(OS_ANDROID)
549 case chrome::DIR_GLOBAL_GCM_STORE:
550 if (!PathService::Get(chrome::DIR_USER_DATA, &cur))
551 return false;
552 cur = cur.Append(kGCMStoreDirname);
553 break;
554 #endif // !defined(OS_ANDROID)
555 #if defined(OS_ANDROID)
556 case chrome::DIR_OFFLINE_PAGE_METADATA:
557 if (!PathService::Get(chrome::DIR_USER_DATA, &cur))
558 return false;
559 cur = cur.Append(kOfflinePageMetadataDirname);
560 break;
561 #endif // defined(OS_ANDROID)
563 default:
564 return false;
567 // TODO(bauerb): http://crbug.com/259796
568 base::ThreadRestrictions::ScopedAllowIO allow_io;
569 if (create_dir && !base::PathExists(cur) &&
570 !base::CreateDirectory(cur))
571 return false;
573 *result = cur;
574 return true;
577 // This cannot be done as a static initializer sadly since Visual Studio will
578 // eliminate this object file if there is no direct entry point into it.
579 void RegisterPathProvider() {
580 PathService::RegisterProvider(PathProvider, PATH_START, PATH_END);
583 void SetInvalidSpecifiedUserDataDir(const base::FilePath& user_data_dir) {
584 g_invalid_specified_user_data_dir.Get() = user_data_dir;
587 const base::FilePath& GetInvalidSpecifiedUserDataDir() {
588 return g_invalid_specified_user_data_dir.Get();
591 } // namespace chrome