blob: f3c5dd1ec78299d0ed6f59517bdc7b98d7b37f4b [file] [log] [blame]
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/installer/setup/installer_crash_reporting.h"
#include <iterator>
#include <memory>
#include <vector>
#include "base/command_line.h"
#include "base/debug/leak_annotations.h"
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
#include "base/version.h"
#include "base/win/registry.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/install_static/install_details.h"
#include "chrome/installer/setup/installer_crash_reporter_client.h"
#include "chrome/installer/setup/installer_state.h"
#include "chrome/installer/util/google_update_settings.h"
#include "components/crash/content/app/crashpad.h"
#include "components/crash/core/common/crash_key.h"
#include "components/crash/core/common/crash_keys.h"
namespace installer {
namespace {
const char* OperationToString(InstallerState::Operation operation) {
switch (operation) {
case InstallerState::SINGLE_INSTALL_OR_UPDATE:
return "single-install-or-update";
case InstallerState::UNINSTALL:
return "uninstall";
case InstallerState::UNINITIALIZED:
// Fall out of switch.
break;
}
NOTREACHED();
return "";
}
// Retrieve the SYSTEM version of TEMP. We do this instead of GetTempPath so
// that both elevated and SYSTEM runs share the same directory.
bool GetSystemTemp(base::FilePath* temp) {
base::win::RegKey reg_key(
HKEY_LOCAL_MACHINE,
L"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment",
KEY_READ);
std::wstring temp_wstring; // presubmit: allow wstring
bool success = reg_key.ReadValue(L"TEMP", &temp_wstring) == ERROR_SUCCESS;
if (success)
*temp = base::FilePath(temp_wstring); // presubmit: allow wstring
return success;
}
} // namespace
void ConfigureCrashReporting(const InstallerState& installer_state) {
// This is inspired by work done in various parts of Chrome startup to connect
// to the crash service. Since the installer does not split its work between
// a stub .exe and a main .dll, crash reporting can be configured in one place
// right here.
// Create the crash client and install it (a la MainDllLoader::Launch).
InstallerCrashReporterClient* crash_client =
new InstallerCrashReporterClient(!installer_state.system_install());
ANNOTATE_LEAKING_OBJECT_PTR(crash_client);
crash_reporter::SetCrashReporterClient(crash_client);
if (installer_state.system_install()) {
base::FilePath temp_dir;
if (GetSystemTemp(&temp_dir)) {
base::FilePath crash_dir = temp_dir.Append(FILE_PATH_LITERAL("Crashpad"));
base::PathService::OverrideAndCreateIfNeeded(chrome::DIR_CRASH_DUMPS,
crash_dir, true, true);
} else {
// Failed to get a temp dir, something's gone wrong.
return;
}
}
crash_reporter::InitializeCrashpadWithEmbeddedHandler(
true, "Chrome Installer", "", base::FilePath());
// Set up the metrics client id (a la child_process_logging::Init()).
std::unique_ptr<metrics::ClientInfo> client_info =
GoogleUpdateSettings::LoadMetricsClientInfo();
if (client_info)
crash_keys::SetMetricsClientIdFromGUID(client_info->client_id);
}
void SetInitialCrashKeys(const InstallerState& state) {
using crash_reporter::CrashKeyString;
static CrashKeyString<64> operation("operation");
operation.Set(OperationToString(state.operation()));
static CrashKeyString<6> is_system_level("system-level");
is_system_level.Set(state.system_install() ? "true" : "false");
// This is a Windows registry key, which maxes out at 255 chars.
static CrashKeyString<256> state_crash_key("state-key");
const base::string16 state_key = state.state_key();
if (!state_key.empty())
state_crash_key.Set(base::UTF16ToUTF8(state_key));
// Set crash keys containing the registry values used to determine Chrome's
// update channel at process startup; see https://crbug.com/579504.
const auto& details = install_static::InstallDetails::Get();
static CrashKeyString<50> ap_value("ap");
ap_value.Set(base::UTF16ToUTF8(details.update_ap()));
static CrashKeyString<32> update_cohort_name("cohort-name");
update_cohort_name.Set(base::UTF16ToUTF8(details.update_cohort_name()));
}
void SetCrashKeysFromCommandLine(const base::CommandLine& command_line) {
crash_keys::SetSwitchesFromCommandLine(command_line, nullptr);
}
void SetCurrentVersionCrashKey(const base::Version* current_version) {
static crash_reporter::CrashKeyString<32> version_key("current-version");
if (current_version)
version_key.Set(current_version->GetString());
else
version_key.Clear();
}
} // namespace installer