Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(437)

Side by Side Diff: apps/app_host/binaries_installer.cc

Issue 23539002: Delete app_host from apps/ (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Removed TODO Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « apps/app_host/binaries_installer.h ('k') | apps/app_host/update.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "apps/app_host/binaries_installer.h"
6
7 #include "base/logging.h"
8 #include "base/threading/platform_thread.h"
9 #include "base/win/scoped_bstr.h"
10 #include "base/win/scoped_com_initializer.h"
11 #include "base/win/scoped_comptr.h"
12 #include "google_update/google_update_idl.h"
13
14
15 namespace app_host {
16
17 // Helpers --------------------------------------------------------------------
18
19 namespace {
20
21 const wchar_t kAppHostAppId[] = L"{FDA71E6F-AC4C-4a00-8B70-9958A68906BF}";
22 const wchar_t kBinariesAppId[] = L"{4DC8B4CA-1BDA-483e-B5FA-D3C12E15B62D}";
23 const int kInstallationPollingIntervalMs = 50;
24
25 HRESULT CreateInstalledApp(IAppBundle* app_bundle,
26 const wchar_t* app_guid,
27 IApp** app) {
28 base::win::ScopedComPtr<IDispatch> idispatch;
29 HRESULT hr = app_bundle->createInstalledApp(base::win::ScopedBstr(app_guid),
30 idispatch.Receive());
31 if (FAILED(hr)) {
32 LOG(ERROR) << "Failed to configure App Bundle: " << hr;
33 return hr;
34 }
35
36 base::win::ScopedComPtr<IApp> temp_app;
37 hr = temp_app.QueryFrom(idispatch);
38 if (FAILED(hr)) {
39 LOG(ERROR) << "Unexpected error querying IApp from "
40 << "IAppBundle->createInstalledApp return value: " << hr;
41 } else {
42 *app = temp_app.Detach();
43 }
44 return hr;
45 }
46
47 HRESULT GetAppHostApValue(IGoogleUpdate3* update3,
48 IAppBundle* app_bundle,
49 BSTR* ap_value) {
50 base::win::ScopedComPtr<IApp> app;
51 HRESULT hr = CreateInstalledApp(app_bundle, kAppHostAppId, app.Receive());
52 if (FAILED(hr))
53 return hr;
54
55 hr = app->get_ap(ap_value);
56 if (FAILED(hr))
57 LOG(ERROR) << "Failed to get the App Launcher AP value.";
58 return hr;
59 }
60
61 HRESULT GetCurrentState(IApp* app,
62 ICurrentState** current_state,
63 CurrentState* state_value) {
64 base::win::ScopedComPtr<IDispatch> idispatch;
65 HRESULT hr = app->get_currentState(idispatch.Receive());
66 if (FAILED(hr)) {
67 LOG(ERROR) << "Failed to get App Bundle state: " << hr;
68 return hr;
69 }
70
71 base::win::ScopedComPtr<ICurrentState> temp_current_state;
72 hr = temp_current_state.QueryFrom(idispatch);
73 if (FAILED(hr)) {
74 LOG(ERROR) << "Unexpected error querying ICurrentState from "
75 << "IApp::get_currentState return value: " << hr;
76 return hr;
77 }
78
79 LONG long_state_value;
80 hr = temp_current_state->get_stateValue(&long_state_value);
81 if (SUCCEEDED(hr)) {
82 *state_value = static_cast<CurrentState>(long_state_value);
83 *current_state = temp_current_state.Detach();
84 } else {
85 LOG(ERROR) << "Failed to get App Bundle state value: " << hr;
86 }
87 return hr;
88 }
89
90 bool CheckIsBusy(IAppBundle* app_bundle, HRESULT* hr) {
91 VARIANT_BOOL variant_is_busy = VARIANT_TRUE;
92 *hr = app_bundle->isBusy(&variant_is_busy);
93 if (FAILED(*hr))
94 LOG(ERROR) << "Failed to check app_bundle->isBusy: " << *hr;
95 return (variant_is_busy == VARIANT_TRUE);
96 }
97
98 void OnUpdateAvailable(IAppBundle* app_bundle, HRESULT* hr) {
99 // If the app bundle is busy we will just wait some more.
100 if (CheckIsBusy(app_bundle, hr) || FAILED(*hr))
101 return;
102 *hr = app_bundle->download();
103 if (FAILED(*hr))
104 LOG(ERROR) << "Failed to initiate bundle download: " << *hr;
105 }
106
107 void OnReadyToInstall(IAppBundle* app_bundle, HRESULT* hr) {
108 // If the app bundle is busy we will just wait some more.
109 if (CheckIsBusy(app_bundle, hr) || FAILED(*hr))
110 return;
111 *hr = app_bundle->install();
112 if (FAILED(*hr))
113 LOG(ERROR) << "Failed to initiate bundle install: " << *hr;
114 }
115
116 HRESULT OnError(ICurrentState* current_state) {
117 LONG error_code;
118 HRESULT hr = current_state->get_errorCode(&error_code);
119 if (FAILED(hr)) {
120 LOG(ERROR) << "Failed to retrieve bundle error code: " << hr;
121 return hr;
122 }
123
124 base::win::ScopedBstr completion_message;
125 HRESULT completion_message_hr =
126 current_state->get_completionMessage(completion_message.Receive());
127 if (FAILED(completion_message_hr)) {
128 LOG(ERROR) << "Bundle installation failed with error " << error_code
129 << ". Error message retrieval failed with error: "
130 << completion_message_hr;
131 } else {
132 LOG(ERROR) << "Bundle installation failed with error " << error_code << ": "
133 << completion_message;
134 }
135 return error_code;
136 }
137
138 HRESULT CreateGoogleUpdate3(IGoogleUpdate3** update3) {
139 base::win::ScopedComPtr<IGoogleUpdate3> temp_update3;
140 HRESULT hr = temp_update3.CreateInstance(CLSID_GoogleUpdate3UserClass);
141 if (SUCCEEDED(hr)) {
142 *update3 = temp_update3.Detach();
143 } else {
144 // TODO(erikwright): Try in-proc to support running elevated? According
145 // to update3_utils.cc (CreateGoogleUpdate3UserClass):
146 // The primary reason for the LocalServer activation failing on Vista/Win7
147 // is that COM does not look at HKCU registration when the code is running
148 // elevated. We fall back to an in-proc mode. The in-proc mode is limited to
149 // one install at a time, so we use it only as a backup mechanism.
150 LOG(ERROR) << "Failed to instantiate GoogleUpdate3: " << hr;
151 }
152 return hr;
153 }
154
155 HRESULT CreateAppBundle(IGoogleUpdate3* update3, IAppBundle** app_bundle) {
156 base::win::ScopedComPtr<IDispatch> idispatch;
157 HRESULT hr = update3->createAppBundle(idispatch.Receive());
158 if (FAILED(hr)) {
159 LOG(ERROR) << "Failed to createAppBundle: " << hr;
160 return hr;
161 }
162
163 base::win::ScopedComPtr<IAppBundle> temp_app_bundle;
164 hr = temp_app_bundle.QueryFrom(idispatch);
165 if (FAILED(hr)) {
166 LOG(ERROR) << "Unexpected error querying IAppBundle from "
167 << "IGoogleUpdate3->createAppBundle return value: " << hr;
168 return hr;
169 }
170
171 hr = temp_app_bundle->initialize();
172 if (FAILED(hr))
173 LOG(ERROR) << "Failed to initialize App Bundle: " << hr;
174 else
175 *app_bundle = temp_app_bundle.Detach();
176 return hr;
177 }
178
179 HRESULT SelectBinariesApValue(IGoogleUpdate3* update3,
180 BSTR* ap_value) {
181 // TODO(erikwright): Uncomment this when we correctly propagate the AP value
182 // from the system-level binaries when quick-enabling the app host at
183 // user-level (http://crbug.com/178479).
184 // base::win::ScopedComPtr<IAppBundle> app_bundle;
185 // HRESULT hr = CreateAppBundle(update3, app_bundle.Receive());
186 // if (FAILED(hr))
187 // return hr;
188
189 // hr = GetAppHostApValue(update3, app_bundle, ap_value);
190 // if (SUCCEEDED(hr))
191 // return hr;
192
193 // TODO(erikwright): distinguish between AppHost not installed and an
194 // error in GetAppHostApValue.
195 // TODO(erikwright): Use stable by default when App Host support is in
196 // stable.
197 base::win::ScopedBstr temp_ap_value;
198 if (temp_ap_value.Allocate(L"2.0-dev-multi-apphost") == NULL) {
199 LOG(ERROR) << "Unexpected error in ScopedBstr::Allocate.";
200 return E_FAIL;
201 }
202 *ap_value = temp_ap_value.Release();
203 return S_OK;
204 }
205
206 HRESULT CreateBinariesIApp(IAppBundle* app_bundle, BSTR ap, IApp** app) {
207 base::win::ScopedComPtr<IDispatch> idispatch;
208 HRESULT hr = app_bundle->createApp(base::win::ScopedBstr(kBinariesAppId),
209 idispatch.Receive());
210 if (FAILED(hr)) {
211 LOG(ERROR) << "Failed to configure App Bundle: " << hr;
212 return hr;
213 }
214
215 base::win::ScopedComPtr<IApp> temp_app;
216 hr = temp_app.QueryFrom(idispatch);
217 if (FAILED(hr)) {
218 LOG(ERROR) << "Unexpected error querying IApp from "
219 << "IAppBundle->createApp return value: " << hr;
220 return hr;
221 }
222
223 hr = temp_app->put_isEulaAccepted(VARIANT_TRUE);
224 if (FAILED(hr)) {
225 LOG(ERROR) << "Failed to set 'EULA Accepted': " << hr;
226 return hr;
227 }
228
229 hr = temp_app->put_ap(ap);
230 if (FAILED(hr))
231 LOG(ERROR) << "Failed to set AP value: " << hr;
232 else
233 *app = temp_app.Detach();
234 return hr;
235 }
236
237 bool CheckIfDone(IAppBundle* app_bundle, IApp* app, HRESULT* hr) {
238 base::win::ScopedComPtr<ICurrentState> current_state;
239 CurrentState state_value;
240 *hr = GetCurrentState(app, current_state.Receive(), &state_value);
241 if (FAILED(*hr))
242 return true;
243
244 switch (state_value) {
245 case STATE_WAITING_TO_CHECK_FOR_UPDATE:
246 case STATE_CHECKING_FOR_UPDATE:
247 case STATE_WAITING_TO_DOWNLOAD:
248 case STATE_RETRYING_DOWNLOAD:
249 case STATE_DOWNLOADING:
250 case STATE_WAITING_TO_INSTALL:
251 case STATE_INSTALLING:
252 case STATE_DOWNLOAD_COMPLETE:
253 case STATE_EXTRACTING:
254 case STATE_APPLYING_DIFFERENTIAL_PATCH:
255 // These states will all transition on their own.
256 return false;
257
258 case STATE_UPDATE_AVAILABLE:
259 OnUpdateAvailable(app_bundle, hr);
260 return FAILED(*hr);
261
262 case STATE_READY_TO_INSTALL:
263 OnReadyToInstall(app_bundle, hr);
264 return FAILED(*hr);
265
266 case STATE_NO_UPDATE:
267 LOG(INFO) << "Google Update reports that the binaries are already "
268 << "installed and up-to-date.";
269 return true;
270
271 case STATE_INSTALL_COMPLETE:
272 return true;
273
274 case STATE_ERROR:
275 *hr = OnError(current_state);
276 return FAILED(*hr);
277
278 case STATE_INIT:
279 case STATE_PAUSED:
280 default:
281 LOG(ERROR) << "Unexpected bundle state: " << state_value << ".";
282 *hr = E_FAIL;
283 return true;
284 }
285 }
286
287 } // namespace
288
289
290 // Globals --------------------------------------------------------------------
291
292 HRESULT InstallBinaries() {
293 base::win::ScopedCOMInitializer initialize_com;
294 if (!initialize_com.succeeded()) {
295 LOG(ERROR) << "COM initialization failed";
296 return E_FAIL;
297 }
298
299 base::win::ScopedComPtr<IGoogleUpdate3> update3;
300 HRESULT hr = CreateGoogleUpdate3(update3.Receive());
301 if (FAILED(hr))
302 return hr;
303
304 base::win::ScopedBstr ap_value;
305 hr = SelectBinariesApValue(update3, ap_value.Receive());
306 if (FAILED(hr))
307 return hr;
308
309 base::win::ScopedComPtr<IAppBundle> app_bundle;
310 hr = CreateAppBundle(update3, app_bundle.Receive());
311 if (FAILED(hr))
312 return hr;
313
314 base::win::ScopedComPtr<IApp> app;
315 hr = CreateBinariesIApp(app_bundle, ap_value, app.Receive());
316 if (FAILED(hr))
317 return hr;
318
319 hr = app_bundle->checkForUpdate();
320 if (FAILED(hr)) {
321 LOG(ERROR) << "Failed to initiate update check: " << hr;
322 return hr;
323 }
324
325 // We rely upon Omaha to eventually time out and transition to a failure
326 // state.
327 while (!CheckIfDone(app_bundle, app, &hr)) {
328 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(
329 kInstallationPollingIntervalMs));
330 }
331 return hr;
332 }
333
334 } // namespace app_host
OLDNEW
« no previous file with comments | « apps/app_host/binaries_installer.h ('k') | apps/app_host/update.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698