blob: bbb0af7cb0518afc9923c8da9c2a27c7e28a002d [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 "components/crash/core/common/crash_keys.h"
#include <deque>
#include <vector>
#include "base/command_line.h"
#include "base/format_macros.h"
#include "base/no_destructor.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "components/crash/core/common/crash_key.h"
namespace crash_keys {
namespace {
#if defined(OS_MACOSX) || defined(OS_WIN)
// When using Crashpad, the crash reporting client ID is the responsibility of
// Crashpad. It is not set directly by Chrome. To make the metrics client ID
// available on the server, it's stored in a distinct key.
const char kMetricsClientId[] = "metrics_client_id";
#else
// When using Breakpad instead of Crashpad, the crash reporting client ID is the
// same as the metrics client ID.
const char kMetricsClientId[] = "guid";
#endif
crash_reporter::CrashKeyString<40> client_id_key(kMetricsClientId);
} // namespace
void SetMetricsClientIdFromGUID(const std::string& metrics_client_guid) {
std::string stripped_guid(metrics_client_guid);
// Remove all instance of '-' char from the GUID. So BCD-WXY becomes BCDWXY.
base::ReplaceSubstringsAfterOffset(
&stripped_guid, 0, "-", base::StringPiece());
if (stripped_guid.empty())
return;
client_id_key.Set(stripped_guid);
}
void ClearMetricsClientId() {
#if defined(OS_MACOSX) || defined(OS_WIN)
// Crashpad always monitors for crashes, but doesn't upload them when
// crash reporting is disabled. The preference to upload crash reports is
// linked to the preference for metrics reporting. When metrics reporting is
// disabled, don't put the metrics client ID into crash dumps. This way, crash
// reports that are saved but not uploaded will not have a metrics client ID
// from the time that metrics reporting was disabled even if they are uploaded
// by user action at a later date.
//
// Breakpad cannot be enabled or disabled without an application restart, and
// it needs to use the metrics client ID as its stable crash client ID, so
// leave its client ID intact even when metrics reporting is disabled while
// the application is running.
client_id_key.Clear();
#endif
}
using SwitchesCrashKeys = std::deque<crash_reporter::CrashKeyString<64>>;
SwitchesCrashKeys& GetSwitchesCrashKeys() {
static base::NoDestructor<SwitchesCrashKeys> switches_keys;
return *switches_keys;
}
static crash_reporter::CrashKeyString<4> num_switches_key("num-switches");
void SetSwitchesFromCommandLine(const base::CommandLine& command_line,
SwitchFilterFunction skip_filter) {
const base::CommandLine::StringVector& argv = command_line.argv();
// Set the number of switches in case of uninteresting switches in
// command_line.
num_switches_key.Set(base::NumberToString(argv.size() - 1));
size_t key_i = 0;
// Go through the argv, skipping the exec path. Stop if there are too many
// switches to hold in crash keys.
for (size_t i = 1; i < argv.size(); ++i) {
#if defined(OS_WIN)
std::string switch_str = base::WideToUTF8(argv[i]);
#else
std::string switch_str = argv[i];
#endif
// Skip uninteresting switches.
if (skip_filter && (*skip_filter)(switch_str))
continue;
if (key_i >= GetSwitchesCrashKeys().size()) {
static base::NoDestructor<std::deque<std::string>> crash_keys_names;
crash_keys_names->emplace_back(
base::StringPrintf("switch-%" PRIuS, key_i + 1));
GetSwitchesCrashKeys().emplace_back(crash_keys_names->back().c_str());
}
GetSwitchesCrashKeys()[key_i++].Set(switch_str);
}
// Clear any remaining switches.
for (; key_i < GetSwitchesCrashKeys().size(); ++key_i)
GetSwitchesCrashKeys()[key_i].Clear();
}
void ResetCommandLineForTesting() {
num_switches_key.Clear();
for (auto& key : GetSwitchesCrashKeys()) {
key.Clear();
}
}
using PrinterInfoKey = crash_reporter::CrashKeyString<64>;
static PrinterInfoKey printer_info_keys[] = {
{"prn-info-1", PrinterInfoKey::Tag::kArray},
{"prn-info-2", PrinterInfoKey::Tag::kArray},
{"prn-info-3", PrinterInfoKey::Tag::kArray},
{"prn-info-4", PrinterInfoKey::Tag::kArray},
};
ScopedPrinterInfo::ScopedPrinterInfo(base::StringPiece data) {
std::vector<base::StringPiece> info = base::SplitStringPiece(
data, ";", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
for (size_t i = 0; i < arraysize(printer_info_keys); ++i) {
if (i < info.size())
printer_info_keys[i].Set(info[i]);
else
printer_info_keys[i].Clear();
}
}
ScopedPrinterInfo::~ScopedPrinterInfo() {
for (auto& crash_key : printer_info_keys) {
crash_key.Clear();
}
}
} // namespace crash_keys