Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(210)

Side by Side Diff: chrome/install_static/install_util.cc

Issue 2487783002: Make Crashpad use the user data dir, rather than always default location (Closed)
Patch Set: . Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698