Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(488)

Side by Side Diff: chrome/app/breakpad_win.cc

Issue 9432033: Add experiments info to crash dumps. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Last Few Nits Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/app/breakpad_win.h ('k') | chrome/app/run_all_unittests.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 10
11 #include <algorithm> 11 #include <algorithm>
12 #include <vector> 12 #include <vector>
13 13
14 #include "base/base_switches.h" 14 #include "base/base_switches.h"
15 #include "base/command_line.h" 15 #include "base/command_line.h"
16 #include "base/environment.h" 16 #include "base/environment.h"
17 #include "base/file_util.h" 17 #include "base/file_util.h"
18 #include "base/file_version_info.h" 18 #include "base/file_version_info.h"
19 #include "base/memory/scoped_ptr.h" 19 #include "base/memory/scoped_ptr.h"
20 #include "base/string_split.h" 20 #include "base/string_split.h"
21 #include "base/string_util.h" 21 #include "base/string_util.h"
22 #include "base/string16.h"
22 #include "base/stringprintf.h" 23 #include "base/stringprintf.h"
23 #include "base/utf_string_conversions.h" 24 #include "base/utf_string_conversions.h"
24 #include "base/win/registry.h" 25 #include "base/win/registry.h"
25 #include "base/win/win_util.h" 26 #include "base/win/win_util.h"
26 #include "breakpad/src/client/windows/handler/exception_handler.h" 27 #include "breakpad/src/client/windows/handler/exception_handler.h"
28 #include "chrome/app/breakpad_field_trial_win.h"
27 #include "chrome/app/hard_error_handler_win.h" 29 #include "chrome/app/hard_error_handler_win.h"
28 #include "chrome/common/child_process_logging.h" 30 #include "chrome/common/child_process_logging.h"
29 #include "chrome/common/chrome_result_codes.h" 31 #include "chrome/common/chrome_result_codes.h"
30 #include "chrome/common/chrome_switches.h" 32 #include "chrome/common/chrome_switches.h"
31 #include "chrome/common/env_vars.h" 33 #include "chrome/common/env_vars.h"
32 #include "chrome/installer/util/google_chrome_sxs_distribution.h" 34 #include "chrome/installer/util/google_chrome_sxs_distribution.h"
33 #include "chrome/installer/util/google_update_settings.h" 35 #include "chrome/installer/util/google_update_settings.h"
34 #include "chrome/installer/util/install_util.h" 36 #include "chrome/installer/util/install_util.h"
35 #include "policy/policy_constants.h" 37 #include "policy/policy_constants.h"
36 38
39 namespace breakpad_win {
40
41 std::vector<google_breakpad::CustomInfoEntry>* g_custom_entries = NULL;
42 size_t g_num_of_experiments_offset = 0;
43 size_t g_experiment_chunks_offset = 0;
44
45 } // namespace breakpad_win
46
47 using breakpad_win::g_custom_entries;
48 using breakpad_win::g_experiment_chunks_offset;
49 using breakpad_win::g_num_of_experiments_offset;
50
37 namespace { 51 namespace {
38 52
39 // Minidump with stacks, PEB, TEB, and unloaded module list. 53 // Minidump with stacks, PEB, TEB, and unloaded module list.
40 const MINIDUMP_TYPE kSmallDumpType = static_cast<MINIDUMP_TYPE>( 54 const MINIDUMP_TYPE kSmallDumpType = static_cast<MINIDUMP_TYPE>(
41 MiniDumpWithProcessThreadData | // Get PEB and TEB. 55 MiniDumpWithProcessThreadData | // Get PEB and TEB.
42 MiniDumpWithUnloadedModules); // Get unloaded modules when available. 56 MiniDumpWithUnloadedModules); // Get unloaded modules when available.
43 57
44 // Minidump with all of the above, plus memory referenced from stack. 58 // Minidump with all of the above, plus memory referenced from stack.
45 const MINIDUMP_TYPE kLargerDumpType = static_cast<MINIDUMP_TYPE>( 59 const MINIDUMP_TYPE kLargerDumpType = static_cast<MINIDUMP_TYPE>(
46 MiniDumpWithProcessThreadData | // Get PEB and TEB. 60 MiniDumpWithProcessThreadData | // Get PEB and TEB.
(...skipping 11 matching lines...) Expand all
58 72
59 const wchar_t kGoogleUpdatePipeName[] = L"\\\\.\\pipe\\GoogleCrashServices\\"; 73 const wchar_t kGoogleUpdatePipeName[] = L"\\\\.\\pipe\\GoogleCrashServices\\";
60 const wchar_t kChromePipeName[] = L"\\\\.\\pipe\\ChromeCrashServices"; 74 const wchar_t kChromePipeName[] = L"\\\\.\\pipe\\ChromeCrashServices";
61 75
62 // This is the well known SID for the system principal. 76 // This is the well known SID for the system principal.
63 const wchar_t kSystemPrincipalSid[] =L"S-1-5-18"; 77 const wchar_t kSystemPrincipalSid[] =L"S-1-5-18";
64 78
65 google_breakpad::ExceptionHandler* g_breakpad = NULL; 79 google_breakpad::ExceptionHandler* g_breakpad = NULL;
66 google_breakpad::ExceptionHandler* g_dumphandler_no_crash = NULL; 80 google_breakpad::ExceptionHandler* g_dumphandler_no_crash = NULL;
67 81
68 // A pointer to the custom entries that we send in the event of a crash. We need 82 static size_t g_url_chunks_offset = 0;
69 // this pointer, along with the offsets into it below, so that we can keep the 83 static size_t g_num_of_extensions_offset = 0;
70 // data updated as the state of the browser changes. 84 static size_t g_extension_ids_offset = 0;
71 static std::vector<google_breakpad::CustomInfoEntry>* g_custom_entries = NULL; 85 static size_t g_client_id_offset = 0;
72 static size_t g_url_chunks_offset; 86 static size_t g_gpu_info_offset = 0;
73 static size_t g_num_of_extensions_offset; 87 static size_t g_printer_info_offset = 0;
74 static size_t g_extension_ids_offset; 88 static size_t g_num_of_views_offset = 0;
75 static size_t g_client_id_offset; 89 static size_t g_num_switches_offset = 0;
76 static size_t g_gpu_info_offset; 90 static size_t g_switches_offset = 0;
77 static size_t g_printer_info_offset;
78 static size_t g_num_of_views_offset;
79 static size_t g_num_switches_offset;
80 static size_t g_switches_offset;
81 91
82 // Maximum length for plugin path to include in plugin crash reports. 92 // Maximum length for plugin path to include in plugin crash reports.
83 const size_t kMaxPluginPathLength = 256; 93 const size_t kMaxPluginPathLength = 256;
84 94
85 // Dumps the current process memory. 95 // Dumps the current process memory.
86 extern "C" void __declspec(dllexport) __cdecl DumpProcess() { 96 extern "C" void __declspec(dllexport) __cdecl DumpProcess() {
87 if (g_breakpad) 97 if (g_breakpad)
88 g_breakpad->WriteMinidump(); 98 g_breakpad->WriteMinidump();
89 } 99 }
90 100
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
246 256
247 if (!special_build.empty()) 257 if (!special_build.empty())
248 g_custom_entries->push_back( 258 g_custom_entries->push_back(
249 google_breakpad::CustomInfoEntry(L"special", special_build.c_str())); 259 google_breakpad::CustomInfoEntry(L"special", special_build.c_str()));
250 260
251 g_num_of_extensions_offset = g_custom_entries->size(); 261 g_num_of_extensions_offset = g_custom_entries->size();
252 g_custom_entries->push_back( 262 g_custom_entries->push_back(
253 google_breakpad::CustomInfoEntry(L"num-extensions", L"N/A")); 263 google_breakpad::CustomInfoEntry(L"num-extensions", L"N/A"));
254 264
255 g_extension_ids_offset = g_custom_entries->size(); 265 g_extension_ids_offset = g_custom_entries->size();
256 for (int i = 0; i < kMaxReportedActiveExtensions; ++i) { 266 // one-based index for the name suffix.
267 for (int i = 1; i <= kMaxReportedActiveExtensions; ++i) {
257 g_custom_entries->push_back(google_breakpad::CustomInfoEntry( 268 g_custom_entries->push_back(google_breakpad::CustomInfoEntry(
258 base::StringPrintf(L"extension-%i", i + 1).c_str(), L"")); 269 base::StringPrintf(L"extension-%i", i).c_str(), L""));
259 } 270 }
260 271
261 // Add empty values for the gpu_info. We'll put the actual values when we 272 // Add empty values for the gpu_info. We'll put the actual values when we
262 // collect them at this location. 273 // collect them at this location.
263 g_gpu_info_offset = g_custom_entries->size(); 274 g_gpu_info_offset = g_custom_entries->size();
264 static const wchar_t* const kGpuEntries[] = { 275 static const wchar_t* const kGpuEntries[] = {
265 L"gpu-venid", 276 L"gpu-venid",
266 L"gpu-devid", 277 L"gpu-devid",
267 L"gpu-driver", 278 L"gpu-driver",
268 L"gpu-psver", 279 L"gpu-psver",
269 L"gpu-vsver", 280 L"gpu-vsver",
270 }; 281 };
271 for (size_t i = 0; i < arraysize(kGpuEntries); ++i) { 282 for (size_t i = 0; i < arraysize(kGpuEntries); ++i) {
272 g_custom_entries->push_back( 283 g_custom_entries->push_back(
273 google_breakpad::CustomInfoEntry(kGpuEntries[i], L"")); 284 google_breakpad::CustomInfoEntry(kGpuEntries[i], L""));
274 } 285 }
275 286
276 // Add empty values for the prn_info-*. We'll put the actual values when we 287 // Add empty values for the prn_info-*. We'll put the actual values when we
277 // collect them at this location. 288 // collect them at this location.
278 g_printer_info_offset = g_custom_entries->size(); 289 g_printer_info_offset = g_custom_entries->size();
279 for (size_t i = 0; i < kMaxReportedPrinterRecords; ++i) { 290 // one-based index for the name suffix.
291 for (size_t i = 1; i <= kMaxReportedPrinterRecords; ++i) {
280 g_custom_entries->push_back( 292 g_custom_entries->push_back(
281 google_breakpad::CustomInfoEntry( 293 google_breakpad::CustomInfoEntry(
282 base::StringPrintf(L"prn-info-%d", i + 1).c_str(), L"")); 294 base::StringPrintf(L"prn-info-%d", i).c_str(), L""));
283 } 295 }
284 296
285 // Read the id from registry. If reporting has never been enabled 297 // Read the id from registry. If reporting has never been enabled
286 // the result will be empty string. Its OK since when user enables reporting 298 // the result will be empty string. Its OK since when user enables reporting
287 // we will insert the new value at this location. 299 // we will insert the new value at this location.
288 std::wstring guid; 300 std::wstring guid;
289 GoogleUpdateSettings::GetMetricsId(&guid); 301 GoogleUpdateSettings::GetMetricsId(&guid);
290 g_client_id_offset = g_custom_entries->size(); 302 g_client_id_offset = g_custom_entries->size();
291 g_custom_entries->push_back( 303 g_custom_entries->push_back(
292 google_breakpad::CustomInfoEntry(L"guid", guid.c_str())); 304 google_breakpad::CustomInfoEntry(L"guid", guid.c_str()));
293 305
294 // Add empty values for the command line switches. We will fill them with 306 // Add empty values for the command line switches. We will fill them with
295 // actual values as part of SetCommandLine(). 307 // actual values as part of SetCommandLine().
296 g_num_switches_offset = g_custom_entries->size(); 308 g_num_switches_offset = g_custom_entries->size();
297 g_custom_entries->push_back( 309 g_custom_entries->push_back(
298 google_breakpad::CustomInfoEntry(L"num-switches", L"")); 310 google_breakpad::CustomInfoEntry(L"num-switches", L""));
299 311
300 g_switches_offset = g_custom_entries->size(); 312 g_switches_offset = g_custom_entries->size();
301 for (int i = 0; i < kMaxSwitches; ++i) { 313 // one-based index for the name suffix.
314 for (int i = 1; i <= kMaxSwitches; ++i) {
302 g_custom_entries->push_back(google_breakpad::CustomInfoEntry( 315 g_custom_entries->push_back(google_breakpad::CustomInfoEntry(
303 base::StringPrintf(L"switch-%i", i + 1).c_str(), L"")); 316 base::StringPrintf(L"switch-%i", i).c_str(), L""));
304 } 317 }
305 318
306 // Fill in the command line arguments using CommandLine::ForCurrentProcess(). 319 // Fill in the command line arguments using CommandLine::ForCurrentProcess().
307 // The browser process may call SetCommandLine() again later on with a command 320 // The browser process may call SetCommandLine() again later on with a command
308 // line that has been augmented with the about:flags experiments. 321 // line that has been augmented with the about:flags experiments.
309 SetCommandLine(CommandLine::ForCurrentProcess()); 322 SetCommandLine(CommandLine::ForCurrentProcess());
310 323
311 if (type == L"renderer" || type == L"plugin" || type == L"gpu-process") { 324 if (type == L"renderer" || type == L"plugin" || type == L"gpu-process") {
312 g_num_of_views_offset = g_custom_entries->size(); 325 g_num_of_views_offset = g_custom_entries->size();
313 g_custom_entries->push_back( 326 g_custom_entries->push_back(
314 google_breakpad::CustomInfoEntry(L"num-views", L"")); 327 google_breakpad::CustomInfoEntry(L"num-views", L""));
315 // Create entries for the URL. Currently we only allow each chunk to be 64 328 // Create entries for the URL. Currently we only allow each chunk to be 64
316 // characters, which isn't enough for a URL. As a hack we create 8 entries 329 // characters, which isn't enough for a URL. As a hack we create 8 entries
317 // and split the URL across the g_custom_entries. 330 // and split the URL across the g_custom_entries.
318 g_url_chunks_offset = g_custom_entries->size(); 331 g_url_chunks_offset = g_custom_entries->size();
319 for (int i = 0; i < kMaxUrlChunks; ++i) { 332 // one-based index for the name suffix.
333 for (int i = 1; i <= kMaxUrlChunks; ++i) {
320 g_custom_entries->push_back(google_breakpad::CustomInfoEntry( 334 g_custom_entries->push_back(google_breakpad::CustomInfoEntry(
321 base::StringPrintf(L"url-chunk-%i", i + 1).c_str(), L"")); 335 base::StringPrintf(L"url-chunk-%i", i).c_str(), L""));
322 } 336 }
323 337
324 if (type == L"plugin") { 338 if (type == L"plugin") {
325 std::wstring plugin_path = 339 std::wstring plugin_path =
326 CommandLine::ForCurrentProcess()->GetSwitchValueNative("plugin-path"); 340 CommandLine::ForCurrentProcess()->GetSwitchValueNative("plugin-path");
327 if (!plugin_path.empty()) 341 if (!plugin_path.empty())
328 SetPluginPath(plugin_path); 342 SetPluginPath(plugin_path);
329 } 343 }
330 } else { 344 } else {
331 g_custom_entries->push_back( 345 g_custom_entries->push_back(
332 google_breakpad::CustomInfoEntry(L"num-views", L"N/A")); 346 google_breakpad::CustomInfoEntry(L"num-views", L"N/A"));
333 } 347 }
334 348
349 g_num_of_experiments_offset = g_custom_entries->size();
350 g_custom_entries->push_back(
351 google_breakpad::CustomInfoEntry(L"num-experiments", L"N/A"));
352
353 g_experiment_chunks_offset = g_custom_entries->size();
354 // We depend on this in UpdateExperiments...
355 DCHECK_NE(0UL, g_experiment_chunks_offset);
356 // And the test code depends on this.
357 DCHECK_EQ(g_num_of_experiments_offset + 1, g_experiment_chunks_offset);
358 // one-based index for the name suffix.
359 for (int i = 1; i <= kMaxReportedExperimentChunks; ++i) {
360 g_custom_entries->push_back(google_breakpad::CustomInfoEntry(
361 base::StringPrintf(L"experiment-chunk-%i", i).c_str(), L""));
362 }
363
335 static google_breakpad::CustomClientInfo custom_client_info; 364 static google_breakpad::CustomClientInfo custom_client_info;
336 custom_client_info.entries = &g_custom_entries->front(); 365 custom_client_info.entries = &g_custom_entries->front();
337 custom_client_info.count = g_custom_entries->size(); 366 custom_client_info.count = g_custom_entries->size();
338 367
339 return &custom_client_info; 368 return &custom_client_info;
340 } 369 }
341 370
342 // This callback is used when we want to get a dump without crashing the 371 // This callback is used when we want to get a dump without crashing the
343 // process. 372 // process.
344 bool DumpDoneCallbackWhenNoCrash(const wchar_t*, const wchar_t*, void*, 373 bool DumpDoneCallbackWhenNoCrash(const wchar_t*, const wchar_t*, void*,
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
528 } 557 }
529 } 558 }
530 559
531 extern "C" void __declspec(dllexport) __cdecl SetNumberOfViews( 560 extern "C" void __declspec(dllexport) __cdecl SetNumberOfViews(
532 int number_of_views) { 561 int number_of_views) {
533 SetIntegerValue(g_num_of_views_offset, number_of_views); 562 SetIntegerValue(g_num_of_views_offset, number_of_views);
534 } 563 }
535 564
536 } // namespace 565 } // namespace
537 566
567 namespace testing {
568
569 // Access to namespace protected functions for testing purposes.
570 void InitCustomInfoEntries() {
571 GetCustomInfo(L"", L"", L"");
572 }
573
574 } // namespace testing
575
538 bool WrapMessageBoxWithSEH(const wchar_t* text, const wchar_t* caption, 576 bool WrapMessageBoxWithSEH(const wchar_t* text, const wchar_t* caption,
539 UINT flags, bool* exit_now) { 577 UINT flags, bool* exit_now) {
540 // We wrap the call to MessageBoxW with a SEH handler because it some 578 // We wrap the call to MessageBoxW with a SEH handler because it some
541 // machines with CursorXP, PeaDict or with FontExplorer installed it crashes 579 // machines with CursorXP, PeaDict or with FontExplorer installed it crashes
542 // uncontrollably here. Being this a best effort deal we better go away. 580 // uncontrollably here. Being this a best effort deal we better go away.
543 __try { 581 __try {
544 *exit_now = (IDOK != ::MessageBoxW(NULL, text, caption, flags)); 582 *exit_now = (IDOK != ::MessageBoxW(NULL, text, caption, flags));
545 } __except(EXCEPTION_EXECUTE_HANDLER) { 583 } __except(EXCEPTION_EXECUTE_HANDLER) {
546 // Its not safe to continue executing, exit silently here. 584 // Its not safe to continue executing, exit silently here.
547 ::TerminateProcess(::GetCurrentProcess(), 585 ::TerminateProcess(::GetCurrentProcess(),
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after
778 // Tells breakpad to handle breakpoint and single step exceptions. 816 // Tells breakpad to handle breakpoint and single step exceptions.
779 // This might break JIT debuggers, but at least it will always 817 // This might break JIT debuggers, but at least it will always
780 // generate a crashdump for these exceptions. 818 // generate a crashdump for these exceptions.
781 g_breakpad->set_handle_debug_exceptions(true); 819 g_breakpad->set_handle_debug_exceptions(true);
782 } 820 }
783 } 821 }
784 822
785 void InitDefaultCrashCallback(LPTOP_LEVEL_EXCEPTION_FILTER filter) { 823 void InitDefaultCrashCallback(LPTOP_LEVEL_EXCEPTION_FILTER filter) {
786 previous_filter = SetUnhandledExceptionFilter(filter); 824 previous_filter = SetUnhandledExceptionFilter(filter);
787 } 825 }
OLDNEW
« no previous file with comments | « chrome/app/breakpad_win.h ('k') | chrome/app/run_all_unittests.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698