Chromium Code Reviews| 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> |
| 11 | 11 |
| 12 #include <algorithm> | 12 #include <algorithm> |
| 13 #include <vector> | 13 #include <vector> |
| 14 | 14 |
| 15 #include "base/base_switches.h" | 15 #include "base/base_switches.h" |
| 16 #include "base/command_line.h" | 16 #include "base/command_line.h" |
| 17 #include "base/debug/crash_logging.h" | |
| 17 #include "base/environment.h" | 18 #include "base/environment.h" |
| 18 #include "base/file_util.h" | 19 #include "base/file_util.h" |
| 19 #include "base/file_version_info.h" | 20 #include "base/file_version_info.h" |
| 20 #include "base/memory/scoped_ptr.h" | 21 #include "base/memory/scoped_ptr.h" |
| 21 #include "base/string_split.h" | 22 #include "base/string_split.h" |
| 22 #include "base/string_util.h" | 23 #include "base/string_util.h" |
| 23 #include "base/string16.h" | 24 #include "base/string16.h" |
| 24 #include "base/stringprintf.h" | 25 #include "base/stringprintf.h" |
| 25 #include "base/utf_string_conversions.h" | 26 #include "base/utf_string_conversions.h" |
| 26 #include "base/win/registry.h" | 27 #include "base/win/registry.h" |
| 27 #include "base/win/win_util.h" | 28 #include "base/win/win_util.h" |
| 28 #include "breakpad/src/client/windows/handler/exception_handler.h" | 29 #include "breakpad/src/client/windows/handler/exception_handler.h" |
| 29 #include "chrome/app/breakpad_field_trial_win.h" | 30 #include "chrome/app/breakpad_field_trial_win.h" |
| 30 #include "chrome/app/crash_analysis_win.h" | 31 #include "chrome/app/crash_analysis_win.h" |
| 31 #include "chrome/app/hard_error_handler_win.h" | 32 #include "chrome/app/hard_error_handler_win.h" |
| 32 #include "chrome/common/child_process_logging.h" | 33 #include "chrome/common/child_process_logging.h" |
| 33 #include "chrome/common/chrome_result_codes.h" | 34 #include "chrome/common/chrome_result_codes.h" |
| 34 #include "chrome/common/chrome_switches.h" | 35 #include "chrome/common/chrome_switches.h" |
| 36 #include "chrome/common/crash_keys.h" | |
| 35 #include "chrome/common/env_vars.h" | 37 #include "chrome/common/env_vars.h" |
| 36 #include "chrome/installer/util/google_chrome_sxs_distribution.h" | 38 #include "chrome/installer/util/google_chrome_sxs_distribution.h" |
| 37 #include "chrome/installer/util/google_update_settings.h" | 39 #include "chrome/installer/util/google_update_settings.h" |
| 38 #include "chrome/installer/util/install_util.h" | 40 #include "chrome/installer/util/install_util.h" |
| 39 #include "policy/policy_constants.h" | 41 #include "policy/policy_constants.h" |
| 40 | 42 |
| 41 // userenv.dll is required for GetProfileType(). | 43 // userenv.dll is required for GetProfileType(). |
| 42 #pragma comment(lib, "userenv.lib") | 44 #pragma comment(lib, "userenv.lib") |
| 43 | 45 |
| 44 namespace breakpad_win { | 46 namespace breakpad_win { |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 96 | 98 |
| 97 static size_t g_url_chunks_offset = 0; | 99 static size_t g_url_chunks_offset = 0; |
| 98 static size_t g_num_of_extensions_offset = 0; | 100 static size_t g_num_of_extensions_offset = 0; |
| 99 static size_t g_extension_ids_offset = 0; | 101 static size_t g_extension_ids_offset = 0; |
| 100 static size_t g_client_id_offset = 0; | 102 static size_t g_client_id_offset = 0; |
| 101 static size_t g_gpu_info_offset = 0; | 103 static size_t g_gpu_info_offset = 0; |
| 102 static size_t g_printer_info_offset = 0; | 104 static size_t g_printer_info_offset = 0; |
| 103 static size_t g_num_of_views_offset = 0; | 105 static size_t g_num_of_views_offset = 0; |
| 104 static size_t g_num_switches_offset = 0; | 106 static size_t g_num_switches_offset = 0; |
| 105 static size_t g_switches_offset = 0; | 107 static size_t g_switches_offset = 0; |
| 108 static size_t g_dynamic_keys_offset = 0; | |
| 109 typedef std::map<std::string, google_breakpad::CustomInfoEntry*> | |
| 110 DynamicEntriesMap; | |
| 111 DynamicEntriesMap* g_dynamic_entries = NULL; | |
|
Scott Hess - ex-Googler
2013/01/16 22:45:28
I went to look if the key could be a string piece
| |
| 106 | 112 |
| 107 // Maximum length for plugin path to include in plugin crash reports. | 113 // Maximum length for plugin path to include in plugin crash reports. |
| 108 const size_t kMaxPluginPathLength = 256; | 114 const size_t kMaxPluginPathLength = 256; |
| 109 | 115 |
| 110 // Dumps the current process memory. | 116 // Dumps the current process memory. |
| 111 extern "C" void __declspec(dllexport) __cdecl DumpProcess() { | 117 extern "C" void __declspec(dllexport) __cdecl DumpProcess() { |
| 112 if (g_breakpad) | 118 if (g_breakpad) |
| 113 g_breakpad->WriteMinidump(); | 119 g_breakpad->WriteMinidump(); |
| 114 } | 120 } |
| 115 | 121 |
| (...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 457 // We depend on this in UpdateExperiments... | 463 // We depend on this in UpdateExperiments... |
| 458 DCHECK_NE(0UL, g_experiment_chunks_offset); | 464 DCHECK_NE(0UL, g_experiment_chunks_offset); |
| 459 // And the test code depends on this. | 465 // And the test code depends on this. |
| 460 DCHECK_EQ(g_num_of_experiments_offset + 1, g_experiment_chunks_offset); | 466 DCHECK_EQ(g_num_of_experiments_offset + 1, g_experiment_chunks_offset); |
| 461 // one-based index for the name suffix. | 467 // one-based index for the name suffix. |
| 462 for (int i = 1; i <= kMaxReportedVariationChunks; ++i) { | 468 for (int i = 1; i <= kMaxReportedVariationChunks; ++i) { |
| 463 g_custom_entries->push_back(google_breakpad::CustomInfoEntry( | 469 g_custom_entries->push_back(google_breakpad::CustomInfoEntry( |
| 464 base::StringPrintf(L"experiment-chunk-%i", i).c_str(), L"")); | 470 base::StringPrintf(L"experiment-chunk-%i", i).c_str(), L"")); |
| 465 } | 471 } |
| 466 | 472 |
| 473 // Create space for dynamic ad-hoc keys. The names and values are set using | |
| 474 // the API defined in base/debug/crash_logging.h. | |
| 475 size_t num_custom_keys = crash_keys::RegisterChromeCrashKeys(); | |
| 476 g_dynamic_keys_offset = g_custom_entries->size(); | |
| 477 for (size_t i = 0; i < num_custom_keys; ++i) { | |
| 478 g_custom_entries->push_back(google_breakpad::CustomInfoEntry()); | |
| 479 } | |
| 480 g_dynamic_entries = new DynamicEntriesMap; | |
| 481 | |
| 467 static google_breakpad::CustomClientInfo custom_client_info; | 482 static google_breakpad::CustomClientInfo custom_client_info; |
| 468 custom_client_info.entries = &g_custom_entries->front(); | 483 custom_client_info.entries = &g_custom_entries->front(); |
| 469 custom_client_info.count = g_custom_entries->size(); | 484 custom_client_info.count = g_custom_entries->size(); |
| 470 | 485 |
| 471 return &custom_client_info; | 486 return &custom_client_info; |
| 472 } | 487 } |
| 473 | 488 |
| 474 // This callback is used when we want to get a dump without crashing the | 489 // This callback is used when we want to get a dump without crashing the |
| 475 // process. | 490 // process. |
| 476 bool DumpDoneCallbackWhenNoCrash(const wchar_t*, const wchar_t*, void*, | 491 bool DumpDoneCallbackWhenNoCrash(const wchar_t*, const wchar_t*, void*, |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 658 info[i].c_str(), | 673 info[i].c_str(), |
| 659 google_breakpad::CustomInfoEntry::kValueMaxLength); | 674 google_breakpad::CustomInfoEntry::kValueMaxLength); |
| 660 } | 675 } |
| 661 } | 676 } |
| 662 | 677 |
| 663 extern "C" void __declspec(dllexport) __cdecl SetNumberOfViews( | 678 extern "C" void __declspec(dllexport) __cdecl SetNumberOfViews( |
| 664 int number_of_views) { | 679 int number_of_views) { |
| 665 SetIntegerValue(g_num_of_views_offset, number_of_views); | 680 SetIntegerValue(g_num_of_views_offset, number_of_views); |
| 666 } | 681 } |
| 667 | 682 |
| 683 void SetCrashKeyValue(const base::StringPiece& key, | |
| 684 const base::StringPiece& value) { | |
| 685 std::string key_string = key.as_string(); | |
| 686 | |
| 687 DynamicEntriesMap::iterator it = g_dynamic_entries->find(key_string); | |
| 688 google_breakpad::CustomInfoEntry* entry = NULL; | |
| 689 if (it == g_dynamic_entries->end()) { | |
| 690 entry = &(*g_custom_entries)[g_dynamic_keys_offset++]; | |
|
Scott Hess - ex-Googler
2013/01/16 22:45:28
Seems like this might want some sort of range chec
Robert Sesek
2013/01/17 19:39:10
Done.
| |
| 691 g_dynamic_entries->insert(std::make_pair(key_string, entry)); | |
| 692 } else { | |
| 693 entry = it->second; | |
| 694 } | |
| 695 | |
| 696 entry->set(UTF8ToWide(key).data(), UTF8ToWide(value).data()); | |
| 697 } | |
| 698 | |
| 699 void ClearCrashKeyValue(const base::StringPiece& key) { | |
| 700 DynamicEntriesMap::iterator it = g_dynamic_entries->find(key.as_string()); | |
| 701 if (it == g_dynamic_entries->end()) | |
| 702 return; | |
| 703 | |
| 704 it->second->set(NULL, NULL); | |
| 705 } | |
| 706 | |
| 668 } // namespace | 707 } // namespace |
| 669 | 708 |
| 670 namespace testing { | 709 namespace testing { |
| 671 | 710 |
| 672 // Access to namespace protected functions for testing purposes. | 711 // Access to namespace protected functions for testing purposes. |
| 673 void InitCustomInfoEntries() { | 712 void InitCustomInfoEntries() { |
| 674 GetCustomInfo(L"", L"", L""); | 713 GetCustomInfo(L"", L"", L""); |
| 675 } | 714 } |
| 676 | 715 |
| 677 } // namespace testing | 716 } // namespace testing |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 859 wchar_t exe_path[MAX_PATH]; | 898 wchar_t exe_path[MAX_PATH]; |
| 860 exe_path[0] = 0; | 899 exe_path[0] = 0; |
| 861 GetModuleFileNameW(NULL, exe_path, MAX_PATH); | 900 GetModuleFileNameW(NULL, exe_path, MAX_PATH); |
| 862 | 901 |
| 863 bool is_per_user_install = InstallUtil::IsPerUserInstall(exe_path); | 902 bool is_per_user_install = InstallUtil::IsPerUserInstall(exe_path); |
| 864 | 903 |
| 865 std::wstring channel_string; | 904 std::wstring channel_string; |
| 866 GoogleUpdateSettings::GetChromeChannelAndModifiers(!is_per_user_install, | 905 GoogleUpdateSettings::GetChromeChannelAndModifiers(!is_per_user_install, |
| 867 &channel_string); | 906 &channel_string); |
| 868 | 907 |
| 908 base::debug::SetCrashKeyReportingFunctions( | |
| 909 &SetCrashKeyValue, &ClearCrashKeyValue); | |
| 910 | |
| 869 google_breakpad::CustomClientInfo* custom_info = | 911 google_breakpad::CustomClientInfo* custom_info = |
| 870 GetCustomInfo(exe_path, process_type, channel_string); | 912 GetCustomInfo(exe_path, process_type, channel_string); |
| 871 | 913 |
| 872 google_breakpad::ExceptionHandler::MinidumpCallback callback = NULL; | 914 google_breakpad::ExceptionHandler::MinidumpCallback callback = NULL; |
| 873 LPTOP_LEVEL_EXCEPTION_FILTER default_filter = NULL; | 915 LPTOP_LEVEL_EXCEPTION_FILTER default_filter = NULL; |
| 874 // We install the post-dump callback only for the browser and service | 916 // We install the post-dump callback only for the browser and service |
| 875 // processes. It spawns a new browser/service process. | 917 // processes. It spawns a new browser/service process. |
| 876 if (process_type == L"browser") { | 918 if (process_type == L"browser") { |
| 877 callback = &DumpDoneCallback; | 919 callback = &DumpDoneCallback; |
| 878 default_filter = &ChromeExceptionFilter; | 920 default_filter = &ChromeExceptionFilter; |
| 879 } else if (process_type == L"service") { | 921 } else if (process_type == L"service") { |
| 880 callback = &DumpDoneCallback; | 922 callback = &DumpDoneCallback; |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 956 previous_filter = SetUnhandledExceptionFilter(filter); | 998 previous_filter = SetUnhandledExceptionFilter(filter); |
| 957 } | 999 } |
| 958 | 1000 |
| 959 void StringVectorToCStringVector(const std::vector<std::wstring>& wstrings, | 1001 void StringVectorToCStringVector(const std::vector<std::wstring>& wstrings, |
| 960 std::vector<const wchar_t*>* cstrings) { | 1002 std::vector<const wchar_t*>* cstrings) { |
| 961 cstrings->clear(); | 1003 cstrings->clear(); |
| 962 cstrings->reserve(wstrings.size()); | 1004 cstrings->reserve(wstrings.size()); |
| 963 for (size_t i = 0; i < wstrings.size(); ++i) | 1005 for (size_t i = 0; i < wstrings.size(); ++i) |
| 964 cstrings->push_back(wstrings[i].c_str()); | 1006 cstrings->push_back(wstrings[i].c_str()); |
| 965 } | 1007 } |
| OLD | NEW |