| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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 <vector> | 10 #include <vector> |
| (...skipping 15 matching lines...) Expand all Loading... |
| 26 namespace { | 26 namespace { |
| 27 | 27 |
| 28 const wchar_t kGoogleUpdatePipeName[] = L"\\\\.\\pipe\\GoogleCrashServices\\"; | 28 const wchar_t kGoogleUpdatePipeName[] = L"\\\\.\\pipe\\GoogleCrashServices\\"; |
| 29 const wchar_t kChromePipeName[] = L"\\\\.\\pipe\\ChromeCrashServices"; | 29 const wchar_t kChromePipeName[] = L"\\\\.\\pipe\\ChromeCrashServices"; |
| 30 | 30 |
| 31 // This is the well known SID for the system principal. | 31 // This is the well known SID for the system principal. |
| 32 const wchar_t kSystemPrincipalSid[] =L"S-1-5-18"; | 32 const wchar_t kSystemPrincipalSid[] =L"S-1-5-18"; |
| 33 | 33 |
| 34 google_breakpad::ExceptionHandler* g_breakpad = NULL; | 34 google_breakpad::ExceptionHandler* g_breakpad = NULL; |
| 35 | 35 |
| 36 // Pointers to memory that will be sent in crash reports. These are kept updated |
| 37 // over the life of the process. |
| 36 std::vector<wchar_t*>* g_url_chunks = NULL; | 38 std::vector<wchar_t*>* g_url_chunks = NULL; |
| 37 | 39 std::vector<wchar_t*>* g_extension_ids = NULL; |
| 38 // A string containing the user's unique metric services id. We send this | |
| 39 // in the crash report. | |
| 40 wchar_t* g_client_id = NULL; | 40 wchar_t* g_client_id = NULL; |
| 41 | 41 |
| 42 // Dumps the current process memory. | 42 // Dumps the current process memory. |
| 43 extern "C" void __declspec(dllexport) __cdecl DumpProcess() { | 43 extern "C" void __declspec(dllexport) __cdecl DumpProcess() { |
| 44 if (g_breakpad) | 44 if (g_breakpad) |
| 45 g_breakpad->WriteMinidump(); | 45 g_breakpad->WriteMinidump(); |
| 46 } | 46 } |
| 47 | 47 |
| 48 // Reduces the size of the string |str| to a max of 64 chars. Required because | 48 // Reduces the size of the string |str| to a max of 64 chars. Required because |
| 49 // breakpad's CustomInfoEntry raises an invalid_parameter error if the string | 49 // breakpad's CustomInfoEntry raises an invalid_parameter error if the string |
| (...skipping 17 matching lines...) Expand all Loading... |
| 67 product = version_info->product_short_name(); | 67 product = version_info->product_short_name(); |
| 68 version = version_info->product_version(); | 68 version = version_info->product_version(); |
| 69 if (!version_info->is_official_build()) | 69 if (!version_info->is_official_build()) |
| 70 version.append(L"-devel"); | 70 version.append(L"-devel"); |
| 71 } else { | 71 } else { |
| 72 // No version info found. Make up the values. | 72 // No version info found. Make up the values. |
| 73 product = L"Chrome"; | 73 product = L"Chrome"; |
| 74 version = L"0.0.0.0-devel"; | 74 version = L"0.0.0.0-devel"; |
| 75 } | 75 } |
| 76 | 76 |
| 77 const int kNumCustomInfoEntries = 17; |
| 78 static std::vector<google_breakpad::CustomInfoEntry> entries; |
| 79 |
| 80 // We save pointers into this as we're building it up and we don't want them |
| 81 // to become invalid due to resizes. |
| 82 entries.reserve(kNumCustomInfoEntries); |
| 83 |
| 77 // Common entries. | 84 // Common entries. |
| 78 google_breakpad::CustomInfoEntry ver_entry(L"ver", version.c_str()); | 85 entries.push_back(google_breakpad::CustomInfoEntry(L"ver", version.c_str())); |
| 79 google_breakpad::CustomInfoEntry prod_entry(L"prod", product.c_str()); | 86 entries.push_back(google_breakpad::CustomInfoEntry(L"plat", L"Win32")); |
| 80 google_breakpad::CustomInfoEntry plat_entry(L"plat", L"Win32"); | 87 entries.push_back(google_breakpad::CustomInfoEntry(L"ptype", type.c_str())); |
| 81 google_breakpad::CustomInfoEntry type_entry(L"ptype", type.c_str()); | 88 |
| 89 g_extension_ids = new std::vector<wchar_t*>(kMaxReportedActiveExtensions); |
| 90 for (int i = 0; i < kMaxReportedActiveExtensions; ++i) { |
| 91 entries.push_back(google_breakpad::CustomInfoEntry( |
| 92 StringPrintf(L"extension-%i", i + 1).c_str(), L"")); |
| 93 (*g_extension_ids)[i] = entries.back().value; |
| 94 } |
| 82 | 95 |
| 83 // Read the id from registry. If reporting has never been enabled | 96 // Read the id from registry. If reporting has never been enabled |
| 84 // the result will be empty string. Its OK since when user enables reporting | 97 // the result will be empty string. Its OK since when user enables reporting |
| 85 // we will insert the new value at this location. | 98 // we will insert the new value at this location. |
| 86 std::wstring guid; | 99 std::wstring guid; |
| 87 GoogleUpdateSettings::GetMetricsId(&guid); | 100 GoogleUpdateSettings::GetMetricsId(&guid); |
| 88 google_breakpad::CustomInfoEntry guid_entry(L"guid", guid.c_str()); | 101 entries.push_back(google_breakpad::CustomInfoEntry(L"guid", guid.c_str())); |
| 102 g_client_id = entries.back().value; |
| 89 | 103 |
| 90 if (type == L"renderer" || type == L"plugin") { | 104 if (type == L"renderer" || type == L"plugin") { |
| 91 // Create entries for the URL. Currently we only allow each chunk to be 64 | 105 // Create entries for the URL. Currently we only allow each chunk to be 64 |
| 92 // characters, which isn't enough for a URL. As a hack we create 8 entries | 106 // characters, which isn't enough for a URL. As a hack we create 8 entries |
| 93 // and split the URL across the entries. | 107 // and split the URL across the entries. |
| 94 google_breakpad::CustomInfoEntry url1(L"url-chunk-1", L""); | 108 g_url_chunks = new std::vector<wchar_t*>(kMaxUrlChunks); |
| 95 google_breakpad::CustomInfoEntry url2(L"url-chunk-2", L""); | 109 for (int i = 0; i < kMaxUrlChunks; ++i) { |
| 96 google_breakpad::CustomInfoEntry url3(L"url-chunk-3", L""); | 110 entries.push_back(google_breakpad::CustomInfoEntry( |
| 97 google_breakpad::CustomInfoEntry url4(L"url-chunk-4", L""); | 111 StringPrintf(L"url-chunk-%i", i + 1).c_str(), L"")); |
| 98 google_breakpad::CustomInfoEntry url5(L"url-chunk-5", L""); | 112 (*g_url_chunks)[i] = entries.back().value; |
| 99 google_breakpad::CustomInfoEntry url6(L"url-chunk-6", L""); | 113 } |
| 100 google_breakpad::CustomInfoEntry url7(L"url-chunk-7", L""); | 114 } else { |
| 101 google_breakpad::CustomInfoEntry url8(L"url-chunk-8", L""); | 115 // Browser-specific entries. |
| 116 google_breakpad::CustomInfoEntry switch1(L"switch-1", L""); |
| 117 google_breakpad::CustomInfoEntry switch2(L"switch-2", L""); |
| 102 | 118 |
| 103 static google_breakpad::CustomInfoEntry entries[] = | 119 // Get the first two command line switches if they exist. The CommandLine |
| 104 { ver_entry, prod_entry, plat_entry, type_entry, guid_entry, | 120 // class does not allow to enumerate the switches so we do it by hand. |
| 105 url1, url2, url3, url4, url5, url6, url7, url8 }; | 121 int num_args = 0; |
| 122 wchar_t** args = ::CommandLineToArgvW(::GetCommandLineW(), &num_args); |
| 123 if (args) { |
| 124 if (num_args > 1) |
| 125 switch1.set_value(TrimToBreakpadMax(args[1]).c_str()); |
| 126 if (num_args > 2) |
| 127 switch2.set_value(TrimToBreakpadMax(args[2]).c_str()); |
| 128 } |
| 106 | 129 |
| 107 std::vector<wchar_t*>* tmp_url_chunks = new std::vector<wchar_t*>(8); | 130 entries.push_back(switch1); |
| 108 for (size_t i = 0; i < 8; ++i) | 131 entries.push_back(switch2); |
| 109 (*tmp_url_chunks)[i] = entries[5 + i].value; | |
| 110 g_url_chunks = tmp_url_chunks; | |
| 111 | |
| 112 g_client_id = entries[4].value; | |
| 113 | |
| 114 static google_breakpad::CustomClientInfo custom_info_renderer | |
| 115 = {entries, arraysize(entries)}; | |
| 116 return &custom_info_renderer; | |
| 117 } | 132 } |
| 118 | 133 |
| 119 // Browser-specific entries. | 134 // If this fails, kNumCustomInfoEntries needs to be increased. |
| 120 google_breakpad::CustomInfoEntry switch1(L"switch-1", L""); | 135 DCHECK(entries.size() <= entries.capacity()); |
| 121 google_breakpad::CustomInfoEntry switch2(L"switch-2", L""); | |
| 122 | 136 |
| 123 // Get the first two command line switches if they exist. The CommandLine | 137 static google_breakpad::CustomClientInfo custom_info_browser = |
| 124 // class does not allow to enumerate the switches so we do it by hand. | 138 {&entries.front(), entries.size()}; |
| 125 int num_args = 0; | |
| 126 wchar_t** args = ::CommandLineToArgvW(::GetCommandLineW(), &num_args); | |
| 127 if (args) { | |
| 128 if (num_args > 1) | |
| 129 switch1.set_value(TrimToBreakpadMax(args[1]).c_str()); | |
| 130 if (num_args > 2) | |
| 131 switch2.set_value(TrimToBreakpadMax(args[2]).c_str()); | |
| 132 } | |
| 133 | 139 |
| 134 static google_breakpad::CustomInfoEntry entries[] = | |
| 135 {ver_entry, prod_entry, plat_entry, type_entry, guid_entry, | |
| 136 switch1, switch2}; | |
| 137 g_client_id = entries[4].value; | |
| 138 static google_breakpad::CustomClientInfo custom_info_browser = | |
| 139 {entries, arraysize(entries)}; | |
| 140 return &custom_info_browser; | 140 return &custom_info_browser; |
| 141 } | 141 } |
| 142 | 142 |
| 143 // Contains the information needed by the worker thread. | 143 // Contains the information needed by the worker thread. |
| 144 struct CrashReporterInfo { | 144 struct CrashReporterInfo { |
| 145 google_breakpad::CustomClientInfo* custom_info; | 145 google_breakpad::CustomClientInfo* custom_info; |
| 146 std::wstring dll_path; | 146 std::wstring dll_path; |
| 147 std::wstring process_type; | 147 std::wstring process_type; |
| 148 }; | 148 }; |
| 149 | 149 |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 242 extern "C" void __declspec(dllexport) __cdecl SetClientId( | 242 extern "C" void __declspec(dllexport) __cdecl SetClientId( |
| 243 const wchar_t* client_id) { | 243 const wchar_t* client_id) { |
| 244 if (client_id == NULL) | 244 if (client_id == NULL) |
| 245 return; | 245 return; |
| 246 | 246 |
| 247 wcscpy_s(g_client_id, | 247 wcscpy_s(g_client_id, |
| 248 google_breakpad::CustomInfoEntry::kValueMaxLength, | 248 google_breakpad::CustomInfoEntry::kValueMaxLength, |
| 249 client_id); | 249 client_id); |
| 250 } | 250 } |
| 251 | 251 |
| 252 extern "C" void __declspec(dllexport) __cdecl SetExtensionID( |
| 253 int index, const wchar_t* id) { |
| 254 DCHECK(id); |
| 255 DCHECK(index < kMaxReportedActiveExtensions); |
| 256 |
| 257 if (!g_extension_ids) |
| 258 return; |
| 259 |
| 260 wcscpy_s((*g_extension_ids)[index], |
| 261 google_breakpad::CustomInfoEntry::kValueMaxLength, |
| 262 id); |
| 263 } |
| 264 |
| 252 } // namespace | 265 } // namespace |
| 253 | 266 |
| 254 // This function is executed by the child process that DumpDoneCallback() | 267 // This function is executed by the child process that DumpDoneCallback() |
| 255 // spawned and basically just shows the 'chrome has crashed' dialog if | 268 // spawned and basically just shows the 'chrome has crashed' dialog if |
| 256 // the CHROME_CRASHED environment variable is present. | 269 // the CHROME_CRASHED environment variable is present. |
| 257 bool ShowRestartDialogIfCrashed(bool* exit_now) { | 270 bool ShowRestartDialogIfCrashed(bool* exit_now) { |
| 258 if (!::GetEnvironmentVariableW(env_vars::kShowRestart, NULL, 0)) | 271 if (!::GetEnvironmentVariableW(env_vars::kShowRestart, NULL, 0)) |
| 259 return false; | 272 return false; |
| 260 | 273 |
| 261 DWORD len = ::GetEnvironmentVariableW(env_vars::kRestartInfo, NULL, 0); | 274 DWORD len = ::GetEnvironmentVariableW(env_vars::kRestartInfo, NULL, 0); |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 405 if (QueueUserWorkItem( | 418 if (QueueUserWorkItem( |
| 406 &InitCrashReporterThread, | 419 &InitCrashReporterThread, |
| 407 info.release(), | 420 info.release(), |
| 408 WT_EXECUTELONGFUNCTION) == 0) { | 421 WT_EXECUTELONGFUNCTION) == 0) { |
| 409 // We failed to queue to the worker pool, initialize in this thread. | 422 // We failed to queue to the worker pool, initialize in this thread. |
| 410 InitCrashReporterThread(info.release()); | 423 InitCrashReporterThread(info.release()); |
| 411 } | 424 } |
| 412 } | 425 } |
| 413 } | 426 } |
| 414 } | 427 } |
| OLD | NEW |