| 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 | 10 |
| (...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 319 google_breakpad::CustomInfoEntry(L"num-views", L"N/A")); | 319 google_breakpad::CustomInfoEntry(L"num-views", L"N/A")); |
| 320 } | 320 } |
| 321 | 321 |
| 322 static google_breakpad::CustomClientInfo custom_client_info; | 322 static google_breakpad::CustomClientInfo custom_client_info; |
| 323 custom_client_info.entries = &g_custom_entries->front(); | 323 custom_client_info.entries = &g_custom_entries->front(); |
| 324 custom_client_info.count = g_custom_entries->size(); | 324 custom_client_info.count = g_custom_entries->size(); |
| 325 | 325 |
| 326 return &custom_client_info; | 326 return &custom_client_info; |
| 327 } | 327 } |
| 328 | 328 |
| 329 // Contains the information needed by the worker thread. | 329 // Contains the information needed by InitCrashReporterMain(). |
| 330 struct CrashReporterInfo { | 330 struct CrashReporterInfo { |
| 331 google_breakpad::CustomClientInfo* custom_info; | 331 google_breakpad::CustomClientInfo* custom_info; |
| 332 std::wstring exe_path; | 332 std::wstring exe_path; |
| 333 std::wstring process_type; | 333 std::wstring process_type; |
| 334 }; | 334 }; |
| 335 | 335 |
| 336 // This callback is used when we want to get a dump without crashing the | 336 // This callback is used when we want to get a dump without crashing the |
| 337 // process. | 337 // process. |
| 338 bool DumpDoneCallbackWhenNoCrash(const wchar_t*, const wchar_t*, void*, | 338 bool DumpDoneCallbackWhenNoCrash(const wchar_t*, const wchar_t*, void*, |
| 339 EXCEPTION_POINTERS* ex_info, | 339 EXCEPTION_POINTERS* ex_info, |
| (...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 598 base::win::RegKey hkcu_policy_key(HKEY_CURRENT_USER, | 598 base::win::RegKey hkcu_policy_key(HKEY_CURRENT_USER, |
| 599 policy::kRegistryMandatorySubKey, KEY_READ); | 599 policy::kRegistryMandatorySubKey, KEY_READ); |
| 600 if (hkcu_policy_key.ReadValueDW(key_name.c_str(), &value) == ERROR_SUCCESS) { | 600 if (hkcu_policy_key.ReadValueDW(key_name.c_str(), &value) == ERROR_SUCCESS) { |
| 601 *result = value != 0; | 601 *result = value != 0; |
| 602 return true; | 602 return true; |
| 603 } | 603 } |
| 604 | 604 |
| 605 return false; | 605 return false; |
| 606 } | 606 } |
| 607 | 607 |
| 608 static DWORD __stdcall InitCrashReporterThread(void* param) { | 608 // TODO(mseaborn): This function could be merged with InitCrashReporter(). |
| 609 scoped_ptr<CrashReporterInfo> info( | 609 static void InitCrashReporterMain(CrashReporterInfo* param) { |
| 610 reinterpret_cast<CrashReporterInfo*>(param)); | 610 scoped_ptr<CrashReporterInfo> info(param); |
| 611 | 611 |
| 612 bool is_per_user_install = | 612 bool is_per_user_install = |
| 613 InstallUtil::IsPerUserInstall(info->exe_path.c_str()); | 613 InstallUtil::IsPerUserInstall(info->exe_path.c_str()); |
| 614 | 614 |
| 615 std::wstring channel_string; | 615 std::wstring channel_string; |
| 616 GoogleUpdateSettings::GetChromeChannelAndModifiers(!is_per_user_install, | 616 GoogleUpdateSettings::GetChromeChannelAndModifiers(!is_per_user_install, |
| 617 &channel_string); | 617 &channel_string); |
| 618 | 618 |
| 619 // GetCustomInfo can take a few milliseconds to get the file information, so | |
| 620 // we do it here so it can run in a separate thread. | |
| 621 info->custom_info = GetCustomInfo(info->exe_path, info->process_type, | 619 info->custom_info = GetCustomInfo(info->exe_path, info->process_type, |
| 622 channel_string); | 620 channel_string); |
| 623 | 621 |
| 624 google_breakpad::ExceptionHandler::MinidumpCallback callback = NULL; | 622 google_breakpad::ExceptionHandler::MinidumpCallback callback = NULL; |
| 625 LPTOP_LEVEL_EXCEPTION_FILTER default_filter = NULL; | 623 LPTOP_LEVEL_EXCEPTION_FILTER default_filter = NULL; |
| 626 // We install the post-dump callback only for the browser and service | 624 // We install the post-dump callback only for the browser and service |
| 627 // processes. It spawns a new browser/service process. | 625 // processes. It spawns a new browser/service process. |
| 628 if (info->process_type == L"browser") { | 626 if (info->process_type == L"browser") { |
| 629 callback = &DumpDoneCallback; | 627 callback = &DumpDoneCallback; |
| 630 default_filter = &ChromeExceptionFilter; | 628 default_filter = &ChromeExceptionFilter; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 662 // via policy). | 660 // via policy). |
| 663 if (!controlled_by_policy) | 661 if (!controlled_by_policy) |
| 664 crash_reporting_enabled = GoogleUpdateSettings::GetCollectStatsConsent(); | 662 crash_reporting_enabled = GoogleUpdateSettings::GetCollectStatsConsent(); |
| 665 | 663 |
| 666 if (!crash_reporting_enabled) { | 664 if (!crash_reporting_enabled) { |
| 667 // Configuration managed or the user did not allow Google Update to send | 665 // Configuration managed or the user did not allow Google Update to send |
| 668 // crashes, we need to use our default crash handler instead, but only | 666 // crashes, we need to use our default crash handler instead, but only |
| 669 // for the browser/service processes. | 667 // for the browser/service processes. |
| 670 if (default_filter) | 668 if (default_filter) |
| 671 InitDefaultCrashCallback(default_filter); | 669 InitDefaultCrashCallback(default_filter); |
| 672 return 0; | 670 return; |
| 673 } | 671 } |
| 674 | 672 |
| 675 // Build the pipe name. It can be either: | 673 // Build the pipe name. It can be either: |
| 676 // System-wide install: "NamedPipe\GoogleCrashServices\S-1-5-18" | 674 // System-wide install: "NamedPipe\GoogleCrashServices\S-1-5-18" |
| 677 // Per-user install: "NamedPipe\GoogleCrashServices\<user SID>" | 675 // Per-user install: "NamedPipe\GoogleCrashServices\<user SID>" |
| 678 std::wstring user_sid; | 676 std::wstring user_sid; |
| 679 if (is_per_user_install) { | 677 if (is_per_user_install) { |
| 680 if (!base::win::GetUserSidString(&user_sid)) { | 678 if (!base::win::GetUserSidString(&user_sid)) { |
| 681 if (default_filter) | 679 if (default_filter) |
| 682 InitDefaultCrashCallback(default_filter); | 680 InitDefaultCrashCallback(default_filter); |
| 683 return -1; | 681 return; |
| 684 } | 682 } |
| 685 } else { | 683 } else { |
| 686 user_sid = kSystemPrincipalSid; | 684 user_sid = kSystemPrincipalSid; |
| 687 } | 685 } |
| 688 | 686 |
| 689 pipe_name = kGoogleUpdatePipeName; | 687 pipe_name = kGoogleUpdatePipeName; |
| 690 pipe_name += user_sid; | 688 pipe_name += user_sid; |
| 691 } | 689 } |
| 692 #ifdef _WIN64 | 690 #ifdef _WIN64 |
| 693 // The protocol for connecting to the out-of-process Breakpad crash | 691 // The protocol for connecting to the out-of-process Breakpad crash |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 731 // handlers. | 729 // handlers. |
| 732 google_breakpad::ExceptionHandler::HANDLER_NONE, | 730 google_breakpad::ExceptionHandler::HANDLER_NONE, |
| 733 dump_type, pipe_name.c_str(), info->custom_info); | 731 dump_type, pipe_name.c_str(), info->custom_info); |
| 734 | 732 |
| 735 if (g_breakpad->IsOutOfProcess()) { | 733 if (g_breakpad->IsOutOfProcess()) { |
| 736 // Tells breakpad to handle breakpoint and single step exceptions. | 734 // Tells breakpad to handle breakpoint and single step exceptions. |
| 737 // This might break JIT debuggers, but at least it will always | 735 // This might break JIT debuggers, but at least it will always |
| 738 // generate a crashdump for these exceptions. | 736 // generate a crashdump for these exceptions. |
| 739 g_breakpad->set_handle_debug_exceptions(true); | 737 g_breakpad->set_handle_debug_exceptions(true); |
| 740 } | 738 } |
| 741 | |
| 742 return 0; | |
| 743 } | 739 } |
| 744 | 740 |
| 745 void InitDefaultCrashCallback(LPTOP_LEVEL_EXCEPTION_FILTER filter) { | 741 void InitDefaultCrashCallback(LPTOP_LEVEL_EXCEPTION_FILTER filter) { |
| 746 previous_filter = SetUnhandledExceptionFilter(filter); | 742 previous_filter = SetUnhandledExceptionFilter(filter); |
| 747 } | 743 } |
| 748 | 744 |
| 749 void InitCrashReporter() { | 745 void InitCrashReporter() { |
| 750 const CommandLine& command = *CommandLine::ForCurrentProcess(); | 746 const CommandLine& command = *CommandLine::ForCurrentProcess(); |
| 751 if (!command.HasSwitch(switches::kDisableBreakpad)) { | 747 if (!command.HasSwitch(switches::kDisableBreakpad)) { |
| 752 // Disable the message box for assertions. | 748 // Disable the message box for assertions. |
| 753 _CrtSetReportMode(_CRT_ASSERT, 0); | 749 _CrtSetReportMode(_CRT_ASSERT, 0); |
| 754 | 750 |
| 755 // Query the custom_info now because if we do it in the thread it's going to | |
| 756 // fail in the sandbox. The thread will delete this object. | |
| 757 CrashReporterInfo* info(new CrashReporterInfo); | 751 CrashReporterInfo* info(new CrashReporterInfo); |
| 758 info->process_type = command.GetSwitchValueNative(switches::kProcessType); | 752 info->process_type = command.GetSwitchValueNative(switches::kProcessType); |
| 759 if (info->process_type.empty()) | 753 if (info->process_type.empty()) |
| 760 info->process_type = L"browser"; | 754 info->process_type = L"browser"; |
| 761 | 755 |
| 762 wchar_t exe_path[MAX_PATH]; | 756 wchar_t exe_path[MAX_PATH]; |
| 763 exe_path[0] = 0; | 757 exe_path[0] = 0; |
| 764 GetModuleFileNameW(NULL, exe_path, MAX_PATH); | 758 GetModuleFileNameW(NULL, exe_path, MAX_PATH); |
| 765 info->exe_path = exe_path; | 759 info->exe_path = exe_path; |
| 766 | 760 |
| 767 // If this is not the browser, we can't be sure that we will be able to | 761 InitCrashReporterMain(info); |
| 768 // initialize the crash_handler in another thread, so we run it right away. | |
| 769 // This is important to keep the thread for the browser process because | |
| 770 // it may take some times to initialize the crash_service process. We use | |
| 771 // the Windows worker pool to make better reuse of the thread. | |
| 772 if (info->process_type != L"browser") { | |
| 773 InitCrashReporterThread(info); | |
| 774 } else { | |
| 775 if (QueueUserWorkItem( | |
| 776 &InitCrashReporterThread, | |
| 777 info, | |
| 778 WT_EXECUTELONGFUNCTION) == 0) { | |
| 779 // We failed to queue to the worker pool, initialize in this thread. | |
| 780 InitCrashReporterThread(info); | |
| 781 } | |
| 782 } | |
| 783 } | 762 } |
| 784 } | 763 } |
| OLD | NEW |