| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 65 // A pointer to the custom entries that we send in the event of a crash. We need | 65 // A pointer to the custom entries that we send in the event of a crash. We need |
| 66 // this pointer, along with the offsets into it below, so that we can keep the | 66 // this pointer, along with the offsets into it below, so that we can keep the |
| 67 // data updated as the state of the browser changes. | 67 // data updated as the state of the browser changes. |
| 68 static std::vector<google_breakpad::CustomInfoEntry>* g_custom_entries = NULL; | 68 static std::vector<google_breakpad::CustomInfoEntry>* g_custom_entries = NULL; |
| 69 static size_t g_url_chunks_offset; | 69 static size_t g_url_chunks_offset; |
| 70 static size_t g_num_of_extensions_offset; | 70 static size_t g_num_of_extensions_offset; |
| 71 static size_t g_extension_ids_offset; | 71 static size_t g_extension_ids_offset; |
| 72 static size_t g_client_id_offset; | 72 static size_t g_client_id_offset; |
| 73 static size_t g_gpu_info_offset; | 73 static size_t g_gpu_info_offset; |
| 74 static size_t g_num_of_views_offset; | 74 static size_t g_num_of_views_offset; |
| 75 static size_t g_num_switches_offset; |
| 76 static size_t g_switches_offset; |
| 77 |
| 78 // The maximum number of command line switches to include in the crash |
| 79 // report's metadata. Note that the mini-dump itself will also contain the |
| 80 // (original) command line arguments within the PEB. |
| 81 const size_t kMaxSwitches = 15; |
| 75 | 82 |
| 76 // Dumps the current process memory. | 83 // Dumps the current process memory. |
| 77 extern "C" void __declspec(dllexport) __cdecl DumpProcess() { | 84 extern "C" void __declspec(dllexport) __cdecl DumpProcess() { |
| 78 if (g_breakpad) | 85 if (g_breakpad) |
| 79 g_breakpad->WriteMinidump(); | 86 g_breakpad->WriteMinidump(); |
| 80 } | 87 } |
| 81 | 88 |
| 82 // Reduces the size of the string |str| to a max of 64 chars. Required because | 89 // Reduces the size of the string |str| to a max of 64 chars. Required because |
| 83 // breakpad's CustomInfoEntry raises an invalid_parameter error if the string | 90 // breakpad's CustomInfoEntry raises an invalid_parameter error if the string |
| 84 // we want to set is longer. | 91 // we want to set is longer. |
| 85 std::wstring TrimToBreakpadMax(const std::wstring& str) { | 92 std::wstring TrimToBreakpadMax(const std::wstring& str) { |
| 86 std::wstring shorter(str); | 93 std::wstring shorter(str); |
| 87 return shorter.substr(0, | 94 return shorter.substr(0, |
| 88 google_breakpad::CustomInfoEntry::kValueMaxLength - 1); | 95 google_breakpad::CustomInfoEntry::kValueMaxLength - 1); |
| 89 } | 96 } |
| 90 | 97 |
| 98 static void SetIntegerValue(size_t offset, int value) { |
| 99 if (!g_custom_entries) |
| 100 return; |
| 101 |
| 102 wcscpy_s((*g_custom_entries)[offset].value, |
| 103 google_breakpad::CustomInfoEntry::kValueMaxLength, |
| 104 base::StringPrintf(L"%d", value).c_str()); |
| 105 } |
| 106 |
| 107 extern "C" void __declspec(dllexport) __cdecl SetCommandLine( |
| 108 const CommandLine* command_line) { |
| 109 if (!g_custom_entries) |
| 110 return; |
| 111 |
| 112 const CommandLine::StringVector& argv = command_line->argv(); |
| 113 |
| 114 // Copy up to the kMaxSwitches arguments into the custom entries array. Skip |
| 115 // past the first argument, as it is just the executable path. |
| 116 size_t argv_i = 1; |
| 117 size_t num_added = 0; |
| 118 |
| 119 for (; argv_i < argv.size() && num_added < kMaxSwitches; |
| 120 ++argv_i, ++num_added) { |
| 121 // TODO(eroman): Filter out flags which aren't useful and just add bloat |
| 122 // to the report. |
| 123 wcsncpy((*g_custom_entries)[g_switches_offset + num_added].value, |
| 124 argv[argv_i].c_str(), |
| 125 google_breakpad::CustomInfoEntry::kValueMaxLength); |
| 126 } |
| 127 |
| 128 // Make note of the total number of switches. This is useful in case we have |
| 129 // truncated at kMaxSwitches, to see how many were unaccounted for. |
| 130 SetIntegerValue(g_num_switches_offset, static_cast<int>(argv.size()) - 1); |
| 131 } |
| 132 |
| 91 // Returns the custom info structure based on the dll in parameter and the | 133 // Returns the custom info structure based on the dll in parameter and the |
| 92 // process type. | 134 // process type. |
| 93 google_breakpad::CustomClientInfo* GetCustomInfo(const std::wstring& dll_path, | 135 google_breakpad::CustomClientInfo* GetCustomInfo(const std::wstring& dll_path, |
| 94 const std::wstring& type) { | 136 const std::wstring& type) { |
| 95 scoped_ptr<FileVersionInfo> | 137 scoped_ptr<FileVersionInfo> |
| 96 version_info(FileVersionInfo::CreateFileVersionInfo(FilePath(dll_path))); | 138 version_info(FileVersionInfo::CreateFileVersionInfo(FilePath(dll_path))); |
| 97 | 139 |
| 98 std::wstring version, product; | 140 std::wstring version, product; |
| 99 std::wstring special_build; | 141 std::wstring special_build; |
| 100 if (version_info.get()) { | 142 if (version_info.get()) { |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 161 | 203 |
| 162 // Read the id from registry. If reporting has never been enabled | 204 // Read the id from registry. If reporting has never been enabled |
| 163 // the result will be empty string. Its OK since when user enables reporting | 205 // the result will be empty string. Its OK since when user enables reporting |
| 164 // we will insert the new value at this location. | 206 // we will insert the new value at this location. |
| 165 std::wstring guid; | 207 std::wstring guid; |
| 166 GoogleUpdateSettings::GetMetricsId(&guid); | 208 GoogleUpdateSettings::GetMetricsId(&guid); |
| 167 g_client_id_offset = g_custom_entries->size(); | 209 g_client_id_offset = g_custom_entries->size(); |
| 168 g_custom_entries->push_back( | 210 g_custom_entries->push_back( |
| 169 google_breakpad::CustomInfoEntry(L"guid", guid.c_str())); | 211 google_breakpad::CustomInfoEntry(L"guid", guid.c_str())); |
| 170 | 212 |
| 213 // Add empty values for the command line switches. We will fill them with |
| 214 // actual values as part of SetCommandLine(). |
| 215 g_num_switches_offset = g_custom_entries->size(); |
| 216 g_custom_entries->push_back( |
| 217 google_breakpad::CustomInfoEntry(L"num-switches", L"")); |
| 218 |
| 219 g_switches_offset = g_custom_entries->size(); |
| 220 for (int i = 0; i < kMaxSwitches; ++i) { |
| 221 g_custom_entries->push_back(google_breakpad::CustomInfoEntry( |
| 222 base::StringPrintf(L"switch-%i", i + 1).c_str(), L"")); |
| 223 } |
| 224 |
| 225 // Fill in the command line arguments using CommandLine::ForCurrentProcess(). |
| 226 // The browser process may call SetCommandLine() again later on with a command |
| 227 // line that has been augmented with the about:flags experiments. |
| 228 SetCommandLine(CommandLine::ForCurrentProcess()); |
| 229 |
| 171 if (type == L"renderer" || type == L"plugin" || type == L"gpu-process") { | 230 if (type == L"renderer" || type == L"plugin" || type == L"gpu-process") { |
| 172 g_num_of_views_offset = g_custom_entries->size(); | 231 g_num_of_views_offset = g_custom_entries->size(); |
| 173 g_custom_entries->push_back( | 232 g_custom_entries->push_back( |
| 174 google_breakpad::CustomInfoEntry(L"num-views", L"")); | 233 google_breakpad::CustomInfoEntry(L"num-views", L"")); |
| 175 // Create entries for the URL. Currently we only allow each chunk to be 64 | 234 // Create entries for the URL. Currently we only allow each chunk to be 64 |
| 176 // characters, which isn't enough for a URL. As a hack we create 8 entries | 235 // characters, which isn't enough for a URL. As a hack we create 8 entries |
| 177 // and split the URL across the g_custom_entries. | 236 // and split the URL across the g_custom_entries. |
| 178 g_url_chunks_offset = g_custom_entries->size(); | 237 g_url_chunks_offset = g_custom_entries->size(); |
| 179 for (int i = 0; i < kMaxUrlChunks; ++i) { | 238 for (int i = 0; i < kMaxUrlChunks; ++i) { |
| 180 g_custom_entries->push_back(google_breakpad::CustomInfoEntry( | 239 g_custom_entries->push_back(google_breakpad::CustomInfoEntry( |
| 181 base::StringPrintf(L"url-chunk-%i", i + 1).c_str(), L"")); | 240 base::StringPrintf(L"url-chunk-%i", i + 1).c_str(), L"")); |
| 182 } | 241 } |
| 183 } else { | 242 } else { |
| 184 g_custom_entries->push_back( | 243 g_custom_entries->push_back( |
| 185 google_breakpad::CustomInfoEntry(L"num-views", L"N/A")); | 244 google_breakpad::CustomInfoEntry(L"num-views", L"N/A")); |
| 186 | |
| 187 // Browser-specific g_custom_entries. | |
| 188 google_breakpad::CustomInfoEntry switch1(L"switch-1", L""); | |
| 189 google_breakpad::CustomInfoEntry switch2(L"switch-2", L""); | |
| 190 | |
| 191 // Get the first two command line switches if they exist. The CommandLine | |
| 192 // class does not allow to enumerate the switches so we do it by hand. | |
| 193 int num_args = 0; | |
| 194 wchar_t** args = ::CommandLineToArgvW(::GetCommandLineW(), &num_args); | |
| 195 if (args) { | |
| 196 if (num_args > 1) | |
| 197 switch1.set_value(TrimToBreakpadMax(args[1]).c_str()); | |
| 198 if (num_args > 2) | |
| 199 switch2.set_value(TrimToBreakpadMax(args[2]).c_str()); | |
| 200 // The caller must free the memory allocated for |args|. | |
| 201 ::LocalFree(args); | |
| 202 } | |
| 203 | |
| 204 g_custom_entries->push_back(switch1); | |
| 205 g_custom_entries->push_back(switch2); | |
| 206 } | 245 } |
| 207 | 246 |
| 208 static google_breakpad::CustomClientInfo custom_client_info; | 247 static google_breakpad::CustomClientInfo custom_client_info; |
| 209 custom_client_info.entries = &g_custom_entries->front(); | 248 custom_client_info.entries = &g_custom_entries->front(); |
| 210 custom_client_info.count = g_custom_entries->size(); | 249 custom_client_info.count = g_custom_entries->size(); |
| 211 | 250 |
| 212 return &custom_client_info; | 251 return &custom_client_info; |
| 213 } | 252 } |
| 214 | 253 |
| 215 // Contains the information needed by the worker thread. | 254 // Contains the information needed by the worker thread. |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 330 return; | 369 return; |
| 331 | 370 |
| 332 if (!g_custom_entries) | 371 if (!g_custom_entries) |
| 333 return; | 372 return; |
| 334 | 373 |
| 335 wcscpy_s((*g_custom_entries)[g_client_id_offset].value, | 374 wcscpy_s((*g_custom_entries)[g_client_id_offset].value, |
| 336 google_breakpad::CustomInfoEntry::kValueMaxLength, | 375 google_breakpad::CustomInfoEntry::kValueMaxLength, |
| 337 client_id); | 376 client_id); |
| 338 } | 377 } |
| 339 | 378 |
| 340 static void SetIntegerValue(size_t offset, int value) { | |
| 341 if (!g_custom_entries) | |
| 342 return; | |
| 343 | |
| 344 wcscpy_s((*g_custom_entries)[offset].value, | |
| 345 google_breakpad::CustomInfoEntry::kValueMaxLength, | |
| 346 base::StringPrintf(L"%d", value).c_str()); | |
| 347 } | |
| 348 | |
| 349 extern "C" void __declspec(dllexport) __cdecl SetNumberOfExtensions( | 379 extern "C" void __declspec(dllexport) __cdecl SetNumberOfExtensions( |
| 350 int number_of_extensions) { | 380 int number_of_extensions) { |
| 351 SetIntegerValue(g_num_of_extensions_offset, number_of_extensions); | 381 SetIntegerValue(g_num_of_extensions_offset, number_of_extensions); |
| 352 } | 382 } |
| 353 | 383 |
| 354 extern "C" void __declspec(dllexport) __cdecl SetExtensionID( | 384 extern "C" void __declspec(dllexport) __cdecl SetExtensionID( |
| 355 int index, const wchar_t* id) { | 385 int index, const wchar_t* id) { |
| 356 DCHECK(id); | 386 DCHECK(id); |
| 357 DCHECK(index < kMaxReportedActiveExtensions); | 387 DCHECK(index < kMaxReportedActiveExtensions); |
| 358 | 388 |
| (...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 630 if (QueueUserWorkItem( | 660 if (QueueUserWorkItem( |
| 631 &InitCrashReporterThread, | 661 &InitCrashReporterThread, |
| 632 info, | 662 info, |
| 633 WT_EXECUTELONGFUNCTION) == 0) { | 663 WT_EXECUTELONGFUNCTION) == 0) { |
| 634 // We failed to queue to the worker pool, initialize in this thread. | 664 // We failed to queue to the worker pool, initialize in this thread. |
| 635 InitCrashReporterThread(info); | 665 InitCrashReporterThread(info); |
| 636 } | 666 } |
| 637 } | 667 } |
| 638 } | 668 } |
| 639 } | 669 } |
| OLD | NEW |