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 SetCommandLineFromCurrent(void) { | |
108 if (!g_custom_entries) | |
109 return; | |
110 | |
111 // Note that CommandLine may be different from the argc/argv that the | |
112 // application was launched with. We intentionally use CommandLine in order | |
113 // to pick up the experiments that about:flags shoved into the CommandLine. | |
114 const CommandLine::StringVector& argv = | |
115 CommandLine::ForCurrentProcess()->argv(); | |
116 | |
117 // Copy up to the kMaxSwitches arguments into the custom entries array. Skip | |
118 // past the first argument, as it is just the executable path. | |
119 size_t argv_i = 1; | |
120 size_t num_added = 0; | |
121 | |
122 for (; argv_i < argv.size() && num_added < kMaxSwitches; ++argv_i) { | |
Nico
2011/09/13 23:04:41
Increment num_added in the for loop instead of in
eroman
2011/09/13 23:27:32
Done.
The reason I was doing it in the body rathe
| |
123 wcscpy_s((*g_custom_entries)[g_switches_offset + num_added++].value, | |
124 google_breakpad::CustomInfoEntry::kValueMaxLength, | |
125 argv[argv_i].c_str()); | |
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 SetCommandLineFromCurrent(). | |
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 will call SetCommandLineFromCurrent() again later on, | |
227 // once it has augmented CommandLine with the about:flags experiments. | |
228 SetCommandLineFromCurrent(); | |
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 |