OLD | NEW |
---|---|
(Empty) | |
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/installer/util/google_update_util.h" | |
6 | |
7 #include "base/command_line.h" | |
8 #include "base/file_path.h" | |
9 #include "base/file_util.h" | |
10 #include "base/logging.h" | |
11 #include "base/process_util.h" | |
12 #include "base/string16.h" | |
13 #include "base/time.h" | |
14 #include "base/win/registry.h" | |
15 #include "base/win/scoped_handle.h" | |
16 #include "chrome/installer/launcher_support/chrome_launcher_support.h" | |
17 #include "chrome/installer/util/google_update_constants.h" | |
18 #include "chrome/installer/util/google_update_settings.h" | |
19 | |
20 using base::win::RegKey; | |
21 | |
22 namespace google_update { | |
23 | |
24 namespace { | |
25 | |
26 const int kGoogleUpdateTimeoutMs = 20 * 1000; | |
27 | |
28 // Returns true iff Google Update is present at the given level. | |
grt (UTC plus 2)
2012/09/24 15:23:39
imo, "iff" doesn't make sense here. just use "if"
huangs
2012/09/24 15:50:59
Done.
| |
29 bool IsGoogleUpdatePresent(bool system_install) { | |
30 // Using the existence of version key in the registry to decide. | |
31 return GoogleUpdateSettings::GetGoogleUpdateVersion(system_install).IsValid(); | |
32 } | |
33 | |
34 // Returns GoogleUpdateSetup.exe's executable path at specified level. | |
35 // or an empty path if none is found. | |
36 FilePath GetGoogleUpdateSetupExe(bool system_install) { | |
37 const HKEY root_key = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; | |
38 RegKey update_key; | |
39 | |
40 if (update_key.Open(root_key, kRegPathGoogleUpdate, KEY_QUERY_VALUE) == | |
41 ERROR_SUCCESS) { | |
42 string16 path_str; | |
43 string16 version_str; | |
44 if ((update_key.ReadValue(kRegPathField, &path_str) == ERROR_SUCCESS) && | |
45 (update_key.ReadValue(kRegGoogleUpdateVersion, &version_str) == | |
46 ERROR_SUCCESS)) { | |
47 return FilePath(path_str).DirName().Append(version_str). | |
48 Append(kGoogleUpdateSetupExe); | |
49 } | |
50 } | |
51 return FilePath(); | |
52 } | |
53 | |
54 // If Google Update is present at system-level, sets |cmd_string| to the command | |
55 // line to install Google Update at user-level and returns true. | |
56 // Otherwise, clears |cmd_string| and returns false. | |
57 bool GetUserLevelGoogleUpdateInstallCommandLine(string16* cmd_string) { | |
58 cmd_string->clear(); | |
59 FilePath google_update_setup(GetGoogleUpdateSetupExe(true)); // system-level. | |
60 if (!google_update_setup.empty()) { | |
61 CommandLine cmd(google_update_setup); | |
62 // Appends parameter "/install runtime=true&needsadmin=false /silent" | |
63 // Constants are found in code.google.com/p/omaha/common/const_cmd_line.h. | |
64 cmd.AppendArg("/install"); | |
65 // The "&" can be used in base::LaunchProcess() without quotation | |
66 // (this is problematic only if run from command prompt). | |
67 cmd.AppendArg("runtime=true&needsadmin=false"); | |
68 cmd.AppendArg("/silent"); | |
69 *cmd_string = cmd.GetCommandLineString(); | |
70 } | |
71 return !cmd_string->empty(); | |
72 } | |
73 | |
74 // Launches command |cmd_string|, and waits for |timeout| milliseconds before | |
75 // timing out. To wait indefinitely, one can set | |
76 // |timeout| to be base::TimeDelta::FromMilliseconds(INFINITE). | |
77 // Returns true if this executes successfully. | |
78 // Returns false if command execution fails to execute, or times out. | |
79 bool LaunchProcessAndWaitWithTimeout(const string16& cmd_string, | |
80 base::TimeDelta timeout) { | |
81 bool success = false; | |
82 base::win::ScopedHandle process; | |
83 int exit_code = 0; | |
84 LOG(INFO) << "Launching: " << cmd_string; | |
85 if (!base::LaunchProcess(cmd_string, base::LaunchOptions(), | |
86 process.Receive())) { | |
87 PLOG(ERROR) << "Failed to launch (" << cmd_string << ")"; | |
88 } else if (!base::WaitForExitCodeWithTimeout(process, &exit_code, timeout)) { | |
89 // The GetExitCodeProcess failed or timed-out. | |
90 LOG(ERROR) <<"Command (" << cmd_string << ") is taking more than " | |
91 << timeout.InMilliseconds() << " milliseconds to complete."; | |
92 } else if (exit_code != 0) { | |
93 LOG(ERROR) << "Command (" << cmd_string << ") exited with code " | |
94 << exit_code; | |
95 } else { | |
96 success = true; | |
97 } | |
98 return success; | |
99 } | |
100 | |
101 } // namespace | |
102 | |
103 bool EnsureUserLevelGoogleUpdatePresent() { | |
104 LOG(INFO) << "Ensuring Google Update is present at user-level."; | |
105 | |
106 bool success = false; | |
107 if (IsGoogleUpdatePresent(false)) { | |
108 success = true; | |
109 } else { | |
110 string16 cmd_string; | |
111 if (!GetUserLevelGoogleUpdateInstallCommandLine(&cmd_string)) { | |
112 LOG(ERROR) << "Cannot find Google Update at system-level."; | |
113 } else { | |
114 success = LaunchProcessAndWaitWithTimeout(cmd_string, | |
115 base::TimeDelta::FromMilliseconds(INFINITE)); | |
116 } | |
117 } | |
118 return success; | |
119 } | |
120 | |
121 bool UninstallGoogleUpdate(bool system_install) { | |
122 bool success = false; | |
123 string16 cmd_string( | |
124 GoogleUpdateSettings::GetUninstallCommandLine(system_install)); | |
125 if (cmd_string.empty()) { | |
126 success = true; // Nothing to; vacuous success. | |
127 } else { | |
128 success = LaunchProcessAndWaitWithTimeout(cmd_string, | |
129 base::TimeDelta::FromMilliseconds(kGoogleUpdateTimeoutMs)); | |
130 } | |
131 return success; | |
132 } | |
133 | |
134 } // namespace google_update | |
OLD | NEW |