| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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/app/breakpad_win.h" | 5 #include "chrome/app/breakpad_win.h" |
| 6 | 6 |
| 7 #include <windows.h> | 7 #include <windows.h> |
| 8 #include <shellapi.h> | 8 #include <shellapi.h> |
| 9 #include <tchar.h> | 9 #include <tchar.h> |
| 10 #include <userenv.h> | 10 #include <userenv.h> |
| (...skipping 683 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 694 google_breakpad::CustomInfoEntry* entry = NULL; | 694 google_breakpad::CustomInfoEntry* entry = NULL; |
| 695 if (it == g_dynamic_entries->end()) { | 695 if (it == g_dynamic_entries->end()) { |
| 696 if (g_dynamic_keys_offset >= g_dynamic_entries_count) | 696 if (g_dynamic_keys_offset >= g_dynamic_entries_count) |
| 697 return; | 697 return; |
| 698 entry = &(*g_custom_entries)[g_dynamic_keys_offset++]; | 698 entry = &(*g_custom_entries)[g_dynamic_keys_offset++]; |
| 699 g_dynamic_entries->insert(std::make_pair(key_string, entry)); | 699 g_dynamic_entries->insert(std::make_pair(key_string, entry)); |
| 700 } else { | 700 } else { |
| 701 entry = it->second; | 701 entry = it->second; |
| 702 } | 702 } |
| 703 | 703 |
| 704 entry->set(base::UTF8ToWide(key).data(), base::UTF8ToWide(value).data()); | 704 entry->set(UTF8ToWide(key).data(), UTF8ToWide(value).data()); |
| 705 } | 705 } |
| 706 | 706 |
| 707 void ClearCrashKeyValue(const base::StringPiece& key) { | 707 void ClearCrashKeyValue(const base::StringPiece& key) { |
| 708 DynamicEntriesMap::iterator it = g_dynamic_entries->find(key.as_string()); | 708 DynamicEntriesMap::iterator it = g_dynamic_entries->find(key.as_string()); |
| 709 if (it == g_dynamic_entries->end()) | 709 if (it == g_dynamic_entries->end()) |
| 710 return; | 710 return; |
| 711 | 711 |
| 712 it->second->set_value(NULL); | 712 it->second->set_value(NULL); |
| 713 } | 713 } |
| 714 | 714 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 736 chrome::RESULT_CODE_RESPAWN_FAILED); | 736 chrome::RESULT_CODE_RESPAWN_FAILED); |
| 737 } | 737 } |
| 738 | 738 |
| 739 return true; | 739 return true; |
| 740 } | 740 } |
| 741 | 741 |
| 742 // This function is executed by the child process that DumpDoneCallback() | 742 // This function is executed by the child process that DumpDoneCallback() |
| 743 // spawned and basically just shows the 'chrome has crashed' dialog if | 743 // spawned and basically just shows the 'chrome has crashed' dialog if |
| 744 // the CHROME_CRASHED environment variable is present. | 744 // the CHROME_CRASHED environment variable is present. |
| 745 bool ShowRestartDialogIfCrashed(bool* exit_now) { | 745 bool ShowRestartDialogIfCrashed(bool* exit_now) { |
| 746 if (!::GetEnvironmentVariableW( | 746 if (!::GetEnvironmentVariableW(ASCIIToWide(env_vars::kShowRestart).c_str(), |
| 747 base::ASCIIToWide(env_vars::kShowRestart).c_str(), NULL, 0)) { | 747 NULL, 0)) { |
| 748 return false; | 748 return false; |
| 749 } | 749 } |
| 750 | 750 |
| 751 // Only show this for the browser process. See crbug.com/132119. | 751 // Only show this for the browser process. See crbug.com/132119. |
| 752 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); | 752 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); |
| 753 std::string process_type = | 753 std::string process_type = |
| 754 command_line.GetSwitchValueASCII(switches::kProcessType); | 754 command_line.GetSwitchValueASCII(switches::kProcessType); |
| 755 if (!process_type.empty()) { | 755 if (!process_type.empty()) { |
| 756 return false; | 756 return false; |
| 757 } | 757 } |
| 758 | 758 |
| 759 DWORD len = ::GetEnvironmentVariableW( | 759 DWORD len = ::GetEnvironmentVariableW( |
| 760 base::ASCIIToWide(env_vars::kRestartInfo).c_str(), NULL, 0); | 760 ASCIIToWide(env_vars::kRestartInfo).c_str(), NULL, 0); |
| 761 if (!len) | 761 if (!len) |
| 762 return true; | 762 return true; |
| 763 | 763 |
| 764 wchar_t* restart_data = new wchar_t[len + 1]; | 764 wchar_t* restart_data = new wchar_t[len + 1]; |
| 765 ::GetEnvironmentVariableW(base::ASCIIToWide(env_vars::kRestartInfo).c_str(), | 765 ::GetEnvironmentVariableW(ASCIIToWide(env_vars::kRestartInfo).c_str(), |
| 766 restart_data, len); | 766 restart_data, len); |
| 767 restart_data[len] = 0; | 767 restart_data[len] = 0; |
| 768 // The CHROME_RESTART var contains the dialog strings separated by '|'. | 768 // The CHROME_RESTART var contains the dialog strings separated by '|'. |
| 769 // See ChromeBrowserMainPartsWin::PrepareRestartOnCrashEnviroment() | 769 // See ChromeBrowserMainPartsWin::PrepareRestartOnCrashEnviroment() |
| 770 // for details. | 770 // for details. |
| 771 std::vector<std::wstring> dlg_strings; | 771 std::vector<std::wstring> dlg_strings; |
| 772 base::SplitString(restart_data, L'|', &dlg_strings); | 772 base::SplitString(restart_data, L'|', &dlg_strings); |
| 773 delete[] restart_data; | 773 delete[] restart_data; |
| 774 if (dlg_strings.size() < 3) | 774 if (dlg_strings.size() < 3) |
| 775 return true; | 775 return true; |
| 776 | 776 |
| 777 // If the UI layout is right-to-left, we need to pass the appropriate MB_XXX | 777 // If the UI layout is right-to-left, we need to pass the appropriate MB_XXX |
| 778 // flags so that an RTL message box is displayed. | 778 // flags so that an RTL message box is displayed. |
| 779 UINT flags = MB_OKCANCEL | MB_ICONWARNING; | 779 UINT flags = MB_OKCANCEL | MB_ICONWARNING; |
| 780 if (dlg_strings[2] == base::ASCIIToWide(env_vars::kRtlLocale)) | 780 if (dlg_strings[2] == ASCIIToWide(env_vars::kRtlLocale)) |
| 781 flags |= MB_RIGHT | MB_RTLREADING; | 781 flags |= MB_RIGHT | MB_RTLREADING; |
| 782 | 782 |
| 783 return WrapMessageBoxWithSEH(dlg_strings[1].c_str(), dlg_strings[0].c_str(), | 783 return WrapMessageBoxWithSEH(dlg_strings[1].c_str(), dlg_strings[0].c_str(), |
| 784 flags, exit_now); | 784 flags, exit_now); |
| 785 } | 785 } |
| 786 | 786 |
| 787 // Crashes the process after generating a dump for the provided exception. Note | 787 // Crashes the process after generating a dump for the provided exception. Note |
| 788 // that the crash reporter should be initialized before calling this function | 788 // that the crash reporter should be initialized before calling this function |
| 789 // for it to do anything. | 789 // for it to do anything. |
| 790 extern "C" int __declspec(dllexport) CrashForException( | 790 extern "C" int __declspec(dllexport) CrashForException( |
| 791 EXCEPTION_POINTERS* info) { | 791 EXCEPTION_POINTERS* info) { |
| 792 if (g_breakpad) { | 792 if (g_breakpad) { |
| 793 g_breakpad->WriteMinidumpForException(info); | 793 g_breakpad->WriteMinidumpForException(info); |
| 794 if (g_crash_analysis) | 794 if (g_crash_analysis) |
| 795 g_crash_analysis->Analyze(info); | 795 g_crash_analysis->Analyze(info); |
| 796 ::TerminateProcess(::GetCurrentProcess(), content::RESULT_CODE_KILLED); | 796 ::TerminateProcess(::GetCurrentProcess(), content::RESULT_CODE_KILLED); |
| 797 } | 797 } |
| 798 return EXCEPTION_CONTINUE_SEARCH; | 798 return EXCEPTION_CONTINUE_SEARCH; |
| 799 } | 799 } |
| 800 | 800 |
| 801 // Determine whether configuration management allows loading the crash reporter. | 801 // Determine whether configuration management allows loading the crash reporter. |
| 802 // Since the configuration management infrastructure is not initialized at this | 802 // Since the configuration management infrastructure is not initialized at this |
| 803 // point, we read the corresponding registry key directly. The return status | 803 // point, we read the corresponding registry key directly. The return status |
| 804 // indicates whether policy data was successfully read. If it is true, |result| | 804 // indicates whether policy data was successfully read. If it is true, |result| |
| 805 // contains the value set by policy. | 805 // contains the value set by policy. |
| 806 static bool MetricsReportingControlledByPolicy(bool* result) { | 806 static bool MetricsReportingControlledByPolicy(bool* result) { |
| 807 std::wstring key_name = | 807 std::wstring key_name = UTF8ToWide(policy::key::kMetricsReportingEnabled); |
| 808 base::UTF8ToWide(policy::key::kMetricsReportingEnabled); | |
| 809 DWORD value = 0; | 808 DWORD value = 0; |
| 810 base::win::RegKey hklm_policy_key(HKEY_LOCAL_MACHINE, | 809 base::win::RegKey hklm_policy_key(HKEY_LOCAL_MACHINE, |
| 811 policy::kRegistryMandatorySubKey, KEY_READ); | 810 policy::kRegistryMandatorySubKey, KEY_READ); |
| 812 if (hklm_policy_key.ReadValueDW(key_name.c_str(), &value) == ERROR_SUCCESS) { | 811 if (hklm_policy_key.ReadValueDW(key_name.c_str(), &value) == ERROR_SUCCESS) { |
| 813 *result = value != 0; | 812 *result = value != 0; |
| 814 return true; | 813 return true; |
| 815 } | 814 } |
| 816 | 815 |
| 817 base::win::RegKey hkcu_policy_key(HKEY_CURRENT_USER, | 816 base::win::RegKey hkcu_policy_key(HKEY_CURRENT_USER, |
| 818 policy::kRegistryMandatorySubKey, KEY_READ); | 817 policy::kRegistryMandatorySubKey, KEY_READ); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 845 | 844 |
| 846 // Check whether configuration management controls crash reporting. | 845 // Check whether configuration management controls crash reporting. |
| 847 bool crash_reporting_enabled = true; | 846 bool crash_reporting_enabled = true; |
| 848 bool controlled_by_policy = | 847 bool controlled_by_policy = |
| 849 MetricsReportingControlledByPolicy(&crash_reporting_enabled); | 848 MetricsReportingControlledByPolicy(&crash_reporting_enabled); |
| 850 | 849 |
| 851 const CommandLine& command = *CommandLine::ForCurrentProcess(); | 850 const CommandLine& command = *CommandLine::ForCurrentProcess(); |
| 852 bool use_crash_service = !controlled_by_policy && | 851 bool use_crash_service = !controlled_by_policy && |
| 853 ((command.HasSwitch(switches::kNoErrorDialogs) || | 852 ((command.HasSwitch(switches::kNoErrorDialogs) || |
| 854 GetEnvironmentVariable( | 853 GetEnvironmentVariable( |
| 855 base::ASCIIToWide(env_vars::kHeadless).c_str(), NULL, 0))); | 854 ASCIIToWide(env_vars::kHeadless).c_str(), NULL, 0))); |
| 856 | 855 |
| 857 std::wstring pipe_name; | 856 std::wstring pipe_name; |
| 858 if (use_crash_service) { | 857 if (use_crash_service) { |
| 859 // Crash reporting is done by crash_service.exe. | 858 // Crash reporting is done by crash_service.exe. |
| 860 pipe_name = kChromePipeName; | 859 pipe_name = kChromePipeName; |
| 861 } else { | 860 } else { |
| 862 // We want to use the Google Update crash reporting. We need to check if the | 861 // We want to use the Google Update crash reporting. We need to check if the |
| 863 // user allows it first (in case the administrator didn't already decide | 862 // user allows it first (in case the administrator didn't already decide |
| 864 // via policy). | 863 // via policy). |
| 865 if (!controlled_by_policy) | 864 if (!controlled_by_policy) |
| (...skipping 15 matching lines...) Expand all Loading... |
| 881 if (!base::win::GetUserSidString(&user_sid)) { | 880 if (!base::win::GetUserSidString(&user_sid)) { |
| 882 return; | 881 return; |
| 883 } | 882 } |
| 884 } else { | 883 } else { |
| 885 user_sid = kSystemPrincipalSid; | 884 user_sid = kSystemPrincipalSid; |
| 886 } | 885 } |
| 887 | 886 |
| 888 pipe_name = kGoogleUpdatePipeName; | 887 pipe_name = kGoogleUpdatePipeName; |
| 889 pipe_name += user_sid; | 888 pipe_name += user_sid; |
| 890 } | 889 } |
| 891 env->SetVar(kPipeNameVar, base::WideToASCII(pipe_name)); | 890 env->SetVar(kPipeNameVar, WideToASCII(pipe_name)); |
| 892 } | 891 } |
| 893 | 892 |
| 894 void InitCrashReporter() { | 893 void InitCrashReporter() { |
| 895 const CommandLine& command = *CommandLine::ForCurrentProcess(); | 894 const CommandLine& command = *CommandLine::ForCurrentProcess(); |
| 896 if (command.HasSwitch(switches::kDisableBreakpad)) | 895 if (command.HasSwitch(switches::kDisableBreakpad)) |
| 897 return; | 896 return; |
| 898 | 897 |
| 899 // Disable the message box for assertions. | 898 // Disable the message box for assertions. |
| 900 _CrtSetReportMode(_CRT_ASSERT, 0); | 899 _CrtSetReportMode(_CRT_ASSERT, 0); |
| 901 | 900 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 940 std::string pipe_name_ascii; | 939 std::string pipe_name_ascii; |
| 941 if (!env->GetVar(kPipeNameVar, &pipe_name_ascii)) { | 940 if (!env->GetVar(kPipeNameVar, &pipe_name_ascii)) { |
| 942 // Breakpad is not enabled. Configuration is managed or the user | 941 // Breakpad is not enabled. Configuration is managed or the user |
| 943 // did not allow Google Update to send crashes. We need to use | 942 // did not allow Google Update to send crashes. We need to use |
| 944 // our default crash handler instead, but only for the | 943 // our default crash handler instead, but only for the |
| 945 // browser/service processes. | 944 // browser/service processes. |
| 946 if (default_filter) | 945 if (default_filter) |
| 947 InitDefaultCrashCallback(default_filter); | 946 InitDefaultCrashCallback(default_filter); |
| 948 return; | 947 return; |
| 949 } | 948 } |
| 950 std::wstring pipe_name = base::ASCIIToWide(pipe_name_ascii); | 949 std::wstring pipe_name = ASCIIToWide(pipe_name_ascii); |
| 951 | 950 |
| 952 #ifdef _WIN64 | 951 #ifdef _WIN64 |
| 953 // The protocol for connecting to the out-of-process Breakpad crash | 952 // The protocol for connecting to the out-of-process Breakpad crash |
| 954 // reporter is different for x86-32 and x86-64: the message sizes | 953 // reporter is different for x86-32 and x86-64: the message sizes |
| 955 // are different because the message struct contains a pointer. As | 954 // are different because the message struct contains a pointer. As |
| 956 // a result, there are two different named pipes to connect to. The | 955 // a result, there are two different named pipes to connect to. The |
| 957 // 64-bit one is distinguished with an "-x64" suffix. | 956 // 64-bit one is distinguished with an "-x64" suffix. |
| 958 pipe_name += L"-x64"; | 957 pipe_name += L"-x64"; |
| 959 #endif | 958 #endif |
| 960 | 959 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1007 previous_filter = SetUnhandledExceptionFilter(filter); | 1006 previous_filter = SetUnhandledExceptionFilter(filter); |
| 1008 } | 1007 } |
| 1009 | 1008 |
| 1010 void StringVectorToCStringVector(const std::vector<std::wstring>& wstrings, | 1009 void StringVectorToCStringVector(const std::vector<std::wstring>& wstrings, |
| 1011 std::vector<const wchar_t*>* cstrings) { | 1010 std::vector<const wchar_t*>* cstrings) { |
| 1012 cstrings->clear(); | 1011 cstrings->clear(); |
| 1013 cstrings->reserve(wstrings.size()); | 1012 cstrings->reserve(wstrings.size()); |
| 1014 for (size_t i = 0; i < wstrings.size(); ++i) | 1013 for (size_t i = 0; i < wstrings.size(); ++i) |
| 1015 cstrings->push_back(wstrings[i].c_str()); | 1014 cstrings->push_back(wstrings[i].c_str()); |
| 1016 } | 1015 } |
| OLD | NEW |