child_process_logging_win.cc revision 58537e28ecd584eab876aee8be7156509866d23a
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/utf_string_conversions.h" 13#include "chrome/common/chrome_constants.h" 14#include "chrome/common/crash_keys.h" 15#include "chrome/common/metrics/variations/variations_util.h" 16#include "chrome/installer/util/google_update_settings.h" 17 18namespace child_process_logging { 19 20namespace { 21 22// exported in breakpad_win.cc: void __declspec(dllexport) __cdecl SetClientId. 23typedef void (__cdecl *MainSetClientId)(const wchar_t*); 24 25// exported in breakpad_win.cc: 26// void __declspec(dllexport) __cdecl SetPrinterInfo. 27typedef void (__cdecl *MainSetPrinterInfo)(const wchar_t*); 28 29// exported in breakpad_win.cc: 30// void __declspec(dllexport) __cdecl SetNumberOfViews. 31typedef void (__cdecl *MainSetNumberOfViews)(int); 32 33// exported in breakpad_win.cc: 34// void __declspec(dllexport) __cdecl SetCommandLine2 35typedef void (__cdecl *MainSetCommandLine)(const wchar_t**, size_t); 36 37// exported in breakpad_field_trial_win.cc: 38// void __declspec(dllexport) __cdecl SetExperimentList3 39typedef void (__cdecl *MainSetExperimentList)(const wchar_t**, size_t, size_t); 40 41// exported in breakpad_win.cc: 42// void __declspec(dllexport) __cdecl SetCrashKeyValueImpl. 43typedef void (__cdecl *SetCrashKeyValue)(const wchar_t*, const wchar_t*); 44 45// exported in breakpad_win.cc: 46// void __declspec(dllexport) __cdecl ClearCrashKeyValueImpl. 47typedef void (__cdecl *ClearCrashKeyValue)(const wchar_t*); 48 49 50// Copied from breakpad_win.cc. 51void StringVectorToCStringVector(const std::vector<std::wstring>& wstrings, 52 std::vector<const wchar_t*>* cstrings) { 53 cstrings->clear(); 54 cstrings->reserve(wstrings.size()); 55 for (size_t i = 0; i < wstrings.size(); ++i) 56 cstrings->push_back(wstrings[i].c_str()); 57} 58 59} // namespace 60 61void SetClientId(const std::string& client_id) { 62 std::string str(client_id); 63 // Remove all instance of '-' char from the GUID. So BCD-WXY becomes BCDWXY. 64 ReplaceSubstringsAfterOffset(&str, 0, "-", ""); 65 66 if (str.empty()) 67 return; 68 69 std::wstring wstr = ASCIIToWide(str); 70 std::wstring old_wstr; 71 if (!GoogleUpdateSettings::GetMetricsId(&old_wstr) || 72 wstr != old_wstr) 73 GoogleUpdateSettings::SetMetricsId(wstr); 74 75 static MainSetClientId set_client_id = NULL; 76 // note: benign race condition on set_client_id. 77 if (!set_client_id) { 78 HMODULE exe_module = GetModuleHandle(chrome::kBrowserProcessExecutableName); 79 if (!exe_module) 80 return; 81 set_client_id = reinterpret_cast<MainSetClientId>( 82 GetProcAddress(exe_module, "SetClientId")); 83 if (!set_client_id) 84 return; 85 } 86 (set_client_id)(wstr.c_str()); 87} 88 89std::string GetClientId() { 90 std::wstring wstr_client_id; 91 if (GoogleUpdateSettings::GetMetricsId(&wstr_client_id)) 92 return WideToASCII(wstr_client_id); 93 else 94 return std::string(); 95} 96 97void SetPrinterInfo(const char* printer_info) { 98 static MainSetPrinterInfo set_printer_info = NULL; 99 // note: benign race condition on set_printer_info. 100 if (!set_printer_info) { 101 HMODULE exe_module = GetModuleHandle(chrome::kBrowserProcessExecutableName); 102 if (!exe_module) 103 return; 104 set_printer_info = reinterpret_cast<MainSetPrinterInfo>( 105 GetProcAddress(exe_module, "SetPrinterInfo")); 106 if (!set_printer_info) 107 return; 108 } 109 (set_printer_info)(UTF8ToWide(printer_info).c_str()); 110} 111 112void SetCommandLine(const CommandLine* command_line) { 113 static MainSetCommandLine set_command_line = NULL; 114 // note: benign race condition on set_command_line. 115 if (!set_command_line) { 116 HMODULE exe_module = GetModuleHandle(chrome::kBrowserProcessExecutableName); 117 if (!exe_module) 118 return; 119 set_command_line = reinterpret_cast<MainSetCommandLine>( 120 GetProcAddress(exe_module, "SetCommandLine2")); 121 if (!set_command_line) 122 return; 123 } 124 125 if (command_line->argv().empty()) 126 return; 127 128 std::vector<const wchar_t*> cstrings; 129 StringVectorToCStringVector(command_line->argv(), &cstrings); 130 (set_command_line)(&cstrings[0], cstrings.size()); 131} 132 133void SetExperimentList(const std::vector<string16>& experiments) { 134 static MainSetExperimentList set_experiment_list = NULL; 135 // note: benign race condition on set_experiment_list. 136 if (!set_experiment_list) { 137 HMODULE exe_module = GetModuleHandle(chrome::kBrowserProcessExecutableName); 138 if (!exe_module) 139 return; 140 set_experiment_list = reinterpret_cast<MainSetExperimentList>( 141 GetProcAddress(exe_module, "SetExperimentList3")); 142 if (!set_experiment_list) 143 return; 144 } 145 146 std::vector<string16> chunks; 147 chrome_variations::GenerateVariationChunks(experiments, &chunks); 148 149 // If the list is empty, notify the child process of the number of experiments 150 // and exit early. 151 if (chunks.empty()) { 152 (set_experiment_list)(NULL, 0, 0); 153 return; 154 } 155 156 std::vector<const wchar_t*> cstrings; 157 StringVectorToCStringVector(chunks, &cstrings); 158 (set_experiment_list)(&cstrings[0], cstrings.size(), experiments.size()); 159} 160 161void SetNumberOfViews(int number_of_views) { 162 static MainSetNumberOfViews set_number_of_views = NULL; 163 // note: benign race condition on set_number_of_views. 164 if (!set_number_of_views) { 165 HMODULE exe_module = GetModuleHandle(chrome::kBrowserProcessExecutableName); 166 if (!exe_module) 167 return; 168 set_number_of_views = reinterpret_cast<MainSetNumberOfViews>( 169 GetProcAddress(exe_module, "SetNumberOfViews")); 170 if (!set_number_of_views) 171 return; 172 } 173 (set_number_of_views)(number_of_views); 174} 175 176namespace { 177 178void SetCrashKeyValueTrampoline(const base::StringPiece& key, 179 const base::StringPiece& value) { 180 static SetCrashKeyValue set_crash_key = NULL; 181 if (!set_crash_key) { 182 HMODULE exe_module = GetModuleHandle(chrome::kBrowserProcessExecutableName); 183 if (!exe_module) 184 return; 185 set_crash_key = reinterpret_cast<SetCrashKeyValue>( 186 GetProcAddress(exe_module, "SetCrashKeyValueImpl")); 187 } 188 189 if (set_crash_key) 190 (set_crash_key)(UTF8ToWide(key).data(), UTF8ToWide(value).data()); 191} 192 193void ClearCrashKeyValueTrampoline(const base::StringPiece& key) { 194 static ClearCrashKeyValue clear_crash_key = NULL; 195 if (!clear_crash_key) { 196 HMODULE exe_module = GetModuleHandle(chrome::kBrowserProcessExecutableName); 197 if (!exe_module) 198 return; 199 clear_crash_key = reinterpret_cast<ClearCrashKeyValue>( 200 GetProcAddress(exe_module, "ClearCrashKeyValueImpl")); 201 } 202 203 if (clear_crash_key) 204 (clear_crash_key)(UTF8ToWide(key).data()); 205} 206 207} // namespace 208 209void Init() { 210 // Note: on other platforms, this is set up during Breakpad initialization, 211 // in ChromeBreakpadClient. But on Windows, that is before the DLL module is 212 // loaded, which is a prerequisite of the crash key system. 213 crash_keys::RegisterChromeCrashKeys(); 214 base::debug::SetCrashKeyReportingFunctions( 215 &SetCrashKeyValueTrampoline, &ClearCrashKeyValueTrampoline); 216} 217 218} // namespace child_process_logging 219