| 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 |