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

Side by Side Diff: chrome/browser/extensions/app_host/binaries_installer_internal.cc

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

Powered by Google App Engine
This is Rietveld 408576698