OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/install_static/install_util.h" | 5 #include "chrome/install_static/install_util.h" |
6 | 6 |
7 #include <windows.h> | 7 #include <windows.h> |
8 #include <assert.h> | 8 #include <assert.h> |
9 #include <algorithm> | 9 #include <algorithm> |
10 #include <iostream> | 10 #include <iostream> |
11 #include <iterator> | 11 #include <iterator> |
12 #include <memory> | 12 #include <memory> |
13 #include <sstream> | 13 #include <sstream> |
14 | 14 |
15 #include "chrome/install_static/policy_path_parser.h" | |
15 #include "chrome_elf/nt_registry/nt_registry.h" | 16 #include "chrome_elf/nt_registry/nt_registry.h" |
16 | 17 |
17 namespace install_static { | 18 namespace install_static { |
18 | 19 |
19 ProcessType g_process_type = ProcessType::UNINITIALIZED; | 20 ProcessType g_process_type = ProcessType::UNINITIALIZED; |
20 | 21 |
21 // TODO(ananta) | 22 // TODO(ananta) |
22 // http://crbug.com/604923 | 23 // http://crbug.com/604923 |
23 // The constants defined in this file are also defined in chrome/installer and | 24 // The constants defined in this file are also defined in chrome/installer and |
24 // other places. we need to unify them. | 25 // other places. we need to unify them. |
(...skipping 29 matching lines...) Expand all Loading... | |
54 const wchar_t kAppGuidGoogleChrome[] = | 55 const wchar_t kAppGuidGoogleChrome[] = |
55 L"{8A69D345-D564-463c-AFF1-A69D9E530F96}"; | 56 L"{8A69D345-D564-463c-AFF1-A69D9E530F96}"; |
56 const wchar_t kAppGuidGoogleBinaries[] = | 57 const wchar_t kAppGuidGoogleBinaries[] = |
57 L"{4DC8B4CA-1BDA-483e-B5FA-D3C12E15B62D}"; | 58 L"{4DC8B4CA-1BDA-483e-B5FA-D3C12E15B62D}"; |
58 | 59 |
59 const wchar_t kHeadless[] = L"CHROME_HEADLESS"; | 60 const wchar_t kHeadless[] = L"CHROME_HEADLESS"; |
60 const wchar_t kShowRestart[] = L"CHROME_CRASHED"; | 61 const wchar_t kShowRestart[] = L"CHROME_CRASHED"; |
61 const wchar_t kRestartInfo[] = L"CHROME_RESTART"; | 62 const wchar_t kRestartInfo[] = L"CHROME_RESTART"; |
62 const wchar_t kRtlLocale[] = L"RIGHT_TO_LEFT"; | 63 const wchar_t kRtlLocale[] = L"RIGHT_TO_LEFT"; |
63 | 64 |
64 const char kGpuProcess[] = "gpu-process"; | 65 const wchar_t kCrashpadHandler[] = L"crashpad-handler"; |
65 const char kPpapiPluginProcess[] = "ppapi"; | 66 const wchar_t kProcessType[] = L"type"; |
66 const char kRendererProcess[] = "renderer"; | 67 const wchar_t kUserDataDirSwitch[] = L"user-data-dir"; |
67 const char kUtilityProcess[] = "utility"; | 68 const wchar_t kUtilityProcess[] = L"utility"; |
68 const char kProcessType[] = "type"; | 69 |
69 const char kCrashpadHandler[] = "crashpad-handler"; | 70 #if defined(GOOGLE_CHROME_BUILD) |
71 const wchar_t kRegistryChromePolicyKey[] = | |
72 L"SOFTWARE\\Policies\\Google\\Chrome"; | |
73 #else | |
74 const wchar_t kRegistryChromePolicyKey[] = | |
75 L"SOFTWARE\\Policies\\Chromium"; | |
76 #endif | |
77 const wchar_t kUserDataDirRegKey[] = L"UserDataDir"; | |
70 | 78 |
71 namespace { | 79 namespace { |
72 | 80 |
73 // TODO(ananta) | 81 // TODO(ananta) |
74 // http://crbug.com/604923 | 82 // http://crbug.com/604923 |
75 // These constants are defined in the chrome/installer directory as well. We | 83 // These constants are defined in the chrome/installer directory as well. We |
76 // need to unify them. | 84 // need to unify them. |
77 #if defined(GOOGLE_CHROME_BUILD) | 85 #if defined(GOOGLE_CHROME_BUILD) |
78 const wchar_t kSxSSuffix[] = L" SxS"; | 86 const wchar_t kSxSSuffix[] = L" SxS"; |
79 const wchar_t kGoogleChromeInstallSubDir1[] = L"Google"; | 87 const wchar_t kGoogleChromeInstallSubDir1[] = L"Google"; |
(...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
369 std::vector<StringType> tokens; | 377 std::vector<StringType> tokens; |
370 std::basic_istringstream<typename StringType::value_type> buffer(str); | 378 std::basic_istringstream<typename StringType::value_type> buffer(str); |
371 for (StringType token; std::getline(buffer, token, delimiter);) { | 379 for (StringType token; std::getline(buffer, token, delimiter);) { |
372 if (trim_spaces) | 380 if (trim_spaces) |
373 TrimT<StringType>(&token); | 381 TrimT<StringType>(&token); |
374 tokens.push_back(token); | 382 tokens.push_back(token); |
375 } | 383 } |
376 return tokens; | 384 return tokens; |
377 } | 385 } |
378 | 386 |
387 // Checks if the key exists in the given hive and expands any string variables. | |
388 bool LoadUserDataDirPolicyFromRegistry(nt::ROOT_KEY hive, | |
389 const wchar_t* key_name, | |
390 std::wstring* dir) { | |
391 std::wstring value; | |
392 bool result = false; | |
393 HANDLE key; | |
394 if (nt::OpenRegKey(hive, kRegistryChromePolicyKey, KEY_READ, &key, nullptr)) { | |
395 if (nt::QueryRegValueSZ(key, key_name, &value)) { | |
396 *dir = install_static::ExpandPathVariables(value); | |
397 result = true; | |
398 } | |
399 nt::CloseRegKey(key); | |
Mark Mentovai
2016/11/10 22:06:17
I’m surprised that OpenRegKey doesn’t return a key
scottmg
2016/11/15 23:23:15
Agreed. Filed https://bugs.chromium.org/p/chromium
| |
400 } | |
401 return result; | |
402 } | |
403 | |
404 void CheckUserDataDirPolicy(std::wstring* user_data_dir) { | |
405 assert(user_data_dir); | |
406 // Policy from the HKLM hive has precedence over HKCU. | |
407 if (!LoadUserDataDirPolicyFromRegistry(nt::HKLM, kUserDataDirRegKey, | |
408 user_data_dir)) { | |
409 LoadUserDataDirPolicyFromRegistry(nt::HKCU, kUserDataDirRegKey, | |
410 user_data_dir); | |
411 } | |
412 } | |
413 | |
379 } // namespace | 414 } // namespace |
380 | 415 |
381 bool IsSxSChrome(const wchar_t* exe_path) { | 416 bool IsSxSChrome(const wchar_t* exe_path) { |
382 return ::wcsstr(exe_path, L"Chrome SxS\\Application") != nullptr; | 417 return ::wcsstr(exe_path, L"Chrome SxS\\Application") != nullptr; |
383 } | 418 } |
384 | 419 |
385 bool IsSystemInstall(const wchar_t* exe_path) { | 420 bool IsSystemInstall(const wchar_t* exe_path) { |
386 wchar_t program_dir[MAX_PATH] = {}; | 421 wchar_t program_dir[MAX_PATH] = {}; |
387 DWORD ret = ::GetEnvironmentVariable(L"PROGRAMFILES", program_dir, MAX_PATH); | 422 DWORD ret = ::GetEnvironmentVariable(L"PROGRAMFILES", program_dir, MAX_PATH); |
388 if (ret && ret < MAX_PATH && !::wcsnicmp(exe_path, program_dir, ret)) { | 423 if (ret && ret < MAX_PATH && !::wcsnicmp(exe_path, program_dir, ret)) { |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
489 } | 524 } |
490 | 525 |
491 bool IsNonBrowserProcess() { | 526 bool IsNonBrowserProcess() { |
492 assert(g_process_type != ProcessType::UNINITIALIZED); | 527 assert(g_process_type != ProcessType::UNINITIALIZED); |
493 return g_process_type == ProcessType::NON_BROWSER_PROCESS; | 528 return g_process_type == ProcessType::NON_BROWSER_PROCESS; |
494 } | 529 } |
495 | 530 |
496 bool GetDefaultUserDataDirectory(std::wstring* result) { | 531 bool GetDefaultUserDataDirectory(std::wstring* result) { |
497 static const wchar_t kLocalAppData[] = L"%LOCALAPPDATA%"; | 532 static const wchar_t kLocalAppData[] = L"%LOCALAPPDATA%"; |
498 | 533 |
499 std::unique_ptr<wchar_t> user_data_dir_path; | 534 std::unique_ptr<wchar_t> user_data_dir_path; |
Mark Mentovai
2016/11/10 22:06:17
This gets a new wchar_t[], so it should be a uniqu
scottmg
2016/11/15 23:23:15
Done.
| |
500 | 535 |
501 // This environment variable should be set on Windows 7 and up. | 536 // This environment variable should be set on Windows 7 and up. |
502 // If we fail to find this variable then we default to the temporary files | 537 // If we fail to find this variable then we default to the temporary files |
503 // path. | 538 // path. |
504 DWORD size = ::ExpandEnvironmentStrings(kLocalAppData, nullptr, 0); | 539 DWORD size = ::ExpandEnvironmentStrings(kLocalAppData, nullptr, 0); |
505 if (size) { | 540 if (size) { |
506 user_data_dir_path.reset(new wchar_t[size]); | 541 user_data_dir_path.reset(new wchar_t[size]); |
507 if (::ExpandEnvironmentStrings(kLocalAppData, user_data_dir_path.get(), | 542 if (::ExpandEnvironmentStrings(kLocalAppData, user_data_dir_path.get(), |
508 size) != size) { | 543 size) != size) { |
509 user_data_dir_path.reset(); | 544 user_data_dir_path.reset(); |
(...skipping 14 matching lines...) Expand all Loading... | |
524 | 559 |
525 *result = user_data_dir_path.get(); | 560 *result = user_data_dir_path.get(); |
526 if ((*result)[result->length() - 1] != L'\\') | 561 if ((*result)[result->length() - 1] != L'\\') |
527 result->append(L"\\"); | 562 result->append(L"\\"); |
528 result->append(install_sub_directory); | 563 result->append(install_sub_directory); |
529 result->append(L"\\"); | 564 result->append(L"\\"); |
530 result->append(kUserDataDirname); | 565 result->append(kUserDataDirname); |
531 return true; | 566 return true; |
532 } | 567 } |
533 | 568 |
534 bool GetDefaultCrashDumpLocation(std::wstring* crash_dir) { | 569 bool GetUserDataDirectory(std::wstring* result) { |
535 // In order to be able to start crash handling very early, we do not rely on | 570 // WARNING! This has to mirror the logic in chrome/app/chrome_main_delegate.cc |
536 // chrome's PathService entries (for DIR_CRASH_DUMPS) being available on | 571 // in InitializeUserDataDir(). This function derives the path in the same way, |
537 // Windows. See https://crbug.com/564398. | 572 // but without using base, nor reporting on failure as the Chrome |
538 if (!GetDefaultUserDataDirectory(crash_dir)) | 573 // implementation does. |
574 std::wstring user_data_dir = GetSwitchValueFromCommandLine( | |
575 ::GetCommandLine(), install_static::kUserDataDirSwitch); | |
576 | |
577 CheckUserDataDirPolicy(&user_data_dir); | |
578 | |
579 // On Windows, trailing separators leave Chrome in a bad state. See | |
580 // crbug.com/464616. | |
581 while (!user_data_dir.empty() && | |
582 (user_data_dir.back() == '\\' || user_data_dir.back() == '/')) { | |
583 user_data_dir = user_data_dir.substr(0, user_data_dir.size() - 1); | |
Mark Mentovai
2016/11/10 22:06:17
If C++11 is guaranteed (and it’s 2016, it should b
scottmg
2016/11/15 23:23:15
Done.
| |
584 } | |
585 | |
586 const bool specified_directory_was_invalid = | |
Mark Mentovai
2016/11/10 22:06:17
This says: If user_data_dir is empty, stop and set
scottmg
2016/11/11 00:24:46
Yeah, you're right. I just copied and adapted the
scottmg
2016/11/15 23:23:15
I think the behaviour is semi-rational now.
| |
587 !user_data_dir.empty() && !RecursiveDirectoryCreate(user_data_dir); | |
588 | |
589 if (specified_directory_was_invalid) { | |
590 if (!GetDefaultUserDataDirectory(&user_data_dir)) { | |
Mark Mentovai
2016/11/10 22:06:17
This can be folded into the if that contains it.
scottmg
2016/11/15 23:23:15
Done.
| |
591 // The Chrome implementation CHECKs() here in the browser process. We | |
592 // don't as this function is used to initialize crash reporting, so | |
593 // we would get no report of this failure. | |
594 assert(false); | |
595 return false; | |
596 } | |
597 } | |
598 | |
599 *result = user_data_dir; | |
600 return true; | |
601 } | |
602 | |
603 bool GetCrashDumpLocation(std::wstring* crash_dir) { | |
604 // In order to be able to start crash handling very early and in chrome_elf, | |
605 // we cannot rely on chrome's PathService entries (for DIR_CRASH_DUMPS) being | |
606 // available on Windows. See https://crbug.com/564398. | |
607 if (!GetUserDataDirectory(crash_dir)) | |
539 return false; | 608 return false; |
540 | 609 |
541 // We have to make sure the user data dir exists on first run. See | 610 // We have to make sure the user data dir exists on first run. See |
542 // http://crbug.com/591504. | 611 // http://crbug.com/591504. |
543 if (!RecursiveDirectoryCreate(crash_dir->c_str())) | 612 if (!RecursiveDirectoryCreate(crash_dir->c_str())) |
544 return false; | 613 return false; |
545 crash_dir->append(L"\\Crashpad"); | 614 crash_dir->append(L"\\Crashpad"); |
546 return true; | 615 return true; |
547 } | 616 } |
548 | 617 |
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
837 *result = -1; | 906 *result = -1; |
838 return true; | 907 return true; |
839 } | 908 } |
840 } | 909 } |
841 } | 910 } |
842 // Here it means that both versions are equal. | 911 // Here it means that both versions are equal. |
843 *result = 0; | 912 *result = 0; |
844 return true; | 913 return true; |
845 } | 914 } |
846 | 915 |
847 std::string GetSwitchValueFromCommandLine(const std::string& command_line, | 916 std::wstring GetSwitchValueFromCommandLine(const std::wstring& command_line, |
848 const std::string& switch_name) { | 917 const std::wstring& switch_name) { |
849 assert(!command_line.empty()); | 918 assert(!command_line.empty()); |
850 assert(!switch_name.empty()); | 919 assert(!switch_name.empty()); |
851 | 920 |
852 std::string command_line_copy = command_line; | 921 std::wstring command_line_copy = command_line; |
853 // Remove leading and trailing spaces. | 922 // Remove leading and trailing spaces. |
854 TrimT<std::string>(&command_line_copy); | 923 TrimT<std::wstring>(&command_line_copy); |
855 | 924 |
856 // Find the switch in the command line. If we don't find the switch, return | 925 // Find the switch in the command line. If we don't find the switch, return |
857 // an empty string. | 926 // an empty string. |
858 std::string switch_token = "--"; | 927 std::wstring switch_token = L"--"; |
859 switch_token += switch_name; | 928 switch_token += switch_name; |
860 switch_token += "="; | 929 switch_token += L"="; |
861 size_t switch_offset = command_line_copy.find(switch_token); | 930 size_t switch_offset = command_line_copy.find(switch_token); |
862 if (switch_offset == std::string::npos) | 931 if (switch_offset == std::string::npos) |
863 return std::string(); | 932 return std::wstring(); |
864 | 933 |
865 // The format is "--<switch name>=blah". Look for a space after the | 934 // The format is "--<switch name>=blah". Look for a space after the |
866 // "--<switch name>=" string. If we don't find a space assume that the switch | 935 // "--<switch name>=" string. If we don't find a space assume that the switch |
867 // value ends at the end of the command line. | 936 // value ends at the end of the command line. |
868 size_t switch_value_start_offset = switch_offset + switch_token.length(); | 937 size_t switch_value_start_offset = switch_offset + switch_token.length(); |
869 if (std::string(kWhiteSpaces).find( | 938 if (std::wstring(kWhiteSpaces16).find( |
870 command_line_copy[switch_value_start_offset]) != std::string::npos) { | 939 command_line_copy[switch_value_start_offset]) != std::wstring::npos) { |
871 switch_value_start_offset = command_line_copy.find_first_not_of( | 940 switch_value_start_offset = command_line_copy.find_first_not_of( |
872 GetWhiteSpacesForType<std::string>(), switch_value_start_offset); | 941 GetWhiteSpacesForType<std::wstring>(), switch_value_start_offset); |
873 if (switch_value_start_offset == std::string::npos) | 942 if (switch_value_start_offset == std::wstring::npos) |
874 return std::string(); | 943 return std::wstring(); |
875 } | 944 } |
876 size_t switch_value_end_offset = | 945 size_t switch_value_end_offset = |
877 command_line_copy.find_first_of(GetWhiteSpacesForType<std::string>(), | 946 command_line_copy.find_first_of(GetWhiteSpacesForType<std::wstring>(), |
878 switch_value_start_offset); | 947 switch_value_start_offset); |
879 if (switch_value_end_offset == std::string::npos) | 948 if (switch_value_end_offset == std::wstring::npos) |
880 switch_value_end_offset = command_line_copy.length(); | 949 switch_value_end_offset = command_line_copy.length(); |
881 | 950 |
882 std::string switch_value = command_line_copy.substr( | 951 std::wstring switch_value = command_line_copy.substr( |
883 switch_value_start_offset, | 952 switch_value_start_offset, |
884 switch_value_end_offset - (switch_offset + switch_token.length())); | 953 switch_value_end_offset - (switch_offset + switch_token.length())); |
885 TrimT<std::string>(&switch_value); | 954 TrimT<std::wstring>(&switch_value); |
886 return switch_value; | 955 return switch_value; |
887 } | 956 } |
888 | 957 |
889 } // namespace install_static | 958 } // namespace install_static |
OLD | NEW |