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

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: Fix incorrect constants. 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
62 #if !defined(OS_CHROMEOS) 77 #if !defined(OS_CHROMEOS)
63 // Checks if elevated recovery simulation switch was present on the command 78 // Checks if elevated recovery simulation switch was present on the command
64 // line. This is for testing purpose. 79 // line. This is for testing purpose.
65 bool SimulatingElevatedRecovery() { 80 bool SimulatingElevatedRecovery() {
66 return base::CommandLine::ForCurrentProcess()->HasSwitch( 81 return base::CommandLine::ForCurrentProcess()->HasSwitch(
67 switches::kSimulateElevatedRecovery); 82 switches::kSimulateElevatedRecovery);
68 } 83 }
69 #endif 84 #endif // !defined(OS_CHROMEOS)
70 85
71 #if defined(OS_WIN) 86 #if defined(OS_WIN)
72 scoped_ptr<base::DictionaryValue> ReadManifest(const base::FilePath& manifest) { 87 scoped_ptr<base::DictionaryValue> ReadManifest(const base::FilePath& manifest) {
73 JSONFileValueSerializer serializer(manifest); 88 JSONFileValueSerializer serializer(manifest);
74 std::string error; 89 std::string error;
75 scoped_ptr<base::Value> root(serializer.Deserialize(NULL, &error)); 90 scoped_ptr<base::Value> root(serializer.Deserialize(NULL, &error));
76 if (root.get() && root->IsType(base::Value::TYPE_DICTIONARY)) { 91 if (root.get() && root->IsType(base::Value::TYPE_DICTIONARY)) {
77 return scoped_ptr<base::DictionaryValue>( 92 return scoped_ptr<base::DictionaryValue>(
78 static_cast<base::DictionaryValue*>(root.release())); 93 static_cast<base::DictionaryValue*>(root.release()));
79 } 94 }
80 return scoped_ptr<base::DictionaryValue>(); 95 return scoped_ptr<base::DictionaryValue>();
81 } 96 }
82 97
98 void WaitForElevatedInstallToComplete(base::Process process) {
99 int installer_exit_code = 0;
100 const base::TimeDelta kMaxWaitTime = base::TimeDelta::FromSeconds(600);
101 if (!process.WaitForExitWithTimeout(kMaxWaitTime, &installer_exit_code)) {
102 UMA_HISTOGRAM_ENUMERATION("RecoveryComponent.Event", RCE_ELEVATED_FAILED,
103 RCE_COUNT);
104 } else {
105 if (installer_exit_code == EXIT_CODE_RECOVERY_SUCCEEDED) {
106 UMA_HISTOGRAM_ENUMERATION("RecoveryComponent.Event",
107 RCE_ELEVATED_SUCCEEDED, RCE_COUNT);
108 } else {
109 UMA_HISTOGRAM_ENUMERATION("RecoveryComponent.Event",
110 RCE_ELEVATED_SKIPPED, RCE_COUNT);
gab 2015/01/12 19:12:20 So if the exit code is not success it means "skip"
robertshield 2015/01/12 23:04:19 That's right.
111 }
112 }
113 }
114
83 void DoElevatedInstallRecoveryComponent(const base::FilePath& path) { 115 void DoElevatedInstallRecoveryComponent(const base::FilePath& path) {
84 const base::FilePath main_file = path.Append(kRecoveryFileName); 116 const base::FilePath main_file = path.Append(kRecoveryFileName);
85 const base::FilePath manifest_file = 117 const base::FilePath manifest_file =
86 path.Append(FILE_PATH_LITERAL("manifest.json")); 118 path.Append(FILE_PATH_LITERAL("manifest.json"));
87 if (!base::PathExists(main_file) || !base::PathExists(manifest_file)) 119 if (!base::PathExists(main_file) || !base::PathExists(manifest_file))
88 return; 120 return;
89 121
90 scoped_ptr<base::DictionaryValue> manifest(ReadManifest(manifest_file)); 122 scoped_ptr<base::DictionaryValue> manifest(ReadManifest(manifest_file));
91 std::string name; 123 std::string name;
92 manifest->GetStringASCII("name", &name); 124 manifest->GetStringASCII("name", &name);
93 if (name != kRecoveryManifestName) 125 if (name != kRecoveryManifestName)
94 return; 126 return;
95 std::string proposed_version; 127 std::string proposed_version;
96 manifest->GetStringASCII("version", &proposed_version); 128 manifest->GetStringASCII("version", &proposed_version);
97 const Version version(proposed_version.c_str()); 129 const Version version(proposed_version.c_str());
98 if (!version.IsValid()) 130 if (!version.IsValid())
99 return; 131 return;
100 132
101 base::CommandLine cmdline(main_file); 133 base::CommandLine cmdline(main_file);
102 std::string arguments; 134 std::string arguments;
103 if (manifest->GetStringASCII("x-recovery-args", &arguments)) 135 if (manifest->GetStringASCII("x-recovery-args", &arguments))
104 cmdline.AppendArg(arguments); 136 cmdline.AppendArg(arguments);
105 std::string add_version; 137 std::string add_version;
106 if (manifest->GetStringASCII("x-recovery-add-version", &add_version) && 138 if (manifest->GetStringASCII("x-recovery-add-version", &add_version) &&
107 add_version == "yes") { 139 add_version == "yes") {
108 cmdline.AppendSwitchASCII("version", version.GetString()); 140 cmdline.AppendSwitchASCII("version", version.GetString());
109 } 141 }
110 142
143 UMA_HISTOGRAM_ENUMERATION("RecoveryComponent.Event", RCE_RUNNING_ELEVATED,
144 RCE_COUNT);
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(
gab 2015/01/12 19:12:20 Cool, didn't know of WorkerPool..! Are you sure th
robertshield 2015/01/12 23:04:19 As sure as I am of anything. Alexei will do an OWN
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 UMA_HISTOGRAM_ENUMERATION("RecoveryComponent.Event",
238 RCE_COMPONENT_DOWNLOAD_ERROR, RCE_COUNT);
197 NOTREACHED() << "Recovery component update error: " << error; 239 NOTREACHED() << "Recovery component update error: " << error;
198 } 240 }
199 241
200 #if defined(OS_WIN) 242 #if defined(OS_WIN)
201 void WaitForInstallToComplete(base::Process process, 243 void WaitForInstallToComplete(base::Process process,
202 const base::FilePath& installer_folder, 244 const base::FilePath& installer_folder,
203 PrefService* prefs) { 245 PrefService* prefs) {
204 int installer_exit_code = 0; 246 int installer_exit_code = 0;
205 const base::TimeDelta kMaxWaitTime = base::TimeDelta::FromSeconds(600); 247 const base::TimeDelta kMaxWaitTime = base::TimeDelta::FromSeconds(600);
206 if (process.WaitForExitWithTimeout(kMaxWaitTime, &installer_exit_code) && 248 if (!process.WaitForExitWithTimeout(kMaxWaitTime, &installer_exit_code)) {
gab 2015/01/12 19:12:20 Hmmm, the ! case should be the failure case in whi
robertshield 2015/01/12 23:04:19 Hrmm, actually, the ! there looks like a typo. Tha
207 installer_exit_code == EXIT_CODE_ELEVATION_NEEDED) { 249 if (installer_exit_code == EXIT_CODE_ELEVATION_NEEDED) {
208 BrowserThread::PostTask( 250 UMA_HISTOGRAM_ENUMERATION("RecoveryComponent.Event", RCE_ELEVATION_NEEDED,
209 BrowserThread::UI, 251 RCE_COUNT);
210 FROM_HERE, 252
211 base::Bind(&SetPrefsForElevatedRecoveryInstall, 253 BrowserThread::PostTask(
212 installer_folder, 254 BrowserThread::UI,
213 prefs)); 255 FROM_HERE,
256 base::Bind(&SetPrefsForElevatedRecoveryInstall,
257 installer_folder,
258 prefs));
259 } else if (installer_exit_code == EXIT_CODE_RECOVERY_SUCCEEDED) {
260 UMA_HISTOGRAM_ENUMERATION("RecoveryComponent.Event", RCE_SUCCEEDED,
261 RCE_COUNT);
262 } else if (installer_exit_code == EXIT_CODE_RECOVERY_SKIPPED) {
263 UMA_HISTOGRAM_ENUMERATION("RecoveryComponent.Event", RCE_SKIPPED,
264 RCE_COUNT);
265 }
266 } else {
267 UMA_HISTOGRAM_ENUMERATION("RecoveryComponent.Event", RCE_FAILED, RCE_COUNT);
214 } 268 }
215 } 269 }
216 270
217 bool RecoveryComponentInstaller::RunInstallCommand( 271 bool RecoveryComponentInstaller::RunInstallCommand(
218 const base::CommandLine& cmdline, 272 const base::CommandLine& cmdline,
219 const base::FilePath& installer_folder) const { 273 const base::FilePath& installer_folder) const {
274 UMA_HISTOGRAM_ENUMERATION("RecoveryComponent.Event", RCE_RUNNING_NON_ELEVATED,
275 RCE_COUNT);
276
220 base::LaunchOptions options; 277 base::LaunchOptions options;
221 options.start_hidden = true; 278 options.start_hidden = true;
222 base::Process process = base::LaunchProcess(cmdline, options); 279 base::Process process = base::LaunchProcess(cmdline, options);
223 if (!process.IsValid()) 280 if (!process.IsValid())
224 return false; 281 return false;
gab 2015/01/12 19:12:20 Do we care about this failure?
robertshield 2015/01/12 23:04:19 The existing code does, what motivates you to want
gab 2015/01/13 18:23:32 Yes, I was asking whether this should also result
225 282
226 // Let worker pool thread wait for us so we don't block Chrome shutdown. 283 // Let worker pool thread wait for us so we don't block Chrome shutdown.
227 base::WorkerPool::PostTask( 284 base::WorkerPool::PostTask(
228 FROM_HERE, 285 FROM_HERE,
229 base::Bind(&WaitForInstallToComplete, 286 base::Bind(&WaitForInstallToComplete,
230 base::Passed(&process), installer_folder, prefs_), 287 base::Passed(&process), installer_folder, prefs_),
231 true); 288 true);
232 289
233 // Returns true regardless of install result since from updater service 290 // Returns true regardless of install result since from updater service
234 // perspective the install is done, even we may need to do elevated 291 // perspective the install is done, even we may need to do elevated
235 // install later. 292 // install later.
236 return true; 293 return true;
237 } 294 }
238 #else 295 #else
239 bool RecoveryComponentInstaller::RunInstallCommand( 296 bool RecoveryComponentInstaller::RunInstallCommand(
240 const base::CommandLine& cmdline, 297 const base::CommandLine& cmdline,
241 const base::FilePath&) const { 298 const base::FilePath&) const {
242 return base::LaunchProcess(cmdline, base::LaunchOptions()).IsValid(); 299 return base::LaunchProcess(cmdline, base::LaunchOptions()).IsValid();
243 } 300 }
244 #endif 301 #endif // defined(OS_WIN)
245 302
246 bool RecoveryComponentInstaller::Install(const base::DictionaryValue& manifest, 303 bool RecoveryComponentInstaller::Install(const base::DictionaryValue& manifest,
247 const base::FilePath& unpack_path) { 304 const base::FilePath& unpack_path) {
248 std::string name; 305 std::string name;
249 manifest.GetStringASCII("name", &name); 306 manifest.GetStringASCII("name", &name);
250 if (name != kRecoveryManifestName) 307 if (name != kRecoveryManifestName)
251 return false; 308 return false;
252 std::string proposed_version; 309 std::string proposed_version;
253 manifest.GetStringASCII("version", &proposed_version); 310 manifest.GetStringASCII("version", &proposed_version);
254 Version version(proposed_version.c_str()); 311 Version version(proposed_version.c_str());
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
315 base::Bind(&SimulateElevatedRecoveryHelper, prefs)); 372 base::Bind(&SimulateElevatedRecoveryHelper, prefs));
316 } 373 }
317 374
318 // We delay execute the registration because we are not required in 375 // We delay execute the registration because we are not required in
319 // the critical path during browser startup. 376 // the critical path during browser startup.
320 BrowserThread::PostDelayedTask( 377 BrowserThread::PostDelayedTask(
321 BrowserThread::UI, 378 BrowserThread::UI,
322 FROM_HERE, 379 FROM_HERE,
323 base::Bind(&RecoveryRegisterHelper, cus, prefs), 380 base::Bind(&RecoveryRegisterHelper, cus, prefs),
324 base::TimeDelta::FromSeconds(6)); 381 base::TimeDelta::FromSeconds(6));
325 #endif 382 #endif // !defined(OS_CHROMEOS)
326 } 383 }
327 384
328 void RegisterPrefsForRecoveryComponent(PrefRegistrySimple* registry) { 385 void RegisterPrefsForRecoveryComponent(PrefRegistrySimple* registry) {
329 registry->RegisterStringPref(prefs::kRecoveryComponentVersion, "0.0.0.0"); 386 registry->RegisterStringPref(prefs::kRecoveryComponentVersion, "0.0.0.0");
330 registry->RegisterFilePathPref(prefs::kRecoveryComponentUnpackPath, 387 registry->RegisterFilePathPref(prefs::kRecoveryComponentUnpackPath,
331 base::FilePath()); 388 base::FilePath());
332 registry->RegisterBooleanPref(prefs::kRecoveryComponentNeedsElevation, false); 389 registry->RegisterBooleanPref(prefs::kRecoveryComponentNeedsElevation, false);
333 } 390 }
334 391
335 void AcceptedElevatedRecoveryInstall(PrefService* prefs) { 392 void AcceptedElevatedRecoveryInstall(PrefService* prefs) {
336 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 393 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
337 394
338 #if defined(OS_WIN) 395 #if defined(OS_WIN)
339 ElevatedInstallRecoveryComponent( 396 ElevatedInstallRecoveryComponent(
340 prefs->GetFilePath(prefs::kRecoveryComponentUnpackPath)); 397 prefs->GetFilePath(prefs::kRecoveryComponentUnpackPath));
341 #endif 398 #endif // OS_WIN
342 prefs->SetBoolean(prefs::kRecoveryComponentNeedsElevation, false); 399 prefs->SetBoolean(prefs::kRecoveryComponentNeedsElevation, false);
343 } 400 }
344 401
345 void DeclinedElevatedRecoveryInstall(PrefService* prefs) { 402 void DeclinedElevatedRecoveryInstall(PrefService* prefs) {
346 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 403 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
347 prefs->SetBoolean(prefs::kRecoveryComponentNeedsElevation, false); 404 prefs->SetBoolean(prefs::kRecoveryComponentNeedsElevation, false);
348 } 405 }
349 406
350 } // namespace component_updater 407 } // 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