blob: d7d96f34fc4205e3bf4054c0d0727ad6a94dc1e5 [file] [log] [blame]
// Copyright 2018 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/chrome_cleaner/crash/crash_keys.h"
#include "base/command_line.h"
#include "base/format_macros.h"
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/synchronization/lock.h"
#include "third_party/crashpad/crashpad/client/crashpad_info.h"
#include "third_party/crashpad/crashpad/client/simple_string_dictionary.h"
namespace chrome_cleaner {
namespace {
base::Lock& GetCrashKeyLock() {
static base::Lock* crash_key_lock = new base::Lock();
return *crash_key_lock;
}
crashpad::SimpleStringDictionary* GetCrashKeys() {
// TODO(crbug.com/870715): Use the new crash key API from
// https://cs.chromium.org/chromium/src/components/crash/core/common/crash_key.h
static crashpad::SimpleStringDictionary* crash_keys =
new crashpad::SimpleStringDictionary();
return crash_keys;
}
void SetCrashKeyInDictionary(crashpad::SimpleStringDictionary* crash_keys,
base::StringPiece key,
base::StringPiece value) {
if (crash_keys->GetValueForKey(key))
LOG(WARNING) << "Crash key \"" << key << "\" being overwritten";
else
DCHECK_LT(crash_keys->GetCount(), crash_keys->num_entries);
crash_keys->SetKeyValue(key, value);
}
} // namespace
void SetCrashKey(base::StringPiece key, base::StringPiece value) {
base::AutoLock lock(GetCrashKeyLock());
SetCrashKeyInDictionary(GetCrashKeys(), key, value);
}
void SetCrashKeysFromCommandLine() {
// Based on Chrome's crash_keys::SetSwitchesFromCommandLine.
static constexpr size_t kMaxArgs = 16;
static constexpr char kKeyFormat[] = "CommandLineArg-%02" PRIuS;
static constexpr char kSizeKey[] = "CommandLineSize";
base::AutoLock lock(GetCrashKeyLock());
crashpad::SimpleStringDictionary* crash_keys = GetCrashKeys();
// Make sure this was only called once.
DCHECK(!crash_keys->GetValueForKey(kSizeKey));
const base::CommandLine::StringVector& argv =
base::CommandLine::ForCurrentProcess()->argv();
// Record the true number of arguments in case there are too many to store.
SetCrashKeyInDictionary(crash_keys, kSizeKey,
base::NumberToString(argv.size()));
// Go through the argv, including the exec path in argv[0]. Stop if there are
// too many arguments to hold in crash keys.
for (size_t key_i = 0; key_i < argv.size() && key_i < kMaxArgs; ++key_i) {
SetCrashKeyInDictionary(crash_keys, base::StringPrintf(kKeyFormat, key_i),
base::WideToUTF8(argv[key_i]));
}
}
void UseCrashKeysToAnnotate(crashpad::CrashpadInfo* crashpad_info) {
crashpad_info->set_simple_annotations(GetCrashKeys());
}
} // namespace chrome_cleaner