This source file includes following definitions.
- RegisterChromeCrashKeys
- SetClientID
- IsBoringSwitch
- SetSwitchesFromCommandLine
- SetVariationsList
- SetActiveExtensions
#include "chrome/common/crash_keys.h"
#include "base/command_line.h"
#include "base/format_macros.h"
#include "base/logging.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 "chrome/installer/util/google_update_settings.h"
#if defined(OS_MACOSX)
#include "breakpad/src/common/simple_string_dictionary.h"
#elif defined(OS_WIN)
#include "breakpad/src/client/windows/common/ipc_protocol.h"
#endif
namespace crash_keys {
const size_t kSmallSize = 63;
const size_t kMediumSize = kSmallSize * 4;
const size_t kLargeSize = kSmallSize * 16;
#if defined(OS_MACOSX)
static const size_t kSingleChunkLength =
google_breakpad::SimpleStringDictionary::value_size - 1;
#elif defined(OS_WIN)
static const size_t kSingleChunkLength =
google_breakpad::CustomInfoEntry::kValueMaxLength - 1;
#else
static const size_t kSingleChunkLength = 63;
#endif
COMPILE_ASSERT(kSmallSize <= kSingleChunkLength,
crash_key_chunk_size_too_small);
#if defined(OS_MACOSX)
COMPILE_ASSERT(kMediumSize <= kSingleChunkLength,
mac_has_medium_size_crash_key_chunks);
#endif
const char kClientID[] = "guid";
const char kChannel[] = "channel";
const char kActiveURL[] = "url-chunk";
const char kSwitch[] = "switch-%" PRIuS;
const char kNumSwitches[] = "num-switches";
const char kNumVariations[] = "num-experiments";
const char kVariations[] = "variations";
const char kExtensionID[] = "extension-%" PRIuS;
const char kNumExtensionsCount[] = "num-extensions";
const char kNumberOfViews[] = "num-views";
const char kShutdownType[] = "shutdown-type";
#if !defined(OS_ANDROID)
const char kGPUVendorID[] = "gpu-venid";
const char kGPUDeviceID[] = "gpu-devid";
#endif
const char kGPUDriverVersion[] = "gpu-driver";
const char kGPUPixelShaderVersion[] = "gpu-psver";
const char kGPUVertexShaderVersion[] = "gpu-vsver";
#if defined(OS_MACOSX)
const char kGPUGLVersion[] = "gpu-glver";
#elif defined(OS_POSIX)
const char kGPUVendor[] = "gpu-gl-vendor";
const char kGPURenderer[] = "gpu-gl-renderer";
#endif
const char kPrinterInfo[] = "prn-info-%" PRIuS;
#if defined(OS_CHROMEOS)
const char kNumberOfUsers[] = "num-users";
#endif
#if defined(OS_MACOSX)
namespace mac {
const char kFirstNSException[] = "firstexception";
const char kFirstNSExceptionTrace[] = "firstexception_bt";
const char kLastNSException[] = "lastexception";
const char kLastNSExceptionTrace[] = "lastexception_bt";
const char kNSException[] = "nsexception";
const char kNSExceptionTrace[] = "nsexception_bt";
const char kSendAction[] = "sendaction";
const char kZombie[] = "zombie";
const char kZombieTrace[] = "zombie_dealloc_bt";
}
#endif
size_t RegisterChromeCrashKeys() {
base::debug::CrashKey fixed_keys[] = {
{ kClientID, kSmallSize },
{ kChannel, kSmallSize },
{ kActiveURL, kLargeSize },
{ kNumSwitches, kSmallSize },
{ kNumVariations, kSmallSize },
{ kVariations, kLargeSize },
{ kNumExtensionsCount, kSmallSize },
{ kNumberOfViews, kSmallSize },
{ kShutdownType, kSmallSize },
#if !defined(OS_ANDROID)
{ kGPUVendorID, kSmallSize },
{ kGPUDeviceID, kSmallSize },
#endif
{ kGPUDriverVersion, kSmallSize },
{ kGPUPixelShaderVersion, kSmallSize },
{ kGPUVertexShaderVersion, kSmallSize },
#if defined(OS_MACOSX)
{ kGPUGLVersion, kSmallSize },
#elif defined(OS_POSIX)
{ kGPUVendor, kSmallSize },
{ kGPURenderer, kSmallSize },
#endif
{ "ppapi_path", kMediumSize },
{ "subresource_url", kLargeSize },
#if defined(OS_CHROMEOS)
{ kNumberOfUsers, kSmallSize },
#endif
#if defined(OS_MACOSX)
{ mac::kFirstNSException, kMediumSize },
{ mac::kFirstNSExceptionTrace, kMediumSize },
{ mac::kLastNSException, kMediumSize },
{ mac::kLastNSExceptionTrace, kMediumSize },
{ mac::kNSException, kMediumSize },
{ mac::kNSExceptionTrace, kMediumSize },
{ mac::kSendAction, kMediumSize },
{ mac::kZombie, kMediumSize },
{ mac::kZombieTrace, kMediumSize },
{ "channel_error_bt", kMediumSize },
{ "remove_route_bt", kMediumSize },
{ "rwhvm_window", kMediumSize },
{ "VideoCaptureDeviceQTKit", kSmallSize },
#endif
};
std::vector<base::debug::CrashKey> keys(
fixed_keys, fixed_keys + arraysize(fixed_keys));
{
static char formatted_keys[kSwitchesMaxCount][sizeof(kSwitch) + 1] =
{{ 0 }};
const size_t formatted_key_len = sizeof(formatted_keys[0]);
for (size_t i = 0; i < kSwitchesMaxCount; ++i) {
int n = base::snprintf(
formatted_keys[i], formatted_key_len, kSwitch, i + 1);
DCHECK_GT(n, 0);
base::debug::CrashKey crash_key = { formatted_keys[i], kSmallSize };
keys.push_back(crash_key);
}
}
{
static char formatted_keys[kExtensionIDMaxCount][sizeof(kExtensionID) + 1] =
{{ 0 }};
const size_t formatted_key_len = sizeof(formatted_keys[0]);
for (size_t i = 0; i < kExtensionIDMaxCount; ++i) {
int n = base::snprintf(
formatted_keys[i], formatted_key_len, kExtensionID, i + 1);
DCHECK_GT(n, 0);
base::debug::CrashKey crash_key = { formatted_keys[i], kSmallSize };
keys.push_back(crash_key);
}
}
{
static char formatted_keys[kPrinterInfoCount][sizeof(kPrinterInfo) + 1] =
{{ 0 }};
const size_t formatted_key_len = sizeof(formatted_keys[0]);
for (size_t i = 0; i < kPrinterInfoCount; ++i) {
int n = base::snprintf(
formatted_keys[i], formatted_key_len, kPrinterInfo, i + 1);
DCHECK_GT(n, 0);
base::debug::CrashKey crash_key = { formatted_keys[i], kSmallSize };
keys.push_back(crash_key);
}
}
return base::debug::InitCrashKeys(&keys.at(0), keys.size(),
kSingleChunkLength);
}
void SetClientID(const std::string& client_id) {
std::string guid(client_id);
ReplaceSubstringsAfterOffset(&guid, 0, "-", "");
if (guid.empty())
return;
base::debug::SetCrashKeyValue(kClientID, guid);
GoogleUpdateSettings::SetMetricsId(guid);
}
static bool IsBoringSwitch(const std::string& flag) {
#if defined(OS_WIN)
return StartsWithASCII(flag, "--channel=", true) ||
StartsWithASCII(flag, "--type=", true) ||
StartsWithASCII(flag, "--flash-broker=", true) ||
StartsWithASCII(flag, "/prefetch:", true) ||
StartsWithASCII(flag, "--plugin-path=", true) ||
StartsWithASCII(flag, "--force-fieldtrials=", true) ||
flag == "--flag-switches-begin" ||
flag == "--flag-switches-end";
#else
return false;
#endif
}
void SetSwitchesFromCommandLine(const CommandLine* command_line) {
DCHECK(command_line);
if (!command_line)
return;
const CommandLine::StringVector& argv = command_line->argv();
base::debug::SetCrashKeyValue(kNumSwitches,
base::StringPrintf("%" PRIuS, argv.size() - 1));
size_t key_i = 1;
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
if (IsBoringSwitch(switch_str))
continue;
if (i > crash_keys::kSwitchesMaxCount)
break;
std::string key = base::StringPrintf(kSwitch, key_i++);
base::debug::SetCrashKeyValue(key, switch_str);
}
for (; key_i <= kSwitchesMaxCount; ++key_i) {
base::debug::ClearCrashKey(base::StringPrintf(kSwitch, key_i));
}
}
void SetVariationsList(const std::vector<std::string>& variations) {
base::debug::SetCrashKeyValue(kNumVariations,
base::StringPrintf("%" PRIuS, variations.size()));
std::string variations_string;
variations_string.reserve(kLargeSize);
for (size_t i = 0; i < variations.size(); ++i) {
const std::string& variation = variations[i];
if (variations_string.size() + variation.size() >= kLargeSize)
break;
variations_string += variation;
variations_string += ",";
}
base::debug::SetCrashKeyValue(kVariations, variations_string);
}
void SetActiveExtensions(const std::set<std::string>& extensions) {
base::debug::SetCrashKeyValue(kNumExtensionsCount,
base::StringPrintf("%" PRIuS, extensions.size()));
std::set<std::string>::const_iterator it = extensions.begin();
for (size_t i = 0; i < kExtensionIDMaxCount; ++i) {
std::string key = base::StringPrintf(kExtensionID, i + 1);
if (it == extensions.end()) {
base::debug::ClearCrashKey(key);
} else {
base::debug::SetCrashKeyValue(key, *it);
++it;
}
}
}
ScopedPrinterInfo::ScopedPrinterInfo(const base::StringPiece& data) {
std::vector<std::string> info;
base::SplitString(data.as_string(), ';', &info);
for (size_t i = 0; i < kPrinterInfoCount; ++i) {
std::string key = base::StringPrintf(kPrinterInfo, i + 1);
std::string value;
if (i < info.size())
value = info[i];
base::debug::SetCrashKeyValue(key, value);
}
}
ScopedPrinterInfo::~ScopedPrinterInfo() {
for (size_t i = 0; i < kPrinterInfoCount; ++i) {
std::string key = base::StringPrintf(kPrinterInfo, i + 1);
base::debug::ClearCrashKey(key);
}
}
}