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 <windows.h> 8 9 #include "base/command_line.h" 10 #include "base/strings/string_number_conversions.h" 11 #include "base/strings/string_util.h" 12 #include "base/strings/stringprintf.h" 13 #include "base/strings/utf_string_conversions.h" 14 #include "chrome/common/chrome_constants.h" 15 #include "chrome/common/metrics/variations/variations_util.h" 16 #include "chrome/installer/util/google_update_settings.h" 17 #include "gpu/config/gpu_info.h" 18 #include "url/gurl.h" 19 20 namespace child_process_logging { 21 22 namespace { 23 24 // exported in breakpad_win.cc: void __declspec(dllexport) __cdecl SetActiveURL. 25 typedef void (__cdecl *MainSetActiveURL)(const wchar_t*); 26 27 // exported in breakpad_win.cc: void __declspec(dllexport) __cdecl SetClientId. 28 typedef void (__cdecl *MainSetClientId)(const wchar_t*); 29 30 // exported in breakpad_win.cc: 31 // void __declspec(dllexport) __cdecl SetNumberOfExtensions. 32 typedef void (__cdecl *MainSetNumberOfExtensions)(int); 33 34 // exported in breakpad_win.cc: 35 // void __declspec(dllexport) __cdecl SetExtensionID. 36 typedef void (__cdecl *MainSetExtensionID)(size_t, const wchar_t*); 37 38 // exported in breakpad_win.cc: void __declspec(dllexport) __cdecl SetGpuInfo. 39 typedef void (__cdecl *MainSetGpuInfo)(const wchar_t*, const wchar_t*, 40 const wchar_t*, const wchar_t*, 41 const wchar_t*); 42 43 // exported in breakpad_win.cc: 44 // void __declspec(dllexport) __cdecl SetPrinterInfo. 45 typedef void (__cdecl *MainSetPrinterInfo)(const wchar_t*); 46 47 // exported in breakpad_win.cc: 48 // void __declspec(dllexport) __cdecl SetNumberOfViews. 49 typedef void (__cdecl *MainSetNumberOfViews)(int); 50 51 // exported in breakpad_win.cc: 52 // void __declspec(dllexport) __cdecl SetCommandLine2 53 typedef void (__cdecl *MainSetCommandLine)(const wchar_t**, size_t); 54 55 // exported in breakpad_field_trial_win.cc: 56 // void __declspec(dllexport) __cdecl SetExperimentList3 57 typedef void (__cdecl *MainSetExperimentList)(const wchar_t**, size_t, size_t); 58 59 // Copied from breakpad_win.cc. 60 void StringVectorToCStringVector(const std::vector<std::wstring>& wstrings, 61 std::vector<const wchar_t*>* cstrings) { 62 cstrings->clear(); 63 cstrings->reserve(wstrings.size()); 64 for (size_t i = 0; i < wstrings.size(); ++i) 65 cstrings->push_back(wstrings[i].c_str()); 66 } 67 68 } // namespace 69 70 void SetActiveURL(const GURL& url) { 71 static MainSetActiveURL set_active_url = NULL; 72 // note: benign race condition on set_active_url. 73 if (!set_active_url) { 74 HMODULE exe_module = GetModuleHandle(chrome::kBrowserProcessExecutableName); 75 if (!exe_module) 76 return; 77 set_active_url = reinterpret_cast<MainSetActiveURL>( 78 GetProcAddress(exe_module, "SetActiveURL")); 79 if (!set_active_url) 80 return; 81 } 82 83 (set_active_url)(UTF8ToWide(url.possibly_invalid_spec()).c_str()); 84 } 85 86 void SetClientId(const std::string& client_id) { 87 std::string str(client_id); 88 // Remove all instance of '-' char from the GUID. So BCD-WXY becomes BCDWXY. 89 ReplaceSubstringsAfterOffset(&str, 0, "-", ""); 90 91 if (str.empty()) 92 return; 93 94 std::wstring wstr = ASCIIToWide(str); 95 std::wstring old_wstr; 96 if (!GoogleUpdateSettings::GetMetricsId(&old_wstr) || 97 wstr != old_wstr) 98 GoogleUpdateSettings::SetMetricsId(wstr); 99 100 static MainSetClientId set_client_id = NULL; 101 // note: benign race condition on set_client_id. 102 if (!set_client_id) { 103 HMODULE exe_module = GetModuleHandle(chrome::kBrowserProcessExecutableName); 104 if (!exe_module) 105 return; 106 set_client_id = reinterpret_cast<MainSetClientId>( 107 GetProcAddress(exe_module, "SetClientId")); 108 if (!set_client_id) 109 return; 110 } 111 (set_client_id)(wstr.c_str()); 112 } 113 114 std::string GetClientId() { 115 std::wstring wstr_client_id; 116 if (GoogleUpdateSettings::GetMetricsId(&wstr_client_id)) 117 return WideToASCII(wstr_client_id); 118 else 119 return std::string(); 120 } 121 122 void SetActiveExtensions(const std::set<std::string>& extension_ids) { 123 static MainSetNumberOfExtensions set_number_of_extensions = NULL; 124 // note: benign race condition on set_number_of_extensions. 125 if (!set_number_of_extensions) { 126 HMODULE exe_module = GetModuleHandle(chrome::kBrowserProcessExecutableName); 127 if (!exe_module) 128 return; 129 set_number_of_extensions = reinterpret_cast<MainSetNumberOfExtensions>( 130 GetProcAddress(exe_module, "SetNumberOfExtensions")); 131 if (!set_number_of_extensions) 132 return; 133 } 134 135 static MainSetExtensionID set_extension_id = NULL; 136 // note: benign race condition on set_extension_id. 137 if (!set_extension_id) { 138 HMODULE exe_module = GetModuleHandle(chrome::kBrowserProcessExecutableName); 139 if (!exe_module) 140 return; 141 set_extension_id = reinterpret_cast<MainSetExtensionID>( 142 GetProcAddress(exe_module, "SetExtensionID")); 143 if (!set_extension_id) 144 return; 145 } 146 147 (set_number_of_extensions)(static_cast<int>(extension_ids.size())); 148 149 std::set<std::string>::const_iterator iter = extension_ids.begin(); 150 for (size_t i = 0; i < kMaxReportedActiveExtensions; ++i) { 151 if (iter != extension_ids.end()) { 152 (set_extension_id)(i, ASCIIToWide(iter->c_str()).c_str()); 153 ++iter; 154 } else { 155 (set_extension_id)(i, L""); 156 } 157 } 158 } 159 160 void SetGpuInfo(const gpu::GPUInfo& gpu_info) { 161 static MainSetGpuInfo set_gpu_info = NULL; 162 // note: benign race condition on set_gpu_info. 163 if (!set_gpu_info) { 164 HMODULE exe_module = GetModuleHandle(chrome::kBrowserProcessExecutableName); 165 if (!exe_module) 166 return; 167 set_gpu_info = reinterpret_cast<MainSetGpuInfo>( 168 GetProcAddress(exe_module, "SetGpuInfo")); 169 if (!set_gpu_info) 170 return; 171 } 172 (set_gpu_info)( 173 base::StringPrintf(L"0x%04x", gpu_info.gpu.vendor_id).c_str(), 174 base::StringPrintf(L"0x%04x", gpu_info.gpu.device_id).c_str(), 175 UTF8ToUTF16(gpu_info.driver_version).c_str(), 176 UTF8ToUTF16(gpu_info.pixel_shader_version).c_str(), 177 UTF8ToUTF16(gpu_info.vertex_shader_version).c_str()); 178 } 179 180 void SetPrinterInfo(const char* printer_info) { 181 static MainSetPrinterInfo set_printer_info = NULL; 182 // note: benign race condition on set_printer_info. 183 if (!set_printer_info) { 184 HMODULE exe_module = GetModuleHandle(chrome::kBrowserProcessExecutableName); 185 if (!exe_module) 186 return; 187 set_printer_info = reinterpret_cast<MainSetPrinterInfo>( 188 GetProcAddress(exe_module, "SetPrinterInfo")); 189 if (!set_printer_info) 190 return; 191 } 192 (set_printer_info)(UTF8ToWide(printer_info).c_str()); 193 } 194 195 void SetCommandLine(const CommandLine* command_line) { 196 static MainSetCommandLine set_command_line = NULL; 197 // note: benign race condition on set_command_line. 198 if (!set_command_line) { 199 HMODULE exe_module = GetModuleHandle(chrome::kBrowserProcessExecutableName); 200 if (!exe_module) 201 return; 202 set_command_line = reinterpret_cast<MainSetCommandLine>( 203 GetProcAddress(exe_module, "SetCommandLine2")); 204 if (!set_command_line) 205 return; 206 } 207 208 if (command_line->argv().empty()) 209 return; 210 211 std::vector<const wchar_t*> cstrings; 212 StringVectorToCStringVector(command_line->argv(), &cstrings); 213 (set_command_line)(&cstrings[0], cstrings.size()); 214 } 215 216 void SetExperimentList(const std::vector<string16>& experiments) { 217 static MainSetExperimentList set_experiment_list = NULL; 218 // note: benign race condition on set_experiment_list. 219 if (!set_experiment_list) { 220 HMODULE exe_module = GetModuleHandle(chrome::kBrowserProcessExecutableName); 221 if (!exe_module) 222 return; 223 set_experiment_list = reinterpret_cast<MainSetExperimentList>( 224 GetProcAddress(exe_module, "SetExperimentList3")); 225 if (!set_experiment_list) 226 return; 227 } 228 229 std::vector<string16> chunks; 230 chrome_variations::GenerateVariationChunks(experiments, &chunks); 231 232 // If the list is empty, notify the child process of the number of experiments 233 // and exit early. 234 if (chunks.empty()) { 235 (set_experiment_list)(NULL, 0, 0); 236 return; 237 } 238 239 std::vector<const wchar_t*> cstrings; 240 StringVectorToCStringVector(chunks, &cstrings); 241 (set_experiment_list)(&cstrings[0], cstrings.size(), experiments.size()); 242 } 243 244 void SetNumberOfViews(int number_of_views) { 245 static MainSetNumberOfViews set_number_of_views = NULL; 246 // note: benign race condition on set_number_of_views. 247 if (!set_number_of_views) { 248 HMODULE exe_module = GetModuleHandle(chrome::kBrowserProcessExecutableName); 249 if (!exe_module) 250 return; 251 set_number_of_views = reinterpret_cast<MainSetNumberOfViews>( 252 GetProcAddress(exe_module, "SetNumberOfViews")); 253 if (!set_number_of_views) 254 return; 255 } 256 (set_number_of_views)(number_of_views); 257 } 258 259 } // namespace child_process_logging 260