| // 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 |