OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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_update.h" | 5 #include "chrome/browser/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/message_loop.h" | 10 #include "base/message_loop.h" |
11 #include "base/path_service.h" | 11 #include "base/path_service.h" |
12 #include "base/string_util.h" | 12 #include "base/string_util.h" |
13 #include "base/task.h" | 13 #include "base/task.h" |
14 #include "base/thread.h" | 14 #include "base/thread.h" |
15 #include "base/win_util.h" | 15 #include "base/win_util.h" |
16 #include "chrome/app/client_util.h" | 16 #include "chrome/app/client_util.h" |
17 #include "chrome/browser/browser_process.h" | 17 #include "chrome/browser/browser_process.h" |
18 #include "chrome/installer/util/google_update_constants.h" | 18 #include "chrome/installer/util/google_update_constants.h" |
19 #include "chrome/installer/util/helper.h" | 19 #include "chrome/installer/util/helper.h" |
20 #include "chrome/installer/util/install_util.h" | 20 #include "chrome/installer/util/install_util.h" |
| 21 #include "chrome/views/window/window.h" |
21 #include "google_update_idl_i.c" | 22 #include "google_update_idl_i.c" |
22 | 23 |
| 24 using views::Window; |
| 25 |
23 namespace { | 26 namespace { |
24 // Check if the currently running instance can be updated by Google Update. | 27 // Check if the currently running instance can be updated by Google Update. |
25 // Returns true only if the instance running is a Google Chrome | 28 // Returns true only if the instance running is a Google Chrome |
26 // distribution installed in a standard location. | 29 // distribution installed in a standard location. |
27 bool CanUpdateCurrentChrome(const std::wstring& chrome_exe_path) { | 30 bool CanUpdateCurrentChrome(const std::wstring& chrome_exe_path) { |
28 #if !defined(GOOGLE_CHROME_BUILD) | 31 #if !defined(GOOGLE_CHROME_BUILD) |
29 return false; | 32 return false; |
30 #else | 33 #else |
31 std::wstring user_exe_path = installer::GetChromeInstallPath(false); | 34 std::wstring user_exe_path = installer::GetChromeInstallPath(false); |
32 std::wstring machine_exe_path = installer::GetChromeInstallPath(true); | 35 std::wstring machine_exe_path = installer::GetChromeInstallPath(true); |
33 std::transform(user_exe_path.begin(), user_exe_path.end(), | 36 std::transform(user_exe_path.begin(), user_exe_path.end(), |
34 user_exe_path.begin(), tolower); | 37 user_exe_path.begin(), tolower); |
35 std::transform(machine_exe_path.begin(), machine_exe_path.end(), | 38 std::transform(machine_exe_path.begin(), machine_exe_path.end(), |
36 machine_exe_path.begin(), tolower); | 39 machine_exe_path.begin(), tolower); |
37 if (chrome_exe_path != user_exe_path && | 40 if (chrome_exe_path != user_exe_path && |
38 chrome_exe_path != machine_exe_path ) { | 41 chrome_exe_path != machine_exe_path ) { |
39 LOG(ERROR) << L"Google Update cannot update Chrome installed in a " | 42 LOG(ERROR) << L"Google Update cannot update Chrome installed in a " |
40 << L"non-standard location: " << chrome_exe_path.c_str() | 43 << L"non-standard location: " << chrome_exe_path.c_str() |
41 << L". The standard location is: " << user_exe_path.c_str() | 44 << L". The standard location is: " << user_exe_path.c_str() |
42 << L" or " << machine_exe_path.c_str() << L"."; | 45 << L" or " << machine_exe_path.c_str() << L"."; |
43 return false; | 46 return false; |
44 } | 47 } |
45 | 48 |
46 return true; | 49 return true; |
47 #endif | 50 #endif |
48 } | 51 } |
49 | 52 |
50 // Creates an instance of a COM Local Server class using either plain vanilla | 53 // Creates an instance of a COM Local Server class using either plain vanilla |
51 // CoCreateInstance, or using the Elevation moniker if running on Vista. | 54 // CoCreateInstance, or using the Elevation moniker if running on Vista. |
| 55 // hwnd must refer to a foregound window in order to get the UAC prompt |
| 56 // showing up in the foreground if running on Vista. It can also be NULL if |
| 57 // background UAC prompts are desired. |
52 HRESULT CoCreateInstanceAsAdmin(REFCLSID class_id, REFIID interface_id, | 58 HRESULT CoCreateInstanceAsAdmin(REFCLSID class_id, REFIID interface_id, |
53 void** interface_ptr) { | 59 HWND hwnd, void** interface_ptr) { |
54 if (!interface_ptr) | 60 if (!interface_ptr) |
55 return E_POINTER; | 61 return E_POINTER; |
56 | 62 |
57 // For Vista we need to instantiate the COM server via the elevation | 63 // For Vista we need to instantiate the COM server via the elevation |
58 // moniker. This ensures that the UAC dialog shows up. | 64 // moniker. This ensures that the UAC dialog shows up. |
59 if (win_util::GetWinVersion() >= win_util::WINVERSION_VISTA) { | 65 if (win_util::GetWinVersion() >= win_util::WINVERSION_VISTA) { |
60 wchar_t class_id_as_string[MAX_PATH] = {0}; | 66 wchar_t class_id_as_string[MAX_PATH] = {0}; |
61 StringFromGUID2(class_id, class_id_as_string, | 67 StringFromGUID2(class_id, class_id_as_string, |
62 arraysize(class_id_as_string)); | 68 arraysize(class_id_as_string)); |
63 | 69 |
64 std::wstring elevation_moniker_name = | 70 std::wstring elevation_moniker_name = |
65 StringPrintf(L"Elevation:Administrator!new:%s", class_id_as_string); | 71 StringPrintf(L"Elevation:Administrator!new:%ls", class_id_as_string); |
66 | 72 |
67 BIND_OPTS3 bind_opts; | 73 BIND_OPTS3 bind_opts; |
68 memset(&bind_opts, 0, sizeof(bind_opts)); | 74 memset(&bind_opts, 0, sizeof(bind_opts)); |
69 | |
70 bind_opts.cbStruct = sizeof(bind_opts); | 75 bind_opts.cbStruct = sizeof(bind_opts); |
71 bind_opts.dwClassContext = CLSCTX_LOCAL_SERVER; | 76 bind_opts.dwClassContext = CLSCTX_LOCAL_SERVER; |
| 77 bind_opts.hwnd = hwnd; |
| 78 |
72 return CoGetObject(elevation_moniker_name.c_str(), &bind_opts, | 79 return CoGetObject(elevation_moniker_name.c_str(), &bind_opts, |
73 interface_id, reinterpret_cast<void**>(interface_ptr)); | 80 interface_id, reinterpret_cast<void**>(interface_ptr)); |
74 } | 81 } |
75 | 82 |
76 return CoCreateInstance(class_id, NULL, CLSCTX_LOCAL_SERVER, | 83 return CoCreateInstance(class_id, NULL, CLSCTX_LOCAL_SERVER, |
77 interface_id, | 84 interface_id, |
78 reinterpret_cast<void**>(interface_ptr)); | 85 reinterpret_cast<void**>(interface_ptr)); |
79 } | 86 } |
80 | 87 |
81 | 88 |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
194 GoogleUpdate::GoogleUpdate() | 201 GoogleUpdate::GoogleUpdate() |
195 : listener_(NULL) { | 202 : listener_(NULL) { |
196 } | 203 } |
197 | 204 |
198 GoogleUpdate::~GoogleUpdate() { | 205 GoogleUpdate::~GoogleUpdate() { |
199 } | 206 } |
200 | 207 |
201 //////////////////////////////////////////////////////////////////////////////// | 208 //////////////////////////////////////////////////////////////////////////////// |
202 // GoogleUpdate, views::DialogDelegate implementation: | 209 // GoogleUpdate, views::DialogDelegate implementation: |
203 | 210 |
204 void GoogleUpdate::CheckForUpdate(bool install_if_newer) { | 211 void GoogleUpdate::CheckForUpdate(bool install_if_newer, Window* window) { |
205 // We need to shunt this request over to InitiateGoogleUpdateCheck and have | 212 // We need to shunt this request over to InitiateGoogleUpdateCheck and have |
206 // it run in the file thread. | 213 // it run in the file thread. |
207 MessageLoop* file_loop = g_browser_process->file_thread()->message_loop(); | 214 MessageLoop* file_loop = g_browser_process->file_thread()->message_loop(); |
208 file_loop->PostTask(FROM_HERE, NewRunnableMethod(this, | 215 file_loop->PostTask(FROM_HERE, NewRunnableMethod(this, |
209 &GoogleUpdate::InitiateGoogleUpdateCheck, | 216 &GoogleUpdate::InitiateGoogleUpdateCheck, |
210 install_if_newer, MessageLoop::current())); | 217 install_if_newer, window, MessageLoop::current())); |
211 } | 218 } |
212 | 219 |
213 // Adds/removes a listener. Only one listener is maintained at the moment. | 220 // Adds/removes a listener. Only one listener is maintained at the moment. |
214 void GoogleUpdate::AddStatusChangeListener( | 221 void GoogleUpdate::AddStatusChangeListener( |
215 GoogleUpdateStatusListener* listener) { | 222 GoogleUpdateStatusListener* listener) { |
216 DCHECK(!listener_); | 223 DCHECK(!listener_); |
217 listener_ = listener; | 224 listener_ = listener; |
218 } | 225 } |
219 | 226 |
220 void GoogleUpdate::RemoveStatusChangeListener() { | 227 void GoogleUpdate::RemoveStatusChangeListener() { |
221 listener_ = NULL; | 228 listener_ = NULL; |
222 } | 229 } |
223 | 230 |
224 //////////////////////////////////////////////////////////////////////////////// | 231 //////////////////////////////////////////////////////////////////////////////// |
225 // GoogleUpdate, private: | 232 // GoogleUpdate, private: |
226 | 233 |
227 bool GoogleUpdate::InitiateGoogleUpdateCheck(bool install_if_newer, | 234 bool GoogleUpdate::InitiateGoogleUpdateCheck(bool install_if_newer, |
| 235 Window* window, |
228 MessageLoop* main_loop) { | 236 MessageLoop* main_loop) { |
229 | 237 |
230 std::wstring chrome_exe_path; | 238 std::wstring chrome_exe_path; |
231 if (!PathService::Get(base::DIR_EXE, &chrome_exe_path)) { | 239 if (!PathService::Get(base::DIR_EXE, &chrome_exe_path)) { |
232 NOTREACHED(); | 240 NOTREACHED(); |
233 return false; | 241 return false; |
234 } | 242 } |
235 | 243 |
236 std::transform(chrome_exe_path.begin(), chrome_exe_path.end(), | 244 std::transform(chrome_exe_path.begin(), chrome_exe_path.end(), |
237 chrome_exe_path.begin(), tolower); | 245 chrome_exe_path.begin(), tolower); |
(...skipping 19 matching lines...) Expand all Loading... |
257 | 265 |
258 if (InstallUtil::IsPerUserInstall(chrome_exe_path.c_str())) { | 266 if (InstallUtil::IsPerUserInstall(chrome_exe_path.c_str())) { |
259 hr = on_demand.CoCreateInstance(CLSID_OnDemandUserAppsClass); | 267 hr = on_demand.CoCreateInstance(CLSID_OnDemandUserAppsClass); |
260 } else { | 268 } else { |
261 // The Update operation needs Admin privileges for writing | 269 // The Update operation needs Admin privileges for writing |
262 // to %ProgramFiles%. On Vista we need to elevate before instantiating | 270 // to %ProgramFiles%. On Vista we need to elevate before instantiating |
263 // the updater instance. | 271 // the updater instance. |
264 if (!install_if_newer) { | 272 if (!install_if_newer) { |
265 hr = on_demand.CoCreateInstance(CLSID_OnDemandMachineAppsClass); | 273 hr = on_demand.CoCreateInstance(CLSID_OnDemandMachineAppsClass); |
266 } else { | 274 } else { |
| 275 HWND foreground_hwnd = NULL; |
| 276 if (window != NULL) { |
| 277 foreground_hwnd = window->GetNativeWindow(); |
| 278 } |
| 279 |
267 hr = CoCreateInstanceAsAdmin(CLSID_OnDemandMachineAppsClass, | 280 hr = CoCreateInstanceAsAdmin(CLSID_OnDemandMachineAppsClass, |
268 IID_IGoogleUpdate, | 281 IID_IGoogleUpdate, foreground_hwnd, |
269 reinterpret_cast<void**>(&on_demand)); | 282 reinterpret_cast<void**>(&on_demand)); |
270 } | 283 } |
271 } | 284 } |
272 | 285 |
273 if (hr != S_OK) | 286 if (hr != S_OK) |
274 return ReportFailure(hr, GOOGLE_UPDATE_ONDEMAND_CLASS_NOT_FOUND, main_loop); | 287 return ReportFailure(hr, GOOGLE_UPDATE_ONDEMAND_CLASS_NOT_FOUND, main_loop); |
275 | 288 |
276 if (!install_if_newer) | 289 if (!install_if_newer) |
277 hr = on_demand->CheckForUpdate(google_update::kChromeGuid, job_observer); | 290 hr = on_demand->CheckForUpdate(google_update::kChromeGuid, job_observer); |
278 else | 291 else |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
317 } | 330 } |
318 | 331 |
319 bool GoogleUpdate::ReportFailure(HRESULT hr, GoogleUpdateErrorCode error_code, | 332 bool GoogleUpdate::ReportFailure(HRESULT hr, GoogleUpdateErrorCode error_code, |
320 MessageLoop* main_loop) { | 333 MessageLoop* main_loop) { |
321 NOTREACHED() << "Communication with Google Update failed: " << hr | 334 NOTREACHED() << "Communication with Google Update failed: " << hr |
322 << " error: " << error_code; | 335 << " error: " << error_code; |
323 main_loop->PostTask(FROM_HERE, NewRunnableMethod(this, | 336 main_loop->PostTask(FROM_HERE, NewRunnableMethod(this, |
324 &GoogleUpdate::ReportResults, UPGRADE_ERROR, error_code)); | 337 &GoogleUpdate::ReportResults, UPGRADE_ERROR, error_code)); |
325 return false; | 338 return false; |
326 } | 339 } |
OLD | NEW |