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" |
19 #include "base/task_runner.h" | 21 #include "base/strings/utf_string_conversions.h" |
20 #include "base/thread_task_runner_handle.h" | 22 #include "base/thread_task_runner_handle.h" |
| 23 #include "base/time/time.h" |
| 24 #include "base/win/scoped_bstr.h" |
21 #include "base/win/windows_version.h" | 25 #include "base/win/windows_version.h" |
22 #include "chrome/grit/generated_resources.h" | 26 #include "chrome/grit/generated_resources.h" |
23 #include "chrome/installer/util/browser_distribution.h" | 27 #include "chrome/installer/util/browser_distribution.h" |
24 #include "chrome/installer/util/google_update_settings.h" | |
25 #include "chrome/installer/util/helper.h" | 28 #include "chrome/installer/util/helper.h" |
26 #include "chrome/installer/util/install_util.h" | 29 #include "chrome/installer/util/install_util.h" |
27 #include "content/public/browser/browser_thread.h" | |
28 #include "ui/base/l10n/l10n_util.h" | 30 #include "ui/base/l10n/l10n_util.h" |
29 #include "ui/base/win/atl_module.h" | 31 #include "ui/base/win/atl_module.h" |
| 32 #include "ui/gfx/geometry/safe_integer_conversions.h" |
30 | 33 |
31 namespace { | 34 namespace { |
32 | 35 |
33 OnDemandAppsClassFactory* g_google_update_factory = nullptr; | 36 // The status of the upgrade. These values are used for a histogram. Do not |
| 37 // reorder. |
| 38 enum GoogleUpdateUpgradeStatus { |
| 39 // The upgrade has started. DEPRECATED. |
| 40 // UPGRADE_STARTED = 0, |
| 41 // A check for upgrade has been initiated. DEPRECATED. |
| 42 // UPGRADE_CHECK_STARTED = 1, |
| 43 // An update is available. |
| 44 UPGRADE_IS_AVAILABLE = 2, |
| 45 // The upgrade happened successfully. |
| 46 UPGRADE_SUCCESSFUL = 3, |
| 47 // No need to upgrade, Chrome is up to date. |
| 48 UPGRADE_ALREADY_UP_TO_DATE = 4, |
| 49 // An error occurred. |
| 50 UPGRADE_ERROR = 5, |
| 51 NUM_UPGRADE_STATUS |
| 52 }; |
| 53 |
| 54 GoogleUpdate3ClassFactory* g_google_update_factory = nullptr; |
| 55 |
| 56 // The time interval, in milliseconds, between polls to Google Update. This |
| 57 // value was chosen unscientificaly during an informal discussion. |
| 58 const int64_t kGoogleUpdatePollIntervalMs = 250; |
| 59 |
| 60 // Constants from Google Update. |
| 61 const HRESULT GOOPDATE_E_APP_UPDATE_DISABLED_BY_POLICY = 0x80040813; |
| 62 const HRESULT GOOPDATEINSTALL_E_INSTALLER_FAILED = 0x80040902; |
34 | 63 |
35 // Check if the currently running instance can be updated by Google Update. | 64 // 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 | 65 // Returns GOOGLE_UPDATE_NO_ERROR only if the instance running is a Google |
37 // Chrome distribution installed in a standard location. | 66 // Chrome distribution installed in a standard location. |
38 GoogleUpdateErrorCode CanUpdateCurrentChrome( | 67 GoogleUpdateErrorCode CanUpdateCurrentChrome( |
39 const base::FilePath& chrome_exe_path, | 68 const base::FilePath& chrome_exe_path, |
40 bool system_level) { | 69 bool system_level_install) { |
41 #if !defined(GOOGLE_CHROME_BUILD) | 70 #if !defined(GOOGLE_CHROME_BUILD) |
42 return CANNOT_UPGRADE_CHROME_IN_THIS_DIRECTORY; | 71 return CANNOT_UPGRADE_CHROME_IN_THIS_DIRECTORY; |
43 #else | 72 #else |
44 DCHECK_NE(InstallUtil::IsPerUserInstall(chrome_exe_path), system_level); | 73 DCHECK_NE(InstallUtil::IsPerUserInstall(chrome_exe_path), |
| 74 system_level_install); |
45 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); | 75 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); |
46 base::FilePath user_exe_path = installer::GetChromeInstallPath(false, dist); | 76 base::FilePath user_exe_path = installer::GetChromeInstallPath(false, dist); |
47 base::FilePath machine_exe_path = installer::GetChromeInstallPath(true, dist); | 77 base::FilePath machine_exe_path = installer::GetChromeInstallPath(true, dist); |
48 if (!base::FilePath::CompareEqualIgnoreCase(chrome_exe_path.value(), | 78 if (!base::FilePath::CompareEqualIgnoreCase(chrome_exe_path.value(), |
49 user_exe_path.value()) && | 79 user_exe_path.value()) && |
50 !base::FilePath::CompareEqualIgnoreCase(chrome_exe_path.value(), | 80 !base::FilePath::CompareEqualIgnoreCase(chrome_exe_path.value(), |
51 machine_exe_path.value())) { | 81 machine_exe_path.value())) { |
52 return CANNOT_UPGRADE_CHROME_IN_THIS_DIRECTORY; | 82 return CANNOT_UPGRADE_CHROME_IN_THIS_DIRECTORY; |
53 } | 83 } |
54 | 84 |
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; | 85 return GOOGLE_UPDATE_NO_ERROR; |
68 #endif | 86 #endif |
69 } | 87 } |
70 | 88 |
71 // Creates an instance of a COM Local Server class using either plain vanilla | 89 // Creates an instance of a COM Local Server class using either plain vanilla |
72 // CoCreateInstance, or using the Elevation moniker if running on Vista. | 90 // 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 | 91 // 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 | 92 // showing up in the foreground if running on Vista. It can also be NULL if |
75 // background UAC prompts are desired. | 93 // background UAC prompts are desired. |
76 HRESULT CoCreateInstanceAsAdmin(REFCLSID class_id, | 94 HRESULT CoCreateInstanceAsAdmin(REFCLSID class_id, |
(...skipping 23 matching lines...) Expand all Loading... |
100 bind_opts.hwnd = hwnd; | 118 bind_opts.hwnd = hwnd; |
101 | 119 |
102 return CoGetObject(elevation_moniker_name.c_str(), &bind_opts, interface_id, | 120 return CoGetObject(elevation_moniker_name.c_str(), &bind_opts, interface_id, |
103 interface_ptr); | 121 interface_ptr); |
104 } | 122 } |
105 | 123 |
106 return CoCreateInstance(class_id, NULL, CLSCTX_LOCAL_SERVER, interface_id, | 124 return CoCreateInstance(class_id, NULL, CLSCTX_LOCAL_SERVER, interface_id, |
107 interface_ptr); | 125 interface_ptr); |
108 } | 126 } |
109 | 127 |
110 HRESULT CreateOnDemandAppsClass( | 128 HRESULT CreateGoogleUpdate3WebClass( |
111 bool system_level, | 129 bool system_level_install, |
112 bool install_if_newer, | 130 bool install_update_if_possible, |
113 gfx::AcceleratedWidget elevation_window, | 131 gfx::AcceleratedWidget elevation_window, |
114 base::win::ScopedComPtr<IGoogleUpdate>* on_demand) { | 132 base::win::ScopedComPtr<IGoogleUpdate3Web>* google_update) { |
115 if (g_google_update_factory) | 133 if (g_google_update_factory) |
116 return g_google_update_factory->Run(on_demand); | 134 return g_google_update_factory->Run(google_update); |
117 | 135 |
118 // For a user-level install, update checks and updates can both be done by a | 136 // For a user-level install, update checks and updates can both be done by a |
119 // normal user with the UserAppsClass. | 137 // normal user with the UserClass. |
120 if (!system_level) | 138 if (!system_level_install) |
121 return on_demand->CreateInstance(CLSID_OnDemandUserAppsClass); | 139 return google_update->CreateInstance(CLSID_GoogleUpdate3WebUserClass); |
122 | 140 |
123 // For a system-level install, update checks can be done by a normal user with | 141 // For a system-level install, update checks can be done by a normal user with |
124 // the MachineAppsClass. | 142 // the ServiceClass. |
125 if (!install_if_newer) | 143 if (!install_update_if_possible) |
126 return on_demand->CreateInstance(CLSID_OnDemandMachineAppsClass); | 144 return google_update->CreateInstance(CLSID_GoogleUpdate3WebMachineClass); |
127 | 145 |
128 // For a system-level install, an update requires Admin privileges for writing | 146 // For a system-level install, an update requires Admin privileges for writing |
129 // to %ProgramFiles%. Elevate while instantiating the MachineAppsClass. | 147 // to %ProgramFiles%. Elevate while instantiating the ServiceClass. |
130 return CoCreateInstanceAsAdmin(CLSID_OnDemandMachineAppsClass, | 148 return CoCreateInstanceAsAdmin(CLSID_GoogleUpdate3WebMachineClass, |
131 IID_IGoogleUpdate, elevation_window, | 149 IID_IGoogleUpdate3Web, elevation_window, |
132 on_demand->ReceiveVoid()); | 150 google_update->ReceiveVoid()); |
133 } | 151 } |
134 | |
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 | 152 |
286 // UpdateCheckDriver ----------------------------------------------------------- | 153 // UpdateCheckDriver ----------------------------------------------------------- |
287 | 154 |
288 // A driver that is created and destroyed on the caller's thread and drives | 155 // A driver that is created and destroyed on the caller's thread and drives |
289 // Google Update on another. | 156 // Google Update on another. |
290 class UpdateCheckDriver { | 157 class UpdateCheckDriver { |
291 public: | 158 public: |
292 // Runs an update check on |task_runner|, invoking |callback| on the caller's | 159 // Runs an update check on |task_runner|, invoking methods of |delegate| on |
293 // thread upon completion. |task_runner| must run a TYPE_UI message loop if | 160 // the caller's thread to report progress and final results. |
294 // the default IGoogleUpdate on-demand COM class is used. | 161 static void RunUpdateCheck( |
295 static void RunUpdateCheck(const scoped_refptr<base::TaskRunner>& task_runner, | 162 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, |
296 bool install_if_newer, | 163 const std::string& locale, |
297 gfx::AcceleratedWidget elevation_window, | 164 bool install_update_if_possible, |
298 const UpdateCheckCallback& callback); | 165 gfx::AcceleratedWidget elevation_window, |
| 166 const base::WeakPtr<UpdateCheckDelegate>& delegate); |
299 | 167 |
300 private: | 168 private: |
301 friend class base::DeleteHelper<UpdateCheckDriver>; | 169 friend class base::DeleteHelper<UpdateCheckDriver>; |
302 | 170 |
303 explicit UpdateCheckDriver(const UpdateCheckCallback& callback); | 171 UpdateCheckDriver( |
304 | 172 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, |
305 // Runs the caller's update check callback with the results of the operation. | 173 const std::string& locale, |
| 174 bool install_update_if_possible, |
| 175 gfx::AcceleratedWidget elevation_window, |
| 176 const base::WeakPtr<UpdateCheckDelegate>& delegate); |
| 177 |
| 178 // Invokes a completion or error method on the caller's delegate, as |
| 179 // appropriate. |
306 ~UpdateCheckDriver(); | 180 ~UpdateCheckDriver(); |
307 | 181 |
308 // Starts an update check. | 182 // Starts an update check. |
309 void BeginUpdateCheck(bool install_if_newer, | 183 void BeginUpdateCheck(); |
310 gfx::AcceleratedWidget elevation_window); | 184 |
311 | 185 // Returns the result of initiating an update check. Sets |error_code| if the |
312 // Helper function for starting an update check. Returns true if the check was | 186 // result is any kind of failure. |
313 // properly started, in which case CompleteUpdateCheck will be invoked upon | 187 HRESULT BeginUpdateCheckInternal(GoogleUpdateErrorCode* error_code); |
314 // completion to return results to the caller on its own thread. | 188 |
315 bool BeginUpdateCheckInternal(bool install_if_newer, | 189 // Sets status_ to UPGRADE_ERROR, error_code_ to |error_code|, hresult_ to |
316 gfx::AcceleratedWidget elevation_window); | 190 // |hresult|, installer_exit_code_ to |installer_exit_code|, and |
317 | 191 // error_message_ to a composition of all values suitable for display to the |
318 // Invoked when results are in from Google Update. | 192 // user. This call should be followed by deletion of the driver, which will |
319 void CompleteUpdateCheck(); | 193 // result in the caller being notified via its delegate. |
320 | |
321 // Prepares |results| to return the upgrade error indicated by |error_code| | |
322 // and |hr|. The string " -- system level" is included in the generated error | |
323 // message when |system_level| is true. | |
324 void OnUpgradeError(GoogleUpdateErrorCode error_code, | 194 void OnUpgradeError(GoogleUpdateErrorCode error_code, |
325 HRESULT hr, | 195 HRESULT hresult, |
326 bool system_level); | 196 int installer_exit_code, |
327 | 197 const base::string16& error_string); |
328 // The caller's task runner, on which |result_callback_| will be run. | 198 |
| 199 // Returns true if |current_state| and |state_value| can be obtained from the |
| 200 // ongoing update check. Otherwise, populates |hresult| with the reason they |
| 201 // could not be obtained. |
| 202 bool GetCurrentState(base::win::ScopedComPtr<ICurrentState>* current_state, |
| 203 CurrentState* state_value, |
| 204 HRESULT* hresult) const; |
| 205 |
| 206 // Returns true if |current_state| and |state_value| constitute an error state |
| 207 // for the ongoing update check, in which case |error_code| is populated with |
| 208 // one of GOOGLE_UPDATE_ERROR_UPDATING, GOOGLE_UPDATE_DISABLED_BY_POLICY, or |
| 209 // GOOGLE_UPDATE_ONDEMAND_CLASS_REPORTED_ERROR. |hresult| is populated with |
| 210 // the most relevant HRESULT (which may be a value from Google Update; see |
| 211 // https://code.google.com/p/omaha/source/browse/trunk/base/error.h). In case |
| 212 // Chrome's installer failed during execution, |installer_exit_code| may be |
| 213 // populated with its process exit code (see enum installer::InstallStatus in |
| 214 // chrome/installer/util/util_constants.h); otherwise, it will be -1. |
| 215 // |error_string| will be populated with a completion message if one is |
| 216 // provided by Google Update. |
| 217 bool IsErrorState(const base::win::ScopedComPtr<ICurrentState>& current_state, |
| 218 CurrentState state_value, |
| 219 GoogleUpdateErrorCode* error_code, |
| 220 HRESULT* hresult, |
| 221 int* installer_exit_code, |
| 222 base::string16* error_string) const; |
| 223 |
| 224 // Returns true if |current_state| and |state_value| constitute a final state |
| 225 // for the ongoing update check, in which case |upgrade_status| is populated |
| 226 // with one of UPGRADE_ALREADY_UP_TO_DATE or UPGRADE_IS_AVAILABLE (in case a |
| 227 // pure check is being performed rather than an update) or UPGRADE_SUCCESSFUL |
| 228 // (in case an update is being performed). For the UPGRADE_IS_AVAILABLE case, |
| 229 // |new_version| will be populated with the available version, if provided by |
| 230 // Google Update. |
| 231 bool IsFinalState(const base::win::ScopedComPtr<ICurrentState>& current_state, |
| 232 CurrentState state_value, |
| 233 GoogleUpdateUpgradeStatus* upgrade_status, |
| 234 base::string16* new_version) const; |
| 235 |
| 236 // Returns true if |current_state| and |state_value| constitute an |
| 237 // intermediate state for the ongoing update check. |new_version| will be |
| 238 // populated with the version to be installed if it is provided by Google |
| 239 // Update for the current state. |progress| will be populated with a number |
| 240 // between 0 and 100 according to how far Google Update has progressed in the |
| 241 // download and install process. |
| 242 bool IsIntermediateState( |
| 243 const base::win::ScopedComPtr<ICurrentState>& current_state, |
| 244 CurrentState state_value, |
| 245 base::string16* new_version, |
| 246 int* progress) const; |
| 247 |
| 248 // Polls Google Update to determine the state of the ongoing check or |
| 249 // update. If the process has reached a terminal state, this instance will be |
| 250 // deleted and the caller will be notified of the final status. Otherwise, the |
| 251 // caller will be notified of the intermediate state (iff it differs from a |
| 252 // previous notification) and another future poll will be scheduled. |
| 253 void PollGoogleUpdate(); |
| 254 |
| 255 // The task runner on which the update checks runs. |
| 256 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; |
| 257 |
| 258 // The caller's task runner, on which methods of |delegate_| will be invoked. |
329 scoped_refptr<base::SingleThreadTaskRunner> result_runner_; | 259 scoped_refptr<base::SingleThreadTaskRunner> result_runner_; |
330 | 260 |
331 // The caller's callback to be run when the update check is compelte. | 261 // The UI locale. |
332 UpdateCheckCallback result_callback_; | 262 std::string locale_; |
333 | 263 |
334 // The results of the update check. | 264 // False to only check for an update; true to also install one if available. |
335 GoogleUpdateUpgradeResult result_; | 265 bool install_update_if_possible_; |
| 266 |
| 267 // A parent window in case any UX is required (e.g., an elevation prompt). |
| 268 gfx::AcceleratedWidget elevation_window_; |
| 269 |
| 270 // The caller's delegate by which feedback is conveyed. |
| 271 base::WeakPtr<UpdateCheckDelegate> delegate_; |
| 272 |
| 273 // True if operating on a per-machine installation rather than a per-user one. |
| 274 bool system_level_install_; |
| 275 |
| 276 // The on-demand updater that is doing the work. |
| 277 base::win::ScopedComPtr<IGoogleUpdate3Web> google_update_; |
| 278 |
| 279 // An app bundle containing the application being updated. |
| 280 base::win::ScopedComPtr<IAppBundleWeb> app_bundle_; |
| 281 |
| 282 // The application being updated (Chrome, Chrome Binaries, or Chrome SxS). |
| 283 base::win::ScopedComPtr<IAppWeb> app_; |
| 284 |
| 285 // The progress value reported most recently to the caller. |
| 286 int last_reported_progress_; |
| 287 |
| 288 // The results of the update check to be logged via UMA and/or reported to the |
| 289 // caller. |
| 290 GoogleUpdateUpgradeStatus status_; |
336 GoogleUpdateErrorCode error_code_; | 291 GoogleUpdateErrorCode error_code_; |
337 base::string16 error_message_; | 292 base::string16 error_message_; |
338 base::string16 version_; | 293 base::string16 new_version_; |
339 HRESULT hresult_; | 294 HRESULT hresult_; |
340 | 295 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 | 296 |
352 DISALLOW_COPY_AND_ASSIGN(UpdateCheckDriver); | 297 DISALLOW_COPY_AND_ASSIGN(UpdateCheckDriver); |
353 }; | 298 }; |
354 | 299 |
355 // static | 300 // static |
356 void UpdateCheckDriver::RunUpdateCheck( | 301 void UpdateCheckDriver::RunUpdateCheck( |
357 const scoped_refptr<base::TaskRunner>& task_runner, | 302 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, |
358 bool install_if_newer, | 303 const std::string& locale, |
| 304 bool install_update_if_possible, |
359 gfx::AcceleratedWidget elevation_window, | 305 gfx::AcceleratedWidget elevation_window, |
360 const UpdateCheckCallback& callback) { | 306 const base::WeakPtr<UpdateCheckDelegate>& delegate) { |
361 // The driver is owned by itself, and will self-destruct when its work is | 307 // The driver is owned by itself, and will self-destruct when its work is |
362 // done. | 308 // done. |
363 UpdateCheckDriver* driver = new UpdateCheckDriver(callback); | 309 UpdateCheckDriver* driver = |
364 task_runner->PostTask( | 310 new UpdateCheckDriver(task_runner, locale, install_update_if_possible, |
365 FROM_HERE, | 311 elevation_window, delegate); |
366 base::Bind(&UpdateCheckDriver::BeginUpdateCheck, base::Unretained(driver), | 312 task_runner->PostTask(FROM_HERE, |
367 install_if_newer, elevation_window)); | 313 base::Bind(&UpdateCheckDriver::BeginUpdateCheck, |
| 314 base::Unretained(driver))); |
368 } | 315 } |
369 | 316 |
370 // Runs on the caller's thread. | 317 // Runs on the caller's thread. |
371 UpdateCheckDriver::UpdateCheckDriver(const UpdateCheckCallback& callback) | 318 UpdateCheckDriver::UpdateCheckDriver( |
372 : result_runner_(base::ThreadTaskRunnerHandle::Get()), | 319 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, |
373 result_callback_(callback), | 320 const std::string& locale, |
374 result_(UPGRADE_ERROR), | 321 bool install_update_if_possible, |
| 322 gfx::AcceleratedWidget elevation_window, |
| 323 const base::WeakPtr<UpdateCheckDelegate>& delegate) |
| 324 : task_runner_(task_runner), |
| 325 result_runner_(base::ThreadTaskRunnerHandle::Get()), |
| 326 locale_(locale), |
| 327 install_update_if_possible_(install_update_if_possible), |
| 328 elevation_window_(elevation_window), |
| 329 delegate_(delegate), |
| 330 system_level_install_(false), |
| 331 last_reported_progress_(0), |
| 332 status_(UPGRADE_ERROR), |
375 error_code_(GOOGLE_UPDATE_NO_ERROR), | 333 error_code_(GOOGLE_UPDATE_NO_ERROR), |
376 hresult_(S_OK), | 334 hresult_(S_OK), |
377 job_observer_(nullptr) { | 335 installer_exit_code_(-1) { |
378 } | 336 } |
379 | 337 |
380 UpdateCheckDriver::~UpdateCheckDriver() { | 338 UpdateCheckDriver::~UpdateCheckDriver() { |
381 DCHECK(result_runner_->BelongsToCurrentThread()); | 339 DCHECK(result_runner_->BelongsToCurrentThread()); |
382 // If there is an error, then error_code must not be blank, and vice versa. | 340 // 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); | 341 DCHECK_NE(status_ == UPGRADE_ERROR, error_code_ == GOOGLE_UPDATE_NO_ERROR); |
384 UMA_HISTOGRAM_ENUMERATION("GoogleUpdate.UpgradeResult", result_, | 342 UMA_HISTOGRAM_ENUMERATION("GoogleUpdate.UpgradeResult", status_, |
385 NUM_UPGRADE_RESULTS); | 343 NUM_UPGRADE_STATUS); |
386 if (result_ == UPGRADE_ERROR) { | 344 if (status_ == UPGRADE_ERROR) { |
387 UMA_HISTOGRAM_ENUMERATION("GoogleUpdate.UpdateErrorCode", error_code_, | 345 UMA_HISTOGRAM_ENUMERATION("GoogleUpdate.UpdateErrorCode", error_code_, |
388 NUM_ERROR_CODES); | 346 NUM_ERROR_CODES); |
389 if (hresult_ != S_OK) | 347 if (FAILED(hresult_)) |
390 UMA_HISTOGRAM_SPARSE_SLOWLY("GoogleUpdate.ErrorHresult", hresult_); | 348 UMA_HISTOGRAM_SPARSE_SLOWLY("GoogleUpdate.ErrorHresult", hresult_); |
391 } | 349 if (installer_exit_code_ != -1) { |
392 result_callback_.Run(result_, error_code_, error_message_, version_); | 350 UMA_HISTOGRAM_SPARSE_SLOWLY("GoogleUpdate.InstallerExitCode", |
393 } | 351 installer_exit_code_); |
394 | 352 } |
395 void UpdateCheckDriver::BeginUpdateCheck( | 353 } |
396 bool install_if_newer, | 354 if (delegate_) { |
397 gfx::AcceleratedWidget elevation_window) { | 355 if (status_ == UPGRADE_ERROR) |
398 // Return results immediately if the driver is not waiting for Google Update. | 356 delegate_->OnError(error_code_, error_message_, new_version_); |
399 if (!BeginUpdateCheckInternal(install_if_newer, elevation_window)) | 357 else if (install_update_if_possible_) |
| 358 delegate_->OnUpgradeComplete(new_version_); |
| 359 else |
| 360 delegate_->OnUpdateCheckComplete(new_version_); |
| 361 } |
| 362 } |
| 363 |
| 364 void UpdateCheckDriver::BeginUpdateCheck() { |
| 365 GoogleUpdateErrorCode error_code = GOOGLE_UPDATE_NO_ERROR; |
| 366 HRESULT hresult = BeginUpdateCheckInternal(&error_code); |
| 367 if (SUCCEEDED(hresult)) { |
| 368 // Start polling. |
| 369 task_runner_->PostTask(FROM_HERE, |
| 370 base::Bind(&UpdateCheckDriver::PollGoogleUpdate, |
| 371 base::Unretained(this))); |
| 372 } else { |
| 373 // Return results immediately since the driver is not polling Google Update. |
| 374 OnUpgradeError(error_code, hresult, -1, base::string16()); |
400 result_runner_->DeleteSoon(FROM_HERE, this); | 375 result_runner_->DeleteSoon(FROM_HERE, this); |
401 } | 376 } |
402 | 377 } |
403 bool UpdateCheckDriver::BeginUpdateCheckInternal( | 378 |
404 bool install_if_newer, | 379 HRESULT UpdateCheckDriver::BeginUpdateCheckInternal( |
405 gfx::AcceleratedWidget elevation_window) { | 380 GoogleUpdateErrorCode* error_code) { |
406 base::FilePath chrome_exe; | 381 base::FilePath chrome_exe; |
407 if (!PathService::Get(base::DIR_EXE, &chrome_exe)) | 382 if (!PathService::Get(base::DIR_EXE, &chrome_exe)) |
408 NOTREACHED(); | 383 NOTREACHED(); |
409 | 384 |
410 const bool system_level = !InstallUtil::IsPerUserInstall(chrome_exe); | 385 system_level_install_ = !InstallUtil::IsPerUserInstall(chrome_exe); |
411 | |
412 // The failures handled here are: | |
413 // CANNOT_UPGRADE_CHROME_IN_THIS_DIRECTORY, | |
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) { | |
418 // These failures are handled in the UX with custom messages. | |
419 result_ = UPGRADE_ERROR; | |
420 return false; | |
421 } | |
422 | 386 |
423 // Make sure ATL is initialized in this module. | 387 // Make sure ATL is initialized in this module. |
424 ui::win::CreateATLModuleIfNeeded(); | 388 ui::win::CreateATLModuleIfNeeded(); |
425 | 389 |
426 HRESULT hr = | 390 *error_code = CanUpdateCurrentChrome(chrome_exe, system_level_install_); |
427 CComObject<GoogleUpdateJobObserver>::CreateInstance(&job_observer_); | 391 if (*error_code != GOOGLE_UPDATE_NO_ERROR) |
428 if (hr != S_OK) { | 392 return E_FAIL; |
429 // Most of the error messages come straight from Google Update. This one is | 393 |
430 // deemed worthy enough to also warrant its own error. | 394 HRESULT hresult = CreateGoogleUpdate3WebClass( |
431 OnUpgradeError(GOOGLE_UPDATE_JOB_SERVER_CREATION_FAILED, hr, false); | 395 system_level_install_, install_update_if_possible_, elevation_window_, |
| 396 &google_update_); |
| 397 if (FAILED(hresult)) { |
| 398 *error_code = GOOGLE_UPDATE_ONDEMAND_CLASS_NOT_FOUND; |
| 399 return hresult; |
| 400 } |
| 401 |
| 402 // The class was created, so all subsequent errors are reported as: |
| 403 *error_code = GOOGLE_UPDATE_ONDEMAND_CLASS_REPORTED_ERROR; |
| 404 base::string16 app_guid = |
| 405 installer::GetAppGuidForUpdates(system_level_install_); |
| 406 DCHECK(!app_guid.empty()); |
| 407 |
| 408 { |
| 409 base::win::ScopedComPtr<IDispatch> dispatch; |
| 410 hresult = google_update_->createAppBundleWeb(dispatch.Receive()); |
| 411 if (FAILED(hresult)) |
| 412 return hresult; |
| 413 hresult = dispatch.QueryInterface(app_bundle_.Receive()); |
| 414 if (FAILED(hresult)) |
| 415 return hresult; |
| 416 } |
| 417 |
| 418 if (!locale_.empty()) { |
| 419 // Ignore the result of this since, while setting the display language is |
| 420 // nice to have, a failure to do so does not affect the likelihood that the |
| 421 // update check and/or install will succeed. |
| 422 app_bundle_->put_displayLanguage( |
| 423 base::win::ScopedBstr(base::UTF8ToUTF16(locale_).c_str())); |
| 424 } |
| 425 |
| 426 hresult = app_bundle_->initialize(); |
| 427 if (FAILED(hresult)) |
| 428 return hresult; |
| 429 if (elevation_window_) { |
| 430 // Likewise, a failure to set the parent window need not block an update |
| 431 // check. |
| 432 app_bundle_->put_parentHWND(reinterpret_cast<ULONG_PTR>(elevation_window_)); |
| 433 } |
| 434 |
| 435 base::win::ScopedComPtr<IDispatch> dispatch; |
| 436 hresult = |
| 437 app_bundle_->createInstalledApp(base::win::ScopedBstr(app_guid.c_str())); |
| 438 if (FAILED(hresult)) |
| 439 return hresult; |
| 440 hresult = app_bundle_->get_appWeb(0, dispatch.Receive()); |
| 441 if (FAILED(hresult)) |
| 442 return hresult; |
| 443 hresult = dispatch.QueryInterface(app_.Receive()); |
| 444 if (FAILED(hresult)) |
| 445 return hresult; |
| 446 return app_bundle_->checkForUpdate(); |
| 447 } |
| 448 |
| 449 bool UpdateCheckDriver::GetCurrentState( |
| 450 base::win::ScopedComPtr<ICurrentState>* current_state, |
| 451 CurrentState* state_value, |
| 452 HRESULT* hresult) const { |
| 453 base::win::ScopedComPtr<IDispatch> dispatch; |
| 454 *hresult = app_->get_currentState(dispatch.Receive()); |
| 455 if (FAILED(*hresult)) |
432 return false; | 456 return false; |
433 } | 457 *hresult = dispatch.QueryInterface(current_state->Receive()); |
434 // Hold a reference on the observer for the lifetime of the driver. | 458 if (FAILED(*hresult)) |
435 job_holder_ = job_observer_; | |
436 | |
437 job_observer_->set_on_complete_callback(base::Bind( | |
438 &UpdateCheckDriver::CompleteUpdateCheck, base::Unretained(this))); | |
439 | |
440 hr = CreateOnDemandAppsClass(system_level, install_if_newer, elevation_window, | |
441 &on_demand_); | |
442 if (hr != S_OK) { | |
443 OnUpgradeError(GOOGLE_UPDATE_ONDEMAND_CLASS_NOT_FOUND, hr, system_level); | |
444 return false; | 459 return false; |
445 } | 460 LONG value = 0; |
446 | 461 *hresult = (*current_state)->get_stateValue(&value); |
447 base::string16 app_guid = installer::GetAppGuidForUpdates(system_level); | 462 if (FAILED(*hresult)) |
448 DCHECK(!app_guid.empty()); | |
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; | 463 return false; |
459 } | 464 *state_value = static_cast<CurrentState>(value); |
460 return true; | 465 return true; |
461 } | 466 } |
462 | 467 |
463 void UpdateCheckDriver::CompleteUpdateCheck() { | 468 bool UpdateCheckDriver::IsErrorState( |
464 result_ = job_observer_->result(); | 469 const base::win::ScopedComPtr<ICurrentState>& current_state, |
465 if (result_ == UPGRADE_ERROR) { | 470 CurrentState state_value, |
466 error_code_ = GOOGLE_UPDATE_ERROR_UPDATING; | 471 GoogleUpdateErrorCode* error_code, |
467 error_message_ = job_observer_->error_message(); | 472 HRESULT* hresult, |
468 } else { | 473 int* installer_exit_code, |
469 version_ = job_observer_->new_version(); | 474 base::string16* error_string) const { |
| 475 if (state_value == STATE_ERROR) { |
| 476 // In general, errors reported by Google Update fall under this category |
| 477 // (see special case below). |
| 478 *error_code = GOOGLE_UPDATE_ERROR_UPDATING; |
| 479 |
| 480 // In general, the exit code of Chrome's installer is unknown (see special |
| 481 // case below). |
| 482 *installer_exit_code = -1; |
| 483 |
| 484 // Report the error_code provided by Google Update if possible, or the |
| 485 // reason it wasn't possible otherwise. |
| 486 LONG long_value = 0; |
| 487 *hresult = current_state->get_errorCode(&long_value); |
| 488 if (SUCCEEDED(*hresult)) |
| 489 *hresult = long_value; |
| 490 |
| 491 // Special cases: |
| 492 // - Use a custom error code if Google Update repoted that the update was |
| 493 // disabled by a Group Policy setting. |
| 494 // - Extract the exit code of Chrome's installer if Google Update repoted |
| 495 // that the update failed because of a failure in the installer. |
| 496 LONG code = 0; |
| 497 if (*hresult == GOOPDATE_E_APP_UPDATE_DISABLED_BY_POLICY) { |
| 498 *error_code = GOOGLE_UPDATE_DISABLED_BY_POLICY; |
| 499 } else if (*hresult == GOOPDATEINSTALL_E_INSTALLER_FAILED && |
| 500 SUCCEEDED(current_state->get_installerResultCode(&code))) { |
| 501 *installer_exit_code = code; |
| 502 } |
| 503 |
| 504 base::win::ScopedBstr message; |
| 505 if (SUCCEEDED(current_state->get_completionMessage(message.Receive()))) |
| 506 error_string->assign(message, message.Length()); |
| 507 |
| 508 return true; |
| 509 } |
| 510 if (state_value == STATE_UPDATE_AVAILABLE && install_update_if_possible_) { |
| 511 *hresult = app_bundle_->install(); |
| 512 if (FAILED(*hresult)) { |
| 513 // Report a failure to start the install as a general error while trying |
| 514 // to interact with Google Update. |
| 515 *error_code = GOOGLE_UPDATE_ONDEMAND_CLASS_REPORTED_ERROR; |
| 516 *installer_exit_code = -1; |
| 517 return true; |
| 518 } |
| 519 // Return false for handling in IsIntermediateState. |
| 520 } |
| 521 return false; |
| 522 } |
| 523 |
| 524 bool UpdateCheckDriver::IsFinalState( |
| 525 const base::win::ScopedComPtr<ICurrentState>& current_state, |
| 526 CurrentState state_value, |
| 527 GoogleUpdateUpgradeStatus* upgrade_status, |
| 528 base::string16* new_version) const { |
| 529 if (state_value == STATE_UPDATE_AVAILABLE && !install_update_if_possible_) { |
| 530 base::win::ScopedBstr version; |
| 531 *upgrade_status = UPGRADE_IS_AVAILABLE; |
| 532 if (SUCCEEDED(current_state->get_availableVersion(version.Receive()))) |
| 533 new_version->assign(version, version.Length()); |
| 534 return true; |
| 535 } |
| 536 if (state_value == STATE_INSTALL_COMPLETE) { |
| 537 DCHECK(install_update_if_possible_); |
| 538 *upgrade_status = UPGRADE_SUCCESSFUL; |
| 539 return true; |
| 540 } |
| 541 if (state_value == STATE_NO_UPDATE) { |
| 542 *upgrade_status = UPGRADE_ALREADY_UP_TO_DATE; |
| 543 return true; |
| 544 } |
| 545 return false; |
| 546 } |
| 547 |
| 548 bool UpdateCheckDriver::IsIntermediateState( |
| 549 const base::win::ScopedComPtr<ICurrentState>& current_state, |
| 550 CurrentState state_value, |
| 551 base::string16* new_version, |
| 552 int* progress) const { |
| 553 // ERROR will have been handled in IsErrorState. UPDATE_AVAILABLE, and |
| 554 // NO_UPDATE will have been handled in IsFinalState if not doing an install, |
| 555 // as will STATE_INSTALL_COMPLETE when doing an install. All other states |
| 556 // following UPDATE_AVAILABLE will only happen when an install is to be done. |
| 557 DCHECK(state_value < STATE_UPDATE_AVAILABLE || install_update_if_possible_); |
| 558 *progress = 0; |
| 559 |
| 560 switch (state_value) { |
| 561 case STATE_INIT: |
| 562 case STATE_WAITING_TO_CHECK_FOR_UPDATE: |
| 563 case STATE_CHECKING_FOR_UPDATE: |
| 564 // There is no news to report yet. |
| 565 break; |
| 566 |
| 567 case STATE_UPDATE_AVAILABLE: { |
| 568 base::win::ScopedBstr version; |
| 569 if (SUCCEEDED(current_state->get_availableVersion(version.Receive()))) |
| 570 new_version->assign(version, version.Length()); |
| 571 break; |
| 572 } |
| 573 |
| 574 case STATE_WAITING_TO_DOWNLOAD: |
| 575 case STATE_RETRYING_DOWNLOAD: |
| 576 break; |
| 577 |
| 578 case STATE_DOWNLOADING: { |
| 579 ULONG bytes_downloaded = 0; |
| 580 ULONG total_bytes = 0; |
| 581 if (SUCCEEDED(current_state->get_bytesDownloaded(&bytes_downloaded)) && |
| 582 SUCCEEDED(current_state->get_totalBytesToDownload(&total_bytes)) && |
| 583 total_bytes) { |
| 584 // 0-50 is downloading. |
| 585 *progress = gfx::ToFlooredInt((static_cast<double>(bytes_downloaded) / |
| 586 static_cast<double>(total_bytes)) * |
| 587 50.0); |
| 588 } |
| 589 break; |
| 590 } |
| 591 |
| 592 case STATE_DOWNLOAD_COMPLETE: |
| 593 case STATE_EXTRACTING: |
| 594 case STATE_APPLYING_DIFFERENTIAL_PATCH: |
| 595 case STATE_READY_TO_INSTALL: |
| 596 case STATE_WAITING_TO_INSTALL: |
| 597 *progress = 50; |
| 598 break; |
| 599 |
| 600 case STATE_INSTALLING: { |
| 601 *progress = 50; |
| 602 LONG install_progress = 0; |
| 603 if (SUCCEEDED(current_state->get_installProgress(&install_progress)) && |
| 604 install_progress >= 0 && install_progress <= 100) { |
| 605 // 50-100 is installing. |
| 606 *progress = (50 + install_progress / 2); |
| 607 } |
| 608 break; |
| 609 } |
| 610 |
| 611 case STATE_INSTALL_COMPLETE: |
| 612 case STATE_PAUSED: |
| 613 case STATE_NO_UPDATE: |
| 614 case STATE_ERROR: |
| 615 default: |
| 616 NOTREACHED(); |
| 617 UMA_HISTOGRAM_SPARSE_SLOWLY("GoogleUpdate.UnexpectedState", state_value); |
| 618 return false; |
| 619 } |
| 620 return true; |
| 621 } |
| 622 |
| 623 void UpdateCheckDriver::PollGoogleUpdate() { |
| 624 base::win::ScopedComPtr<ICurrentState> state; |
| 625 CurrentState state_value = STATE_INIT; |
| 626 HRESULT hresult = S_OK; |
| 627 GoogleUpdateErrorCode error_code = GOOGLE_UPDATE_NO_ERROR; |
| 628 int installer_exit_code = -1; |
| 629 base::string16 error_string; |
| 630 GoogleUpdateUpgradeStatus upgrade_status = UPGRADE_ERROR; |
| 631 base::string16 new_version; |
| 632 int progress = 0; |
| 633 |
| 634 if (!GetCurrentState(&state, &state_value, &hresult)) { |
| 635 OnUpgradeError(GOOGLE_UPDATE_ONDEMAND_CLASS_REPORTED_ERROR, hresult, -1, |
| 636 base::string16()); |
| 637 } else if (IsErrorState(state, state_value, &error_code, &hresult, |
| 638 &installer_exit_code, &error_string)) { |
| 639 OnUpgradeError(error_code, hresult, installer_exit_code, error_string); |
| 640 } else if (IsFinalState(state, state_value, &upgrade_status, &new_version)) { |
| 641 status_ = upgrade_status; |
| 642 error_code_ = GOOGLE_UPDATE_NO_ERROR; |
| 643 error_message_.clear(); |
| 644 if (!new_version.empty()) |
| 645 new_version_ = new_version; |
| 646 hresult_ = S_OK; |
| 647 installer_exit_code_ = -1; |
| 648 } else if (IsIntermediateState(state, state_value, &new_version, &progress)) { |
| 649 bool got_new_version = new_version_.empty() && !new_version.empty(); |
| 650 if (got_new_version) |
| 651 new_version_ = new_version; |
| 652 // Give the caller this status update if it differs from the last one given. |
| 653 if (got_new_version || progress != last_reported_progress_) { |
| 654 last_reported_progress_ = progress; |
| 655 |
| 656 // It is safe to post this task with an unretained pointer since the task |
| 657 // is guaranteed to run before a subsequent DeleteSoon is handled. |
| 658 result_runner_->PostTask( |
| 659 FROM_HERE, |
| 660 base::Bind(&UpdateCheckDelegate::OnUpgradeProgress, delegate_, |
| 661 last_reported_progress_, new_version_)); |
| 662 } |
| 663 |
| 664 // Schedule the next check. |
| 665 task_runner_->PostDelayedTask( |
| 666 FROM_HERE, base::Bind(&UpdateCheckDriver::PollGoogleUpdate, |
| 667 base::Unretained(this)), |
| 668 base::TimeDelta::FromMilliseconds(kGoogleUpdatePollIntervalMs)); |
| 669 // Early return for this non-terminal state. |
| 670 return; |
470 } | 671 } |
471 | 672 |
472 // Release the reference on the COM objects before bouncing back to the | 673 // Release the reference on the COM objects before bouncing back to the |
473 // caller's thread. | 674 // caller's thread. |
474 on_demand_.Release(); | 675 state.Release(); |
475 job_holder_.Release(); | 676 app_.Release(); |
476 job_observer_ = nullptr; | 677 app_bundle_.Release(); |
| 678 google_update_.Release(); |
477 | 679 |
478 result_runner_->DeleteSoon(FROM_HERE, this); | 680 result_runner_->DeleteSoon(FROM_HERE, this); |
479 } | 681 } |
480 | 682 |
481 void UpdateCheckDriver::OnUpgradeError(GoogleUpdateErrorCode error_code, | 683 void UpdateCheckDriver::OnUpgradeError(GoogleUpdateErrorCode error_code, |
482 HRESULT hr, | 684 HRESULT hresult, |
483 bool system_level) { | 685 int installer_exit_code, |
484 result_ = UPGRADE_ERROR; | 686 const base::string16& error_string) { |
| 687 status_ = UPGRADE_ERROR; |
485 error_code_ = error_code; | 688 error_code_ = error_code; |
486 hresult_ = hr; | 689 hresult_ = hresult; |
| 690 installer_exit_code_ = installer_exit_code; |
487 base::string16 error_msg = | 691 base::string16 error_msg = |
488 base::StringPrintf(L"%d: 0x%x", error_code_, hresult_); | 692 base::StringPrintf(L"%d: 0x%x", error_code_, hresult_); |
489 if (system_level) | 693 if (installer_exit_code_ != -1) |
| 694 error_msg += base::StringPrintf(L": %d", installer_exit_code_); |
| 695 if (system_level_install_) |
490 error_msg += L" -- system level"; | 696 error_msg += L" -- system level"; |
491 error_message_ = l10n_util::GetStringFUTF16( | 697 if (error_string.empty()) { |
492 IDS_ABOUT_BOX_ERROR_UPDATE_CHECK_FAILED, error_msg); | 698 error_message_ = l10n_util::GetStringFUTF16( |
| 699 IDS_ABOUT_BOX_ERROR_UPDATE_CHECK_FAILED, error_msg); |
| 700 } else { |
| 701 error_message_ = l10n_util::GetStringFUTF16( |
| 702 IDS_ABOUT_BOX_GOOGLE_UPDATE_ERROR, error_string, error_msg); |
| 703 } |
493 } | 704 } |
494 | 705 |
495 } // namespace | 706 } // namespace |
496 | 707 |
497 | 708 |
498 // Globals --------------------------------------------------------------------- | 709 // Globals --------------------------------------------------------------------- |
499 | 710 |
500 void BeginUpdateCheck(const scoped_refptr<base::TaskRunner>& task_runner, | 711 void BeginUpdateCheck( |
501 bool install_if_newer, | 712 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, |
502 gfx::AcceleratedWidget elevation_window, | 713 const std::string& locale, |
503 const UpdateCheckCallback& callback) { | 714 bool install_update_if_possible, |
504 UpdateCheckDriver::RunUpdateCheck(task_runner, install_if_newer, | 715 gfx::AcceleratedWidget elevation_window, |
505 elevation_window, callback); | 716 const base::WeakPtr<UpdateCheckDelegate>& delegate) { |
| 717 UpdateCheckDriver::RunUpdateCheck(task_runner, locale, |
| 718 install_update_if_possible, |
| 719 elevation_window, delegate); |
506 } | 720 } |
507 | 721 |
508 | 722 |
509 // Private API exposed for testing. -------------------------------------------- | 723 // Private API exposed for testing. -------------------------------------------- |
510 | 724 |
511 void SetGoogleUpdateFactoryForTesting( | 725 void SetGoogleUpdateFactoryForTesting( |
512 const OnDemandAppsClassFactory& google_update_factory) { | 726 const GoogleUpdate3ClassFactory& google_update_factory) { |
513 if (g_google_update_factory) { | 727 if (g_google_update_factory) { |
514 delete g_google_update_factory; | 728 delete g_google_update_factory; |
515 g_google_update_factory = nullptr; | 729 g_google_update_factory = nullptr; |
516 } | 730 } |
517 if (!google_update_factory.is_null()) { | 731 if (!google_update_factory.is_null()) { |
518 g_google_update_factory = | 732 g_google_update_factory = |
519 new OnDemandAppsClassFactory(google_update_factory); | 733 new GoogleUpdate3ClassFactory(google_update_factory); |
520 } | 734 } |
521 } | 735 } |
OLD | NEW |