google_update_util.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
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 20using base::win::RegKey; 21 22namespace google_update { 23 24namespace { 25 26const int kGoogleUpdateTimeoutMs = 20 * 1000; 27 28// Returns true if Google Update is present at the given level. 29bool 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. 36FilePath 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. 57bool 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. 79bool 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 103bool 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 121bool 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 135