File: chrome_crash_reporter_client_win.cc

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (215 lines) | stat: -rw-r--r-- 7,871 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// TODO(ananta/scottmg)
// Add test coverage for Crashpad.
#include "chrome/app/chrome_crash_reporter_client_win.h"

#include <windows.h>

#include <assert.h>
#include <shellapi.h>

#include <iterator>
#include <memory>
#include <string>
#include <vector>

#include "base/command_line.h"
#include "base/debug/leak_annotations.h"
#include "base/files/file_path.h"
#include "base/format_macros.h"
#include "base/notreached.h"
#include "base/rand_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/win/current_module.h"
#include "chrome/chrome_elf/chrome_elf_constants.h"
#include "chrome/common/chrome_result_codes.h"
#include "chrome/install_static/install_util.h"
#include "chrome/install_static/user_data_dir.h"
#include "components/crash/core/app/crashpad.h"
#include "components/version_info/channel.h"

ChromeCrashReporterClient::ChromeCrashReporterClient() = default;

ChromeCrashReporterClient::~ChromeCrashReporterClient() = default;

// static
void ChromeCrashReporterClient::InitializeCrashReportingForProcess() {
  static ChromeCrashReporterClient* instance = nullptr;
  if (instance) {
    return;
  }

  instance = new ChromeCrashReporterClient();
  ANNOTATE_LEAKING_OBJECT_PTR(instance);

  std::wstring process_type = install_static::GetCommandLineSwitchValue(
      ::GetCommandLine(), install_static::kProcessType);

  // Don't set up Crashpad crash reporting in the Crashpad handler itself, nor
  // in the fallback crash handler for the Crashpad handler process.
  if (process_type != install_static::kCrashpadHandler &&
      process_type != install_static::kFallbackHandler) {
    crash_reporter::SetCrashReporterClient(instance);

    std::wstring user_data_dir;
    if (process_type.empty()) {
      install_static::GetUserDataDirectory(&user_data_dir, nullptr);
    }

    // TODO(wfh): Add a DCHECK for success. See https://crbug.com/1329269.
    std::ignore = crash_reporter::InitializeCrashpadWithEmbeddedHandler(
        /*initial_client=*/process_type.empty(),
        install_static::WideToUTF8(process_type),
        install_static::WideToUTF8(user_data_dir), base::FilePath());
  }
}

bool ChromeCrashReporterClient::GetAlternativeCrashDumpLocation(
    std::wstring* crash_dir) {
  // By setting the BREAKPAD_DUMP_LOCATION environment variable, an alternate
  // location to write breakpad crash dumps can be set.
  *crash_dir = install_static::GetEnvironmentString(L"BREAKPAD_DUMP_LOCATION");
  return !crash_dir->empty();
}

void ChromeCrashReporterClient::GetProductNameAndVersion(
    const std::wstring& exe_path,
    std::wstring* product_name,
    std::wstring* version,
    std::wstring* special_build,
    std::wstring* channel_name) {
  assert(product_name);
  assert(version);
  assert(special_build);
  assert(channel_name);

  install_static::GetExecutableVersionDetails(exe_path, product_name, version,
                                              special_build, channel_name);
}

void ChromeCrashReporterClient::GetProductInfo(ProductInfo* product_info) {
  std::wstring product_name, version, special_build, channel_name;
  wchar_t exe_file[MAX_PATH] = {};
  CHECK(::GetModuleFileName(nullptr, exe_file, std::size(exe_file)));
  GetProductNameAndVersion(exe_file, &product_name, &version, &special_build,
                           &channel_name);
  product_info->product_name = base::WideToUTF8(product_name);
  product_info->version = base::WideToUTF8(version);
  product_info->channel = base::WideToUTF8(channel_name);
}

bool ChromeCrashReporterClient::GetShouldDumpLargerDumps() {
  // Capture larger dumps for Google Chrome beta, dev, and canary channels, and
  // Chromium builds. The Google Chrome stable channel uses smaller dumps.
  return install_static::GetChromeChannel() != version_info::Channel::STABLE;
}

bool ChromeCrashReporterClient::ReportingIsEnforcedByPolicy(
    bool* crashpad_enabled) {
  // Determine whether configuration management allows loading the crash
  // reporter.
  // Since the configuration management infrastructure is not initialized at
  // this point, we read the corresponding registry key directly. The return
  // status indicates whether policy data was successfully read. If it is true,
  // |breakpad_enabled| contains the value set by policy.
  return install_static::ReportingIsEnforcedByPolicy(crashpad_enabled);
}

bool ChromeCrashReporterClient::GetCrashDumpLocation(std::wstring* crash_dir) {
  // By setting the BREAKPAD_DUMP_LOCATION environment variable, an alternate
  // location to write breakpad crash dumps can be set.
  // If this environment variable exists, then for the time being,
  // short-circuit how it's handled on Windows. Honoring this
  // variable is required in order to symbolize stack traces in
  // Telemetry based tests: http://crbug.com/561763.
  if (GetAlternativeCrashDumpLocation(crash_dir)) {
    return true;
  }

  *crash_dir = install_static::GetCrashDumpLocation();
  return !crash_dir->empty();
}

bool ChromeCrashReporterClient::GetCrashMetricsLocation(
    std::wstring* metrics_dir) {
  if (!GetCollectStatsConsent()) {
    return false;
  }
  install_static::GetUserDataDirectory(metrics_dir, nullptr);
  return !metrics_dir->empty();
}

bool ChromeCrashReporterClient::IsRunningUnattended() {
  return install_static::HasEnvironmentVariable(install_static::kHeadless);
}

bool ChromeCrashReporterClient::GetCollectStatsConsent() {
  return install_static::GetCollectStatsConsent();
}

bool ChromeCrashReporterClient::GetCollectStatsInSample() {
  return install_static::GetCollectStatsInSample();
}

bool ChromeCrashReporterClient::ShouldMonitorCrashHandlerExpensively() {
  // The expensive mechanism dedicates a process to be crashpad_handler's own
  // crashpad_handler. In Google Chrome, scale back on this in the more stable
  // channels. There's a fallback crash handler that can catch crashes when this
  // expensive mechanism isn't used, although the fallback crash handler has
  // different characteristics so it's desirable to use the expensive mechanism
  // at least some of the time.
  double probability;
  switch (install_static::GetChromeChannel()) {
    case version_info::Channel::STABLE:
      return false;

    case version_info::Channel::BETA:
      probability = 0.1;
      break;

    case version_info::Channel::DEV:
      probability = 0.25;
      break;

    default:
      probability = 0.5;
      break;
  }

  return base::RandDouble() < probability;
}

bool ChromeCrashReporterClient::EnableBreakpadForProcess(
    const std::string& process_type) {
  // This is not used by Crashpad (at least on Windows).
  NOTREACHED();
}

std::wstring ChromeCrashReporterClient::GetWerRuntimeExceptionModule() {
  // We require that chrome_wer.dll is installed next to chrome_elf.dll. This
  // approach means we don't need to check for the dll's existence on disk early
  // in the process lifetime - we never load this dll ourselves - it is only
  // loaded by WerFault.exe after certain crashes. We do not use base::FilePath
  // and friends as chrome_elf will eventually not depend on //base.

  wchar_t elf_file[MAX_PATH];
  DWORD len = GetModuleFileName(CURRENT_MODULE(), elf_file, MAX_PATH);
  // On error return an empty path to indicate than a module is not to be
  // registered. This is harmless.
  if (len == 0 || len == MAX_PATH) {
    return std::wstring();
  }

  wchar_t elf_dir[MAX_PATH];
  wchar_t* file_start = nullptr;
  DWORD dir_len = GetFullPathName(elf_file, MAX_PATH, elf_dir, &file_start);
  if (dir_len == 0 || dir_len > len || !file_start) {
    return std::wstring();
  }

  // file_start points to the start of the filename in the elf_dir buffer.
  return std::wstring(elf_dir, file_start).append(kWerDll);
}