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 if Google Update is present at the given level. |
| 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 |