OLD | NEW |
---|---|
1 // Copyright (c) 2014 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/component_updater/sw_reporter_installer_win.h" | 5 #include "chrome/browser/component_updater/sw_reporter_installer_win.h" |
6 | 6 |
7 #include <stdint.h> | 7 #include <stdint.h> |
8 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
10 #include <map> | 10 #include <map> |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
114 | 114 |
115 void ReportExperimentError(SwReporterExperimentError error) { | 115 void ReportExperimentError(SwReporterExperimentError error) { |
116 UMA_HISTOGRAM_ENUMERATION("SoftwareReporter.ExperimentErrors", error, | 116 UMA_HISTOGRAM_ENUMERATION("SoftwareReporter.ExperimentErrors", error, |
117 SW_REPORTER_EXPERIMENT_ERROR_MAX); | 117 SW_REPORTER_EXPERIMENT_ERROR_MAX); |
118 } | 118 } |
119 | 119 |
120 // Run the software reporter on the next Chrome startup after it's downloaded. | 120 // Run the software reporter on the next Chrome startup after it's downloaded. |
121 // (This is the default |reporter_runner| function passed to the | 121 // (This is the default |reporter_runner| function passed to the |
122 // |SwReporterInstallerTraits| constructor in |RegisterSwReporterComponent| | 122 // |SwReporterInstallerTraits| constructor in |RegisterSwReporterComponent| |
123 // below.) | 123 // below.) |
124 void RunSwReporterAfterStartup( | 124 void RunSwReportersAfterStartup( |
125 const safe_browsing::SwReporterInvocation& invocation, | 125 const safe_browsing::SwReporterQueue& invocations, |
126 const base::Version& version) { | 126 const base::Version& version) { |
127 content::BrowserThread::PostAfterStartupTask( | 127 content::BrowserThread::PostAfterStartupTask( |
128 FROM_HERE, base::ThreadTaskRunnerHandle::Get(), | 128 FROM_HERE, base::ThreadTaskRunnerHandle::Get(), |
129 base::Bind(&safe_browsing::RunSwReporter, invocation, version, | 129 base::Bind(&safe_browsing::RunSwReporters, invocations, version, |
130 base::ThreadTaskRunnerHandle::Get(), | 130 base::ThreadTaskRunnerHandle::Get(), |
131 base::WorkerPool::GetTaskRunner(true))); | 131 base::WorkerPool::GetTaskRunner(true))); |
132 } | 132 } |
133 | 133 |
134 // Ensures |str| contains only alphanumeric characters and characters from | 134 // Ensures |str| contains only alphanumeric characters and characters from |
135 // |extras|, and is not longer than |max_length|. | 135 // |extras|, and is not longer than |max_length|. |
136 bool ValidateString(const std::string& str, | 136 bool ValidateString(const std::string& str, |
137 const std::string& extras, | 137 const std::string& extras, |
138 size_t max_length) { | 138 size_t max_length) { |
139 return str.size() <= max_length && | 139 return str.size() <= max_length && |
140 std::all_of(str.cbegin(), str.cend(), [&extras](char c) { | 140 std::all_of(str.cbegin(), str.cend(), [&extras](char c) { |
141 return base::IsAsciiAlpha(c) || base::IsAsciiDigit(c) || | 141 return base::IsAsciiAlpha(c) || base::IsAsciiDigit(c) || |
142 extras.find(c) != std::string::npos; | 142 extras.find(c) != std::string::npos; |
143 }); | 143 }); |
144 } | 144 } |
145 | 145 |
146 // Reads the command-line params and an UMA histogram suffix from the manifest, | 146 // Reads the command-line params and an UMA histogram suffix from the manifest, |
147 // and launch the SwReporter with those parameters. If anything goes wrong the | 147 // and launch the SwReporter with those parameters. If anything goes wrong the |
csharp
2016/09/13 17:09:03
nit: This last sentence is no longer true, there i
Joe Mason
2016/09/13 19:24:54
That's actually what the comment already says, but
| |
148 // SwReporter should not be run at all, instead of falling back to the default. | 148 // SwReporter should not be run at all, instead of falling back to the default. |
149 void RunExperimentalSwReporter(const base::FilePath& exe_path, | 149 void RunExperimentalSwReporter(const base::FilePath& exe_path, |
150 const base::Version& version, | 150 const base::Version& version, |
151 std::unique_ptr<base::DictionaryValue> manifest, | 151 std::unique_ptr<base::DictionaryValue> manifest, |
152 const SwReporterRunner& reporter_runner) { | 152 const SwReporterRunner& reporter_runner) { |
153 // The experiment requires launch_params so if they aren't present just | 153 // The experiment requires launch_params so if they aren't present just |
154 // return. This isn't an error because the user could get into the experiment | 154 // return. This isn't an error because the user could get into the experiment |
155 // group before they've downloaded the experiment component. | 155 // group before they've downloaded the experiment component. |
156 base::Value* launch_params = nullptr; | 156 base::Value* launch_params = nullptr; |
157 if (!manifest->Get("launch_params", &launch_params)) | 157 if (!manifest->Get("launch_params", &launch_params)) |
158 return; | 158 return; |
159 | 159 |
160 const base::ListValue* parameter_list = nullptr; | 160 const base::ListValue* parameter_list = nullptr; |
161 if (!launch_params->GetAsList(¶meter_list) || parameter_list->empty() || | 161 if (!launch_params->GetAsList(¶meter_list) || parameter_list->empty()) { |
162 // For future expansion, the manifest takes a list of invocation | |
163 // parameters, but currently we only support a single invocation. | |
164 parameter_list->GetSize() > 1) { | |
165 ReportExperimentError(SW_REPORTER_EXPERIMENT_ERROR_BAD_PARAMS); | 162 ReportExperimentError(SW_REPORTER_EXPERIMENT_ERROR_BAD_PARAMS); |
166 return; | 163 return; |
167 } | 164 } |
168 | 165 |
169 const base::DictionaryValue* invocation_params = nullptr; | 166 safe_browsing::SwReporterQueue invocations; |
170 if (!parameter_list->GetDictionary(0, &invocation_params)) { | 167 for (const auto& iter : *parameter_list) { |
171 ReportExperimentError(SW_REPORTER_EXPERIMENT_ERROR_BAD_PARAMS); | 168 const base::DictionaryValue* invocation_params = nullptr; |
172 return; | 169 if (!iter->GetAsDictionary(&invocation_params)) { |
173 } | |
174 | |
175 // Max length of the registry and histogram suffix. Fairly arbitrary: the | |
176 // Windows registry accepts much longer keys, but we need to display this | |
177 // string in histograms as well. | |
178 constexpr size_t kMaxSuffixLength = 80; | |
179 | |
180 // The suffix must be an alphanumeric string. (Empty is fine as long as the | |
181 // "suffix" key is present.) | |
182 std::string suffix; | |
183 const base::Value* suffix_value = nullptr; | |
184 if (!invocation_params->Get("suffix", &suffix_value) || | |
185 !suffix_value->GetAsString(&suffix) || | |
186 (!suffix.empty() && | |
187 !ValidateString(suffix, std::string(), kMaxSuffixLength))) { | |
188 ReportExperimentError(SW_REPORTER_EXPERIMENT_ERROR_BAD_PARAMS); | |
189 return; | |
190 } | |
191 | |
192 // Build a command line for the reporter out of the executable path and the | |
193 // arguments from the manifest. (The "arguments" key must be present, but | |
194 // it's ok if it's an empty list or a list of empty strings.) | |
195 std::vector<base::string16> argv = {exe_path.value()}; | |
196 const base::Value* arguments_value = nullptr; | |
197 const base::ListValue* arguments = nullptr; | |
198 if (!invocation_params->Get("arguments", &arguments_value) || | |
199 !arguments_value->GetAsList(&arguments)) { | |
200 ReportExperimentError(SW_REPORTER_EXPERIMENT_ERROR_BAD_PARAMS); | |
201 return; | |
202 } | |
203 | |
204 for (const auto& value : *arguments) { | |
205 base::string16 argument; | |
206 if (!value->GetAsString(&argument)) { | |
207 ReportExperimentError(SW_REPORTER_EXPERIMENT_ERROR_BAD_PARAMS); | 170 ReportExperimentError(SW_REPORTER_EXPERIMENT_ERROR_BAD_PARAMS); |
208 return; | 171 return; |
209 } | 172 } |
210 if (!argument.empty()) | 173 |
211 argv.push_back(argument); | 174 // Max length of the registry and histogram suffix. Fairly arbitrary: the |
175 // Windows registry accepts much longer keys, but we need to display this | |
176 // string in histograms as well. | |
177 constexpr size_t kMaxSuffixLength = 80; | |
178 | |
179 // The suffix must be an alphanumeric string. (Empty is fine as long as the | |
180 // "suffix" key is present.) | |
181 std::string suffix; | |
182 if (!invocation_params->GetString("suffix", &suffix) || | |
183 !ValidateString(suffix, std::string(), kMaxSuffixLength)) { | |
184 ReportExperimentError(SW_REPORTER_EXPERIMENT_ERROR_BAD_PARAMS); | |
185 return; | |
186 } | |
187 | |
188 // Build a command line for the reporter out of the executable path and the | |
189 // arguments from the manifest. (The "arguments" key must be present, but | |
190 // it's ok if it's an empty list or a list of empty strings.) | |
191 const base::ListValue* arguments = nullptr; | |
192 if (!invocation_params->GetList("arguments", &arguments)) { | |
193 ReportExperimentError(SW_REPORTER_EXPERIMENT_ERROR_BAD_PARAMS); | |
194 return; | |
195 } | |
196 | |
197 std::vector<base::string16> argv = {exe_path.value()}; | |
198 for (const auto& value : *arguments) { | |
199 base::string16 argument; | |
200 if (!value->GetAsString(&argument)) { | |
201 ReportExperimentError(SW_REPORTER_EXPERIMENT_ERROR_BAD_PARAMS); | |
202 return; | |
203 } | |
204 if (!argument.empty()) | |
205 argv.push_back(argument); | |
206 } | |
207 | |
208 base::CommandLine command_line(argv); | |
209 | |
210 // Add the histogram suffix to the command-line as well, so that the | |
211 // reporter will add the same suffix to registry keys where it writes | |
212 // metrics. | |
213 if (!suffix.empty()) | |
214 command_line.AppendSwitchASCII("registry-suffix", suffix); | |
215 | |
216 // "prompt" is optional, but if present must be a boolean. | |
217 safe_browsing::SwReporterInvocation::Flags flags = 0; | |
218 const base::Value* prompt_value = nullptr; | |
219 if (invocation_params->Get("prompt", &prompt_value)) { | |
220 bool prompt = false; | |
221 if (!prompt_value->GetAsBoolean(&prompt)) { | |
222 ReportExperimentError(SW_REPORTER_EXPERIMENT_ERROR_BAD_PARAMS); | |
223 return; | |
224 } | |
225 if (prompt) | |
226 flags |= safe_browsing::SwReporterInvocation::FLAG_TRIGGER_PROMPT; | |
227 } | |
228 | |
229 auto invocation = | |
230 safe_browsing::SwReporterInvocation::FromCommandLine(command_line); | |
231 invocation.suffix = suffix; | |
232 invocation.flags = flags; | |
233 invocations.push(invocation); | |
212 } | 234 } |
213 | 235 |
214 base::CommandLine command_line(argv); | 236 DCHECK(!invocations.empty()); |
215 | 237 reporter_runner.Run(invocations, version); |
216 // Add the histogram suffix to the command-line as well, so that the | |
217 // reporter will add the same suffix to registry keys where it writes | |
218 // metrics. | |
219 if (!suffix.empty()) | |
220 command_line.AppendSwitchASCII("registry-suffix", suffix); | |
221 | |
222 auto invocation = | |
223 safe_browsing::SwReporterInvocation::FromCommandLine(command_line); | |
224 invocation.suffix = suffix; | |
225 invocation.is_experimental = true; | |
226 | |
227 reporter_runner.Run(invocation, version); | |
228 } | 238 } |
229 | 239 |
230 } // namespace | 240 } // namespace |
231 | 241 |
232 SwReporterInstallerTraits::SwReporterInstallerTraits( | 242 SwReporterInstallerTraits::SwReporterInstallerTraits( |
233 const SwReporterRunner& reporter_runner, | 243 const SwReporterRunner& reporter_runner, |
234 bool is_experimental_engine_supported) | 244 bool is_experimental_engine_supported) |
235 : reporter_runner_(reporter_runner), | 245 : reporter_runner_(reporter_runner), |
236 is_experimental_engine_supported_(is_experimental_engine_supported) {} | 246 is_experimental_engine_supported_(is_experimental_engine_supported) {} |
237 | 247 |
(...skipping 23 matching lines...) Expand all Loading... | |
261 void SwReporterInstallerTraits::ComponentReady( | 271 void SwReporterInstallerTraits::ComponentReady( |
262 const base::Version& version, | 272 const base::Version& version, |
263 const base::FilePath& install_dir, | 273 const base::FilePath& install_dir, |
264 std::unique_ptr<base::DictionaryValue> manifest) { | 274 std::unique_ptr<base::DictionaryValue> manifest) { |
265 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 275 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
266 const base::FilePath exe_path(install_dir.Append(kSwReporterExeName)); | 276 const base::FilePath exe_path(install_dir.Append(kSwReporterExeName)); |
267 if (IsExperimentalEngineEnabled()) { | 277 if (IsExperimentalEngineEnabled()) { |
268 RunExperimentalSwReporter(exe_path, version, std::move(manifest), | 278 RunExperimentalSwReporter(exe_path, version, std::move(manifest), |
269 reporter_runner_); | 279 reporter_runner_); |
270 } else { | 280 } else { |
271 reporter_runner_.Run( | 281 safe_browsing::SwReporterQueue invocations; |
272 safe_browsing::SwReporterInvocation::FromFilePath(exe_path), version); | 282 invocations.push( |
283 safe_browsing::SwReporterInvocation::FromFilePath(exe_path)); | |
284 reporter_runner_.Run(invocations, version); | |
273 } | 285 } |
274 } | 286 } |
275 | 287 |
276 base::FilePath SwReporterInstallerTraits::GetRelativeInstallDir() const { | 288 base::FilePath SwReporterInstallerTraits::GetRelativeInstallDir() const { |
277 return base::FilePath(FILE_PATH_LITERAL("SwReporter")); | 289 return base::FilePath(FILE_PATH_LITERAL("SwReporter")); |
278 } | 290 } |
279 | 291 |
280 void SwReporterInstallerTraits::GetHash(std::vector<uint8_t>* hash) const { | 292 void SwReporterInstallerTraits::GetHash(std::vector<uint8_t>* hash) const { |
281 DCHECK(hash); | 293 DCHECK(hash); |
282 hash->assign(kSha256Hash, kSha256Hash + sizeof(kSha256Hash)); | 294 hash->assign(kSha256Hash, kSha256Hash + sizeof(kSha256Hash)); |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
398 } | 410 } |
399 | 411 |
400 // The experiment is only enabled on x86. There's no way to check this in the | 412 // The experiment is only enabled on x86. There's no way to check this in the |
401 // variations config so we'll hard-code it. | 413 // variations config so we'll hard-code it. |
402 const bool is_experimental_engine_supported = | 414 const bool is_experimental_engine_supported = |
403 base::win::OSInfo::GetInstance()->architecture() == | 415 base::win::OSInfo::GetInstance()->architecture() == |
404 base::win::OSInfo::X86_ARCHITECTURE; | 416 base::win::OSInfo::X86_ARCHITECTURE; |
405 | 417 |
406 // Install the component. | 418 // Install the component. |
407 std::unique_ptr<ComponentInstallerTraits> traits( | 419 std::unique_ptr<ComponentInstallerTraits> traits( |
408 new SwReporterInstallerTraits(base::Bind(&RunSwReporterAfterStartup), | 420 new SwReporterInstallerTraits(base::Bind(&RunSwReportersAfterStartup), |
409 is_experimental_engine_supported)); | 421 is_experimental_engine_supported)); |
410 // |cus| will take ownership of |installer| during installer->Register(cus). | 422 // |cus| will take ownership of |installer| during installer->Register(cus). |
411 DefaultComponentInstaller* installer = | 423 DefaultComponentInstaller* installer = |
412 new DefaultComponentInstaller(std::move(traits)); | 424 new DefaultComponentInstaller(std::move(traits)); |
413 installer->Register(cus, base::Closure()); | 425 installer->Register(cus, base::Closure()); |
414 } | 426 } |
415 | 427 |
416 void RegisterPrefsForSwReporter(PrefRegistrySimple* registry) { | 428 void RegisterPrefsForSwReporter(PrefRegistrySimple* registry) { |
417 registry->RegisterInt64Pref(prefs::kSwReporterLastTimeTriggered, 0); | 429 registry->RegisterInt64Pref(prefs::kSwReporterLastTimeTriggered, 0); |
418 registry->RegisterIntegerPref(prefs::kSwReporterLastExitCode, -1); | 430 registry->RegisterIntegerPref(prefs::kSwReporterLastExitCode, -1); |
419 registry->RegisterBooleanPref(prefs::kSwReporterPendingPrompt, false); | 431 registry->RegisterBooleanPref(prefs::kSwReporterPendingPrompt, false); |
420 } | 432 } |
421 | 433 |
422 void RegisterProfilePrefsForSwReporter( | 434 void RegisterProfilePrefsForSwReporter( |
423 user_prefs::PrefRegistrySyncable* registry) { | 435 user_prefs::PrefRegistrySyncable* registry) { |
424 registry->RegisterStringPref(prefs::kSwReporterPromptVersion, ""); | 436 registry->RegisterStringPref(prefs::kSwReporterPromptVersion, ""); |
425 | 437 |
426 registry->RegisterStringPref(prefs::kSwReporterPromptSeed, ""); | 438 registry->RegisterStringPref(prefs::kSwReporterPromptSeed, ""); |
427 } | 439 } |
428 | 440 |
429 } // namespace component_updater | 441 } // namespace component_updater |
OLD | NEW |