12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "apps/app_host/binaries_installer.h" 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h" 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/threading/platform_thread.h" 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/win/scoped_bstr.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/win/scoped_com_initializer.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/win/scoped_comptr.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "google_update/google_update_idl.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace app_host { 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Helpers -------------------------------------------------------------------- 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const wchar_t kAppHostAppId[] = L"{FDA71E6F-AC4C-4a00-8B70-9958A68906BF}"; 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const wchar_t kBinariesAppId[] = L"{4DC8B4CA-1BDA-483e-B5FA-D3C12E15B62D}"; 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kInstallationPollingIntervalMs = 50; 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)HRESULT CreateInstalledApp(IAppBundle* app_bundle, 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const wchar_t* app_guid, 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IApp** app) { 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::win::ScopedComPtr<IDispatch> idispatch; 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) HRESULT hr = app_bundle->createInstalledApp(base::win::ScopedBstr(app_guid), 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) idispatch.Receive()); 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (FAILED(hr)) { 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Failed to configure App Bundle: " << hr; 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return hr; 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::win::ScopedComPtr<IApp> temp_app; 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) hr = temp_app.QueryFrom(idispatch); 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (FAILED(hr)) { 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Unexpected error querying IApp from " 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << "IAppBundle->createInstalledApp return value: " << hr; 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *app = temp_app.Detach(); 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return hr; 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)HRESULT GetAppHostApValue(IGoogleUpdate3* update3, 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IAppBundle* app_bundle, 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BSTR* ap_value) { 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::win::ScopedComPtr<IApp> app; 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) HRESULT hr = CreateInstalledApp(app_bundle, kAppHostAppId, app.Receive()); 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (FAILED(hr)) 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return hr; 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) hr = app->get_ap(ap_value); 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (FAILED(hr)) 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Failed to get the App Launcher AP value."; 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return hr; 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)HRESULT GetCurrentState(IApp* app, 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ICurrentState** current_state, 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CurrentState* state_value) { 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::win::ScopedComPtr<IDispatch> idispatch; 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) HRESULT hr = app->get_currentState(idispatch.Receive()); 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (FAILED(hr)) { 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Failed to get App Bundle state: " << hr; 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return hr; 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::win::ScopedComPtr<ICurrentState> temp_current_state; 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) hr = temp_current_state.QueryFrom(idispatch); 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (FAILED(hr)) { 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Unexpected error querying ICurrentState from " 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << "IApp::get_currentState return value: " << hr; 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return hr; 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LONG long_state_value; 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) hr = temp_current_state->get_stateValue(&long_state_value); 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (SUCCEEDED(hr)) { 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *state_value = static_cast<CurrentState>(long_state_value); 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *current_state = temp_current_state.Detach(); 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Failed to get App Bundle state value: " << hr; 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return hr; 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool CheckIsBusy(IAppBundle* app_bundle, HRESULT* hr) { 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) VARIANT_BOOL variant_is_busy = VARIANT_TRUE; 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *hr = app_bundle->isBusy(&variant_is_busy); 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (FAILED(*hr)) 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Failed to check app_bundle->isBusy: " << *hr; 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return (variant_is_busy == VARIANT_TRUE); 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void OnUpdateAvailable(IAppBundle* app_bundle, HRESULT* hr) { 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If the app bundle is busy we will just wait some more. 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (CheckIsBusy(app_bundle, hr) || FAILED(*hr)) 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *hr = app_bundle->download(); 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (FAILED(*hr)) 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Failed to initiate bundle download: " << *hr; 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void OnReadyToInstall(IAppBundle* app_bundle, HRESULT* hr) { 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If the app bundle is busy we will just wait some more. 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (CheckIsBusy(app_bundle, hr) || FAILED(*hr)) 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *hr = app_bundle->install(); 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (FAILED(*hr)) 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Failed to initiate bundle install: " << *hr; 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)HRESULT OnError(ICurrentState* current_state) { 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LONG error_code; 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) HRESULT hr = current_state->get_errorCode(&error_code); 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (FAILED(hr)) { 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Failed to retrieve bundle error code: " << hr; 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return hr; 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::win::ScopedBstr completion_message; 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) HRESULT completion_message_hr = 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) current_state->get_completionMessage(completion_message.Receive()); 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (FAILED(completion_message_hr)) { 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Bundle installation failed with error " << error_code 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << ". Error message retrieval failed with error: " 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << completion_message_hr; 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Bundle installation failed with error " << error_code << ": " 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << completion_message; 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return error_code; 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)HRESULT CreateGoogleUpdate3(IGoogleUpdate3** update3) { 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::win::ScopedComPtr<IGoogleUpdate3> temp_update3; 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) HRESULT hr = temp_update3.CreateInstance(CLSID_GoogleUpdate3UserClass); 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (SUCCEEDED(hr)) { 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *update3 = temp_update3.Detach(); 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(erikwright): Try in-proc to support running elevated? According 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // to update3_utils.cc (CreateGoogleUpdate3UserClass): 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The primary reason for the LocalServer activation failing on Vista/Win7 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // is that COM does not look at HKCU registration when the code is running 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // elevated. We fall back to an in-proc mode. The in-proc mode is limited to 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // one install at a time, so we use it only as a backup mechanism. 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Failed to instantiate GoogleUpdate3: " << hr; 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return hr; 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)HRESULT CreateAppBundle(IGoogleUpdate3* update3, IAppBundle** app_bundle) { 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::win::ScopedComPtr<IDispatch> idispatch; 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) HRESULT hr = update3->createAppBundle(idispatch.Receive()); 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (FAILED(hr)) { 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Failed to createAppBundle: " << hr; 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return hr; 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::win::ScopedComPtr<IAppBundle> temp_app_bundle; 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) hr = temp_app_bundle.QueryFrom(idispatch); 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (FAILED(hr)) { 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Unexpected error querying IAppBundle from " 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << "IGoogleUpdate3->createAppBundle return value: " << hr; 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return hr; 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) hr = temp_app_bundle->initialize(); 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (FAILED(hr)) 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Failed to initialize App Bundle: " << hr; 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *app_bundle = temp_app_bundle.Detach(); 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return hr; 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)HRESULT SelectBinariesApValue(IGoogleUpdate3* update3, 1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BSTR* ap_value) { 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(erikwright): Uncomment this when we correctly propagate the AP value 1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // from the system-level binaries when quick-enabling the app host at 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // user-level (http://crbug.com/178479). 1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // base::win::ScopedComPtr<IAppBundle> app_bundle; 1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // HRESULT hr = CreateAppBundle(update3, app_bundle.Receive()); 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // if (FAILED(hr)) 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // return hr; 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // hr = GetAppHostApValue(update3, app_bundle, ap_value); 1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // if (SUCCEEDED(hr)) 1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // return hr; 1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(erikwright): distinguish between AppHost not installed and an 1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // error in GetAppHostApValue. 1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(erikwright): Use stable by default when App Host support is in 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // stable. 1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::win::ScopedBstr temp_ap_value; 1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (temp_ap_value.Allocate(L"2.0-dev-multi-apphost") == NULL) { 1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Unexpected error in ScopedBstr::Allocate."; 2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return E_FAIL; 2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *ap_value = temp_ap_value.Release(); 2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return S_OK; 2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)HRESULT CreateBinariesIApp(IAppBundle* app_bundle, BSTR ap, IApp** app) { 2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::win::ScopedComPtr<IDispatch> idispatch; 2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) HRESULT hr = app_bundle->createApp(base::win::ScopedBstr(kBinariesAppId), 2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) idispatch.Receive()); 2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (FAILED(hr)) { 2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Failed to configure App Bundle: " << hr; 2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return hr; 2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::win::ScopedComPtr<IApp> temp_app; 2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) hr = temp_app.QueryFrom(idispatch); 2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (FAILED(hr)) { 2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Unexpected error querying IApp from " 2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << "IAppBundle->createApp return value: " << hr; 2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return hr; 2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) hr = temp_app->put_isEulaAccepted(VARIANT_TRUE); 2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (FAILED(hr)) { 2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Failed to set 'EULA Accepted': " << hr; 2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return hr; 2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) hr = temp_app->put_ap(ap); 2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (FAILED(hr)) 2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Failed to set AP value: " << hr; 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else 2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *app = temp_app.Detach(); 2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return hr; 2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool CheckIfDone(IAppBundle* app_bundle, IApp* app, HRESULT* hr) { 2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::win::ScopedComPtr<ICurrentState> current_state; 2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CurrentState state_value; 2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *hr = GetCurrentState(app, current_state.Receive(), &state_value); 2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (FAILED(*hr)) 2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) switch (state_value) { 2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case STATE_WAITING_TO_CHECK_FOR_UPDATE: 2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case STATE_CHECKING_FOR_UPDATE: 2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case STATE_WAITING_TO_DOWNLOAD: 2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case STATE_RETRYING_DOWNLOAD: 2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case STATE_DOWNLOADING: 2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case STATE_WAITING_TO_INSTALL: 2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case STATE_INSTALLING: 2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case STATE_DOWNLOAD_COMPLETE: 2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case STATE_EXTRACTING: 2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case STATE_APPLYING_DIFFERENTIAL_PATCH: 2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // These states will all transition on their own. 2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case STATE_UPDATE_AVAILABLE: 2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OnUpdateAvailable(app_bundle, hr); 2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return FAILED(*hr); 2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case STATE_READY_TO_INSTALL: 2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OnReadyToInstall(app_bundle, hr); 2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return FAILED(*hr); 2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case STATE_NO_UPDATE: 2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(INFO) << "Google Update reports that the binaries are already " 2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << "installed and up-to-date."; 2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case STATE_INSTALL_COMPLETE: 2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case STATE_ERROR: 2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *hr = OnError(current_state); 2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return FAILED(*hr); 2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case STATE_INIT: 2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case STATE_PAUSED: 2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) default: 2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Unexpected bundle state: " << state_value << "."; 2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *hr = E_FAIL; 2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace 2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Globals -------------------------------------------------------------------- 2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)HRESULT InstallBinaries() { 2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::win::ScopedCOMInitializer initialize_com; 2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!initialize_com.succeeded()) { 2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "COM initialization failed"; 2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return E_FAIL; 2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::win::ScopedComPtr<IGoogleUpdate3> update3; 3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) HRESULT hr = CreateGoogleUpdate3(update3.Receive()); 3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (FAILED(hr)) 3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return hr; 3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::win::ScopedBstr ap_value; 3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) hr = SelectBinariesApValue(update3, ap_value.Receive()); 3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (FAILED(hr)) 3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return hr; 3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::win::ScopedComPtr<IAppBundle> app_bundle; 3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) hr = CreateAppBundle(update3, app_bundle.Receive()); 3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (FAILED(hr)) 3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return hr; 3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::win::ScopedComPtr<IApp> app; 3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) hr = CreateBinariesIApp(app_bundle, ap_value, app.Receive()); 3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (FAILED(hr)) 3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return hr; 3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) hr = app_bundle->checkForUpdate(); 3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (FAILED(hr)) { 3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Failed to initiate update check: " << hr; 3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return hr; 3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We rely upon Omaha to eventually time out and transition to a failure 3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // state. 3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) while (!CheckIfDone(app_bundle, app, &hr)) { 3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds( 3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) kInstallationPollingIntervalMs)); 3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return hr; 3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace app_host 335