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 |