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 #include "base/command_line.h"
      8 #include "base/format_macros.h"
      9 #include "base/strings/string_number_conversions.h"
     10 #include "base/strings/string_split.h"
     11 #include "base/strings/string_util.h"
     12 #include "base/strings/utf_string_conversions.h"
     13 #include "chrome/common/metrics/variations/variations_util.h"
     14 #include "chrome/installer/util/google_update_settings.h"
     15 #include "gpu/config/gpu_info.h"
     16 #include "url/gurl.h"
     17 
     18 namespace child_process_logging {
     19 
     20 // Account for the terminating null character.
     21 static const size_t kMaxActiveURLSize = 1024 + 1;
     22 static const size_t kClientIdSize = 32 + 1;
     23 static const size_t kChannelSize = 32;
     24 
     25 // We use static strings to hold the most recent active url and the client
     26 // identifier. If we crash, the crash handler code will send the contents of
     27 // these strings to the browser.
     28 char g_active_url[kMaxActiveURLSize];
     29 char g_client_id[kClientIdSize];
     30 
     31 char g_channel[kChannelSize] = "";
     32 
     33 static const size_t kGpuStringSize = 32;
     34 char g_gpu_vendor_id[kGpuStringSize] = "";
     35 char g_gpu_device_id[kGpuStringSize] = "";
     36 char g_gpu_gl_vendor[kGpuStringSize] = "";
     37 char g_gpu_gl_renderer[kGpuStringSize] = "";
     38 char g_gpu_driver_ver[kGpuStringSize] = "";
     39 char g_gpu_ps_ver[kGpuStringSize] = "";
     40 char g_gpu_vs_ver[kGpuStringSize] = "";
     41 
     42 char g_printer_info[kPrinterInfoStrLen * kMaxReportedPrinterRecords + 1] = "";
     43 
     44 static const size_t kNumSize = 32;
     45 char g_num_extensions[kNumSize] = "";
     46 char g_num_switches[kNumSize] = "";
     47 char g_num_variations[kNumSize] = "";
     48 char g_num_views[kNumSize] = "";
     49 
     50 static const size_t kMaxExtensionSize =
     51     kExtensionLen * kMaxReportedActiveExtensions + 1;
     52 char g_extension_ids[kMaxExtensionSize] = "";
     53 
     54 // Assume command line switches are less than 64 chars.
     55 static const size_t kMaxSwitchesSize = kSwitchLen * kMaxSwitches + 1;
     56 char g_switches[kMaxSwitchesSize] = "";
     57 
     58 static const size_t kMaxVariationChunksSize =
     59     kMaxVariationChunkSize * kMaxReportedVariationChunks + 1;
     60 char g_variation_chunks[kMaxVariationChunksSize] = "";
     61 
     62 void SetActiveURL(const GURL& url) {
     63   base::strlcpy(g_active_url, url.possibly_invalid_spec().c_str(),
     64                 arraysize(g_active_url));
     65 }
     66 
     67 void SetClientId(const std::string& client_id) {
     68   std::string str(client_id);
     69   ReplaceSubstringsAfterOffset(&str, 0, "-", std::string());
     70 
     71   if (str.empty())
     72     return;
     73 
     74   base::strlcpy(g_client_id, str.c_str(), kClientIdSize);
     75   std::wstring wstr = ASCIIToWide(str);
     76   GoogleUpdateSettings::SetMetricsId(wstr);
     77 }
     78 
     79 std::string GetClientId() {
     80   return std::string(g_client_id);
     81 }
     82 
     83 void SetActiveExtensions(const std::set<std::string>& extension_ids) {
     84   snprintf(g_num_extensions, arraysize(g_num_extensions), "%" PRIuS,
     85            extension_ids.size());
     86 
     87   std::string extension_str;
     88   std::set<std::string>::const_iterator iter = extension_ids.begin();
     89   for (size_t i = 0;
     90        i < kMaxReportedActiveExtensions && iter != extension_ids.end();
     91        ++i, ++iter) {
     92     extension_str += *iter;
     93   }
     94   base::strlcpy(g_extension_ids, extension_str.c_str(),
     95                 arraysize(g_extension_ids));
     96 }
     97 
     98 void SetGpuInfo(const gpu::GPUInfo& gpu_info) {
     99   snprintf(g_gpu_vendor_id, arraysize(g_gpu_vendor_id), "0x%04x",
    100            gpu_info.gpu.vendor_id);
    101   snprintf(g_gpu_device_id, arraysize(g_gpu_device_id), "0x%04x",
    102            gpu_info.gpu.device_id);
    103   base::strlcpy(g_gpu_gl_vendor, gpu_info.gl_vendor.c_str(),
    104                 arraysize(g_gpu_gl_vendor));
    105   base::strlcpy(g_gpu_gl_renderer, gpu_info.gl_renderer.c_str(),
    106                 arraysize(g_gpu_gl_renderer));
    107   base::strlcpy(g_gpu_driver_ver, gpu_info.driver_version.c_str(),
    108                 arraysize(g_gpu_driver_ver));
    109   base::strlcpy(g_gpu_ps_ver, gpu_info.pixel_shader_version.c_str(),
    110                 arraysize(g_gpu_ps_ver));
    111   base::strlcpy(g_gpu_vs_ver,  gpu_info.vertex_shader_version.c_str(),
    112                 arraysize(g_gpu_vs_ver));
    113 }
    114 
    115 void SetPrinterInfo(const char* printer_info) {
    116   std::string printer_info_str;
    117   std::vector<std::string> info;
    118   base::SplitString(printer_info, L';', &info);
    119   DCHECK_LE(info.size(), kMaxReportedPrinterRecords);
    120   for (size_t i = 0; i < info.size(); ++i) {
    121     printer_info_str += info[i];
    122     // Truncate long switches, align short ones with spaces to be trimmed later.
    123     printer_info_str.resize((i + 1) * kPrinterInfoStrLen, ' ');
    124   }
    125   base::strlcpy(g_printer_info, printer_info_str.c_str(),
    126                 arraysize(g_printer_info));
    127 }
    128 
    129 void SetNumberOfViews(int number_of_views) {
    130   snprintf(g_num_views, arraysize(g_num_views), "%d", number_of_views);
    131 }
    132 
    133 void SetCommandLine(const CommandLine* command_line) {
    134   const CommandLine::StringVector& argv = command_line->argv();
    135 
    136   snprintf(g_num_switches, arraysize(g_num_switches), "%" PRIuS,
    137            argv.size() - 1);
    138 
    139   std::string command_line_str;
    140   for (size_t argv_i = 1;
    141        argv_i < argv.size() && argv_i <= kMaxSwitches;
    142        ++argv_i) {
    143     command_line_str += argv[argv_i];
    144     // Truncate long switches, align short ones with spaces to be trimmed later.
    145     command_line_str.resize(argv_i * kSwitchLen, ' ');
    146   }
    147   base::strlcpy(g_switches, command_line_str.c_str(), arraysize(g_switches));
    148 }
    149 
    150 void SetExperimentList(const std::vector<string16>& experiments) {
    151   std::vector<string16> chunks;
    152   chrome_variations::GenerateVariationChunks(experiments, &chunks);
    153 
    154   // Store up to |kMaxReportedVariationChunks| chunks.
    155   std::string chunks_str;
    156   const size_t number_of_chunks_to_report =
    157       std::min(chunks.size(), kMaxReportedVariationChunks);
    158   for (size_t i = 0; i < number_of_chunks_to_report; ++i) {
    159     chunks_str += UTF16ToUTF8(chunks[i]);
    160     // Align short chunks with spaces to be trimmed later.
    161     chunks_str.resize(i * kMaxVariationChunkSize, ' ');
    162   }
    163   base::strlcpy(g_variation_chunks, chunks_str.c_str(),
    164                 arraysize(g_variation_chunks));
    165 
    166   // Make note of the total number of experiments, which may be greater than
    167   // what was able to fit in |kMaxReportedVariationChunks|. This is useful when
    168   // correlating stability with the number of experiments running
    169   // simultaneously.
    170   snprintf(g_num_variations, arraysize(g_num_variations), "%" PRIuS,
    171            experiments.size());
    172 }
    173 
    174 void SetChannel(const std::string& channel) {
    175   base::strlcpy(g_channel, channel.c_str(), arraysize(g_channel));
    176 }
    177 
    178 }  // namespace child_process_logging
    179