Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(463)

Side by Side Diff: chrome/browser/component_updater/recovery_component_installer.cc

Issue 846663003: Add UMA metrics to recovery component. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Move UMA_ macros to helper function. Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | tools/metrics/histograms/histograms.xml » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 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/recovery_component_installer.h" 5 #include "chrome/browser/component_updater/recovery_component_installer.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 #include <string> 8 #include <string>
9 9
10 #include "base/base_paths.h" 10 #include "base/base_paths.h"
11 #include "base/bind.h" 11 #include "base/bind.h"
12 #include "base/command_line.h" 12 #include "base/command_line.h"
13 #include "base/compiler_specific.h" 13 #include "base/compiler_specific.h"
14 #include "base/files/file_path.h" 14 #include "base/files/file_path.h"
15 #include "base/files/file_util.h" 15 #include "base/files/file_util.h"
16 #include "base/json/json_file_value_serializer.h" 16 #include "base/json/json_file_value_serializer.h"
17 #include "base/logging.h" 17 #include "base/logging.h"
18 #include "base/memory/scoped_ptr.h" 18 #include "base/memory/scoped_ptr.h"
19 #include "base/metrics/histogram.h"
19 #include "base/path_service.h" 20 #include "base/path_service.h"
20 #include "base/prefs/pref_registry_simple.h" 21 #include "base/prefs/pref_registry_simple.h"
21 #include "base/prefs/pref_service.h" 22 #include "base/prefs/pref_service.h"
22 #include "base/process/kill.h" 23 #include "base/process/kill.h"
23 #include "base/process/launch.h" 24 #include "base/process/launch.h"
24 #include "base/process/process.h" 25 #include "base/process/process.h"
25 #include "base/threading/worker_pool.h" 26 #include "base/threading/worker_pool.h"
26 #include "chrome/common/chrome_switches.h" 27 #include "chrome/common/chrome_switches.h"
27 #include "chrome/common/pref_names.h" 28 #include "chrome/common/pref_names.h"
28 #include "components/component_updater/component_updater_paths.h" 29 #include "components/component_updater/component_updater_paths.h"
(...skipping 23 matching lines...) Expand all
52 53
53 const char kRecoveryManifestName[] = "ChromeRecovery"; 54 const char kRecoveryManifestName[] = "ChromeRecovery";
54 55
55 // ChromeRecovery process exit codes. 56 // ChromeRecovery process exit codes.
56 enum ChromeRecoveryExitCode { 57 enum ChromeRecoveryExitCode {
57 EXIT_CODE_RECOVERY_SUCCEEDED = 0, 58 EXIT_CODE_RECOVERY_SUCCEEDED = 0,
58 EXIT_CODE_RECOVERY_SKIPPED = 1, 59 EXIT_CODE_RECOVERY_SKIPPED = 1,
59 EXIT_CODE_ELEVATION_NEEDED = 2, 60 EXIT_CODE_ELEVATION_NEEDED = 2,
60 }; 61 };
61 62
63 enum RecoveryComponentEvent {
64 RCE_RUNNING_NON_ELEVATED = 0,
65 RCE_ELEVATION_NEEDED = 1,
66 RCE_FAILED = 2,
67 RCE_SUCCEEDED = 3,
68 RCE_SKIPPED = 4,
69 RCE_RUNNING_ELEVATED = 5,
70 RCE_ELEVATED_FAILED = 6,
71 RCE_ELEVATED_SUCCEEDED = 7,
72 RCE_ELEVATED_SKIPPED = 8,
73 RCE_COMPONENT_DOWNLOAD_ERROR = 9,
74 RCE_COUNT
75 };
76
77 void RecordRecoveryComponentUMAEvent(RecoveryComponentEvent event) {
78 UMA_HISTOGRAM_ENUMERATION("RecoveryComponent.Event", event, RCE_COUNT);
79 }
80
62 #if !defined(OS_CHROMEOS) 81 #if !defined(OS_CHROMEOS)
63 // Checks if elevated recovery simulation switch was present on the command 82 // Checks if elevated recovery simulation switch was present on the command
64 // line. This is for testing purpose. 83 // line. This is for testing purpose.
65 bool SimulatingElevatedRecovery() { 84 bool SimulatingElevatedRecovery() {
66 return base::CommandLine::ForCurrentProcess()->HasSwitch( 85 return base::CommandLine::ForCurrentProcess()->HasSwitch(
67 switches::kSimulateElevatedRecovery); 86 switches::kSimulateElevatedRecovery);
68 } 87 }
69 #endif 88 #endif // !defined(OS_CHROMEOS)
70 89
71 #if defined(OS_WIN) 90 #if defined(OS_WIN)
72 scoped_ptr<base::DictionaryValue> ReadManifest(const base::FilePath& manifest) { 91 scoped_ptr<base::DictionaryValue> ReadManifest(const base::FilePath& manifest) {
73 JSONFileValueSerializer serializer(manifest); 92 JSONFileValueSerializer serializer(manifest);
74 std::string error; 93 std::string error;
75 scoped_ptr<base::Value> root(serializer.Deserialize(NULL, &error)); 94 scoped_ptr<base::Value> root(serializer.Deserialize(NULL, &error));
76 if (root.get() && root->IsType(base::Value::TYPE_DICTIONARY)) { 95 if (root.get() && root->IsType(base::Value::TYPE_DICTIONARY)) {
77 return scoped_ptr<base::DictionaryValue>( 96 return scoped_ptr<base::DictionaryValue>(
78 static_cast<base::DictionaryValue*>(root.release())); 97 static_cast<base::DictionaryValue*>(root.release()));
79 } 98 }
80 return scoped_ptr<base::DictionaryValue>(); 99 return scoped_ptr<base::DictionaryValue>();
81 } 100 }
82 101
102 void WaitForElevatedInstallToComplete(base::Process process) {
103 int installer_exit_code = 0;
104 const base::TimeDelta kMaxWaitTime = base::TimeDelta::FromSeconds(600);
105 if (process.WaitForExitWithTimeout(kMaxWaitTime, &installer_exit_code)) {
106 if (installer_exit_code == EXIT_CODE_RECOVERY_SUCCEEDED) {
107 RecordRecoveryComponentUMAEvent(RCE_ELEVATED_SUCCEEDED);
108 } else {
109 RecordRecoveryComponentUMAEvent(RCE_ELEVATED_SKIPPED);
110 }
111 } else {
112 RecordRecoveryComponentUMAEvent(RCE_ELEVATED_FAILED);
113 }
114 }
115
83 void DoElevatedInstallRecoveryComponent(const base::FilePath& path) { 116 void DoElevatedInstallRecoveryComponent(const base::FilePath& path) {
84 const base::FilePath main_file = path.Append(kRecoveryFileName); 117 const base::FilePath main_file = path.Append(kRecoveryFileName);
85 const base::FilePath manifest_file = 118 const base::FilePath manifest_file =
86 path.Append(FILE_PATH_LITERAL("manifest.json")); 119 path.Append(FILE_PATH_LITERAL("manifest.json"));
87 if (!base::PathExists(main_file) || !base::PathExists(manifest_file)) 120 if (!base::PathExists(main_file) || !base::PathExists(manifest_file))
88 return; 121 return;
89 122
90 scoped_ptr<base::DictionaryValue> manifest(ReadManifest(manifest_file)); 123 scoped_ptr<base::DictionaryValue> manifest(ReadManifest(manifest_file));
91 std::string name; 124 std::string name;
92 manifest->GetStringASCII("name", &name); 125 manifest->GetStringASCII("name", &name);
93 if (name != kRecoveryManifestName) 126 if (name != kRecoveryManifestName)
94 return; 127 return;
95 std::string proposed_version; 128 std::string proposed_version;
96 manifest->GetStringASCII("version", &proposed_version); 129 manifest->GetStringASCII("version", &proposed_version);
97 const Version version(proposed_version.c_str()); 130 const Version version(proposed_version.c_str());
98 if (!version.IsValid()) 131 if (!version.IsValid())
99 return; 132 return;
100 133
101 base::CommandLine cmdline(main_file); 134 base::CommandLine cmdline(main_file);
102 std::string arguments; 135 std::string arguments;
103 if (manifest->GetStringASCII("x-recovery-args", &arguments)) 136 if (manifest->GetStringASCII("x-recovery-args", &arguments))
104 cmdline.AppendArg(arguments); 137 cmdline.AppendArg(arguments);
105 std::string add_version; 138 std::string add_version;
106 if (manifest->GetStringASCII("x-recovery-add-version", &add_version) && 139 if (manifest->GetStringASCII("x-recovery-add-version", &add_version) &&
107 add_version == "yes") { 140 add_version == "yes") {
108 cmdline.AppendSwitchASCII("version", version.GetString()); 141 cmdline.AppendSwitchASCII("version", version.GetString());
109 } 142 }
110 143
144 RecordRecoveryComponentUMAEvent(RCE_RUNNING_ELEVATED);
145
111 base::LaunchOptions options; 146 base::LaunchOptions options;
112 options.start_hidden = true; 147 options.start_hidden = true;
113 base::LaunchElevatedProcess(cmdline, options); 148 base::Process process = base::LaunchElevatedProcess(cmdline, options);
149
150 base::WorkerPool::PostTask(
151 FROM_HERE,
152 base::Bind(&WaitForElevatedInstallToComplete, base::Passed(&process)),
153 true);
114 } 154 }
115 155
116 void ElevatedInstallRecoveryComponent(const base::FilePath& installer_path) { 156 void ElevatedInstallRecoveryComponent(const base::FilePath& installer_path) {
117 base::WorkerPool::PostTask( 157 base::WorkerPool::PostTask(
118 FROM_HERE, 158 FROM_HERE,
119 base::Bind(&DoElevatedInstallRecoveryComponent, installer_path), 159 base::Bind(&DoElevatedInstallRecoveryComponent, installer_path),
120 true); 160 true);
121 } 161 }
122 #endif 162 #endif // defined(OS_WIN)
123 163
124 } // namespace 164 } // namespace
125 165
126 // Component installer that is responsible to repair the chrome installation 166 // Component installer that is responsible to repair the chrome installation
127 // or repair the Google update installation. This is a last resort safety 167 // or repair the Google update installation. This is a last resort safety
128 // mechanism. 168 // mechanism.
129 // For user Chrome, recovery component just installs silently. For machine 169 // For user Chrome, recovery component just installs silently. For machine
130 // Chrome, elevation may be needed. If that happens, the installer will set 170 // Chrome, elevation may be needed. If that happens, the installer will set
131 // preference flag prefs::kRecoveryComponentNeedsElevation to request that. 171 // preference flag prefs::kRecoveryComponentNeedsElevation to request that.
132 // There is a global error service monitors this flag and will pop up 172 // There is a global error service monitors this flag and will pop up
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
187 prefs->SetBoolean(prefs::kRecoveryComponentNeedsElevation, true); 227 prefs->SetBoolean(prefs::kRecoveryComponentNeedsElevation, true);
188 } 228 }
189 229
190 RecoveryComponentInstaller::RecoveryComponentInstaller(const Version& version, 230 RecoveryComponentInstaller::RecoveryComponentInstaller(const Version& version,
191 PrefService* prefs) 231 PrefService* prefs)
192 : current_version_(version), prefs_(prefs) { 232 : current_version_(version), prefs_(prefs) {
193 DCHECK(version.IsValid()); 233 DCHECK(version.IsValid());
194 } 234 }
195 235
196 void RecoveryComponentInstaller::OnUpdateError(int error) { 236 void RecoveryComponentInstaller::OnUpdateError(int error) {
237 RecordRecoveryComponentUMAEvent(RCE_COMPONENT_DOWNLOAD_ERROR);
197 NOTREACHED() << "Recovery component update error: " << error; 238 NOTREACHED() << "Recovery component update error: " << error;
198 } 239 }
199 240
200 #if defined(OS_WIN) 241 #if defined(OS_WIN)
201 void WaitForInstallToComplete(base::Process process, 242 void WaitForInstallToComplete(base::Process process,
202 const base::FilePath& installer_folder, 243 const base::FilePath& installer_folder,
203 PrefService* prefs) { 244 PrefService* prefs) {
204 int installer_exit_code = 0; 245 int installer_exit_code = 0;
205 const base::TimeDelta kMaxWaitTime = base::TimeDelta::FromSeconds(600); 246 const base::TimeDelta kMaxWaitTime = base::TimeDelta::FromSeconds(600);
206 if (process.WaitForExitWithTimeout(kMaxWaitTime, &installer_exit_code) && 247 if (process.WaitForExitWithTimeout(kMaxWaitTime, &installer_exit_code)) {
207 installer_exit_code == EXIT_CODE_ELEVATION_NEEDED) { 248 if (installer_exit_code == EXIT_CODE_ELEVATION_NEEDED) {
208 BrowserThread::PostTask( 249 RecordRecoveryComponentUMAEvent(RCE_ELEVATION_NEEDED);
209 BrowserThread::UI, 250
210 FROM_HERE, 251 BrowserThread::PostTask(
211 base::Bind(&SetPrefsForElevatedRecoveryInstall, 252 BrowserThread::UI,
212 installer_folder, 253 FROM_HERE,
213 prefs)); 254 base::Bind(&SetPrefsForElevatedRecoveryInstall,
255 installer_folder,
256 prefs));
257 } else if (installer_exit_code == EXIT_CODE_RECOVERY_SUCCEEDED) {
258 RecordRecoveryComponentUMAEvent(RCE_SUCCEEDED);
259 } else if (installer_exit_code == EXIT_CODE_RECOVERY_SKIPPED) {
260 RecordRecoveryComponentUMAEvent(RCE_SKIPPED);
261 }
262 } else {
263 RecordRecoveryComponentUMAEvent(RCE_FAILED);
214 } 264 }
215 } 265 }
216 266
217 bool RecoveryComponentInstaller::RunInstallCommand( 267 bool RecoveryComponentInstaller::RunInstallCommand(
218 const base::CommandLine& cmdline, 268 const base::CommandLine& cmdline,
219 const base::FilePath& installer_folder) const { 269 const base::FilePath& installer_folder) const {
270 RecordRecoveryComponentUMAEvent(RCE_RUNNING_NON_ELEVATED);
271
220 base::LaunchOptions options; 272 base::LaunchOptions options;
221 options.start_hidden = true; 273 options.start_hidden = true;
222 base::Process process = base::LaunchProcess(cmdline, options); 274 base::Process process = base::LaunchProcess(cmdline, options);
223 if (!process.IsValid()) 275 if (!process.IsValid())
224 return false; 276 return false;
225 277
226 // Let worker pool thread wait for us so we don't block Chrome shutdown. 278 // Let worker pool thread wait for us so we don't block Chrome shutdown.
227 base::WorkerPool::PostTask( 279 base::WorkerPool::PostTask(
228 FROM_HERE, 280 FROM_HERE,
229 base::Bind(&WaitForInstallToComplete, 281 base::Bind(&WaitForInstallToComplete,
230 base::Passed(&process), installer_folder, prefs_), 282 base::Passed(&process), installer_folder, prefs_),
231 true); 283 true);
232 284
233 // Returns true regardless of install result since from updater service 285 // Returns true regardless of install result since from updater service
234 // perspective the install is done, even we may need to do elevated 286 // perspective the install is done, even we may need to do elevated
235 // install later. 287 // install later.
236 return true; 288 return true;
237 } 289 }
238 #else 290 #else
239 bool RecoveryComponentInstaller::RunInstallCommand( 291 bool RecoveryComponentInstaller::RunInstallCommand(
240 const base::CommandLine& cmdline, 292 const base::CommandLine& cmdline,
241 const base::FilePath&) const { 293 const base::FilePath&) const {
242 return base::LaunchProcess(cmdline, base::LaunchOptions()).IsValid(); 294 return base::LaunchProcess(cmdline, base::LaunchOptions()).IsValid();
243 } 295 }
244 #endif 296 #endif // defined(OS_WIN)
245 297
246 bool RecoveryComponentInstaller::Install(const base::DictionaryValue& manifest, 298 bool RecoveryComponentInstaller::Install(const base::DictionaryValue& manifest,
247 const base::FilePath& unpack_path) { 299 const base::FilePath& unpack_path) {
248 std::string name; 300 std::string name;
249 manifest.GetStringASCII("name", &name); 301 manifest.GetStringASCII("name", &name);
250 if (name != kRecoveryManifestName) 302 if (name != kRecoveryManifestName)
251 return false; 303 return false;
252 std::string proposed_version; 304 std::string proposed_version;
253 manifest.GetStringASCII("version", &proposed_version); 305 manifest.GetStringASCII("version", &proposed_version);
254 Version version(proposed_version.c_str()); 306 Version version(proposed_version.c_str());
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
315 base::Bind(&SimulateElevatedRecoveryHelper, prefs)); 367 base::Bind(&SimulateElevatedRecoveryHelper, prefs));
316 } 368 }
317 369
318 // We delay execute the registration because we are not required in 370 // We delay execute the registration because we are not required in
319 // the critical path during browser startup. 371 // the critical path during browser startup.
320 BrowserThread::PostDelayedTask( 372 BrowserThread::PostDelayedTask(
321 BrowserThread::UI, 373 BrowserThread::UI,
322 FROM_HERE, 374 FROM_HERE,
323 base::Bind(&RecoveryRegisterHelper, cus, prefs), 375 base::Bind(&RecoveryRegisterHelper, cus, prefs),
324 base::TimeDelta::FromSeconds(6)); 376 base::TimeDelta::FromSeconds(6));
325 #endif 377 #endif // !defined(OS_CHROMEOS)
326 } 378 }
327 379
328 void RegisterPrefsForRecoveryComponent(PrefRegistrySimple* registry) { 380 void RegisterPrefsForRecoveryComponent(PrefRegistrySimple* registry) {
329 registry->RegisterStringPref(prefs::kRecoveryComponentVersion, "0.0.0.0"); 381 registry->RegisterStringPref(prefs::kRecoveryComponentVersion, "0.0.0.0");
330 registry->RegisterFilePathPref(prefs::kRecoveryComponentUnpackPath, 382 registry->RegisterFilePathPref(prefs::kRecoveryComponentUnpackPath,
331 base::FilePath()); 383 base::FilePath());
332 registry->RegisterBooleanPref(prefs::kRecoveryComponentNeedsElevation, false); 384 registry->RegisterBooleanPref(prefs::kRecoveryComponentNeedsElevation, false);
333 } 385 }
334 386
335 void AcceptedElevatedRecoveryInstall(PrefService* prefs) { 387 void AcceptedElevatedRecoveryInstall(PrefService* prefs) {
336 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 388 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
337 389
338 #if defined(OS_WIN) 390 #if defined(OS_WIN)
339 ElevatedInstallRecoveryComponent( 391 ElevatedInstallRecoveryComponent(
340 prefs->GetFilePath(prefs::kRecoveryComponentUnpackPath)); 392 prefs->GetFilePath(prefs::kRecoveryComponentUnpackPath));
341 #endif 393 #endif // OS_WIN
342 prefs->SetBoolean(prefs::kRecoveryComponentNeedsElevation, false); 394 prefs->SetBoolean(prefs::kRecoveryComponentNeedsElevation, false);
343 } 395 }
344 396
345 void DeclinedElevatedRecoveryInstall(PrefService* prefs) { 397 void DeclinedElevatedRecoveryInstall(PrefService* prefs) {
346 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 398 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
347 prefs->SetBoolean(prefs::kRecoveryComponentNeedsElevation, false); 399 prefs->SetBoolean(prefs::kRecoveryComponentNeedsElevation, false);
348 } 400 }
349 401
350 } // namespace component_updater 402 } // namespace component_updater
OLDNEW
« no previous file with comments | « no previous file | tools/metrics/histograms/histograms.xml » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698