OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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.h" | 5 #include "chrome/browser/google/google_update.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/file_path.h" | 11 #include "base/file_path.h" |
12 #include "base/message_loop.h" | 12 #include "base/message_loop.h" |
13 #include "base/path_service.h" | 13 #include "base/path_service.h" |
14 #include "base/string_util.h" | 14 #include "base/string_util.h" |
15 #include "base/stringprintf.h" | 15 #include "base/stringprintf.h" |
16 #include "base/task.h" | 16 #include "base/task.h" |
17 #include "base/threading/thread.h" | 17 #include "base/threading/thread.h" |
18 #include "base/win/scoped_comptr.h" | 18 #include "base/win/scoped_comptr.h" |
19 #include "base/win/windows_version.h" | 19 #include "base/win/windows_version.h" |
20 #include "chrome/installer/util/browser_distribution.h" | 20 #include "chrome/installer/util/browser_distribution.h" |
21 #include "chrome/installer/util/google_update_settings.h" | 21 #include "chrome/installer/util/google_update_settings.h" |
22 #include "chrome/installer/util/helper.h" | 22 #include "chrome/installer/util/helper.h" |
23 #include "chrome/installer/util/install_util.h" | 23 #include "chrome/installer/util/install_util.h" |
24 #include "content/browser/browser_thread.h" | 24 #include "content/browser/browser_thread.h" |
| 25 #include "grit/generated_resources.h" |
25 #include "google_update_idl_i.c" | 26 #include "google_update_idl_i.c" |
| 27 #include "ui/base/l10n/l10n_util.h" |
26 #include "views/widget/widget.h" | 28 #include "views/widget/widget.h" |
27 | 29 |
28 namespace { | 30 namespace { |
29 | 31 |
30 // Check if the currently running instance can be updated by Google Update. | 32 // Check if the currently running instance can be updated by Google Update. |
31 // Returns GOOGLE_UPDATE_NO_ERROR only if the instance running is a Google | 33 // Returns GOOGLE_UPDATE_NO_ERROR only if the instance running is a Google |
32 // Chrome distribution installed in a standard location. | 34 // Chrome distribution installed in a standard location. |
33 GoogleUpdateErrorCode CanUpdateCurrentChrome( | 35 GoogleUpdateErrorCode CanUpdateCurrentChrome( |
34 const std::wstring& chrome_exe_path) { | 36 const FilePath& chrome_exe_path) { |
35 #if !defined(GOOGLE_CHROME_BUILD) | 37 #if !defined(GOOGLE_CHROME_BUILD) |
36 return CANNOT_UPGRADE_CHROME_IN_THIS_DIRECTORY; | 38 return CANNOT_UPGRADE_CHROME_IN_THIS_DIRECTORY; |
37 #else | 39 #else |
38 // TODO(tommi): Check if using the default distribution is always the right | 40 // TODO(tommi): Check if using the default distribution is always the right |
39 // thing to do. | 41 // thing to do. |
40 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); | 42 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); |
41 std::wstring user_exe_path = | 43 FilePath user_exe_path = installer::GetChromeInstallPath(false, dist); |
42 installer::GetChromeInstallPath(false, dist).value(); | 44 FilePath machine_exe_path = installer::GetChromeInstallPath(true, dist); |
43 std::wstring machine_exe_path = | 45 if (!FilePath::CompareEqualIgnoreCase(chrome_exe_path.value(), |
44 installer::GetChromeInstallPath(true, dist).value(); | 46 user_exe_path.value()) && |
45 std::transform(user_exe_path.begin(), user_exe_path.end(), | 47 !FilePath::CompareEqualIgnoreCase(chrome_exe_path.value(), |
46 user_exe_path.begin(), tolower); | 48 machine_exe_path.value())) { |
47 std::transform(machine_exe_path.begin(), machine_exe_path.end(), | |
48 machine_exe_path.begin(), tolower); | |
49 if (chrome_exe_path != user_exe_path && | |
50 chrome_exe_path != machine_exe_path ) { | |
51 LOG(ERROR) << L"Google Update cannot update Chrome installed in a " | 49 LOG(ERROR) << L"Google Update cannot update Chrome installed in a " |
52 << L"non-standard location: " << chrome_exe_path.c_str() | 50 << L"non-standard location: " << chrome_exe_path.value().c_str() |
53 << L". The standard location is: " << user_exe_path.c_str() | 51 << L". The standard location is: " |
54 << L" or " << machine_exe_path.c_str() << L"."; | 52 << user_exe_path.value().c_str() |
| 53 << L" or " << machine_exe_path.value().c_str() << L"."; |
55 return CANNOT_UPGRADE_CHROME_IN_THIS_DIRECTORY; | 54 return CANNOT_UPGRADE_CHROME_IN_THIS_DIRECTORY; |
56 } | 55 } |
57 | 56 |
58 std::wstring app_guid = installer::GetAppGuidForUpdates( | 57 string16 app_guid = installer::GetAppGuidForUpdates( |
59 !InstallUtil::IsPerUserInstall(chrome_exe_path.c_str())); | 58 !InstallUtil::IsPerUserInstall(chrome_exe_path.value().c_str())); |
60 DCHECK(!app_guid.empty()); | 59 DCHECK(!app_guid.empty()); |
61 | 60 |
62 if (GoogleUpdateSettings::GetAppUpdatePolicy(app_guid, NULL) == | 61 if (GoogleUpdateSettings::GetAppUpdatePolicy(app_guid, NULL) == |
63 GoogleUpdateSettings::UPDATES_DISABLED) | 62 GoogleUpdateSettings::UPDATES_DISABLED) |
64 return GOOGLE_UPDATE_DISABLED_BY_POLICY; | 63 return GOOGLE_UPDATE_DISABLED_BY_POLICY; |
65 | 64 |
66 return GOOGLE_UPDATE_NO_ERROR; | 65 return GOOGLE_UPDATE_NO_ERROR; |
67 #endif | 66 #endif |
68 } | 67 } |
69 | 68 |
70 // Creates an instance of a COM Local Server class using either plain vanilla | 69 // Creates an instance of a COM Local Server class using either plain vanilla |
71 // CoCreateInstance, or using the Elevation moniker if running on Vista. | 70 // CoCreateInstance, or using the Elevation moniker if running on Vista. |
72 // hwnd must refer to a foregound window in order to get the UAC prompt | 71 // hwnd must refer to a foregound window in order to get the UAC prompt |
73 // showing up in the foreground if running on Vista. It can also be NULL if | 72 // showing up in the foreground if running on Vista. It can also be NULL if |
74 // background UAC prompts are desired. | 73 // background UAC prompts are desired. |
75 HRESULT CoCreateInstanceAsAdmin(REFCLSID class_id, REFIID interface_id, | 74 HRESULT CoCreateInstanceAsAdmin(REFCLSID class_id, REFIID interface_id, |
76 HWND hwnd, void** interface_ptr) { | 75 HWND hwnd, void** interface_ptr) { |
77 if (!interface_ptr) | 76 if (!interface_ptr) |
78 return E_POINTER; | 77 return E_POINTER; |
79 | 78 |
80 // For Vista we need to instantiate the COM server via the elevation | 79 // For Vista we need to instantiate the COM server via the elevation |
81 // moniker. This ensures that the UAC dialog shows up. | 80 // moniker. This ensures that the UAC dialog shows up. |
82 if (base::win::GetVersion() >= base::win::VERSION_VISTA) { | 81 if (base::win::GetVersion() >= base::win::VERSION_VISTA) { |
83 wchar_t class_id_as_string[MAX_PATH] = {0}; | 82 wchar_t class_id_as_string[MAX_PATH] = {0}; |
84 StringFromGUID2(class_id, class_id_as_string, | 83 StringFromGUID2(class_id, class_id_as_string, |
85 arraysize(class_id_as_string)); | 84 arraysize(class_id_as_string)); |
86 | 85 |
87 std::wstring elevation_moniker_name = | 86 string16 elevation_moniker_name = |
88 base::StringPrintf(L"Elevation:Administrator!new:%ls", | 87 base::StringPrintf(L"Elevation:Administrator!new:%ls", |
89 class_id_as_string); | 88 class_id_as_string); |
90 | 89 |
91 BIND_OPTS3 bind_opts; | 90 BIND_OPTS3 bind_opts; |
92 memset(&bind_opts, 0, sizeof(bind_opts)); | 91 memset(&bind_opts, 0, sizeof(bind_opts)); |
93 bind_opts.cbStruct = sizeof(bind_opts); | 92 bind_opts.cbStruct = sizeof(bind_opts); |
94 bind_opts.dwClassContext = CLSCTX_LOCAL_SERVER; | 93 bind_opts.dwClassContext = CLSCTX_LOCAL_SERVER; |
95 bind_opts.hwnd = hwnd; | 94 bind_opts.hwnd = hwnd; |
96 | 95 |
97 return CoGetObject(elevation_moniker_name.c_str(), &bind_opts, | 96 return CoGetObject(elevation_moniker_name.c_str(), &bind_opts, |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
159 STDMETHOD(OnComplete)(CompletionCodes code, const TCHAR* text) { | 158 STDMETHOD(OnComplete)(CompletionCodes code, const TCHAR* text) { |
160 switch (code) { | 159 switch (code) { |
161 case COMPLETION_CODE_SUCCESS_CLOSE_UI: | 160 case COMPLETION_CODE_SUCCESS_CLOSE_UI: |
162 case COMPLETION_CODE_SUCCESS: { | 161 case COMPLETION_CODE_SUCCESS: { |
163 if (result_ == UPGRADE_STARTED) | 162 if (result_ == UPGRADE_STARTED) |
164 result_ = UPGRADE_SUCCESSFUL; | 163 result_ = UPGRADE_SUCCESSFUL; |
165 else if (result_ == UPGRADE_CHECK_STARTED) | 164 else if (result_ == UPGRADE_CHECK_STARTED) |
166 result_ = UPGRADE_ALREADY_UP_TO_DATE; | 165 result_ = UPGRADE_ALREADY_UP_TO_DATE; |
167 break; | 166 break; |
168 } | 167 } |
| 168 case COMPLETION_CODE_ERROR: |
| 169 error_message_ = text; |
169 default: { | 170 default: { |
170 NOTREACHED(); | 171 NOTREACHED(); |
171 result_ = UPGRADE_ERROR; | 172 result_ = UPGRADE_ERROR; |
172 break; | 173 break; |
173 } | 174 } |
174 } | 175 } |
175 | 176 |
176 event_sink_ = NULL; | 177 event_sink_ = NULL; |
177 | 178 |
178 // We no longer need to spin the message loop that we started spinning in | 179 // We no longer need to spin the message loop that we started spinning in |
(...skipping 10 matching lines...) Expand all Loading... |
189 STDMETHOD(GetResult)(GoogleUpdateUpgradeResult* result) { | 190 STDMETHOD(GetResult)(GoogleUpdateUpgradeResult* result) { |
190 // Intermediary steps should never be reported to the client. | 191 // Intermediary steps should never be reported to the client. |
191 DCHECK(result_ != UPGRADE_STARTED && result_ != UPGRADE_CHECK_STARTED); | 192 DCHECK(result_ != UPGRADE_STARTED && result_ != UPGRADE_CHECK_STARTED); |
192 | 193 |
193 *result = result_; | 194 *result = result_; |
194 return S_OK; | 195 return S_OK; |
195 } | 196 } |
196 | 197 |
197 // Returns which version Google Update found on the server (if a more | 198 // Returns which version Google Update found on the server (if a more |
198 // recent version was found). Otherwise, this will be blank. | 199 // recent version was found). Otherwise, this will be blank. |
199 STDMETHOD(GetVersionInfo)(std::wstring* version_string) { | 200 STDMETHOD(GetVersionInfo)(string16* version_string) { |
200 *version_string = new_version_; | 201 *version_string = new_version_; |
201 return S_OK; | 202 return S_OK; |
202 } | 203 } |
203 | 204 |
| 205 // Returns the Google Update supplied error string that describes the error |
| 206 // that occurred during the update check/upgrade. |
| 207 STDMETHOD(GetErrorMessage)(string16* error_message) { |
| 208 *error_message = error_message_; |
| 209 return S_OK; |
| 210 } |
| 211 |
204 private: | 212 private: |
205 // The status/result of the Google Update operation. | 213 // The status/result of the Google Update operation. |
206 GoogleUpdateUpgradeResult result_; | 214 GoogleUpdateUpgradeResult result_; |
207 | 215 |
208 // The version string Google Update found. | 216 // The version string Google Update found. |
209 std::wstring new_version_; | 217 string16 new_version_; |
| 218 |
| 219 // An error message, if any. |
| 220 string16 error_message_; |
210 | 221 |
211 // Allows us control the upgrade process to a small degree. After OnComplete | 222 // Allows us control the upgrade process to a small degree. After OnComplete |
212 // has been called, this object can not be used. | 223 // has been called, this object can not be used. |
213 base::win::ScopedComPtr<IProgressWndEvents> event_sink_; | 224 base::win::ScopedComPtr<IProgressWndEvents> event_sink_; |
214 }; | 225 }; |
215 | 226 |
216 //////////////////////////////////////////////////////////////////////////////// | 227 //////////////////////////////////////////////////////////////////////////////// |
217 // GoogleUpdate, public: | 228 // GoogleUpdate, public: |
218 | 229 |
219 GoogleUpdate::GoogleUpdate() | 230 GoogleUpdate::GoogleUpdate() |
(...skipping 15 matching lines...) Expand all Loading... |
235 base::Bind(&GoogleUpdate::InitiateGoogleUpdateCheck, this, | 246 base::Bind(&GoogleUpdate::InitiateGoogleUpdateCheck, this, |
236 install_if_newer, window, MessageLoop::current())); | 247 install_if_newer, window, MessageLoop::current())); |
237 } | 248 } |
238 | 249 |
239 //////////////////////////////////////////////////////////////////////////////// | 250 //////////////////////////////////////////////////////////////////////////////// |
240 // GoogleUpdate, private: | 251 // GoogleUpdate, private: |
241 | 252 |
242 void GoogleUpdate::InitiateGoogleUpdateCheck(bool install_if_newer, | 253 void GoogleUpdate::InitiateGoogleUpdateCheck(bool install_if_newer, |
243 views::Widget* window, | 254 views::Widget* window, |
244 MessageLoop* main_loop) { | 255 MessageLoop* main_loop) { |
245 FilePath chrome_exe_path; | 256 FilePath chrome_exe; |
246 if (!PathService::Get(base::DIR_EXE, &chrome_exe_path)) | 257 if (!PathService::Get(base::DIR_EXE, &chrome_exe)) |
247 NOTREACHED(); | 258 NOTREACHED(); |
248 | 259 |
249 std::wstring chrome_exe = chrome_exe_path.value(); | |
250 | |
251 std::transform(chrome_exe.begin(), chrome_exe.end(), | |
252 chrome_exe.begin(), tolower); | |
253 | |
254 GoogleUpdateErrorCode error_code = CanUpdateCurrentChrome(chrome_exe); | 260 GoogleUpdateErrorCode error_code = CanUpdateCurrentChrome(chrome_exe); |
255 if (error_code != GOOGLE_UPDATE_NO_ERROR) { | 261 if (error_code != GOOGLE_UPDATE_NO_ERROR) { |
256 main_loop->PostTask( | 262 main_loop->PostTask( |
257 FROM_HERE, | 263 FROM_HERE, |
258 base::Bind(&GoogleUpdate::ReportResults, this, | 264 base::Bind(&GoogleUpdate::ReportResults, this, |
259 UPGRADE_ERROR, error_code)); | 265 UPGRADE_ERROR, error_code, string16())); |
260 return; | 266 return; |
261 } | 267 } |
262 | 268 |
263 CComObject<GoogleUpdateJobObserver>* job_observer; | 269 CComObject<GoogleUpdateJobObserver>* job_observer; |
264 HRESULT hr = | 270 HRESULT hr = |
265 CComObject<GoogleUpdateJobObserver>::CreateInstance(&job_observer); | 271 CComObject<GoogleUpdateJobObserver>::CreateInstance(&job_observer); |
266 if (hr != S_OK) { | 272 if (hr != S_OK) { |
267 ReportFailure(hr, GOOGLE_UPDATE_JOB_SERVER_CREATION_FAILED, main_loop); | 273 // Most of the error messages come straight from Google Update. This one is |
| 274 // deemed worthy enough to also warrant its own error. |
| 275 string16 error_code = base::StringPrintf(L"0x%x", hr); |
| 276 ReportFailure( |
| 277 hr, GOOGLE_UPDATE_JOB_SERVER_CREATION_FAILED, |
| 278 l10n_util::GetStringFUTF16(IDS_ABOUT_BOX_ERROR_COCREATE_FAILED, |
| 279 error_code), |
| 280 main_loop); |
268 return; | 281 return; |
269 } | 282 } |
270 | 283 |
271 base::win::ScopedComPtr<IJobObserver> job_holder(job_observer); | 284 base::win::ScopedComPtr<IJobObserver> job_holder(job_observer); |
272 | 285 |
273 base::win::ScopedComPtr<IGoogleUpdate> on_demand; | 286 base::win::ScopedComPtr<IGoogleUpdate> on_demand; |
274 | 287 |
275 bool system_level = false; | 288 bool system_level = false; |
276 | 289 |
277 if (InstallUtil::IsPerUserInstall(chrome_exe.c_str())) { | 290 if (InstallUtil::IsPerUserInstall(chrome_exe.value().c_str())) { |
278 hr = on_demand.CreateInstance(CLSID_OnDemandUserAppsClass); | 291 hr = on_demand.CreateInstance(CLSID_OnDemandUserAppsClass); |
279 } else { | 292 } else { |
280 // The Update operation needs Admin privileges for writing | 293 // The Update operation needs Admin privileges for writing |
281 // to %ProgramFiles%. On Vista we need to elevate before instantiating | 294 // to %ProgramFiles%. On Vista we need to elevate before instantiating |
282 // the updater instance. | 295 // the updater instance. |
283 if (!install_if_newer) { | 296 if (!install_if_newer) { |
284 hr = on_demand.CreateInstance(CLSID_OnDemandMachineAppsClass); | 297 hr = on_demand.CreateInstance(CLSID_OnDemandMachineAppsClass); |
285 } else { | 298 } else { |
286 HWND foreground_hwnd = NULL; | 299 HWND foreground_hwnd = NULL; |
287 if (window != NULL) { | 300 if (window != NULL) { |
288 foreground_hwnd = window->GetNativeWindow(); | 301 foreground_hwnd = window->GetNativeWindow(); |
289 } | 302 } |
290 | 303 |
291 hr = CoCreateInstanceAsAdmin(CLSID_OnDemandMachineAppsClass, | 304 hr = CoCreateInstanceAsAdmin(CLSID_OnDemandMachineAppsClass, |
292 IID_IGoogleUpdate, foreground_hwnd, | 305 IID_IGoogleUpdate, foreground_hwnd, |
293 reinterpret_cast<void**>(on_demand.Receive())); | 306 reinterpret_cast<void**>(on_demand.Receive())); |
294 } | 307 } |
295 system_level = true; | 308 system_level = true; |
296 } | 309 } |
297 | 310 |
298 if (hr != S_OK) { | 311 if (hr != S_OK) { |
299 ReportFailure(hr, GOOGLE_UPDATE_ONDEMAND_CLASS_NOT_FOUND, main_loop); | 312 ReportFailure(hr, GOOGLE_UPDATE_ONDEMAND_CLASS_NOT_FOUND, |
| 313 string16(), main_loop); |
300 return; | 314 return; |
301 } | 315 } |
302 | 316 |
303 std::wstring app_guid = installer::GetAppGuidForUpdates(system_level); | 317 string16 app_guid = installer::GetAppGuidForUpdates(system_level); |
304 DCHECK(!app_guid.empty()); | 318 DCHECK(!app_guid.empty()); |
305 | 319 |
306 if (!install_if_newer) | 320 if (!install_if_newer) |
307 hr = on_demand->CheckForUpdate(app_guid.c_str(), job_observer); | 321 hr = on_demand->CheckForUpdate(app_guid.c_str(), job_observer); |
308 else | 322 else |
309 hr = on_demand->Update(app_guid.c_str(), job_observer); | 323 hr = on_demand->Update(app_guid.c_str(), job_observer); |
310 | 324 |
311 if (hr != S_OK) { | 325 if (hr != S_OK) { |
312 ReportFailure(hr, GOOGLE_UPDATE_ONDEMAND_CLASS_REPORTED_ERROR, main_loop); | 326 ReportFailure(hr, GOOGLE_UPDATE_ONDEMAND_CLASS_REPORTED_ERROR, |
| 327 string16(), main_loop); |
313 return; | 328 return; |
314 } | 329 } |
315 | 330 |
316 // We need to spin the message loop while Google Update is running so that it | 331 // We need to spin the message loop while Google Update is running so that it |
317 // can report back to us through GoogleUpdateJobObserver. This message loop | 332 // can report back to us through GoogleUpdateJobObserver. This message loop |
318 // will terminate once Google Update sends us the completion status | 333 // will terminate once Google Update sends us the completion status |
319 // (success/error). See OnComplete(). | 334 // (success/error). See OnComplete(). |
320 MessageLoop::current()->Run(); | 335 MessageLoop::current()->Run(); |
321 | 336 |
322 GoogleUpdateUpgradeResult results; | 337 GoogleUpdateUpgradeResult results; |
323 hr = job_observer->GetResult(&results); | 338 hr = job_observer->GetResult(&results); |
324 if (hr != S_OK) { | 339 if (hr != S_OK) { |
325 ReportFailure(hr, GOOGLE_UPDATE_GET_RESULT_CALL_FAILED, main_loop); | 340 ReportFailure(hr, GOOGLE_UPDATE_GET_RESULT_CALL_FAILED, |
| 341 string16(), main_loop); |
326 return; | 342 return; |
327 } | 343 } |
328 | 344 |
329 if (results == UPGRADE_ERROR) { | 345 if (results == UPGRADE_ERROR) { |
330 ReportFailure(hr, GOOGLE_UPDATE_ERROR_UPDATING, main_loop); | 346 string16 error_message; |
| 347 job_observer->GetErrorMessage(&error_message); |
| 348 ReportFailure(hr, GOOGLE_UPDATE_ERROR_UPDATING, error_message, main_loop); |
331 return; | 349 return; |
332 } | 350 } |
333 | 351 |
334 hr = job_observer->GetVersionInfo(&version_available_); | 352 hr = job_observer->GetVersionInfo(&version_available_); |
335 if (hr != S_OK) { | 353 if (hr != S_OK) { |
336 ReportFailure(hr, GOOGLE_UPDATE_GET_VERSION_INFO_FAILED, main_loop); | 354 ReportFailure(hr, GOOGLE_UPDATE_GET_VERSION_INFO_FAILED, |
| 355 string16(), main_loop); |
337 return; | 356 return; |
338 } | 357 } |
339 | 358 |
340 main_loop->PostTask( | 359 main_loop->PostTask( |
341 FROM_HERE, | 360 FROM_HERE, |
342 base::Bind(&GoogleUpdate::ReportResults, this, | 361 base::Bind(&GoogleUpdate::ReportResults, this, |
343 results, GOOGLE_UPDATE_NO_ERROR)); | 362 results, GOOGLE_UPDATE_NO_ERROR, string16())); |
344 job_holder = NULL; | 363 job_holder = NULL; |
345 on_demand = NULL; | 364 on_demand = NULL; |
346 } | 365 } |
347 | 366 |
348 void GoogleUpdate::ReportResults(GoogleUpdateUpgradeResult results, | 367 void GoogleUpdate::ReportResults(GoogleUpdateUpgradeResult results, |
349 GoogleUpdateErrorCode error_code) { | 368 GoogleUpdateErrorCode error_code, |
| 369 const string16& error_message) { |
350 // If we get an error, then error code must not be blank, and vice versa. | 370 // If we get an error, then error code must not be blank, and vice versa. |
351 DCHECK(results == UPGRADE_ERROR ? error_code != GOOGLE_UPDATE_NO_ERROR : | 371 DCHECK(results == UPGRADE_ERROR ? error_code != GOOGLE_UPDATE_NO_ERROR : |
352 error_code == GOOGLE_UPDATE_NO_ERROR); | 372 error_code == GOOGLE_UPDATE_NO_ERROR); |
353 if (listener_) | 373 if (listener_) { |
354 listener_->OnReportResults(results, error_code, version_available_); | 374 listener_->OnReportResults( |
| 375 results, error_code, error_message, version_available_); |
| 376 } |
355 } | 377 } |
356 | 378 |
357 bool GoogleUpdate::ReportFailure(HRESULT hr, GoogleUpdateErrorCode error_code, | 379 bool GoogleUpdate::ReportFailure(HRESULT hr, |
| 380 GoogleUpdateErrorCode error_code, |
| 381 const string16& error_message, |
358 MessageLoop* main_loop) { | 382 MessageLoop* main_loop) { |
359 NOTREACHED() << "Communication with Google Update failed: " << hr | 383 NOTREACHED() << "Communication with Google Update failed: " << hr |
360 << " error: " << error_code; | 384 << " error: " << error_code |
| 385 << ", message: " << error_message.c_str(); |
361 main_loop->PostTask( | 386 main_loop->PostTask( |
362 FROM_HERE, | 387 FROM_HERE, |
363 base::Bind(&GoogleUpdate::ReportResults, this, | 388 base::Bind(&GoogleUpdate::ReportResults, this, |
364 UPGRADE_ERROR, error_code)); | 389 UPGRADE_ERROR, error_code, error_message)); |
365 return false; | 390 return false; |
366 } | 391 } |
OLD | NEW |