Chromium Code Reviews| OLD | NEW |
|---|---|
| 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/google/google_update_win.h" | 5 #include "chrome/browser/google/google_update_win.h" |
| 6 | 6 |
| 7 #include <atlbase.h> | 7 #include <atlbase.h> |
| 8 #include <atlcom.h> | 8 #include <atlcom.h> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| 11 #include "base/callback.h" | 11 #include "base/callback.h" |
| 12 #include "base/files/file_path.h" | 12 #include "base/files/file_path.h" |
| 13 #include "base/location.h" | 13 #include "base/location.h" |
| 14 #include "base/metrics/histogram.h" | 14 #include "base/metrics/histogram.h" |
| 15 #include "base/metrics/sparse_histogram.h" | 15 #include "base/metrics/sparse_histogram.h" |
| 16 #include "base/path_service.h" | 16 #include "base/path_service.h" |
| 17 #include "base/sequenced_task_runner_helpers.h" | |
| 18 #include "base/single_thread_task_runner.h" | |
| 17 #include "base/strings/string_util.h" | 19 #include "base/strings/string_util.h" |
| 18 #include "base/strings/stringprintf.h" | 20 #include "base/strings/stringprintf.h" |
| 21 #include "base/strings/utf_string_conversions.h" | |
| 19 #include "base/task_runner.h" | 22 #include "base/task_runner.h" |
| 20 #include "base/thread_task_runner_handle.h" | 23 #include "base/thread_task_runner_handle.h" |
| 24 #include "base/time/time.h" | |
| 25 #include "base/win/scoped_bstr.h" | |
| 21 #include "base/win/windows_version.h" | 26 #include "base/win/windows_version.h" |
| 22 #include "chrome/grit/generated_resources.h" | 27 #include "chrome/grit/generated_resources.h" |
| 23 #include "chrome/installer/util/browser_distribution.h" | 28 #include "chrome/installer/util/browser_distribution.h" |
| 24 #include "chrome/installer/util/google_update_settings.h" | |
| 25 #include "chrome/installer/util/helper.h" | 29 #include "chrome/installer/util/helper.h" |
| 26 #include "chrome/installer/util/install_util.h" | 30 #include "chrome/installer/util/install_util.h" |
| 27 #include "content/public/browser/browser_thread.h" | |
| 28 #include "ui/base/l10n/l10n_util.h" | 31 #include "ui/base/l10n/l10n_util.h" |
| 29 #include "ui/base/win/atl_module.h" | 32 #include "ui/base/win/atl_module.h" |
| 30 | 33 |
| 31 namespace { | 34 namespace { |
| 32 | 35 |
| 33 OnDemandAppsClassFactory* g_google_update_factory = nullptr; | 36 GoogleUpdate3ClassFactory* g_google_update_factory = nullptr; |
| 37 | |
| 38 // Constants from Google Update. | |
| 39 const HRESULT GOOPDATE_E_APP_UPDATE_DISABLED_BY_POLICY = 0x80040813; | |
| 40 const HRESULT GOOPDATEINSTALL_E_INSTALLER_FAILED = 0x80040902; | |
| 34 | 41 |
| 35 // Check if the currently running instance can be updated by Google Update. | 42 // Check if the currently running instance can be updated by Google Update. |
| 36 // Returns GOOGLE_UPDATE_NO_ERROR only if the instance running is a Google | 43 // Returns GOOGLE_UPDATE_NO_ERROR only if the instance running is a Google |
| 37 // Chrome distribution installed in a standard location. | 44 // Chrome distribution installed in a standard location. |
| 38 GoogleUpdateErrorCode CanUpdateCurrentChrome( | 45 GoogleUpdateErrorCode CanUpdateCurrentChrome( |
| 39 const base::FilePath& chrome_exe_path, | 46 const base::FilePath& chrome_exe_path, |
| 40 bool system_level) { | 47 bool system_level) { |
| 41 #if !defined(GOOGLE_CHROME_BUILD) | 48 #if !defined(GOOGLE_CHROME_BUILD) |
| 42 return CANNOT_UPGRADE_CHROME_IN_THIS_DIRECTORY; | 49 return CANNOT_UPGRADE_CHROME_IN_THIS_DIRECTORY; |
| 43 #else | 50 #else |
| 44 DCHECK_NE(InstallUtil::IsPerUserInstall(chrome_exe_path), system_level); | 51 DCHECK_NE(InstallUtil::IsPerUserInstall(chrome_exe_path), system_level); |
| 45 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); | 52 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); |
| 46 base::FilePath user_exe_path = installer::GetChromeInstallPath(false, dist); | 53 base::FilePath user_exe_path = installer::GetChromeInstallPath(false, dist); |
| 47 base::FilePath machine_exe_path = installer::GetChromeInstallPath(true, dist); | 54 base::FilePath machine_exe_path = installer::GetChromeInstallPath(true, dist); |
| 48 if (!base::FilePath::CompareEqualIgnoreCase(chrome_exe_path.value(), | 55 if (!base::FilePath::CompareEqualIgnoreCase(chrome_exe_path.value(), |
| 49 user_exe_path.value()) && | 56 user_exe_path.value()) && |
| 50 !base::FilePath::CompareEqualIgnoreCase(chrome_exe_path.value(), | 57 !base::FilePath::CompareEqualIgnoreCase(chrome_exe_path.value(), |
| 51 machine_exe_path.value())) { | 58 machine_exe_path.value())) { |
| 52 return CANNOT_UPGRADE_CHROME_IN_THIS_DIRECTORY; | 59 return CANNOT_UPGRADE_CHROME_IN_THIS_DIRECTORY; |
| 53 } | 60 } |
| 54 | 61 |
| 55 base::string16 app_guid = installer::GetAppGuidForUpdates(system_level); | |
| 56 DCHECK(!app_guid.empty()); | |
| 57 | |
| 58 GoogleUpdateSettings::UpdatePolicy update_policy = | |
| 59 GoogleUpdateSettings::GetAppUpdatePolicy(app_guid, NULL); | |
| 60 | |
| 61 if (update_policy == GoogleUpdateSettings::UPDATES_DISABLED) | |
| 62 return GOOGLE_UPDATE_DISABLED_BY_POLICY; | |
| 63 | |
| 64 if (update_policy == GoogleUpdateSettings::AUTO_UPDATES_ONLY) | |
| 65 return GOOGLE_UPDATE_DISABLED_BY_POLICY_AUTO_ONLY; | |
| 66 | |
| 67 return GOOGLE_UPDATE_NO_ERROR; | 62 return GOOGLE_UPDATE_NO_ERROR; |
| 68 #endif | 63 #endif |
| 69 } | 64 } |
| 70 | 65 |
| 71 // Creates an instance of a COM Local Server class using either plain vanilla | 66 // Creates an instance of a COM Local Server class using either plain vanilla |
| 72 // CoCreateInstance, or using the Elevation moniker if running on Vista. | 67 // CoCreateInstance, or using the Elevation moniker if running on Vista. |
| 73 // hwnd must refer to a foregound window in order to get the UAC prompt | 68 // hwnd must refer to a foregound window in order to get the UAC prompt |
| 74 // showing up in the foreground if running on Vista. It can also be NULL if | 69 // showing up in the foreground if running on Vista. It can also be NULL if |
| 75 // background UAC prompts are desired. | 70 // background UAC prompts are desired. |
| 76 HRESULT CoCreateInstanceAsAdmin(REFCLSID class_id, | 71 HRESULT CoCreateInstanceAsAdmin(REFCLSID class_id, |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 100 bind_opts.hwnd = hwnd; | 95 bind_opts.hwnd = hwnd; |
| 101 | 96 |
| 102 return CoGetObject(elevation_moniker_name.c_str(), &bind_opts, interface_id, | 97 return CoGetObject(elevation_moniker_name.c_str(), &bind_opts, interface_id, |
| 103 interface_ptr); | 98 interface_ptr); |
| 104 } | 99 } |
| 105 | 100 |
| 106 return CoCreateInstance(class_id, NULL, CLSCTX_LOCAL_SERVER, interface_id, | 101 return CoCreateInstance(class_id, NULL, CLSCTX_LOCAL_SERVER, interface_id, |
| 107 interface_ptr); | 102 interface_ptr); |
| 108 } | 103 } |
| 109 | 104 |
| 110 HRESULT CreateOnDemandAppsClass( | 105 HRESULT CreateGoogleUpdate3Class( |
| 111 bool system_level, | 106 bool system_level, |
| 112 bool install_if_newer, | 107 bool install_if_newer, |
| 113 gfx::AcceleratedWidget elevation_window, | 108 gfx::AcceleratedWidget elevation_window, |
| 114 base::win::ScopedComPtr<IGoogleUpdate>* on_demand) { | 109 base::win::ScopedComPtr<IGoogleUpdate3>* google_update) { |
| 115 if (g_google_update_factory) | 110 if (g_google_update_factory) |
| 116 return g_google_update_factory->Run(on_demand); | 111 return g_google_update_factory->Run(google_update); |
| 117 | 112 |
| 118 // For a user-level install, update checks and updates can both be done by a | 113 // For a user-level install, update checks and updates can both be done by a |
| 119 // normal user with the UserAppsClass. | 114 // normal user with the UserClass. |
| 120 if (!system_level) | 115 if (!system_level) |
| 121 return on_demand->CreateInstance(CLSID_OnDemandUserAppsClass); | 116 return google_update->CreateInstance(CLSID_GoogleUpdate3UserClass); |
| 122 | 117 |
| 123 // For a system-level install, update checks can be done by a normal user with | 118 // For a system-level install, update checks can be done by a normal user with |
| 124 // the MachineAppsClass. | 119 // the ServiceClass. |
| 125 if (!install_if_newer) | 120 if (!install_if_newer) |
| 126 return on_demand->CreateInstance(CLSID_OnDemandMachineAppsClass); | 121 return google_update->CreateInstance(CLSID_GoogleUpdate3ServiceClass); |
| 127 | 122 |
| 128 // For a system-level install, an update requires Admin privileges for writing | 123 // For a system-level install, an update requires Admin privileges for writing |
| 129 // to %ProgramFiles%. Elevate while instantiating the MachineAppsClass. | 124 // to %ProgramFiles%. Elevate while instantiating the ServiceClass. |
| 130 return CoCreateInstanceAsAdmin(CLSID_OnDemandMachineAppsClass, | 125 return CoCreateInstanceAsAdmin(CLSID_GoogleUpdate3ServiceClass, |
| 131 IID_IGoogleUpdate, elevation_window, | 126 IID_IGoogleUpdate3, elevation_window, |
| 132 on_demand->ReceiveVoid()); | 127 google_update->ReceiveVoid()); |
| 133 } | 128 } |
| 134 | 129 |
| 135 | |
| 136 // GoogleUpdateJobObserver ----------------------------------------------------- | |
| 137 | |
| 138 // The GoogleUpdateJobObserver COM class is responsible for receiving status | |
| 139 // reports from google Update. It keeps track of the progress as Google Update | |
| 140 // notifies this observer and runs a completion callback once Google Update | |
| 141 // reports that it is done. | |
| 142 class GoogleUpdateJobObserver : public CComObjectRootEx<CComSingleThreadModel>, | |
| 143 public IJobObserver { | |
| 144 public: | |
| 145 BEGIN_COM_MAP(GoogleUpdateJobObserver) | |
| 146 COM_INTERFACE_ENTRY(IJobObserver) | |
| 147 END_COM_MAP() | |
| 148 | |
| 149 GoogleUpdateJobObserver(); | |
| 150 virtual ~GoogleUpdateJobObserver(); | |
| 151 | |
| 152 // Sets the callback to be invoked when Google Update reports that the job is | |
| 153 // done. | |
| 154 void set_on_complete_callback(const base::Closure& on_complete_callback) { | |
| 155 on_complete_callback_ = on_complete_callback; | |
| 156 } | |
| 157 | |
| 158 // Returns the results of the update operation. | |
| 159 GoogleUpdateUpgradeResult result() const { | |
| 160 // Intermediary steps should never be reported to the client. | |
| 161 DCHECK_NE(UPGRADE_STARTED, result_); | |
| 162 DCHECK_NE(UPGRADE_CHECK_STARTED, result_); | |
| 163 return result_; | |
| 164 } | |
| 165 | |
| 166 // Returns which version Google Update found on the server (if a more | |
| 167 // recent version was found). Otherwise, this will be blank. | |
| 168 base::string16 new_version() const { return new_version_; } | |
| 169 | |
| 170 // Returns the Google Update supplied error string that describes the error | |
| 171 // that occurred during the update check/upgrade. | |
| 172 base::string16 error_message() const { return error_message_; } | |
| 173 | |
| 174 private: | |
| 175 // IJobObserver: | |
| 176 STDMETHOD(OnShow)() override; | |
| 177 STDMETHOD(OnCheckingForUpdate)() override; | |
| 178 STDMETHOD(OnUpdateAvailable)(const TCHAR* version_string) override; | |
| 179 STDMETHOD(OnWaitingToDownload)() override; | |
| 180 STDMETHOD(OnDownloading)(int time_remaining_ms, int pos) override; | |
| 181 STDMETHOD(OnWaitingToInstall)() override; | |
| 182 STDMETHOD(OnInstalling)() override; | |
| 183 STDMETHOD(OnPause)() override; | |
| 184 STDMETHOD(OnComplete)(LegacyCompletionCodes code, const TCHAR* text) override; | |
| 185 STDMETHOD(SetEventSink)(IProgressWndEvents* event_sink) override; | |
| 186 | |
| 187 // The task runner associated with the thread in which the job runs. | |
| 188 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; | |
| 189 | |
| 190 // A callback to be run to complete processing; | |
| 191 base::Closure on_complete_callback_; | |
| 192 | |
| 193 // The status/result of the Google Update operation. | |
| 194 GoogleUpdateUpgradeResult result_; | |
| 195 | |
| 196 // The version string Google Update found. | |
| 197 base::string16 new_version_; | |
| 198 | |
| 199 // An error message, if any. | |
| 200 base::string16 error_message_; | |
| 201 | |
| 202 // Allows us control the upgrade process to a small degree. After OnComplete | |
| 203 // has been called, this object can not be used. | |
| 204 base::win::ScopedComPtr<IProgressWndEvents> event_sink_; | |
| 205 | |
| 206 DISALLOW_COPY_AND_ASSIGN(GoogleUpdateJobObserver); | |
| 207 }; | |
| 208 | |
| 209 GoogleUpdateJobObserver::GoogleUpdateJobObserver() | |
| 210 : task_runner_(base::ThreadTaskRunnerHandle::Get()), | |
| 211 result_(UPGRADE_ERROR) { | |
| 212 } | |
| 213 | |
| 214 GoogleUpdateJobObserver::~GoogleUpdateJobObserver() { | |
| 215 } | |
| 216 | |
| 217 STDMETHODIMP GoogleUpdateJobObserver::OnShow() { | |
| 218 return S_OK; | |
| 219 } | |
| 220 | |
| 221 STDMETHODIMP GoogleUpdateJobObserver::OnCheckingForUpdate() { | |
| 222 result_ = UPGRADE_CHECK_STARTED; | |
| 223 return S_OK; | |
| 224 } | |
| 225 | |
| 226 STDMETHODIMP GoogleUpdateJobObserver::OnUpdateAvailable( | |
| 227 const TCHAR* version_string) { | |
| 228 result_ = UPGRADE_IS_AVAILABLE; | |
| 229 new_version_ = version_string; | |
| 230 return S_OK; | |
| 231 } | |
| 232 | |
| 233 STDMETHODIMP GoogleUpdateJobObserver::OnWaitingToDownload() { | |
| 234 return S_OK; | |
| 235 } | |
| 236 | |
| 237 STDMETHODIMP GoogleUpdateJobObserver::OnDownloading(int time_remaining_ms, | |
| 238 int pos) { | |
| 239 return S_OK; | |
| 240 } | |
| 241 | |
| 242 STDMETHODIMP GoogleUpdateJobObserver::OnWaitingToInstall() { | |
| 243 return S_OK; | |
| 244 } | |
| 245 | |
| 246 STDMETHODIMP GoogleUpdateJobObserver::OnInstalling() { | |
| 247 result_ = UPGRADE_STARTED; | |
| 248 return S_OK; | |
| 249 } | |
| 250 | |
| 251 STDMETHODIMP GoogleUpdateJobObserver::OnPause() { | |
| 252 return S_OK; | |
| 253 } | |
| 254 | |
| 255 STDMETHODIMP GoogleUpdateJobObserver::OnComplete(LegacyCompletionCodes code, | |
| 256 const TCHAR* text) { | |
| 257 if (code == COMPLETION_CODE_ERROR) { | |
| 258 error_message_ = text; | |
| 259 result_ = UPGRADE_ERROR; | |
| 260 } else { | |
| 261 // Everything that isn't an error is some form of success. Chrome doesn't | |
| 262 // support any of the fancy codes (e.g., COMPLETION_CODE_REBOOT), but they | |
| 263 // shouldn't be generated anyway. | |
| 264 LOG_IF(DFATAL, (code != COMPLETION_CODE_SUCCESS && | |
| 265 code != COMPLETION_CODE_SUCCESS_CLOSE_UI)) | |
| 266 << "Unexpected LegacyCompletionCode from IGoogleUpdate: " << code; | |
| 267 if (result_ == UPGRADE_STARTED) | |
| 268 result_ = UPGRADE_SUCCESSFUL; | |
| 269 else if (result_ == UPGRADE_CHECK_STARTED) | |
| 270 result_ = UPGRADE_ALREADY_UP_TO_DATE; | |
| 271 } | |
| 272 | |
| 273 event_sink_ = NULL; | |
| 274 | |
| 275 task_runner_->PostTask(FROM_HERE, on_complete_callback_); | |
| 276 return S_OK; | |
| 277 } | |
| 278 | |
| 279 STDMETHODIMP GoogleUpdateJobObserver::SetEventSink( | |
| 280 IProgressWndEvents* event_sink) { | |
| 281 event_sink_ = event_sink; | |
| 282 return S_OK; | |
| 283 } | |
| 284 | |
| 285 | |
| 286 // UpdateCheckDriver ----------------------------------------------------------- | 130 // UpdateCheckDriver ----------------------------------------------------------- |
| 287 | 131 |
| 288 // A driver that is created and destroyed on the caller's thread and drives | 132 // A driver that is created and destroyed on the caller's thread and drives |
| 289 // Google Update on another. | 133 // Google Update on another. |
| 290 class UpdateCheckDriver { | 134 class UpdateCheckDriver { |
| 291 public: | 135 public: |
| 292 // Runs an update check on |task_runner|, invoking |callback| on the caller's | 136 // Runs an update check on |task_runner|, invoking |callback| on the caller's |
| 293 // thread upon completion. |task_runner| must run a TYPE_UI message loop if | 137 // thread upon completion. |task_runner| must run a TYPE_UI message loop if |
| 294 // the default IGoogleUpdate on-demand COM class is used. | 138 // the default IGoogleUpdate on-demand COM class is used. |
| 295 static void RunUpdateCheck(const scoped_refptr<base::TaskRunner>& task_runner, | 139 static void RunUpdateCheck(const scoped_refptr<base::TaskRunner>& task_runner, |
| 140 const std::string& locale, | |
| 296 bool install_if_newer, | 141 bool install_if_newer, |
| 297 gfx::AcceleratedWidget elevation_window, | 142 gfx::AcceleratedWidget elevation_window, |
| 298 const UpdateCheckCallback& callback); | 143 const UpdateCheckCallback& callback); |
| 299 | 144 |
| 300 private: | 145 private: |
| 301 friend class base::DeleteHelper<UpdateCheckDriver>; | 146 friend class base::DeleteHelper<UpdateCheckDriver>; |
| 302 | 147 |
| 303 explicit UpdateCheckDriver(const UpdateCheckCallback& callback); | 148 UpdateCheckDriver(const scoped_refptr<base::TaskRunner>& task_runner, |
| 149 const std::string& locale, | |
| 150 bool install_if_newer, | |
| 151 gfx::AcceleratedWidget elevation_window, | |
| 152 const UpdateCheckCallback& callback); | |
| 304 | 153 |
| 305 // Runs the caller's update check callback with the results of the operation. | 154 // Runs the caller's update check callback with the results of the operation. |
| 306 ~UpdateCheckDriver(); | 155 ~UpdateCheckDriver(); |
| 307 | 156 |
| 308 // Starts an update check. | 157 // Starts an update check. |
| 309 void BeginUpdateCheck(bool install_if_newer, | 158 void BeginUpdateCheck(); |
| 310 gfx::AcceleratedWidget elevation_window); | |
| 311 | 159 |
| 312 // Helper function for starting an update check. Returns true if the check was | 160 // Helper function for starting an update check. Returns true if the check was |
| 313 // properly started, in which case CompleteUpdateCheck will be invoked upon | 161 // properly started. |
| 314 // completion to return results to the caller on its own thread. | 162 bool BeginUpdateCheckInternal(); |
| 315 bool BeginUpdateCheckInternal(bool install_if_newer, | |
| 316 gfx::AcceleratedWidget elevation_window); | |
| 317 | |
| 318 // Invoked when results are in from Google Update. | |
| 319 void CompleteUpdateCheck(); | |
| 320 | 163 |
| 321 // Prepares |results| to return the upgrade error indicated by |error_code| | 164 // Prepares |results| to return the upgrade error indicated by |error_code| |
|
Peter Kasting
2015/05/07 22:37:29
What is |results|? Does this mean |result_|?
grt (UTC plus 2)
2015/05/08 18:51:50
Comment revised.
| |
| 322 // and |hr|. The string " -- system level" is included in the generated error | 165 // and |hr|. The string " -- system level" is included in the generated error |
| 323 // message when |system_level| is true. | 166 // message when appropriate. |
| 324 void OnUpgradeError(GoogleUpdateErrorCode error_code, | 167 void OnUpgradeError(GoogleUpdateErrorCode error_code, |
| 325 HRESULT hr, | 168 HRESULT hr, |
|
Peter Kasting
2015/05/07 22:37:28
Nit: Some functions use |hr| and some |hresult| --
grt (UTC plus 2)
2015/05/08 18:51:50
Done.
| |
| 326 bool system_level); | 169 int installer_exit_code, |
| 170 const base::string16& error_string); | |
| 171 | |
| 172 // Returns true if |current_state| and |state_value| can be obtained from the | |
| 173 // ongoing update check. Otherwise, populates |hresult| with the reason they | |
| 174 // could not be obtained. | |
|
Peter Kasting
2015/05/07 22:37:29
Is it possible to simply return the HRESULT, using
grt (UTC plus 2)
2015/05/08 18:51:49
Yes, although I find that the logic in PollGoogleU
| |
| 175 bool GetCurrentState(base::win::ScopedComPtr<ICurrentState>* current_state, | |
| 176 CurrentState* state_value, | |
| 177 HRESULT* hresult); | |
| 178 | |
| 179 // Returns true if |current_state| and |state_value| constitute an error state | |
| 180 // for the ongoing update check, in which case |error_code| is populated with | |
| 181 // one of GOOGLE_UPDATE_ERROR_UPDATING, GOOGLE_UPDATE_DISABLED_BY_POLICY, or | |
| 182 // GOOGLE_UPDATE_ONDEMAND_CLASS_REPORTED_ERROR. |hresult| is populated with | |
| 183 // the most relevant HRESULT (which may be a value from Google Update; see | |
| 184 // https://code.google.com/p/omaha/source/browse/trunk/base/error.h). In case | |
| 185 // Chrome's installer failed during execution, |installer_exit_code| may be | |
| 186 // populated with its process exit code (see enum installer::InstallStatus in | |
| 187 // chrome/installer/util/util_constants.h); otherwise, it will be -1. | |
| 188 // |error_string| will be populated with a completion message if one is | |
| 189 // provided by Google Update. | |
| 190 bool IsErrorState(const base::win::ScopedComPtr<ICurrentState>& current_state, | |
| 191 CurrentState state_value, | |
| 192 GoogleUpdateErrorCode* error_code, | |
| 193 HRESULT* hresult, | |
| 194 int* installer_exit_code, | |
| 195 base::string16* error_string); | |
| 196 | |
| 197 // Returns true if |current_state| and |state_value| constitute a final state | |
| 198 // for the ongoing update check, in which case |upgrade_result| is populated | |
| 199 // with one of UPGRADE_ALREADY_UP_TO_DATE or UPGRADE_IS_AVAILABLE (in case a | |
| 200 // pure check is being performed rather than an update) or UPGRADE_SUCCESSFUL | |
| 201 // (in case an update is being performed). For the UPGRADE_IS_AVAILABLE case, | |
| 202 // |new_version| will be populated with the available version, if provided by | |
| 203 // Google Update. | |
| 204 bool IsFinalState(const base::win::ScopedComPtr<ICurrentState>& current_state, | |
| 205 CurrentState state_value, | |
| 206 GoogleUpdateUpgradeResult* upgrade_result, | |
| 207 base::string16* new_version); | |
| 208 | |
| 209 // Returns true if |current_state| and |state_value| constitute an | |
| 210 // intermediate state for the ongoing update check, in which case | |
| 211 // |upgrade_result| is populated with UPGRADE_STARTED (in case an update is | |
| 212 // being performed) or UPGRADE_CHECK_STARTED (in case a pure check is being | |
| 213 // performed rather than an update). |new_version| will be populated with the | |
| 214 // version to be installed if it is provided by Google Update for the current | |
| 215 // state. |progress| will be populated with a number between 0.0 and 1.0 | |
| 216 // according to how far Google Update has progressed in the download and | |
| 217 // install process. | |
| 218 bool IsIntermediateState( | |
|
Peter Kasting
2015/05/07 22:37:28
Nit: Somehow conceptually it seems like this shoul
grt (UTC plus 2)
2015/05/08 18:51:49
I have them in this order to match the order in wh
| |
| 219 const base::win::ScopedComPtr<ICurrentState>& current_state, | |
| 220 CurrentState state_value, | |
| 221 GoogleUpdateUpgradeResult* upgrade_result, | |
| 222 base::string16* new_version, | |
| 223 double* progress); | |
| 224 | |
| 225 // Pools Google Update to determine the state of the ongoing check or | |
|
Peter Kasting
2015/05/07 22:37:28
Nit: Polls
grt (UTC plus 2)
2015/05/08 18:51:49
Doh!
| |
| 226 // update. If the process has reached a terminal state, this instance will be | |
| 227 // deleted and the caller will be notified of the final status. Otherwise, the | |
| 228 // caller will be notified of the intermediate state (iff it differs from a | |
| 229 // previuos notification) and another future poll will be scheduled. | |
|
Peter Kasting
2015/05/07 22:37:29
Nit: previous
grt (UTC plus 2)
2015/05/08 18:51:49
Done.
| |
| 230 void PollGoogleUpdate(); | |
| 231 | |
| 232 // The task runner on which the update checks runs. | |
| 233 scoped_refptr<base::TaskRunner> task_runner_; | |
| 327 | 234 |
| 328 // The caller's task runner, on which |result_callback_| will be run. | 235 // The caller's task runner, on which |result_callback_| will be run. |
| 329 scoped_refptr<base::SingleThreadTaskRunner> result_runner_; | 236 scoped_refptr<base::SingleThreadTaskRunner> result_runner_; |
| 330 | 237 |
| 238 // The UI locale. | |
| 239 std::string locale_; | |
| 240 | |
| 241 // False to only check for an update; true to also install one if available. | |
| 242 bool install_if_newer_; | |
|
Peter Kasting
2015/05/07 22:37:28
Nit: install_update_if_possible_ or install_availa
grt (UTC plus 2)
2015/05/08 18:51:49
Done.
| |
| 243 | |
| 244 // A parent window in case any UX is required (e.g., an elevation prompt). | |
| 245 gfx::AcceleratedWidget elevation_window_; | |
| 246 | |
| 331 // The caller's callback to be run when the update check is compelte. | 247 // The caller's callback to be run when the update check is compelte. |
| 332 UpdateCheckCallback result_callback_; | 248 UpdateCheckCallback result_callback_; |
| 333 | 249 |
| 334 // The results of the update check. | 250 // True if operating at system-level. |
|
Peter Kasting
2015/05/07 22:37:28
Nit: "...instead of user-level" (I assume)
grt (UTC plus 2)
2015/05/08 18:51:49
Done.
| |
| 251 bool system_level_; | |
| 252 | |
| 253 // The on-demand updater that is doing the work. | |
| 254 base::win::ScopedComPtr<IGoogleUpdate3> google_update_; | |
| 255 | |
| 256 // An app bundle containing the application being updated. | |
| 257 base::win::ScopedComPtr<IAppBundle> app_bundle_; | |
| 258 | |
| 259 // The application being updated (Chrome, Chrome Binaries, or Chrome SxS). | |
| 260 base::win::ScopedComPtr<IApp> app_; | |
| 261 | |
| 262 // The intermediate status of an ongoing operation that was most recently | |
| 263 // reported to the caller. | |
| 264 GoogleUpdateUpgradeResult last_result_; | |
| 265 double last_progress_; | |
| 266 | |
| 267 // The results of the update check to be logged via UMA and/or reported to the | |
| 268 // caller. | |
| 335 GoogleUpdateUpgradeResult result_; | 269 GoogleUpdateUpgradeResult result_; |
| 336 GoogleUpdateErrorCode error_code_; | 270 GoogleUpdateErrorCode error_code_; |
| 337 base::string16 error_message_; | 271 base::string16 error_message_; |
| 338 base::string16 version_; | 272 base::string16 new_version_; |
| 339 HRESULT hresult_; | 273 HRESULT hresult_; |
| 340 | 274 int installer_exit_code_; |
| 341 // A direct pointer to the job observer by which the driver is notified of | |
| 342 // interesting events from Google Update. | |
| 343 CComObject<GoogleUpdateJobObserver>* job_observer_; | |
| 344 | |
| 345 // A scoped pointer to |job_observer_| that holds a reference to it, keeping | |
| 346 // it alive. | |
| 347 base::win::ScopedComPtr<IJobObserver> job_holder_; | |
| 348 | |
| 349 // The on-demand updater that is doing the work. | |
| 350 base::win::ScopedComPtr<IGoogleUpdate> on_demand_; | |
| 351 | 275 |
| 352 DISALLOW_COPY_AND_ASSIGN(UpdateCheckDriver); | 276 DISALLOW_COPY_AND_ASSIGN(UpdateCheckDriver); |
| 353 }; | 277 }; |
| 354 | 278 |
| 355 // static | 279 // static |
| 356 void UpdateCheckDriver::RunUpdateCheck( | 280 void UpdateCheckDriver::RunUpdateCheck( |
| 357 const scoped_refptr<base::TaskRunner>& task_runner, | 281 const scoped_refptr<base::TaskRunner>& task_runner, |
| 282 const std::string& locale, | |
| 358 bool install_if_newer, | 283 bool install_if_newer, |
| 359 gfx::AcceleratedWidget elevation_window, | 284 gfx::AcceleratedWidget elevation_window, |
| 360 const UpdateCheckCallback& callback) { | 285 const UpdateCheckCallback& callback) { |
| 361 // The driver is owned by itself, and will self-destruct when its work is | 286 // The driver is owned by itself, and will self-destruct when its work is |
| 362 // done. | 287 // done. |
| 363 UpdateCheckDriver* driver = new UpdateCheckDriver(callback); | 288 UpdateCheckDriver* driver = new UpdateCheckDriver( |
| 364 task_runner->PostTask( | 289 task_runner, locale, install_if_newer, elevation_window, callback); |
| 365 FROM_HERE, | 290 task_runner->PostTask(FROM_HERE, |
| 366 base::Bind(&UpdateCheckDriver::BeginUpdateCheck, base::Unretained(driver), | 291 base::Bind(&UpdateCheckDriver::BeginUpdateCheck, |
| 367 install_if_newer, elevation_window)); | 292 base::Unretained(driver))); |
| 368 } | 293 } |
| 369 | 294 |
| 370 // Runs on the caller's thread. | 295 // Runs on the caller's thread. |
| 371 UpdateCheckDriver::UpdateCheckDriver(const UpdateCheckCallback& callback) | 296 UpdateCheckDriver::UpdateCheckDriver( |
| 372 : result_runner_(base::ThreadTaskRunnerHandle::Get()), | 297 const scoped_refptr<base::TaskRunner>& task_runner, |
| 298 const std::string& locale, | |
| 299 bool install_if_newer, | |
| 300 gfx::AcceleratedWidget elevation_window, | |
| 301 const UpdateCheckCallback& callback) | |
| 302 : task_runner_(task_runner), | |
| 303 result_runner_(base::ThreadTaskRunnerHandle::Get()), | |
| 304 locale_(locale), | |
| 305 install_if_newer_(install_if_newer), | |
| 306 elevation_window_(elevation_window), | |
| 373 result_callback_(callback), | 307 result_callback_(callback), |
| 308 system_level_(false), | |
| 309 last_result_(UPGRADE_ERROR), | |
| 310 last_progress_(0.0), | |
| 374 result_(UPGRADE_ERROR), | 311 result_(UPGRADE_ERROR), |
| 375 error_code_(GOOGLE_UPDATE_NO_ERROR), | 312 error_code_(GOOGLE_UPDATE_NO_ERROR), |
| 376 hresult_(S_OK), | 313 hresult_(S_OK), |
| 377 job_observer_(nullptr) { | 314 installer_exit_code_(-1) { |
| 378 } | 315 } |
| 379 | 316 |
| 380 UpdateCheckDriver::~UpdateCheckDriver() { | 317 UpdateCheckDriver::~UpdateCheckDriver() { |
| 381 DCHECK(result_runner_->BelongsToCurrentThread()); | 318 DCHECK(result_runner_->BelongsToCurrentThread()); |
| 382 // If there is an error, then error_code must not be blank, and vice versa. | 319 // If there is an error, then error_code must not be blank, and vice versa. |
| 383 DCHECK_NE(result_ == UPGRADE_ERROR, error_code_ == GOOGLE_UPDATE_NO_ERROR); | 320 DCHECK_NE(result_ == UPGRADE_ERROR, error_code_ == GOOGLE_UPDATE_NO_ERROR); |
| 384 UMA_HISTOGRAM_ENUMERATION("GoogleUpdate.UpgradeResult", result_, | 321 UMA_HISTOGRAM_ENUMERATION("GoogleUpdate.UpgradeResult", result_, |
| 385 NUM_UPGRADE_RESULTS); | 322 NUM_UPGRADE_RESULTS); |
| 386 if (result_ == UPGRADE_ERROR) { | 323 if (result_ == UPGRADE_ERROR) { |
| 387 UMA_HISTOGRAM_ENUMERATION("GoogleUpdate.UpdateErrorCode", error_code_, | 324 UMA_HISTOGRAM_ENUMERATION("GoogleUpdate.UpdateErrorCode", error_code_, |
| 388 NUM_ERROR_CODES); | 325 NUM_ERROR_CODES); |
| 389 if (hresult_ != S_OK) | 326 if (FAILED(hresult_)) |
| 390 UMA_HISTOGRAM_SPARSE_SLOWLY("GoogleUpdate.ErrorHresult", hresult_); | 327 UMA_HISTOGRAM_SPARSE_SLOWLY("GoogleUpdate.ErrorHresult", hresult_); |
| 328 if (installer_exit_code_ != -1) { | |
| 329 UMA_HISTOGRAM_SPARSE_SLOWLY("GoogleUpdate.InstallerExitCode", | |
| 330 installer_exit_code_); | |
| 331 } | |
| 391 } | 332 } |
| 392 result_callback_.Run(result_, error_code_, error_message_, version_); | 333 result_callback_.Run(result_, 0.0, error_code_, error_message_, new_version_); |
| 393 } | 334 } |
| 394 | 335 |
| 395 void UpdateCheckDriver::BeginUpdateCheck( | 336 void UpdateCheckDriver::BeginUpdateCheck() { |
| 396 bool install_if_newer, | |
| 397 gfx::AcceleratedWidget elevation_window) { | |
| 398 // Return results immediately if the driver is not waiting for Google Update. | 337 // Return results immediately if the driver is not waiting for Google Update. |
| 399 if (!BeginUpdateCheckInternal(install_if_newer, elevation_window)) | 338 if (!BeginUpdateCheckInternal()) |
| 400 result_runner_->DeleteSoon(FROM_HERE, this); | 339 result_runner_->DeleteSoon(FROM_HERE, this); |
| 401 } | 340 } |
| 402 | 341 |
| 403 bool UpdateCheckDriver::BeginUpdateCheckInternal( | 342 bool UpdateCheckDriver::BeginUpdateCheckInternal() { |
| 404 bool install_if_newer, | |
| 405 gfx::AcceleratedWidget elevation_window) { | |
| 406 base::FilePath chrome_exe; | 343 base::FilePath chrome_exe; |
| 407 if (!PathService::Get(base::DIR_EXE, &chrome_exe)) | 344 if (!PathService::Get(base::DIR_EXE, &chrome_exe)) |
| 408 NOTREACHED(); | 345 NOTREACHED(); |
| 409 | 346 |
| 410 const bool system_level = !InstallUtil::IsPerUserInstall(chrome_exe); | 347 system_level_ = !InstallUtil::IsPerUserInstall(chrome_exe); |
|
Peter Kasting
2015/05/07 22:37:29
Nit: Maybe we should make the bool member be |per_
grt (UTC plus 2)
2015/05/08 18:51:50
I agree that it seems backward, but system_level i
Peter Kasting
2015/05/09 02:19:01
OK; I would still suggest "system_level_install_"
grt (UTC plus 2)
2015/05/12 20:21:51
Done.
| |
| 411 | 348 |
| 412 // The failures handled here are: | 349 // CANNOT_UPGRADE_CHROME_IN_THIS_DIRECTORY is handled here. |
|
Peter Kasting
2015/05/07 22:37:28
Nit: This maybe should go inside the conditional
grt (UTC plus 2)
2015/05/08 18:51:50
It turns out that this comment was a lie. I've rea
| |
| 413 // CANNOT_UPGRADE_CHROME_IN_THIS_DIRECTORY, | 350 error_code_ = CanUpdateCurrentChrome(chrome_exe, system_level_); |
| 414 // GOOGLE_UPDATE_DISABLED_BY_POLICY, and | |
| 415 // GOOGLE_UPDATE_DISABLED_BY_POLICY_AUTO_ONLY. | |
| 416 error_code_ = CanUpdateCurrentChrome(chrome_exe, system_level); | |
| 417 if (error_code_ != GOOGLE_UPDATE_NO_ERROR) { | 351 if (error_code_ != GOOGLE_UPDATE_NO_ERROR) { |
| 418 // These failures are handled in the UX with custom messages. | 352 // This failure is handled in the UX with a custom message. |
| 419 result_ = UPGRADE_ERROR; | 353 result_ = UPGRADE_ERROR; |
| 420 return false; | 354 return false; |
| 421 } | 355 } |
| 422 | 356 |
| 423 // Make sure ATL is initialized in this module. | 357 // Make sure ATL is initialized in this module. |
| 424 ui::win::CreateATLModuleIfNeeded(); | 358 ui::win::CreateATLModuleIfNeeded(); |
| 425 | 359 |
| 426 HRESULT hr = | 360 // A failure to create the main update class is reported with this code: |
| 427 CComObject<GoogleUpdateJobObserver>::CreateInstance(&job_observer_); | 361 GoogleUpdateErrorCode error_code = GOOGLE_UPDATE_ONDEMAND_CLASS_NOT_FOUND; |
| 428 if (hr != S_OK) { | 362 HRESULT hr = S_OK; |
| 429 // Most of the error messages come straight from Google Update. This one is | 363 do { |
|
Peter Kasting
2015/05/07 22:37:28
A do { } while(false) construction here just so yo
grt (UTC plus 2)
2015/05/08 18:51:49
Done.
| |
| 430 // deemed worthy enough to also warrant its own error. | 364 hr = CreateGoogleUpdate3Class(system_level_, install_if_newer_, |
| 431 OnUpgradeError(GOOGLE_UPDATE_JOB_SERVER_CREATION_FAILED, hr, false); | 365 elevation_window_, &google_update_); |
| 366 if (FAILED(hr)) { | |
| 367 DLOG(ERROR) << "failed to create GoogleUpdate3 class " << std::hex << hr; | |
|
Peter Kasting
2015/05/07 22:37:28
Logging is uncommon in Chromium code and the old c
grt (UTC plus 2)
2015/05/08 18:51:50
All of these are DLOG, so there's no bloat. That s
| |
| 368 break; | |
| 369 } | |
| 370 | |
| 371 // The class was created, so all subsequent errors are reported as: | |
| 372 error_code = GOOGLE_UPDATE_ONDEMAND_CLASS_REPORTED_ERROR; | |
| 373 base::string16 app_guid = installer::GetAppGuidForUpdates(system_level_); | |
| 374 DCHECK(!app_guid.empty()); | |
| 375 | |
| 376 base::win::ScopedComPtr<IDispatch> dispatch; | |
| 377 hr = google_update_->createAppBundle(dispatch.Receive()); | |
| 378 if (FAILED(hr)) | |
| 379 break; | |
| 380 hr = dispatch.QueryInterface(app_bundle_.Receive()); | |
| 381 if (FAILED(hr)) | |
| 382 break; | |
| 383 dispatch.Release(); | |
|
Peter Kasting
2015/05/07 22:37:28
Nit: I tend to think it's clearer to use something
grt (UTC plus 2)
2015/05/08 18:51:49
Done.
| |
| 384 | |
| 385 if (!locale_.empty()) { | |
| 386 hr = app_bundle_->put_displayLanguage( | |
| 387 base::win::ScopedBstr(base::UTF8ToUTF16(locale_).c_str())); | |
| 388 DLOG_IF(ERROR, FAILED(hr)) << std::hex << hr; | |
| 389 } | |
|
Peter Kasting
2015/05/07 22:37:29
Nit: Maybe blank line below this? Not sure, but i
grt (UTC plus 2)
2015/05/08 18:51:50
Done.
| |
| 390 // This doesn't work. Perhaps it isn't needed since elevation is done by | |
|
Peter Kasting
2015/05/07 22:37:29
What does "doesn't work" mean?
Also, how is this
grt (UTC plus 2)
2015/05/08 18:51:49
Causes Google Update to crash. :-(
| |
| 391 // Chrome. | |
| 392 // hr = app_bundle_->put_parentHWND( | |
| 393 // reinterpret_cast<ULONG_PTR>(elevation_window_)); | |
| 394 // DLOG_IF(ERROR, FAILED(hr)) << std::hex << hr; | |
| 395 hr = app_bundle_->initialize(); | |
| 396 if (FAILED(hr)) { | |
| 397 DLOG(ERROR) << "initialize failed " << std::hex << hr; | |
| 398 break; | |
| 399 } | |
| 400 hr = app_bundle_->createInstalledApp( | |
| 401 base::win::ScopedBstr(app_guid.c_str()), dispatch.Receive()); | |
| 402 if (FAILED(hr)) { | |
| 403 DLOG(ERROR) << "createInstalledApp failed " << std::hex << hr; | |
| 404 break; | |
| 405 } | |
| 406 hr = dispatch.QueryInterface(app_.Receive()); | |
| 407 if (FAILED(hr)) | |
| 408 break; | |
| 409 hr = app_bundle_->checkForUpdate(); | |
| 410 DLOG_IF(ERROR, FAILED(hr)) << "checkForUpdate failed " << std::hex << hr; | |
| 411 } while (false); | |
| 412 | |
| 413 if (FAILED(hr)) { | |
| 414 OnUpgradeError(error_code, hr, -1, base::string16()); | |
| 432 return false; | 415 return false; |
| 433 } | 416 } |
| 434 // Hold a reference on the observer for the lifetime of the driver. | 417 |
| 435 job_holder_ = job_observer_; | 418 task_runner_->PostTask( |
| 436 | 419 FROM_HERE, |
| 437 job_observer_->set_on_complete_callback(base::Bind( | 420 base::Bind(&UpdateCheckDriver::PollGoogleUpdate, base::Unretained(this))); |
| 438 &UpdateCheckDriver::CompleteUpdateCheck, base::Unretained(this))); | 421 |
| 439 | 422 return true; |
| 440 hr = CreateOnDemandAppsClass(system_level, install_if_newer, elevation_window, | 423 } |
| 441 &on_demand_); | 424 |
| 442 if (hr != S_OK) { | 425 bool UpdateCheckDriver::GetCurrentState( |
| 443 OnUpgradeError(GOOGLE_UPDATE_ONDEMAND_CLASS_NOT_FOUND, hr, system_level); | 426 base::win::ScopedComPtr<ICurrentState>* current_state, |
| 427 CurrentState* state_value, | |
| 428 HRESULT* hresult) { | |
| 429 base::win::ScopedComPtr<IDispatch> dispatch; | |
| 430 *hresult = app_->get_currentState(dispatch.Receive()); | |
| 431 if (FAILED(*hresult)) { | |
| 432 DLOG(ERROR) << "failed getting currentState " << std::hex << *hresult; | |
| 444 return false; | 433 return false; |
| 445 } | 434 } |
| 446 | 435 *hresult = dispatch.QueryInterface(current_state->Receive()); |
| 447 base::string16 app_guid = installer::GetAppGuidForUpdates(system_level); | 436 if (FAILED(*hresult)) { |
| 448 DCHECK(!app_guid.empty()); | 437 DLOG(ERROR) << "failed getting ICurrentState " << std::hex << *hresult; |
| 449 | |
| 450 if (install_if_newer) | |
| 451 hr = on_demand_->Update(app_guid.c_str(), job_observer_); | |
| 452 else | |
| 453 hr = on_demand_->CheckForUpdate(app_guid.c_str(), job_observer_); | |
| 454 | |
| 455 if (hr != S_OK) { | |
| 456 OnUpgradeError(GOOGLE_UPDATE_ONDEMAND_CLASS_REPORTED_ERROR, hr, | |
| 457 system_level); | |
| 458 return false; | 438 return false; |
| 459 } | 439 } |
| 440 dispatch.Release(); | |
|
Peter Kasting
2015/05/07 22:37:28
Why is this call needed?
grt (UTC plus 2)
2015/05/08 18:51:49
For consistency with the previous uses of IDispatc
Peter Kasting
2015/05/09 02:19:01
I guess the question is more, either a Release() o
grt (UTC plus 2)
2015/05/12 20:21:51
Done.
| |
| 441 LONG value = 0; | |
| 442 *hresult = (*current_state)->get_stateValue(&value); | |
| 443 if (FAILED(*hresult)) { | |
| 444 DLOG(ERROR) << "failed getting state value " << std::hex << *hresult; | |
| 445 return false; | |
| 446 } | |
| 447 *state_value = static_cast<CurrentState>(value); | |
| 460 return true; | 448 return true; |
| 461 } | 449 } |
| 462 | 450 |
| 463 void UpdateCheckDriver::CompleteUpdateCheck() { | 451 bool UpdateCheckDriver::IsErrorState( |
| 464 result_ = job_observer_->result(); | 452 const base::win::ScopedComPtr<ICurrentState>& current_state, |
| 465 if (result_ == UPGRADE_ERROR) { | 453 CurrentState state_value, |
| 466 error_code_ = GOOGLE_UPDATE_ERROR_UPDATING; | 454 GoogleUpdateErrorCode* error_code, |
| 467 error_message_ = job_observer_->error_message(); | 455 HRESULT* hresult, |
| 468 } else { | 456 int* installer_exit_code, |
| 469 version_ = job_observer_->new_version(); | 457 base::string16* error_string) { |
| 458 if (state_value == STATE_ERROR) { | |
| 459 // In general, errors reported by Google Update fall under this category | |
| 460 // (see special case below). | |
| 461 *error_code = GOOGLE_UPDATE_ERROR_UPDATING; | |
| 462 | |
| 463 // In general, the exit code of Chrome's installer is unknown (see special | |
| 464 // case below). | |
| 465 *installer_exit_code = -1; | |
| 466 | |
| 467 // Report the error_code provided by Google Update if possible, or the | |
| 468 // reason it wasn't possible otherwise. | |
| 469 LONG long_value = 0; | |
| 470 *hresult = current_state->get_errorCode(&long_value); | |
| 471 if (SUCCEEDED(*hresult)) | |
| 472 *hresult = long_value; | |
| 473 | |
| 474 // Special cases: | |
| 475 // - Use a custom error code if Google Update repoted that the update was | |
| 476 // disabled by a Group Policy setting. | |
| 477 // - Extract the exit code of Chrome's installer if Google Update repoted | |
| 478 // that the update failed becuase of a failure in the installer. | |
|
Peter Kasting
2015/05/07 22:37:28
Nit: because
grt (UTC plus 2)
2015/05/08 18:51:49
Done.
| |
| 479 LONG code = 0; | |
| 480 if (*hresult == GOOPDATE_E_APP_UPDATE_DISABLED_BY_POLICY) { | |
| 481 *error_code = GOOGLE_UPDATE_DISABLED_BY_POLICY; | |
| 482 } else if (*hresult == GOOPDATEINSTALL_E_INSTALLER_FAILED && | |
| 483 SUCCEEDED(current_state->get_installerResultCode(&code))) { | |
| 484 *installer_exit_code = code; | |
| 485 } | |
| 486 | |
| 487 base::win::ScopedBstr message; | |
| 488 if (SUCCEEDED(current_state->get_completionMessage(message.Receive()))) | |
| 489 error_string->assign(message, message.Length()); | |
| 490 | |
| 491 return true; | |
| 492 } | |
| 493 if (state_value == STATE_UPDATE_AVAILABLE && install_if_newer_) { | |
| 494 *hresult = app_bundle_->install(); | |
| 495 if (FAILED(*hresult)) { | |
| 496 DLOG(ERROR) << "install() failed " << std::hex << *hresult; | |
| 497 // Report a failure to start the install as a general error while trying | |
| 498 // to interact with Google Update. | |
| 499 *error_code = GOOGLE_UPDATE_ONDEMAND_CLASS_REPORTED_ERROR; | |
| 500 *installer_exit_code = -1; | |
| 501 return true; | |
| 502 } | |
| 503 // Return false for handling in IsIntermediateState. | |
| 504 } | |
| 505 return false; | |
| 506 } | |
| 507 | |
| 508 bool UpdateCheckDriver::IsFinalState( | |
| 509 const base::win::ScopedComPtr<ICurrentState>& current_state, | |
| 510 CurrentState state_value, | |
| 511 GoogleUpdateUpgradeResult* upgrade_result, | |
| 512 base::string16* new_version) { | |
| 513 if (state_value == STATE_UPDATE_AVAILABLE && !install_if_newer_) { | |
| 514 base::win::ScopedBstr version; | |
| 515 *upgrade_result = UPGRADE_IS_AVAILABLE; | |
| 516 if (SUCCEEDED(current_state->get_availableVersion(version.Receive()))) | |
| 517 new_version->assign(version, version.Length()); | |
| 518 return true; | |
| 519 } else if (state_value == STATE_INSTALL_COMPLETE) { | |
|
Peter Kasting
2015/05/07 22:37:28
Nit: No else after return (2 places)
grt (UTC plus 2)
2015/05/08 18:51:50
Done.
| |
| 520 DCHECK(install_if_newer_); | |
| 521 *upgrade_result = UPGRADE_SUCCESSFUL; | |
| 522 return true; | |
| 523 } else if (state_value == STATE_NO_UPDATE) { | |
| 524 *upgrade_result = UPGRADE_ALREADY_UP_TO_DATE; | |
| 525 return true; | |
| 526 } | |
| 527 return false; | |
| 528 } | |
| 529 | |
| 530 bool UpdateCheckDriver::IsIntermediateState( | |
| 531 const base::win::ScopedComPtr<ICurrentState>& current_state, | |
| 532 CurrentState state_value, | |
| 533 GoogleUpdateUpgradeResult* upgrade_result, | |
| 534 base::string16* new_version, | |
| 535 double* progress) { | |
| 536 // ERROR will have been handled in IsErrorState. UPDATE_AVAILABLE, and | |
| 537 // NO_UPDATE will have been handled in IsFinalState if not doing an install, | |
| 538 // as will STATE_INSTALL_COMPLETE when doing an install. All other states | |
| 539 // following UPDATE_AVAILABLE will only happen when an install is to be done. | |
| 540 DCHECK(state_value < STATE_UPDATE_AVAILABLE || install_if_newer_); | |
| 541 *upgrade_result = install_if_newer_ ? UPGRADE_STARTED : UPGRADE_CHECK_STARTED; | |
| 542 *progress = 0.0; | |
| 543 | |
| 544 switch (state_value) { | |
| 545 case STATE_INIT: | |
| 546 case STATE_WAITING_TO_CHECK_FOR_UPDATE: | |
| 547 case STATE_CHECKING_FOR_UPDATE: | |
| 548 break; | |
| 549 | |
| 550 case STATE_UPDATE_AVAILABLE: { | |
| 551 base::win::ScopedBstr version; | |
| 552 if (SUCCEEDED(current_state->get_availableVersion(version.Receive()))) | |
| 553 new_version->assign(version, version.Length()); | |
| 554 break; | |
| 555 } | |
| 556 | |
| 557 case STATE_WAITING_TO_DOWNLOAD: | |
| 558 case STATE_RETRYING_DOWNLOAD: | |
| 559 break; | |
| 560 | |
| 561 case STATE_DOWNLOADING: { | |
| 562 ULONG bytes_downloaded = 0; | |
| 563 ULONG total_bytes = 0; | |
| 564 if (SUCCEEDED(current_state->get_bytesDownloaded(&bytes_downloaded)) && | |
| 565 SUCCEEDED(current_state->get_totalBytesToDownload(&total_bytes)) && | |
| 566 total_bytes) { | |
| 567 // Divide by two, as 0-50% is downloading. | |
| 568 *progress = (static_cast<double>(bytes_downloaded) / | |
| 569 static_cast<double>(total_bytes)) / | |
| 570 2.0; | |
| 571 } | |
| 572 break; | |
| 573 } | |
| 574 | |
| 575 case STATE_DOWNLOAD_COMPLETE: | |
| 576 case STATE_EXTRACTING: | |
| 577 case STATE_APPLYING_DIFFERENTIAL_PATCH: | |
| 578 case STATE_READY_TO_INSTALL: | |
| 579 case STATE_WAITING_TO_INSTALL: | |
| 580 *progress = 0.5; | |
| 581 break; | |
| 582 | |
| 583 case STATE_INSTALLING: { | |
| 584 *progress = 0.5; | |
| 585 LONG install_progress = 0; | |
| 586 if (SUCCEEDED(current_state->get_installProgress(&install_progress)) && | |
| 587 install_progress >= 0 && install_progress <= 100) { | |
|
Peter Kasting
2015/05/07 22:37:28
Seems like the effect of this is to clamp all out-
grt (UTC plus 2)
2015/05/08 18:51:49
I can't say if a flaw in Google Update will ever c
Peter Kasting
2015/05/09 02:19:01
OK, fair enough.
| |
| 588 // 50-100% is installing. | |
| 589 *progress = (100.0 + install_progress) / 200.0; | |
| 590 } | |
| 591 break; | |
| 592 } | |
| 593 | |
| 594 case STATE_INSTALL_COMPLETE: | |
| 595 case STATE_PAUSED: | |
| 596 case STATE_NO_UPDATE: | |
| 597 case STATE_ERROR: | |
| 598 default: | |
| 599 NOTREACHED(); | |
| 600 UMA_HISTOGRAM_SPARSE_SLOWLY("GoogleUpdate.UnexpectedState", state_value); | |
| 601 return false; | |
| 602 } | |
| 603 return true; | |
| 604 } | |
| 605 | |
| 606 void UpdateCheckDriver::PollGoogleUpdate() { | |
| 607 base::win::ScopedComPtr<ICurrentState> state; | |
| 608 CurrentState state_value = STATE_INIT; | |
| 609 HRESULT hr = S_OK; | |
| 610 | |
|
Peter Kasting
2015/05/07 22:37:28
Nit: This blank line and the two below seem a bit
grt (UTC plus 2)
2015/05/08 18:51:49
Removed.
| |
| 611 GoogleUpdateErrorCode error_code = GOOGLE_UPDATE_NO_ERROR; | |
| 612 int installer_exit_code = -1; | |
| 613 base::string16 error_string; | |
| 614 | |
| 615 GoogleUpdateUpgradeResult upgrade_result = UPGRADE_ERROR; | |
| 616 base::string16 new_version; | |
| 617 | |
| 618 double progress = 0.0; | |
| 619 | |
| 620 if (!GetCurrentState(&state, &state_value, &hr)) { | |
| 621 OnUpgradeError(GOOGLE_UPDATE_ONDEMAND_CLASS_REPORTED_ERROR, hr, -1, | |
| 622 base::string16()); | |
| 623 } else if (IsErrorState(state, state_value, &error_code, &hr, | |
| 624 &installer_exit_code, &error_string)) { | |
| 625 OnUpgradeError(error_code, hr, installer_exit_code, error_string); | |
| 626 } else if (IsFinalState(state, state_value, &upgrade_result, &new_version)) { | |
| 627 result_ = upgrade_result; | |
| 628 error_code_ = GOOGLE_UPDATE_NO_ERROR; | |
| 629 error_message_.clear(); | |
| 630 if (!new_version.empty()) | |
| 631 new_version_ = new_version; | |
| 632 hresult_ = S_OK; | |
| 633 installer_exit_code_ = -1; | |
| 634 } else if (IsIntermediateState(state, state_value, &upgrade_result, | |
| 635 &new_version, &progress)) { | |
| 636 if (!new_version.empty()) | |
| 637 new_version_ = new_version; | |
| 638 // Give the caller this status update if it differs from the last one given | |
| 639 // and schedule the next check. | |
| 640 if (upgrade_result != last_result_ || progress != last_progress_) { | |
| 641 last_result_ = upgrade_result; | |
| 642 last_progress_ = progress; | |
| 643 | |
| 644 result_runner_->PostTask( | |
| 645 FROM_HERE, | |
| 646 base::Bind(result_callback_, last_result_, last_progress_, | |
| 647 GOOGLE_UPDATE_NO_ERROR, base::string16(), new_version_)); | |
| 648 } | |
| 649 | |
| 650 task_runner_->PostDelayedTask( | |
| 651 FROM_HERE, base::Bind(&UpdateCheckDriver::PollGoogleUpdate, | |
| 652 base::Unretained(this)), | |
| 653 base::TimeDelta::FromMilliseconds(250L)); | |
|
Peter Kasting
2015/05/07 22:37:28
Nit: Explicit 'L' suffix not necessary
You may wa
grt (UTC plus 2)
2015/05/08 18:51:49
Done.
| |
| 654 // Early return for this non-terminal state. | |
| 655 return; | |
| 470 } | 656 } |
| 471 | 657 |
| 472 // Release the reference on the COM objects before bouncing back to the | 658 // Release the reference on the COM objects before bouncing back to the |
| 473 // caller's thread. | 659 // caller's thread. |
| 474 on_demand_.Release(); | 660 state.Release(); |
| 475 job_holder_.Release(); | 661 app_.Release(); |
| 476 job_observer_ = nullptr; | 662 app_bundle_.Release(); |
| 663 google_update_.Release(); | |
| 477 | 664 |
| 478 result_runner_->DeleteSoon(FROM_HERE, this); | 665 result_runner_->DeleteSoon(FROM_HERE, this); |
| 479 } | 666 } |
| 480 | 667 |
| 481 void UpdateCheckDriver::OnUpgradeError(GoogleUpdateErrorCode error_code, | 668 void UpdateCheckDriver::OnUpgradeError(GoogleUpdateErrorCode error_code, |
| 482 HRESULT hr, | 669 HRESULT hr, |
| 483 bool system_level) { | 670 int installer_exit_code, |
| 671 const base::string16& error_string) { | |
| 484 result_ = UPGRADE_ERROR; | 672 result_ = UPGRADE_ERROR; |
| 485 error_code_ = error_code; | 673 error_code_ = error_code; |
| 486 hresult_ = hr; | 674 hresult_ = hr; |
| 675 installer_exit_code_ = installer_exit_code; | |
| 487 base::string16 error_msg = | 676 base::string16 error_msg = |
| 488 base::StringPrintf(L"%d: 0x%x", error_code_, hresult_); | 677 base::StringPrintf(L"%d: 0x%x", error_code_, hresult_); |
| 489 if (system_level) | 678 if (installer_exit_code_ != -1) |
| 679 error_msg += base::StringPrintf(L": %d", installer_exit_code_); | |
| 680 if (system_level_) | |
| 490 error_msg += L" -- system level"; | 681 error_msg += L" -- system level"; |
| 491 error_message_ = l10n_util::GetStringFUTF16( | 682 if (error_string.empty()) { |
| 492 IDS_ABOUT_BOX_ERROR_UPDATE_CHECK_FAILED, error_msg); | 683 error_message_ = l10n_util::GetStringFUTF16( |
| 684 IDS_ABOUT_BOX_ERROR_UPDATE_CHECK_FAILED, error_msg); | |
| 685 } else { | |
| 686 error_message_ = l10n_util::GetStringFUTF16( | |
| 687 IDS_ABOUT_BOX_GOOGLE_UPDATE_ERROR, error_string, error_msg); | |
| 688 } | |
| 493 } | 689 } |
| 494 | 690 |
| 495 } // namespace | 691 } // namespace |
| 496 | 692 |
| 497 | 693 |
| 498 // Globals --------------------------------------------------------------------- | 694 // Globals --------------------------------------------------------------------- |
| 499 | 695 |
| 500 void BeginUpdateCheck(const scoped_refptr<base::TaskRunner>& task_runner, | 696 void BeginUpdateCheck(const scoped_refptr<base::TaskRunner>& task_runner, |
| 697 const std::string& locale, | |
| 501 bool install_if_newer, | 698 bool install_if_newer, |
| 502 gfx::AcceleratedWidget elevation_window, | 699 gfx::AcceleratedWidget elevation_window, |
| 503 const UpdateCheckCallback& callback) { | 700 const UpdateCheckCallback& callback) { |
| 504 UpdateCheckDriver::RunUpdateCheck(task_runner, install_if_newer, | 701 UpdateCheckDriver::RunUpdateCheck(task_runner, locale, install_if_newer, |
| 505 elevation_window, callback); | 702 elevation_window, callback); |
| 506 } | 703 } |
| 507 | 704 |
| 508 | 705 |
| 509 // Private API exposed for testing. -------------------------------------------- | 706 // Private API exposed for testing. -------------------------------------------- |
| 510 | 707 |
| 511 void SetGoogleUpdateFactoryForTesting( | 708 void SetGoogleUpdateFactoryForTesting( |
| 512 const OnDemandAppsClassFactory& google_update_factory) { | 709 const GoogleUpdate3ClassFactory& google_update_factory) { |
| 513 if (g_google_update_factory) { | 710 if (g_google_update_factory) { |
| 514 delete g_google_update_factory; | 711 delete g_google_update_factory; |
| 515 g_google_update_factory = nullptr; | 712 g_google_update_factory = nullptr; |
| 516 } | 713 } |
| 517 if (!google_update_factory.is_null()) { | 714 if (!google_update_factory.is_null()) { |
| 518 g_google_update_factory = | 715 g_google_update_factory = |
| 519 new OnDemandAppsClassFactory(google_update_factory); | 716 new GoogleUpdate3ClassFactory(google_update_factory); |
| 520 } | 717 } |
| 521 } | 718 } |
| OLD | NEW |