Home | History | Annotate | Download | only in common
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/common/child_process_logging.h"
      6 
      7 #import <Foundation/Foundation.h>
      8 
      9 #include "base/command_line.h"
     10 #include "base/strings/string_number_conversions.h"
     11 #include "base/strings/string_split.h"
     12 #include "base/strings/string_util.h"
     13 #include "base/strings/stringprintf.h"
     14 #include "base/strings/sys_string_conversions.h"
     15 #include "base/strings/utf_string_conversions.h"
     16 #include "chrome/common/metrics/variations/variations_util.h"
     17 #include "chrome/installer/util/google_update_settings.h"
     18 #include "gpu/config/gpu_info.h"
     19 #include "url/gurl.h"
     20 
     21 namespace child_process_logging {
     22 
     23 using base::debug::SetCrashKeyValueFuncT;
     24 using base::debug::ClearCrashKeyValueFuncT;
     25 using base::debug::SetCrashKeyValue;
     26 using base::debug::ClearCrashKey;
     27 
     28 const size_t kMaxNumCrashURLChunks = 8;
     29 const size_t kMaxNumURLChunkValueLength = 255;
     30 const char* kUrlChunkFormatStr = "url-chunk-%d";
     31 const char* kGuidParamName = "guid";
     32 const char* kGPUVendorIdParamName = "gpu-venid";
     33 const char* kGPUDeviceIdParamName = "gpu-devid";
     34 const char* kGPUDriverVersionParamName = "gpu-driver";
     35 const char* kGPUPixelShaderVersionParamName = "gpu-psver";
     36 const char* kGPUVertexShaderVersionParamName = "gpu-vsver";
     37 const char* kGPUGLVersionParamName = "gpu-glver";
     38 const char* kNumberOfViews = "num-views";
     39 const char* kNumExtensionsName = "num-extensions";
     40 const char* kExtensionNameFormat = "extension-%zu";
     41 const char* kPrinterInfoNameFormat = "prn-info-%zu";
     42 
     43 // Account for the terminating null character.
     44 static const size_t kClientIdSize = 32 + 1;
     45 static char g_client_id[kClientIdSize];
     46 
     47 void SetActiveURLImpl(const GURL& url,
     48                       SetCrashKeyValueFuncT set_key_func,
     49                       ClearCrashKeyValueFuncT clear_key_func) {
     50   // First remove any old url chunks we might have lying around.
     51   for (size_t i = 0; i < kMaxNumCrashURLChunks; i++) {
     52     // On Windows the url-chunk items are 1-based, so match that.
     53     clear_key_func(base::StringPrintf(kUrlChunkFormatStr, i + 1));
     54   }
     55 
     56   const std::string& raw_url = url.possibly_invalid_spec();
     57   size_t raw_url_length = raw_url.length();
     58 
     59   // Bail on zero-length URLs.
     60   if (raw_url_length == 0) {
     61     return;
     62   }
     63 
     64   // Parcel the URL up into up to 8, 255 byte segments.
     65   size_t offset = 0;
     66   for (size_t i = 0;
     67        i < kMaxNumCrashURLChunks && offset < raw_url_length;
     68        ++i) {
     69 
     70     // On Windows the url-chunk items are 1-based, so match that.
     71     std::string key = base::StringPrintf(kUrlChunkFormatStr, i + 1);
     72     size_t length = std::min(kMaxNumURLChunkValueLength,
     73                              raw_url_length - offset);
     74     std::string value = raw_url.substr(offset, length);
     75     set_key_func(key, value);
     76 
     77     // Next chunk.
     78     offset += kMaxNumURLChunkValueLength;
     79   }
     80 }
     81 
     82 void SetClientIdImpl(const std::string& client_id,
     83                      SetCrashKeyValueFuncT set_key_func) {
     84   set_key_func(kGuidParamName, client_id);
     85 }
     86 
     87 void SetActiveURL(const GURL& url) {
     88   SetActiveURLImpl(url, SetCrashKeyValue, ClearCrashKey);
     89 }
     90 
     91 void SetClientId(const std::string& client_id) {
     92   std::string str(client_id);
     93   ReplaceSubstringsAfterOffset(&str, 0, "-", "");
     94 
     95   base::strlcpy(g_client_id, str.c_str(), kClientIdSize);
     96     SetClientIdImpl(str, SetCrashKeyValue);
     97 
     98   std::wstring wstr = ASCIIToWide(str);
     99   GoogleUpdateSettings::SetMetricsId(wstr);
    100 }
    101 
    102 std::string GetClientId() {
    103   return std::string(g_client_id);
    104 }
    105 
    106 void SetActiveExtensions(const std::set<std::string>& extension_ids) {
    107   // Log the count separately to track heavy users.
    108   const int count = static_cast<int>(extension_ids.size());
    109   SetCrashKeyValue(kNumExtensionsName, base::IntToString(count));
    110 
    111   // Record up to |kMaxReportedActiveExtensions| extensions, clearing
    112   // keys if there aren't that many.
    113   std::set<std::string>::const_iterator iter = extension_ids.begin();
    114   for (size_t i = 0; i < kMaxReportedActiveExtensions; ++i) {
    115     std::string key = base::StringPrintf(kExtensionNameFormat, i);
    116     if (iter != extension_ids.end()) {
    117       SetCrashKeyValue(key, *iter);
    118       ++iter;
    119     } else {
    120       ClearCrashKey(key);
    121     }
    122   }
    123 }
    124 
    125 void SetGpuKeyValue(const char* param_name, const std::string& value_str,
    126                     SetCrashKeyValueFuncT set_key_func) {
    127   set_key_func(param_name, value_str);
    128 }
    129 
    130 void SetGpuInfoImpl(const gpu::GPUInfo& gpu_info,
    131                     SetCrashKeyValueFuncT set_key_func) {
    132   SetGpuKeyValue(kGPUVendorIdParamName,
    133                  base::StringPrintf("0x%04x", gpu_info.gpu.vendor_id),
    134                  set_key_func);
    135   SetGpuKeyValue(kGPUDeviceIdParamName,
    136                  base::StringPrintf("0x%04x", gpu_info.gpu.device_id),
    137                  set_key_func);
    138   SetGpuKeyValue(kGPUDriverVersionParamName,
    139                  gpu_info.driver_version,
    140                  set_key_func);
    141   SetGpuKeyValue(kGPUPixelShaderVersionParamName,
    142                  gpu_info.pixel_shader_version,
    143                  set_key_func);
    144   SetGpuKeyValue(kGPUVertexShaderVersionParamName,
    145                  gpu_info.vertex_shader_version,
    146                  set_key_func);
    147   SetGpuKeyValue(kGPUGLVersionParamName,
    148                  gpu_info.gl_version,
    149                  set_key_func);
    150 }
    151 
    152 void SetGpuInfo(const gpu::GPUInfo& gpu_info) {
    153   SetGpuInfoImpl(gpu_info, SetCrashKeyValue);
    154 }
    155 
    156 void SetPrinterInfo(const char* printer_info) {
    157   std::vector<std::string> info;
    158   base::SplitString(printer_info, ';', &info);
    159   info.resize(kMaxReportedPrinterRecords);
    160   for (size_t i = 0; i < info.size(); ++i) {
    161     std::string key = base::StringPrintf(kPrinterInfoNameFormat, i);
    162     if (!info[i].empty()) {
    163       SetCrashKeyValue(key, info[i]);
    164     } else {
    165       ClearCrashKey(key);
    166     }
    167   }
    168 }
    169 
    170 void SetNumberOfViewsImpl(int number_of_views,
    171                           SetCrashKeyValueFuncT set_key_func) {
    172   std::string value = base::IntToString(number_of_views);
    173   set_key_func(kNumberOfViews, value);
    174 }
    175 
    176 void SetNumberOfViews(int number_of_views) {
    177   SetNumberOfViewsImpl(number_of_views, SetCrashKeyValue);
    178 }
    179 
    180 void SetCommandLine(const CommandLine* command_line) {
    181   DCHECK(command_line);
    182   if (!command_line)
    183     return;
    184 
    185   // These should match the corresponding strings in breakpad_win.cc.
    186   const char* kNumSwitchesKey = "num-switches";
    187   const char* kSwitchKeyFormat = "switch-%zu";  // 1-based.
    188 
    189   // Note the total number of switches, not including the exec path.
    190   const CommandLine::StringVector& argv = command_line->argv();
    191   SetCrashKeyValue(kNumSwitchesKey,
    192                    base::StringPrintf("%zu", argv.size() - 1));
    193 
    194   size_t key_i = 0;
    195   for (size_t i = 1; i < argv.size() && key_i < kMaxSwitches; ++i, ++key_i) {
    196     // TODO(shess): Skip boring switches.
    197     std::string key = base::StringPrintf(kSwitchKeyFormat, key_i + 1);
    198     SetCrashKeyValue(key, argv[i]);
    199   }
    200 
    201   // Clear out any stale keys.
    202   for (; key_i < kMaxSwitches; ++key_i) {
    203     std::string key = base::StringPrintf(kSwitchKeyFormat, key_i + 1);
    204     ClearCrashKey(key);
    205   }
    206 }
    207 
    208 void SetExperimentList(const std::vector<string16>& experiments) {
    209   // These should match the corresponding strings in breakpad_win.cc.
    210   const char* kNumExperimentsKey = "num-experiments";
    211   const char* kExperimentChunkFormat = "experiment-chunk-%zu";  // 1-based
    212 
    213   std::vector<string16> chunks;
    214   chrome_variations::GenerateVariationChunks(experiments, &chunks);
    215 
    216   // Store up to |kMaxReportedVariationChunks| chunks.
    217   for (size_t i = 0; i < kMaxReportedVariationChunks; ++i) {
    218     std::string key = base::StringPrintf(kExperimentChunkFormat, i + 1);
    219     if (i < chunks.size()) {
    220       std::string value = UTF16ToUTF8(chunks[i]);
    221       SetCrashKeyValue(key, value);
    222     } else {
    223       ClearCrashKey(key);
    224     }
    225   }
    226 
    227   // Make note of the total number of experiments, which may be greater than
    228   // what was able to fit in |kMaxReportedVariationChunks|. This is useful when
    229   // correlating stability with the number of experiments running
    230   // simultaneously.
    231   SetCrashKeyValue(kNumExperimentsKey,
    232                    base::StringPrintf("%zu", experiments.size()));
    233 }
    234 
    235 void SetChannel(const std::string& channel) {
    236   // This should match the corresponding string in breakpad_win.cc.
    237   const std::string kChannelKey = "channel";
    238   SetCrashKeyValue(kChannelKey, channel);
    239 }
    240 
    241 }  // namespace child_process_logging
    242