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