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

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: Expand to include result codes. 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)) {
xiaoling 2015/01/09 23:06:06 Does this block handle both of the following cases
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);
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(
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)) {
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_ELEVATION_NEEDED,
gab 2015/01/09 22:41:22 Wrong event here and below?
robertshield 2015/01/09 22:45:32 Done.
261 RCE_COUNT);
262 } else if (installer_exit_code == EXIT_CODE_RECOVERY_SKIPPED) {
263 UMA_HISTOGRAM_ENUMERATION("RecoveryComponent.Event", RCE_ELEVATION_NEEDED,
264 RCE_COUNT);
265 }
214 } 266 }
215 } 267 }
216 268
217 bool RecoveryComponentInstaller::RunInstallCommand( 269 bool RecoveryComponentInstaller::RunInstallCommand(
218 const base::CommandLine& cmdline, 270 const base::CommandLine& cmdline,
219 const base::FilePath& installer_folder) const { 271 const base::FilePath& installer_folder) const {
272 UMA_HISTOGRAM_ENUMERATION("RecoveryComponent.Event", RCE_RUNNING_NON_ELEVATED,
273 RCE_COUNT);
274
220 base::LaunchOptions options; 275 base::LaunchOptions options;
221 options.start_hidden = true; 276 options.start_hidden = true;
222 base::Process process = base::LaunchProcess(cmdline, options); 277 base::Process process = base::LaunchProcess(cmdline, options);
223 if (!process.IsValid()) 278 if (!process.IsValid())
224 return false; 279 return false;
225 280
226 // Let worker pool thread wait for us so we don't block Chrome shutdown. 281 // Let worker pool thread wait for us so we don't block Chrome shutdown.
227 base::WorkerPool::PostTask( 282 base::WorkerPool::PostTask(
228 FROM_HERE, 283 FROM_HERE,
229 base::Bind(&WaitForInstallToComplete, 284 base::Bind(&WaitForInstallToComplete,
230 base::Passed(&process), installer_folder, prefs_), 285 base::Passed(&process), installer_folder, prefs_),
231 true); 286 true);
232 287
233 // Returns true regardless of install result since from updater service 288 // Returns true regardless of install result since from updater service
234 // perspective the install is done, even we may need to do elevated 289 // perspective the install is done, even we may need to do elevated
235 // install later. 290 // install later.
236 return true; 291 return true;
237 } 292 }
238 #else 293 #else
239 bool RecoveryComponentInstaller::RunInstallCommand( 294 bool RecoveryComponentInstaller::RunInstallCommand(
240 const base::CommandLine& cmdline, 295 const base::CommandLine& cmdline,
241 const base::FilePath&) const { 296 const base::FilePath&) const {
242 return base::LaunchProcess(cmdline, base::LaunchOptions()).IsValid(); 297 return base::LaunchProcess(cmdline, base::LaunchOptions()).IsValid();
243 } 298 }
244 #endif 299 #endif // defined(OS_WIN)
245 300
246 bool RecoveryComponentInstaller::Install(const base::DictionaryValue& manifest, 301 bool RecoveryComponentInstaller::Install(const base::DictionaryValue& manifest,
247 const base::FilePath& unpack_path) { 302 const base::FilePath& unpack_path) {
248 std::string name; 303 std::string name;
249 manifest.GetStringASCII("name", &name); 304 manifest.GetStringASCII("name", &name);
250 if (name != kRecoveryManifestName) 305 if (name != kRecoveryManifestName)
251 return false; 306 return false;
252 std::string proposed_version; 307 std::string proposed_version;
253 manifest.GetStringASCII("version", &proposed_version); 308 manifest.GetStringASCII("version", &proposed_version);
254 Version version(proposed_version.c_str()); 309 Version version(proposed_version.c_str());
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
315 base::Bind(&SimulateElevatedRecoveryHelper, prefs)); 370 base::Bind(&SimulateElevatedRecoveryHelper, prefs));
316 } 371 }
317 372
318 // We delay execute the registration because we are not required in 373 // We delay execute the registration because we are not required in
319 // the critical path during browser startup. 374 // the critical path during browser startup.
320 BrowserThread::PostDelayedTask( 375 BrowserThread::PostDelayedTask(
321 BrowserThread::UI, 376 BrowserThread::UI,
322 FROM_HERE, 377 FROM_HERE,
323 base::Bind(&RecoveryRegisterHelper, cus, prefs), 378 base::Bind(&RecoveryRegisterHelper, cus, prefs),
324 base::TimeDelta::FromSeconds(6)); 379 base::TimeDelta::FromSeconds(6));
325 #endif 380 #endif // !defined(OS_CHROMEOS)
326 } 381 }
327 382
328 void RegisterPrefsForRecoveryComponent(PrefRegistrySimple* registry) { 383 void RegisterPrefsForRecoveryComponent(PrefRegistrySimple* registry) {
329 registry->RegisterStringPref(prefs::kRecoveryComponentVersion, "0.0.0.0"); 384 registry->RegisterStringPref(prefs::kRecoveryComponentVersion, "0.0.0.0");
330 registry->RegisterFilePathPref(prefs::kRecoveryComponentUnpackPath, 385 registry->RegisterFilePathPref(prefs::kRecoveryComponentUnpackPath,
331 base::FilePath()); 386 base::FilePath());
332 registry->RegisterBooleanPref(prefs::kRecoveryComponentNeedsElevation, false); 387 registry->RegisterBooleanPref(prefs::kRecoveryComponentNeedsElevation, false);
333 } 388 }
334 389
335 void AcceptedElevatedRecoveryInstall(PrefService* prefs) { 390 void AcceptedElevatedRecoveryInstall(PrefService* prefs) {
336 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 391 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
337 392
338 #if defined(OS_WIN) 393 #if defined(OS_WIN)
339 ElevatedInstallRecoveryComponent( 394 ElevatedInstallRecoveryComponent(
340 prefs->GetFilePath(prefs::kRecoveryComponentUnpackPath)); 395 prefs->GetFilePath(prefs::kRecoveryComponentUnpackPath));
341 #endif 396 #endif // OS_WIN
342 prefs->SetBoolean(prefs::kRecoveryComponentNeedsElevation, false); 397 prefs->SetBoolean(prefs::kRecoveryComponentNeedsElevation, false);
343 } 398 }
344 399
345 void DeclinedElevatedRecoveryInstall(PrefService* prefs) { 400 void DeclinedElevatedRecoveryInstall(PrefService* prefs) {
346 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 401 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
347 prefs->SetBoolean(prefs::kRecoveryComponentNeedsElevation, false); 402 prefs->SetBoolean(prefs::kRecoveryComponentNeedsElevation, false);
348 } 403 }
349 404
350 } // namespace component_updater 405 } // 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