Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / app / kasko_client.cc
blobf9699e9073cc0ae3631eb3db4bf1d116b2e177e9
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #if defined(KASKO)
7 #include "chrome/app/kasko_client.h"
9 #include <windows.h>
11 #include <string>
12 #include <vector>
14 #include "base/logging.h"
15 #include "base/process/process_handle.h"
16 #include "breakpad/src/client/windows/common/ipc_protocol.h"
17 #include "chrome/app/chrome_watcher_client_win.h"
18 #include "chrome/chrome_watcher/chrome_watcher_main_api.h"
19 #include "chrome/common/chrome_constants.h"
20 #include "components/crash/content/app/crash_keys_win.h"
21 #include "syzygy/kasko/api/client.h"
23 namespace {
25 ChromeWatcherClient* g_chrome_watcher_client = nullptr;
26 kasko::api::MinidumpType g_minidump_type = kasko::api::SMALL_DUMP_TYPE;
28 void GetKaskoCrashKeys(const kasko::api::CrashKey** crash_keys,
29 size_t* crash_key_count) {
30 static_assert(
31 sizeof(kasko::api::CrashKey) == sizeof(google_breakpad::CustomInfoEntry),
32 "CrashKey and CustomInfoEntry structs are not compatible.");
33 static_assert(offsetof(kasko::api::CrashKey, name) ==
34 offsetof(google_breakpad::CustomInfoEntry, name),
35 "CrashKey and CustomInfoEntry structs are not compatible.");
36 static_assert(offsetof(kasko::api::CrashKey, value) ==
37 offsetof(google_breakpad::CustomInfoEntry, value),
38 "CrashKey and CustomInfoEntry structs are not compatible.");
39 static_assert(
40 sizeof(reinterpret_cast<kasko::api::CrashKey*>(0)->name) ==
41 sizeof(reinterpret_cast<google_breakpad::CustomInfoEntry*>(0)->name),
42 "CrashKey and CustomInfoEntry structs are not compatible.");
43 static_assert(
44 sizeof(reinterpret_cast<kasko::api::CrashKey*>(0)->value) ==
45 sizeof(reinterpret_cast<google_breakpad::CustomInfoEntry*>(0)->value),
46 "CrashKey and CustomInfoEntry structs are not compatible.");
48 *crash_key_count =
49 breakpad::CrashKeysWin::keeper()->custom_info_entries().size();
50 *crash_keys = reinterpret_cast<const kasko::api::CrashKey*>(
51 breakpad::CrashKeysWin::keeper()->custom_info_entries().data());
54 } // namespace
56 KaskoClient::KaskoClient(ChromeWatcherClient* chrome_watcher_client,
57 kasko::api::MinidumpType minidump_type) {
58 DCHECK(!g_chrome_watcher_client);
59 g_minidump_type = minidump_type;
60 g_chrome_watcher_client = chrome_watcher_client;
62 kasko::api::InitializeClient(
63 GetKaskoEndpoint(base::GetCurrentProcId()).c_str());
65 // Register the crash keys so that they will be available whether a crash
66 // report is triggered directly by the browser process or requested by the
67 // Chrome Watcher process.
68 size_t crash_key_count = 0;
69 const kasko::api::CrashKey* crash_keys = nullptr;
70 GetKaskoCrashKeys(&crash_keys, &crash_key_count);
71 kasko::api::RegisterCrashKeys(crash_keys, crash_key_count);
74 KaskoClient::~KaskoClient() {
75 DCHECK(g_chrome_watcher_client);
76 g_chrome_watcher_client = nullptr;
77 kasko::api::ShutdownClient();
80 // Sends a diagnostic report for the current process, then terminates it.
81 // |info| is an optional exception record describing an exception on the current
82 // thread.
83 // |protobuf| is an optional buffer of length |protobuf_length|.
84 // |base_addresses| and |lengths| are optional null-terminated arrays of the
85 // same length. For each entry in |base_addresses|, a memory range starting at
86 // the specified address and having the length specified in the corresponding
87 // entry in |lengths| will be explicitly included in the report.
88 extern "C" void __declspec(dllexport)
89 ReportCrashWithProtobufAndMemoryRanges(EXCEPTION_POINTERS* info,
90 const char* protobuf,
91 size_t protobuf_length,
92 const void* const* base_addresses,
93 const size_t* lengths) {
94 if (g_chrome_watcher_client && g_chrome_watcher_client->EnsureInitialized()) {
95 size_t crash_key_count = 0;
96 const kasko::api::CrashKey* crash_keys = nullptr;
97 GetKaskoCrashKeys(&crash_keys, &crash_key_count);
98 std::vector<kasko::api::MemoryRange> memory_ranges;
99 if (base_addresses && lengths) {
100 for (int i = 0; base_addresses[i] != nullptr && lengths[i] != 0; ++i) {
101 kasko::api::MemoryRange memory_range = {base_addresses[i], lengths[i]};
102 memory_ranges.push_back(memory_range);
105 kasko::api::SendReport(info, g_minidump_type, protobuf, protobuf_length,
106 crash_keys, crash_key_count,
107 memory_ranges.size() ? &memory_ranges[0] : nullptr,
108 memory_ranges.size());
111 // The Breakpad integration hooks TerminateProcess. Sidestep it to avoid a
112 // secondary report.
114 using TerminateProcessWithoutDumpProc = void(__cdecl*)();
115 TerminateProcessWithoutDumpProc terminate_process_without_dump =
116 reinterpret_cast<TerminateProcessWithoutDumpProc>(::GetProcAddress(
117 ::GetModuleHandle(chrome::kBrowserProcessExecutableName),
118 "TerminateProcessWithoutDump"));
119 CHECK(terminate_process_without_dump);
120 terminate_process_without_dump();
123 extern "C" void __declspec(dllexport) ReportCrashWithProtobuf(
124 EXCEPTION_POINTERS* info, const char* protobuf, size_t protobuf_length) {
125 ReportCrashWithProtobufAndMemoryRanges(info, protobuf, protobuf_length,
126 nullptr, nullptr);
129 #endif // defined(KASKO)