| 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.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/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" |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 70 // Creates an instance of a COM Local Server class using either plain vanilla | 70 // Creates an instance of a COM Local Server class using either plain vanilla |
| 71 // CoCreateInstance, or using the Elevation moniker if running on Vista. | 71 // 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 | 72 // 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 | 73 // showing up in the foreground if running on Vista. It can also be NULL if |
| 74 // background UAC prompts are desired. | 74 // background UAC prompts are desired. |
| 75 HRESULT CoCreateInstanceAsAdmin(REFCLSID class_id, REFIID interface_id, | 75 HRESULT CoCreateInstanceAsAdmin(REFCLSID class_id, REFIID interface_id, |
| 76 HWND hwnd, void** interface_ptr) { | 76 HWND hwnd, void** interface_ptr) { |
| 77 if (!interface_ptr) | 77 if (!interface_ptr) |
| 78 return E_POINTER; | 78 return E_POINTER; |
| 79 | 79 |
| 80 // For Vista we need to instantiate the COM server via the elevation | 80 // For Vista, need to instantiate the COM server via the elevation |
| 81 // moniker. This ensures that the UAC dialog shows up. | 81 // moniker. This ensures that the UAC dialog shows up. |
| 82 if (base::win::GetVersion() >= base::win::VERSION_VISTA) { | 82 if (base::win::GetVersion() >= base::win::VERSION_VISTA) { |
| 83 wchar_t class_id_as_string[MAX_PATH] = {0}; | 83 wchar_t class_id_as_string[MAX_PATH] = {0}; |
| 84 StringFromGUID2(class_id, class_id_as_string, | 84 StringFromGUID2(class_id, class_id_as_string, |
| 85 arraysize(class_id_as_string)); | 85 arraysize(class_id_as_string)); |
| 86 | 86 |
| 87 string16 elevation_moniker_name = | 87 string16 elevation_moniker_name = |
| 88 base::StringPrintf(L"Elevation:Administrator!new:%ls", | 88 base::StringPrintf(L"Elevation:Administrator!new:%ls", |
| 89 class_id_as_string); | 89 class_id_as_string); |
| 90 | 90 |
| 91 BIND_OPTS3 bind_opts; | 91 BIND_OPTS3 bind_opts; |
| 92 memset(&bind_opts, 0, sizeof(bind_opts)); | 92 memset(&bind_opts, 0, sizeof(bind_opts)); |
| 93 bind_opts.cbStruct = sizeof(bind_opts); | 93 bind_opts.cbStruct = sizeof(bind_opts); |
| 94 bind_opts.dwClassContext = CLSCTX_LOCAL_SERVER; | 94 bind_opts.dwClassContext = CLSCTX_LOCAL_SERVER; |
| 95 bind_opts.hwnd = hwnd; | 95 bind_opts.hwnd = hwnd; |
| 96 | 96 |
| 97 return CoGetObject(elevation_moniker_name.c_str(), &bind_opts, | 97 return CoGetObject(elevation_moniker_name.c_str(), &bind_opts, |
| 98 interface_id, reinterpret_cast<void**>(interface_ptr)); | 98 interface_id, reinterpret_cast<void**>(interface_ptr)); |
| 99 } | 99 } |
| 100 | 100 |
| 101 return CoCreateInstance(class_id, NULL, CLSCTX_LOCAL_SERVER, | 101 return CoCreateInstance(class_id, NULL, CLSCTX_LOCAL_SERVER, |
| 102 interface_id, | 102 interface_id, |
| 103 reinterpret_cast<void**>(interface_ptr)); | 103 reinterpret_cast<void**>(interface_ptr)); |
| 104 } | 104 } |
| 105 | 105 |
| 106 | 106 |
| 107 } // namespace | 107 } // namespace |
| 108 | 108 |
| 109 //////////////////////////////////////////////////////////////////////////////// | |
| 110 // | |
| 111 // The GoogleUpdateJobObserver COM class is responsible for receiving status | 109 // The GoogleUpdateJobObserver COM class is responsible for receiving status |
| 112 // reports from google Update. It keeps track of the progress as Google Update | 110 // reports from google Update. It keeps track of the progress as GoogleUpdate |
| 113 // notifies us and ends the message loop we are spinning in once Google Update | 111 // notifies this observer and ends the message loop that is spinning in once |
| 114 // reports that it is done. | 112 // GoogleUpdate reports that it is done. |
| 115 // | |
| 116 //////////////////////////////////////////////////////////////////////////////// | |
| 117 class GoogleUpdateJobObserver | 113 class GoogleUpdateJobObserver |
| 118 : public CComObjectRootEx<CComSingleThreadModel>, | 114 : public CComObjectRootEx<CComSingleThreadModel>, |
| 119 public IJobObserver { | 115 public IJobObserver { |
| 120 public: | 116 public: |
| 121 BEGIN_COM_MAP(GoogleUpdateJobObserver) | 117 BEGIN_COM_MAP(GoogleUpdateJobObserver) |
| 122 COM_INTERFACE_ENTRY(IJobObserver) | 118 COM_INTERFACE_ENTRY(IJobObserver) |
| 123 END_COM_MAP() | 119 END_COM_MAP() |
| 124 | 120 |
| 125 GoogleUpdateJobObserver() | 121 GoogleUpdateJobObserver() |
| 126 : result_(UPGRADE_ERROR) { | 122 : result_(UPGRADE_ERROR) { |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 170 error_message_ = text; | 166 error_message_ = text; |
| 171 default: { | 167 default: { |
| 172 NOTREACHED(); | 168 NOTREACHED(); |
| 173 result_ = UPGRADE_ERROR; | 169 result_ = UPGRADE_ERROR; |
| 174 break; | 170 break; |
| 175 } | 171 } |
| 176 } | 172 } |
| 177 | 173 |
| 178 event_sink_ = NULL; | 174 event_sink_ = NULL; |
| 179 | 175 |
| 180 // We no longer need to spin the message loop that we started spinning in | 176 // No longer need to spin the message loop that started spinning in |
| 181 // InitiateGoogleUpdateCheck. | 177 // InitiateGoogleUpdateCheck. |
| 182 MessageLoop::current()->Quit(); | 178 MessageLoop::current()->Quit(); |
| 183 return S_OK; | 179 return S_OK; |
| 184 } | 180 } |
| 185 STDMETHOD(SetEventSink)(IProgressWndEvents* event_sink) { | 181 STDMETHOD(SetEventSink)(IProgressWndEvents* event_sink) { |
| 186 event_sink_ = event_sink; | 182 event_sink_ = event_sink; |
| 187 return S_OK; | 183 return S_OK; |
| 188 } | 184 } |
| 189 | 185 |
| 190 // Returns the results of the update operation. | 186 // Returns the results of the update operation. |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 228 //////////////////////////////////////////////////////////////////////////////// | 224 //////////////////////////////////////////////////////////////////////////////// |
| 229 // GoogleUpdate, public: | 225 // GoogleUpdate, public: |
| 230 | 226 |
| 231 GoogleUpdate::GoogleUpdate() | 227 GoogleUpdate::GoogleUpdate() |
| 232 : listener_(NULL) { | 228 : listener_(NULL) { |
| 233 } | 229 } |
| 234 | 230 |
| 235 GoogleUpdate::~GoogleUpdate() { | 231 GoogleUpdate::~GoogleUpdate() { |
| 236 } | 232 } |
| 237 | 233 |
| 238 void GoogleUpdate::CheckForUpdate(bool install_if_newer, | 234 void GoogleUpdate::CheckForUpdate(bool install_if_newer, HWND window) { |
| 239 views::Widget* window) { | 235 // Need to shunt this request over to InitiateGoogleUpdateCheck and have |
| 240 // We need to shunt this request over to InitiateGoogleUpdateCheck and have | |
| 241 // it run in the file thread. | 236 // it run in the file thread. |
| 242 BrowserThread::PostTask( | 237 BrowserThread::PostTask( |
| 243 BrowserThread::FILE, FROM_HERE, | 238 BrowserThread::FILE, FROM_HERE, |
| 244 base::Bind(&GoogleUpdate::InitiateGoogleUpdateCheck, this, | 239 base::Bind(&GoogleUpdate::InitiateGoogleUpdateCheck, this, |
| 245 install_if_newer, window, MessageLoop::current())); | 240 install_if_newer, window, MessageLoop::current())); |
| 246 } | 241 } |
| 247 | 242 |
| 248 //////////////////////////////////////////////////////////////////////////////// | 243 //////////////////////////////////////////////////////////////////////////////// |
| 249 // GoogleUpdate, private: | 244 // GoogleUpdate, private: |
| 250 | 245 |
| 251 void GoogleUpdate::InitiateGoogleUpdateCheck(bool install_if_newer, | 246 void GoogleUpdate::InitiateGoogleUpdateCheck(bool install_if_newer, |
| 252 views::Widget* window, | 247 HWND window, |
| 253 MessageLoop* main_loop) { | 248 MessageLoop* main_loop) { |
| 254 FilePath chrome_exe; | 249 FilePath chrome_exe; |
| 255 if (!PathService::Get(base::DIR_EXE, &chrome_exe)) | 250 if (!PathService::Get(base::DIR_EXE, &chrome_exe)) |
| 256 NOTREACHED(); | 251 NOTREACHED(); |
| 257 | 252 |
| 258 GoogleUpdateErrorCode error_code = CanUpdateCurrentChrome(chrome_exe); | 253 GoogleUpdateErrorCode error_code = CanUpdateCurrentChrome(chrome_exe); |
| 259 if (error_code != GOOGLE_UPDATE_NO_ERROR) { | 254 if (error_code != GOOGLE_UPDATE_NO_ERROR) { |
| 260 main_loop->PostTask( | 255 main_loop->PostTask( |
| 261 FROM_HERE, | 256 FROM_HERE, |
| 262 base::Bind(&GoogleUpdate::ReportResults, this, | 257 base::Bind(&GoogleUpdate::ReportResults, this, |
| (...skipping 20 matching lines...) Expand all Loading... |
| 283 base::win::ScopedComPtr<IJobObserver> job_holder(job_observer); | 278 base::win::ScopedComPtr<IJobObserver> job_holder(job_observer); |
| 284 | 279 |
| 285 base::win::ScopedComPtr<IGoogleUpdate> on_demand; | 280 base::win::ScopedComPtr<IGoogleUpdate> on_demand; |
| 286 | 281 |
| 287 bool system_level = false; | 282 bool system_level = false; |
| 288 | 283 |
| 289 if (InstallUtil::IsPerUserInstall(chrome_exe.value().c_str())) { | 284 if (InstallUtil::IsPerUserInstall(chrome_exe.value().c_str())) { |
| 290 hr = on_demand.CreateInstance(CLSID_OnDemandUserAppsClass); | 285 hr = on_demand.CreateInstance(CLSID_OnDemandUserAppsClass); |
| 291 } else { | 286 } else { |
| 292 // The Update operation needs Admin privileges for writing | 287 // The Update operation needs Admin privileges for writing |
| 293 // to %ProgramFiles%. On Vista we need to elevate before instantiating | 288 // to %ProgramFiles%. On Vista, need to elevate before instantiating |
| 294 // the updater instance. | 289 // the updater instance. |
| 295 if (!install_if_newer) { | 290 if (!install_if_newer) { |
| 296 hr = on_demand.CreateInstance(CLSID_OnDemandMachineAppsClass); | 291 hr = on_demand.CreateInstance(CLSID_OnDemandMachineAppsClass); |
| 297 } else { | 292 } else { |
| 298 HWND foreground_hwnd = NULL; | |
| 299 if (window != NULL) { | |
| 300 foreground_hwnd = window->GetNativeWindow(); | |
| 301 } | |
| 302 | |
| 303 hr = CoCreateInstanceAsAdmin(CLSID_OnDemandMachineAppsClass, | 293 hr = CoCreateInstanceAsAdmin(CLSID_OnDemandMachineAppsClass, |
| 304 IID_IGoogleUpdate, foreground_hwnd, | 294 IID_IGoogleUpdate, window, |
| 305 reinterpret_cast<void**>(on_demand.Receive())); | 295 reinterpret_cast<void**>(on_demand.Receive())); |
| 306 } | 296 } |
| 307 system_level = true; | 297 system_level = true; |
| 308 } | 298 } |
| 309 | 299 |
| 310 if (hr != S_OK) { | 300 if (hr != S_OK) { |
| 311 GoogleUpdateErrorCode error = GOOGLE_UPDATE_ONDEMAND_CLASS_NOT_FOUND; | 301 GoogleUpdateErrorCode error = GOOGLE_UPDATE_ONDEMAND_CLASS_NOT_FOUND; |
| 312 string16 error_code = base::StringPrintf(L"%d: 0x%x", error, hr); | 302 string16 error_code = base::StringPrintf(L"%d: 0x%x", error, hr); |
| 313 if (system_level) | 303 if (system_level) |
| 314 error_code += L" -- system level"; | 304 error_code += L" -- system level"; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 332 GoogleUpdateErrorCode error = GOOGLE_UPDATE_ONDEMAND_CLASS_REPORTED_ERROR; | 322 GoogleUpdateErrorCode error = GOOGLE_UPDATE_ONDEMAND_CLASS_REPORTED_ERROR; |
| 333 string16 error_code = base::StringPrintf(L"%d: 0x%x", error, hr); | 323 string16 error_code = base::StringPrintf(L"%d: 0x%x", error, hr); |
| 334 ReportFailure(hr, error, | 324 ReportFailure(hr, error, |
| 335 l10n_util::GetStringFUTF16( | 325 l10n_util::GetStringFUTF16( |
| 336 IDS_ABOUT_BOX_ERROR_UPDATE_CHECK_FAILED, | 326 IDS_ABOUT_BOX_ERROR_UPDATE_CHECK_FAILED, |
| 337 error_code), | 327 error_code), |
| 338 main_loop); | 328 main_loop); |
| 339 return; | 329 return; |
| 340 } | 330 } |
| 341 | 331 |
| 342 // We need to spin the message loop while Google Update is running so that it | 332 // Need to spin the message loop while Google Update is running so that it |
| 343 // can report back to us through GoogleUpdateJobObserver. This message loop | 333 // can report back to us through GoogleUpdateJobObserver. This message loop |
| 344 // will terminate once Google Update sends us the completion status | 334 // will terminate once Google Update sends us the completion status |
| 345 // (success/error). See OnComplete(). | 335 // (success/error). See OnComplete(). |
| 346 MessageLoop::current()->Run(); | 336 MessageLoop::current()->Run(); |
| 347 | 337 |
| 348 GoogleUpdateUpgradeResult results; | 338 GoogleUpdateUpgradeResult results; |
| 349 hr = job_observer->GetResult(&results); | 339 hr = job_observer->GetResult(&results); |
| 350 | 340 |
| 351 if (hr != S_OK) { | 341 if (hr != S_OK) { |
| 352 GoogleUpdateErrorCode error = GOOGLE_UPDATE_GET_RESULT_CALL_FAILED; | 342 GoogleUpdateErrorCode error = GOOGLE_UPDATE_GET_RESULT_CALL_FAILED; |
| (...skipping 29 matching lines...) Expand all Loading... |
| 382 FROM_HERE, | 372 FROM_HERE, |
| 383 base::Bind(&GoogleUpdate::ReportResults, this, | 373 base::Bind(&GoogleUpdate::ReportResults, this, |
| 384 results, GOOGLE_UPDATE_NO_ERROR, string16())); | 374 results, GOOGLE_UPDATE_NO_ERROR, string16())); |
| 385 job_holder = NULL; | 375 job_holder = NULL; |
| 386 on_demand = NULL; | 376 on_demand = NULL; |
| 387 } | 377 } |
| 388 | 378 |
| 389 void GoogleUpdate::ReportResults(GoogleUpdateUpgradeResult results, | 379 void GoogleUpdate::ReportResults(GoogleUpdateUpgradeResult results, |
| 390 GoogleUpdateErrorCode error_code, | 380 GoogleUpdateErrorCode error_code, |
| 391 const string16& error_message) { | 381 const string16& error_message) { |
| 392 // If we get an error, then error code must not be blank, and vice versa. | 382 // If there is an error, then error code must not be blank, and vice versa. |
| 393 DCHECK(results == UPGRADE_ERROR ? error_code != GOOGLE_UPDATE_NO_ERROR : | 383 DCHECK(results == UPGRADE_ERROR ? error_code != GOOGLE_UPDATE_NO_ERROR : |
| 394 error_code == GOOGLE_UPDATE_NO_ERROR); | 384 error_code == GOOGLE_UPDATE_NO_ERROR); |
| 395 if (listener_) { | 385 if (listener_) { |
| 396 listener_->OnReportResults( | 386 listener_->OnReportResults( |
| 397 results, error_code, error_message, version_available_); | 387 results, error_code, error_message, version_available_); |
| 398 } | 388 } |
| 399 } | 389 } |
| 400 | 390 |
| 401 bool GoogleUpdate::ReportFailure(HRESULT hr, | 391 bool GoogleUpdate::ReportFailure(HRESULT hr, |
| 402 GoogleUpdateErrorCode error_code, | 392 GoogleUpdateErrorCode error_code, |
| 403 const string16& error_message, | 393 const string16& error_message, |
| 404 MessageLoop* main_loop) { | 394 MessageLoop* main_loop) { |
| 405 NOTREACHED() << "Communication with Google Update failed: " << hr | 395 NOTREACHED() << "Communication with Google Update failed: " << hr |
| 406 << " error: " << error_code | 396 << " error: " << error_code |
| 407 << ", message: " << error_message.c_str(); | 397 << ", message: " << error_message.c_str(); |
| 408 main_loop->PostTask( | 398 main_loop->PostTask( |
| 409 FROM_HERE, | 399 FROM_HERE, |
| 410 base::Bind(&GoogleUpdate::ReportResults, this, | 400 base::Bind(&GoogleUpdate::ReportResults, this, |
| 411 UPGRADE_ERROR, error_code, error_message)); | 401 UPGRADE_ERROR, error_code, error_message)); |
| 412 return false; | 402 return false; |
| 413 } | 403 } |
| OLD | NEW |