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 |