Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(381)

Side by Side Diff: chrome/browser/google/google_update.cc

Issue 8394042: Pass through installer errors from Google Update to the About box. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 string16& 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 string16 user_exe_path =
42 installer::GetChromeInstallPath(false, dist).value(); 44 installer::GetChromeInstallPath(false, dist).value();
43 std::wstring machine_exe_path = 45 string16 machine_exe_path =
44 installer::GetChromeInstallPath(true, dist).value(); 46 installer::GetChromeInstallPath(true, dist).value();
45 std::transform(user_exe_path.begin(), user_exe_path.end(), 47 std::transform(user_exe_path.begin(), user_exe_path.end(),
46 user_exe_path.begin(), tolower); 48 user_exe_path.begin(), tolower);
47 std::transform(machine_exe_path.begin(), machine_exe_path.end(), 49 std::transform(machine_exe_path.begin(), machine_exe_path.end(),
48 machine_exe_path.begin(), tolower); 50 machine_exe_path.begin(), tolower);
49 if (chrome_exe_path != user_exe_path && 51 if (chrome_exe_path != user_exe_path &&
50 chrome_exe_path != machine_exe_path ) { 52 chrome_exe_path != machine_exe_path ) {
51 LOG(ERROR) << L"Google Update cannot update Chrome installed in a " 53 LOG(ERROR) << L"Google Update cannot update Chrome installed in a "
52 << L"non-standard location: " << chrome_exe_path.c_str() 54 << L"non-standard location: " << chrome_exe_path.c_str()
53 << L". The standard location is: " << user_exe_path.c_str() 55 << L". The standard location is: " << user_exe_path.c_str()
54 << L" or " << machine_exe_path.c_str() << L"."; 56 << L" or " << machine_exe_path.c_str() << L".";
55 return CANNOT_UPGRADE_CHROME_IN_THIS_DIRECTORY; 57 return CANNOT_UPGRADE_CHROME_IN_THIS_DIRECTORY;
56 } 58 }
57 59
58 std::wstring app_guid = installer::GetAppGuidForUpdates( 60 string16 app_guid = installer::GetAppGuidForUpdates(
59 !InstallUtil::IsPerUserInstall(chrome_exe_path.c_str())); 61 !InstallUtil::IsPerUserInstall(chrome_exe_path.c_str()));
60 DCHECK(!app_guid.empty()); 62 DCHECK(!app_guid.empty());
61 63
62 if (GoogleUpdateSettings::GetAppUpdatePolicy(app_guid, NULL) == 64 if (GoogleUpdateSettings::GetAppUpdatePolicy(app_guid, NULL) ==
63 GoogleUpdateSettings::UPDATES_DISABLED) 65 GoogleUpdateSettings::UPDATES_DISABLED)
64 return GOOGLE_UPDATE_DISABLED_BY_POLICY; 66 return GOOGLE_UPDATE_DISABLED_BY_POLICY;
65 67
66 return GOOGLE_UPDATE_NO_ERROR; 68 return GOOGLE_UPDATE_NO_ERROR;
67 #endif 69 #endif
68 } 70 }
69 71
70 // Creates an instance of a COM Local Server class using either plain vanilla 72 // Creates an instance of a COM Local Server class using either plain vanilla
71 // CoCreateInstance, or using the Elevation moniker if running on Vista. 73 // 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 74 // 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 75 // showing up in the foreground if running on Vista. It can also be NULL if
74 // background UAC prompts are desired. 76 // background UAC prompts are desired.
75 HRESULT CoCreateInstanceAsAdmin(REFCLSID class_id, REFIID interface_id, 77 HRESULT CoCreateInstanceAsAdmin(REFCLSID class_id, REFIID interface_id,
76 HWND hwnd, void** interface_ptr) { 78 HWND hwnd, void** interface_ptr) {
77 if (!interface_ptr) 79 if (!interface_ptr)
78 return E_POINTER; 80 return E_POINTER;
79 81
80 // For Vista we need to instantiate the COM server via the elevation 82 // For Vista we need to instantiate the COM server via the elevation
81 // moniker. This ensures that the UAC dialog shows up. 83 // moniker. This ensures that the UAC dialog shows up.
82 if (base::win::GetVersion() >= base::win::VERSION_VISTA) { 84 if (base::win::GetVersion() >= base::win::VERSION_VISTA) {
83 wchar_t class_id_as_string[MAX_PATH] = {0}; 85 wchar_t class_id_as_string[MAX_PATH] = {0};
84 StringFromGUID2(class_id, class_id_as_string, 86 StringFromGUID2(class_id, class_id_as_string,
85 arraysize(class_id_as_string)); 87 arraysize(class_id_as_string));
86 88
87 std::wstring elevation_moniker_name = 89 string16 elevation_moniker_name =
88 base::StringPrintf(L"Elevation:Administrator!new:%ls", 90 base::StringPrintf(L"Elevation:Administrator!new:%ls",
89 class_id_as_string); 91 class_id_as_string);
90 92
91 BIND_OPTS3 bind_opts; 93 BIND_OPTS3 bind_opts;
92 memset(&bind_opts, 0, sizeof(bind_opts)); 94 memset(&bind_opts, 0, sizeof(bind_opts));
93 bind_opts.cbStruct = sizeof(bind_opts); 95 bind_opts.cbStruct = sizeof(bind_opts);
94 bind_opts.dwClassContext = CLSCTX_LOCAL_SERVER; 96 bind_opts.dwClassContext = CLSCTX_LOCAL_SERVER;
95 bind_opts.hwnd = hwnd; 97 bind_opts.hwnd = hwnd;
96 98
97 return CoGetObject(elevation_moniker_name.c_str(), &bind_opts, 99 return CoGetObject(elevation_moniker_name.c_str(), &bind_opts,
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
159 STDMETHOD(OnComplete)(CompletionCodes code, const TCHAR* text) { 161 STDMETHOD(OnComplete)(CompletionCodes code, const TCHAR* text) {
160 switch (code) { 162 switch (code) {
161 case COMPLETION_CODE_SUCCESS_CLOSE_UI: 163 case COMPLETION_CODE_SUCCESS_CLOSE_UI:
162 case COMPLETION_CODE_SUCCESS: { 164 case COMPLETION_CODE_SUCCESS: {
163 if (result_ == UPGRADE_STARTED) 165 if (result_ == UPGRADE_STARTED)
164 result_ = UPGRADE_SUCCESSFUL; 166 result_ = UPGRADE_SUCCESSFUL;
165 else if (result_ == UPGRADE_CHECK_STARTED) 167 else if (result_ == UPGRADE_CHECK_STARTED)
166 result_ = UPGRADE_ALREADY_UP_TO_DATE; 168 result_ = UPGRADE_ALREADY_UP_TO_DATE;
167 break; 169 break;
168 } 170 }
171 case COMPLETION_CODE_ERROR:
172 error_message_ = text;
169 default: { 173 default: {
170 NOTREACHED(); 174 NOTREACHED();
171 result_ = UPGRADE_ERROR; 175 result_ = UPGRADE_ERROR;
172 break; 176 break;
173 } 177 }
174 } 178 }
175 179
176 event_sink_ = NULL; 180 event_sink_ = NULL;
177 181
178 // We no longer need to spin the message loop that we started spinning in 182 // We no longer need to spin the message loop that we started spinning in
(...skipping 10 matching lines...) Expand all
189 STDMETHOD(GetResult)(GoogleUpdateUpgradeResult* result) { 193 STDMETHOD(GetResult)(GoogleUpdateUpgradeResult* result) {
190 // Intermediary steps should never be reported to the client. 194 // Intermediary steps should never be reported to the client.
191 DCHECK(result_ != UPGRADE_STARTED && result_ != UPGRADE_CHECK_STARTED); 195 DCHECK(result_ != UPGRADE_STARTED && result_ != UPGRADE_CHECK_STARTED);
192 196
193 *result = result_; 197 *result = result_;
194 return S_OK; 198 return S_OK;
195 } 199 }
196 200
197 // Returns which version Google Update found on the server (if a more 201 // Returns which version Google Update found on the server (if a more
198 // recent version was found). Otherwise, this will be blank. 202 // recent version was found). Otherwise, this will be blank.
199 STDMETHOD(GetVersionInfo)(std::wstring* version_string) { 203 STDMETHOD(GetVersionInfo)(string16* version_string) {
200 *version_string = new_version_; 204 *version_string = new_version_;
201 return S_OK; 205 return S_OK;
202 } 206 }
203 207
208 // Returns which version Google Update found on the server (if a more
209 // recent version was found). Otherwise, this will be blank.
210 STDMETHOD(GetErrorMessage)(string16* error_message) {
211 *error_message = error_message_;
212 return S_OK;
213 }
214
204 private: 215 private:
205 // The status/result of the Google Update operation. 216 // The status/result of the Google Update operation.
206 GoogleUpdateUpgradeResult result_; 217 GoogleUpdateUpgradeResult result_;
207 218
208 // The version string Google Update found. 219 // The version string Google Update found.
209 std::wstring new_version_; 220 string16 new_version_;
221
222 // An error message, if any.
223 string16 error_message_;
210 224
211 // Allows us control the upgrade process to a small degree. After OnComplete 225 // Allows us control the upgrade process to a small degree. After OnComplete
212 // has been called, this object can not be used. 226 // has been called, this object can not be used.
213 base::win::ScopedComPtr<IProgressWndEvents> event_sink_; 227 base::win::ScopedComPtr<IProgressWndEvents> event_sink_;
214 }; 228 };
215 229
216 //////////////////////////////////////////////////////////////////////////////// 230 ////////////////////////////////////////////////////////////////////////////////
217 // GoogleUpdate, public: 231 // GoogleUpdate, public:
218 232
219 GoogleUpdate::GoogleUpdate() 233 GoogleUpdate::GoogleUpdate()
(...skipping 19 matching lines...) Expand all
239 //////////////////////////////////////////////////////////////////////////////// 253 ////////////////////////////////////////////////////////////////////////////////
240 // GoogleUpdate, private: 254 // GoogleUpdate, private:
241 255
242 void GoogleUpdate::InitiateGoogleUpdateCheck(bool install_if_newer, 256 void GoogleUpdate::InitiateGoogleUpdateCheck(bool install_if_newer,
243 views::Widget* window, 257 views::Widget* window,
244 MessageLoop* main_loop) { 258 MessageLoop* main_loop) {
245 FilePath chrome_exe_path; 259 FilePath chrome_exe_path;
246 if (!PathService::Get(base::DIR_EXE, &chrome_exe_path)) 260 if (!PathService::Get(base::DIR_EXE, &chrome_exe_path))
247 NOTREACHED(); 261 NOTREACHED();
248 262
249 std::wstring chrome_exe = chrome_exe_path.value(); 263 string16 chrome_exe = chrome_exe_path.value();
250 264
251 std::transform(chrome_exe.begin(), chrome_exe.end(), 265 std::transform(chrome_exe.begin(), chrome_exe.end(),
252 chrome_exe.begin(), tolower); 266 chrome_exe.begin(), tolower);
253 267
254 GoogleUpdateErrorCode error_code = CanUpdateCurrentChrome(chrome_exe); 268 GoogleUpdateErrorCode error_code = CanUpdateCurrentChrome(chrome_exe);
255 if (error_code != GOOGLE_UPDATE_NO_ERROR) { 269 if (error_code != GOOGLE_UPDATE_NO_ERROR) {
256 main_loop->PostTask( 270 main_loop->PostTask(
257 FROM_HERE, 271 FROM_HERE,
258 base::Bind(&GoogleUpdate::ReportResults, this, 272 base::Bind(&GoogleUpdate::ReportResults, this,
259 UPGRADE_ERROR, error_code)); 273 UPGRADE_ERROR, error_code, string16()));
260 return; 274 return;
261 } 275 }
262 276
263 CComObject<GoogleUpdateJobObserver>* job_observer; 277 CComObject<GoogleUpdateJobObserver>* job_observer;
264 HRESULT hr = 278 HRESULT hr =
265 CComObject<GoogleUpdateJobObserver>::CreateInstance(&job_observer); 279 CComObject<GoogleUpdateJobObserver>::CreateInstance(&job_observer);
266 if (hr != S_OK) { 280 if (hr != S_OK) {
267 ReportFailure(hr, GOOGLE_UPDATE_JOB_SERVER_CREATION_FAILED, main_loop); 281 // Most of the error messages come straight from Google Update. This one is
282 // deemed worthy enough to also warrant its own error.
283 ReportFailure(
284 hr, GOOGLE_UPDATE_JOB_SERVER_CREATION_FAILED,
285 l10n_util::GetStringUTF16(IDS_ABOUT_BOX_ERROR_COCREATE_FAILED),
286 main_loop);
268 return; 287 return;
269 } 288 }
270 289
271 base::win::ScopedComPtr<IJobObserver> job_holder(job_observer); 290 base::win::ScopedComPtr<IJobObserver> job_holder(job_observer);
272 291
273 base::win::ScopedComPtr<IGoogleUpdate> on_demand; 292 base::win::ScopedComPtr<IGoogleUpdate> on_demand;
274 293
275 bool system_level = false; 294 bool system_level = false;
276 295
277 if (InstallUtil::IsPerUserInstall(chrome_exe.c_str())) { 296 if (InstallUtil::IsPerUserInstall(chrome_exe.c_str())) {
(...skipping 11 matching lines...) Expand all
289 } 308 }
290 309
291 hr = CoCreateInstanceAsAdmin(CLSID_OnDemandMachineAppsClass, 310 hr = CoCreateInstanceAsAdmin(CLSID_OnDemandMachineAppsClass,
292 IID_IGoogleUpdate, foreground_hwnd, 311 IID_IGoogleUpdate, foreground_hwnd,
293 reinterpret_cast<void**>(on_demand.Receive())); 312 reinterpret_cast<void**>(on_demand.Receive()));
294 } 313 }
295 system_level = true; 314 system_level = true;
296 } 315 }
297 316
298 if (hr != S_OK) { 317 if (hr != S_OK) {
299 ReportFailure(hr, GOOGLE_UPDATE_ONDEMAND_CLASS_NOT_FOUND, main_loop); 318 ReportFailure(hr, GOOGLE_UPDATE_ONDEMAND_CLASS_NOT_FOUND,
319 string16(), main_loop);
300 return; 320 return;
301 } 321 }
302 322
303 std::wstring app_guid = installer::GetAppGuidForUpdates(system_level); 323 string16 app_guid = installer::GetAppGuidForUpdates(system_level);
304 DCHECK(!app_guid.empty()); 324 DCHECK(!app_guid.empty());
305 325
306 if (!install_if_newer) 326 if (!install_if_newer)
307 hr = on_demand->CheckForUpdate(app_guid.c_str(), job_observer); 327 hr = on_demand->CheckForUpdate(app_guid.c_str(), job_observer);
308 else 328 else
309 hr = on_demand->Update(app_guid.c_str(), job_observer); 329 hr = on_demand->Update(app_guid.c_str(), job_observer);
310 330
311 if (hr != S_OK) { 331 if (hr != S_OK) {
312 ReportFailure(hr, GOOGLE_UPDATE_ONDEMAND_CLASS_REPORTED_ERROR, main_loop); 332 ReportFailure(hr, GOOGLE_UPDATE_ONDEMAND_CLASS_REPORTED_ERROR,
333 string16(), main_loop);
313 return; 334 return;
314 } 335 }
315 336
316 // We need to spin the message loop while Google Update is running so that it 337 // 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 338 // can report back to us through GoogleUpdateJobObserver. This message loop
318 // will terminate once Google Update sends us the completion status 339 // will terminate once Google Update sends us the completion status
319 // (success/error). See OnComplete(). 340 // (success/error). See OnComplete().
320 MessageLoop::current()->Run(); 341 MessageLoop::current()->Run();
321 342
322 GoogleUpdateUpgradeResult results; 343 GoogleUpdateUpgradeResult results;
323 hr = job_observer->GetResult(&results); 344 hr = job_observer->GetResult(&results);
324 if (hr != S_OK) { 345 if (hr != S_OK) {
325 ReportFailure(hr, GOOGLE_UPDATE_GET_RESULT_CALL_FAILED, main_loop); 346 ReportFailure(hr, GOOGLE_UPDATE_GET_RESULT_CALL_FAILED,
347 string16(), main_loop);
326 return; 348 return;
327 } 349 }
328 350
329 if (results == UPGRADE_ERROR) { 351 if (results == UPGRADE_ERROR) {
330 ReportFailure(hr, GOOGLE_UPDATE_ERROR_UPDATING, main_loop); 352 string16 error_message;
353 job_observer->GetErrorMessage(&error_message);
354 ReportFailure(hr, GOOGLE_UPDATE_ERROR_UPDATING, error_message, main_loop);
331 return; 355 return;
332 } 356 }
333 357
334 hr = job_observer->GetVersionInfo(&version_available_); 358 hr = job_observer->GetVersionInfo(&version_available_);
335 if (hr != S_OK) { 359 if (hr != S_OK) {
336 ReportFailure(hr, GOOGLE_UPDATE_GET_VERSION_INFO_FAILED, main_loop); 360 ReportFailure(hr, GOOGLE_UPDATE_GET_VERSION_INFO_FAILED,
361 string16(), main_loop);
337 return; 362 return;
338 } 363 }
339 364
340 main_loop->PostTask( 365 main_loop->PostTask(
341 FROM_HERE, 366 FROM_HERE,
342 base::Bind(&GoogleUpdate::ReportResults, this, 367 base::Bind(&GoogleUpdate::ReportResults, this,
343 results, GOOGLE_UPDATE_NO_ERROR)); 368 results, GOOGLE_UPDATE_NO_ERROR, string16()));
344 job_holder = NULL; 369 job_holder = NULL;
345 on_demand = NULL; 370 on_demand = NULL;
346 } 371 }
347 372
348 void GoogleUpdate::ReportResults(GoogleUpdateUpgradeResult results, 373 void GoogleUpdate::ReportResults(GoogleUpdateUpgradeResult results,
349 GoogleUpdateErrorCode error_code) { 374 GoogleUpdateErrorCode error_code,
375 const string16& error_message) {
350 // If we get an error, then error code must not be blank, and vice versa. 376 // 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 : 377 DCHECK(results == UPGRADE_ERROR ? error_code != GOOGLE_UPDATE_NO_ERROR :
352 error_code == GOOGLE_UPDATE_NO_ERROR); 378 error_code == GOOGLE_UPDATE_NO_ERROR);
353 if (listener_) 379 if (listener_) {
354 listener_->OnReportResults(results, error_code, version_available_); 380 listener_->OnReportResults(
381 results, error_code, error_message, version_available_);
382 }
355 } 383 }
356 384
357 bool GoogleUpdate::ReportFailure(HRESULT hr, GoogleUpdateErrorCode error_code, 385 bool GoogleUpdate::ReportFailure(HRESULT hr,
386 GoogleUpdateErrorCode error_code,
387 const string16& error_message,
358 MessageLoop* main_loop) { 388 MessageLoop* main_loop) {
359 NOTREACHED() << "Communication with Google Update failed: " << hr 389 NOTREACHED() << "Communication with Google Update failed: " << hr
360 << " error: " << error_code; 390 << " error: " << error_code
391 << ", message: " << error_message.c_str();
361 main_loop->PostTask( 392 main_loop->PostTask(
362 FROM_HERE, 393 FROM_HERE,
363 base::Bind(&GoogleUpdate::ReportResults, this, 394 base::Bind(&GoogleUpdate::ReportResults, this,
364 UPGRADE_ERROR, error_code)); 395 UPGRADE_ERROR, error_code, error_message));
365 return false; 396 return false;
366 } 397 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698