// Copyright (c) 2011 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/common/child_process_logging.h" #import <Foundation/Foundation.h> #include "base/string_number_conversions.h" #include "base/string_util.h" #include "base/stringprintf.h" #include "base/utf_string_conversions.h" #include "chrome/installer/util/google_update_settings.h" #include "content/common/gpu/gpu_info.h" #include "googleurl/src/gurl.h" namespace child_process_logging { const int kMaxNumCrashURLChunks = 8; const int kMaxNumURLChunkValueLength = 255; const char *kUrlChunkFormatStr = "url-chunk-%d"; const char *kGuidParamName = "guid"; const char *kGPUVendorIdParamName = "gpu-vendid"; const char *kGPUDeviceIdParamName = "gpu-devid"; const char *kGPUDriverVersionParamName = "gpu-driver"; const char *kGPUPixelShaderVersionParamName = "gpu-psver"; const char *kGPUVertexShaderVersionParamName = "gpu-vsver"; const char *kGPUGLVersionParamName = "gpu-glver"; const char *kNumberOfViews = "num-views"; NSString* const kNumExtensionsName = @"num-extensions"; NSString* const kExtensionNameFormat = @"extension-%d"; static SetCrashKeyValueFuncPtr g_set_key_func; static ClearCrashKeyValueFuncPtr g_clear_key_func; // Account for the terminating null character. static const size_t kClientIdSize = 32 + 1; static char g_client_id[kClientIdSize]; void SetCrashKeyFunctions(SetCrashKeyValueFuncPtr set_key_func, ClearCrashKeyValueFuncPtr clear_key_func) { g_set_key_func = set_key_func; g_clear_key_func = clear_key_func; } void SetActiveURLImpl(const GURL& url, SetCrashKeyValueFuncPtr set_key_func, ClearCrashKeyValueFuncPtr clear_key_func) { NSString *kUrlChunkFormatStr_utf8 = [NSString stringWithUTF8String:kUrlChunkFormatStr]; // First remove any old url chunks we might have lying around. for (int i = 0; i < kMaxNumCrashURLChunks; i++) { // On Windows the url-chunk items are 1-based, so match that. NSString *key = [NSString stringWithFormat:kUrlChunkFormatStr_utf8, i+1]; clear_key_func(key); } const std::string& raw_url_utf8 = url.possibly_invalid_spec(); NSString *raw_url = [NSString stringWithUTF8String:raw_url_utf8.c_str()]; size_t raw_url_length = [raw_url length]; // Bail on zero-length URLs. if (raw_url_length == 0) { return; } // Parcel the URL up into up to 8, 255 byte segments. size_t start_ofs = 0; for (int i = 0; i < kMaxNumCrashURLChunks && start_ofs < raw_url_length; ++i) { // On Windows the url-chunk items are 1-based, so match that. NSString *key = [NSString stringWithFormat:kUrlChunkFormatStr_utf8, i+1]; NSRange range; range.location = start_ofs; range.length = std::min((size_t)kMaxNumURLChunkValueLength, raw_url_length - start_ofs); NSString *value = [raw_url substringWithRange:range]; set_key_func(key, value); // Next chunk. start_ofs += kMaxNumURLChunkValueLength; } } void SetClientIdImpl(const std::string& client_id, SetCrashKeyValueFuncPtr set_key_func) { NSString *key = [NSString stringWithUTF8String:kGuidParamName]; NSString *value = [NSString stringWithUTF8String:client_id.c_str()]; set_key_func(key, value); } void SetActiveURL(const GURL& url) { if (g_set_key_func && g_clear_key_func) SetActiveURLImpl(url, g_set_key_func, g_clear_key_func); } void SetClientId(const std::string& client_id) { std::string str(client_id); ReplaceSubstringsAfterOffset(&str, 0, "-", ""); base::strlcpy(g_client_id, str.c_str(), kClientIdSize); if (g_set_key_func) SetClientIdImpl(str, g_set_key_func); std::wstring wstr = ASCIIToWide(str); GoogleUpdateSettings::SetMetricsId(wstr); } std::string GetClientId() { return std::string(g_client_id); } void SetActiveExtensions(const std::set<std::string>& extension_ids) { if (!g_set_key_func) return; // Log the count separately to track heavy users. const int count = static_cast<int>(extension_ids.size()); g_set_key_func(kNumExtensionsName, [NSString stringWithFormat:@"%i", count]); // Record up to |kMaxReportedActiveExtensions| extensions, clearing // keys if there aren't that many. std::set<std::string>::const_iterator iter = extension_ids.begin(); for (int i = 0; i < kMaxReportedActiveExtensions; ++i) { NSString* key = [NSString stringWithFormat:kExtensionNameFormat, i]; if (iter != extension_ids.end()) { g_set_key_func(key, [NSString stringWithUTF8String:iter->c_str()]); ++iter; } else { g_clear_key_func(key); } } } void SetGpuKeyValue(const char* param_name, const std::string& value_str, SetCrashKeyValueFuncPtr set_key_func) { NSString *key = [NSString stringWithUTF8String:param_name]; NSString *value = [NSString stringWithUTF8String:value_str.c_str()]; set_key_func(key, value); } void SetGpuInfoImpl(const GPUInfo& gpu_info, SetCrashKeyValueFuncPtr set_key_func) { SetGpuKeyValue(kGPUVendorIdParamName, base::StringPrintf("0x%04x", gpu_info.vendor_id), set_key_func); SetGpuKeyValue(kGPUDeviceIdParamName, base::StringPrintf("0x%04x", gpu_info.device_id), set_key_func); SetGpuKeyValue(kGPUDriverVersionParamName, gpu_info.driver_version, set_key_func); SetGpuKeyValue(kGPUPixelShaderVersionParamName, gpu_info.pixel_shader_version, set_key_func); SetGpuKeyValue(kGPUVertexShaderVersionParamName, gpu_info.vertex_shader_version, set_key_func); SetGpuKeyValue(kGPUGLVersionParamName, gpu_info.gl_version, set_key_func); } void SetGpuInfo(const GPUInfo& gpu_info) { if (g_set_key_func) SetGpuInfoImpl(gpu_info, g_set_key_func); } void SetNumberOfViewsImpl(int number_of_views, SetCrashKeyValueFuncPtr set_key_func) { NSString *key = [NSString stringWithUTF8String:kNumberOfViews]; NSString *value = [NSString stringWithFormat:@"%d", number_of_views]; set_key_func(key, value); } void SetNumberOfViews(int number_of_views) { if (g_set_key_func) SetNumberOfViewsImpl(number_of_views, g_set_key_func); } } // namespace child_process_logging