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

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: More wood behind fewer return statements. Created 8 years, 4 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;
miket_OOO 2012/08/23 23:51:01 No braces needed for these one-line blocks.
erikwright (departed) 2012/08/31 21:04:48 Done.
28 } else {
29 *is_busy = (variant_is_busy == VARIANT_TRUE);
30 }
31 return hr;
32 }
33
34 HRESULT OnUpdateAvailable(IAppBundle* app_bundle) {
35 // If the app bundle is 'busy' we will just wait some more.
miket_OOO 2012/08/23 23:51:01 Why quotes around busy? Does it mean something dif
erikwright (departed) 2012/08/31 21:04:48 Done.
36 bool is_busy = false;
37 HRESULT hr = CheckIsBusy(app_bundle, &is_busy);
robertshield 2012/08/16 21:15:53 what does it mean for the app bundle to be 'busy'
38 if (SUCCEEDED(hr) && !is_busy) {
39 hr = app_bundle->download();
40 if (FAILED(hr))
41 LOG(ERROR) << "Failed to initiate bundle download: " << hr;
42 }
43 return hr;
44 }
45
46 HRESULT OnReadyToInstall(IAppBundle* app_bundle) {
47 // If the app bundle is 'busy' we will just wait some more.
48 bool is_busy = false;
49 HRESULT hr = CheckIsBusy(app_bundle, &is_busy);
50 if (SUCCEEDED(hr) && !is_busy) {
51 hr = app_bundle->install();
52 if (FAILED(hr))
53 LOG(ERROR) << "Failed to initiate bundle install: " << hr;
54 }
55 return hr;
56 }
57
58 HRESULT OnError(ICurrentState* current_state) {
59 LONG error_code;
60 HRESULT hr = current_state->get_errorCode(&error_code);
61 if (FAILED(hr)) {
62 LOG(ERROR) << "Failed to retrieve bundle error code: " << hr;
63 } else {
64 hr = error_code;
65
66 ScopedBstr completion_message;
67 HRESULT completion_message_hr =
68 current_state->get_completionMessage(completion_message.Receive());
69 if (FAILED(completion_message_hr)) {
70 LOG(ERROR) << "Bundle installation failed with error " << hr
71 << ". Error message retrieval failed with error: "
72 << completion_message_hr;
miket_OOO 2012/08/23 23:51:01 one-liner braces
erikwright (departed) 2012/08/31 21:04:48 I don't think these qualify as one-liner according
73 } else {
74 LOG(ERROR) << "Bundle installation failed with error " << hr << ": "
75 << completion_message;
76 }
77 }
78
79 return hr;
80 }
81
82 HRESULT GetCurrentState(IApp* app,
83 ICurrentState** current_state,
84 CurrentState* state_value) {
85 HRESULT hr = S_OK;
86
87 ScopedComPtr<ICurrentState> temp_current_state;
88 {
89 ScopedComPtr<IDispatch> idispatch;
90 hr = app->get_currentState(idispatch.Receive());
91 if (FAILED(hr)) {
92 LOG(ERROR) << "Failed to get App Bundle state: " << hr;
93 } else {
94 hr = temp_current_state.QueryFrom(idispatch);
95 if (FAILED(hr))
96 LOG(ERROR) << "Unexpected error: " << hr;
miket_OOO 2012/08/23 23:51:01 Might as well give a little more context for this
erikwright (departed) 2012/08/31 21:04:48 Done.
97 }
98 }
99
100 if (SUCCEEDED(hr)) {
101 LONG long_state_value;
102 hr = temp_current_state->get_stateValue(&long_state_value);
103 if (FAILED(hr))
104 LOG(ERROR) << "Failed to get App Bundle state value: " << hr;
105 *state_value = static_cast<CurrentState>(long_state_value);
106 *current_state = temp_current_state.Detach();
107 }
108
109 return hr;
110 }
111
112 HRESULT CreateInstalledApp(IAppBundle* app_bundle,
113 const wchar_t* app_guid,
114 IApp** app) {
115 ScopedComPtr<IApp> temp_app;
116 ScopedComPtr<IDispatch> idispatch;
117 HRESULT hr = app_bundle->createInstalledApp(ScopedBstr(app_guid),
118 idispatch.Receive());
119 if (FAILED(hr)) {
120 LOG(ERROR) << "Failed to configure App Bundle: " << hr;
121 } else {
122 hr = temp_app.QueryFrom(idispatch);
123 if (FAILED(hr))
124 LOG(ERROR) << "Unexpected error: " << hr;
125 else
126 *app = temp_app.Detach();
127 }
128
129 return hr;
130 }
131
132 } // namespace
133
134 bool CheckIfDone(IAppBundle* app_bundle, IApp* app, HRESULT* hr) {
miket_OOO 2012/08/23 23:51:01 Suggestion: if you have a local hr that's copied t
erikwright (departed) 2012/08/31 21:04:48 No, hr is returned to the caller of InstallBinarie
miket_OOO 2012/08/31 21:48:43 OK, good. I should have looked but I'd convinced m
135 ScopedComPtr<ICurrentState> current_state;
136 CurrentState state_value;
137 *hr = GetCurrentState(app, current_state.Receive(), &state_value);
138
139 bool complete = false;
140
141 if (SUCCEEDED(hr)) {
142 switch (state_value) {
143 case STATE_WAITING_TO_CHECK_FOR_UPDATE:
144 case STATE_CHECKING_FOR_UPDATE:
145 case STATE_WAITING_TO_DOWNLOAD:
146 case STATE_RETRYING_DOWNLOAD:
147 case STATE_DOWNLOADING:
148 case STATE_WAITING_TO_INSTALL:
149 case STATE_INSTALLING:
150 case STATE_DOWNLOAD_COMPLETE:
151 case STATE_EXTRACTING:
152 case STATE_APPLYING_DIFFERENTIAL_PATCH:
153 // These states will all transition on their own.
154 break;
155
156 case STATE_UPDATE_AVAILABLE:
157 *hr = OnUpdateAvailable(app_bundle);
158 break;
159
160 case STATE_READY_TO_INSTALL:
161 *hr = OnReadyToInstall(app_bundle);
162 break;
163
164 case STATE_NO_UPDATE:
165 LOG(INFO) << "Google Update reports that the binaries are already "
166 << "installed and up-to-date.";
167 complete = true;
168 break;
169
170 case STATE_INSTALL_COMPLETE:
171 complete = true;
172 break;
173
174 case STATE_ERROR:
175 *hr = OnError(current_state);
176 break;
177
178 case STATE_INIT:
179 case STATE_PAUSED:
180 default:
181 LOG(ERROR) << "Unexpected bundle state: " << state_value << ".";
182 *hr = E_FAIL;
183 break;
184 }
185 }
186
187 return FAILED(*hr) || complete;
188 }
189
190 HRESULT CreateAppBundle(IGoogleUpdate3* update3, IAppBundle** app_bundle) {
191 HRESULT hr = S_OK;
192
193 ScopedComPtr<IAppBundle> temp_app_bundle;
194 {
195 ScopedComPtr<IDispatch> idispatch;
196 hr = update3->createAppBundle(idispatch.Receive());
197 if (FAILED(hr)) {
198 LOG(ERROR) << "Failed to createAppBundle: " << hr;
199 } else {
200 hr = temp_app_bundle.QueryFrom(idispatch);
201 if (FAILED(hr))
202 LOG(ERROR) << "Unexpected error: " << hr;
203 }
204 }
205
206 if (SUCCEEDED(hr)) {
207 hr = temp_app_bundle->initialize();
208 if (FAILED(hr))
209 LOG(ERROR) << "Failed to initialize App Bundle: " << hr;
210 else
211 *app_bundle = temp_app_bundle.Detach();
212 }
213
214 return hr;
215 }
216
217 HRESULT GetAppHostAPValue(IGoogleUpdate3* update3, BSTR* ap_value) {
218 ScopedComPtr<IAppBundle> app_bundle;
219 HRESULT hr = CreateAppBundle(update3, app_bundle.Receive());
220 if (SUCCEEDED(hr)) {
221 ScopedComPtr<IApp> app;
222 hr = CreateInstalledApp(app_bundle, kAppHostAppId, app.Receive());
223 if (SUCCEEDED(hr)) {
224 hr = app->get_ap(ap_value);
225 if (FAILED(hr))
226 LOG(ERROR) << "Failed to get the App Host AP value.";
227 }
228 }
229
230 return hr;
231 }
232
233 HRESULT CreateBinariesIApp(IAppBundle* app_bundle, BSTR ap, IApp** app) {
234 HRESULT hr = S_OK;
235
236 ScopedComPtr<IApp> temp_app;
237 {
238 ScopedComPtr<IDispatch> idispatch;
239 hr = app_bundle->createApp(ScopedBstr(kBinariesAppId), idispatch.Receive());
240 if (FAILED(hr)) {
241 LOG(ERROR) << "Failed to configure App Bundle: " << hr;
242 } else {
243 hr = temp_app.QueryFrom(idispatch);
244 if (FAILED(hr))
245 LOG(ERROR) << "Unexpected error: " << hr;
246 }
247 }
248
249 if (SUCCEEDED(hr)) {
250 hr = temp_app->put_isEulaAccepted(VARIANT_TRUE);
251 if (FAILED(hr))
252 LOG(ERROR) << "Failed to set 'EULA Accepted': " << hr;
253 }
254
255 if (SUCCEEDED(hr)) {
256 hr = temp_app->put_ap(ap);
257 if (FAILED(hr))
258 LOG(ERROR) << "Failed to set AP value: " << hr;
259 }
260
261 if (SUCCEEDED(hr))
262 *app = temp_app.Detach();
miket_OOO 2012/08/23 23:51:01 This could slide, but I can see cases where temp_a
erikwright (departed) 2012/08/31 21:04:48 Are you suggesting that a potential code change co
miket_OOO 2012/08/31 21:48:43 Ah, OK. I was confused. It belongs to the RAII guy
263
264 return S_OK;
265 }
266
267 HRESULT CreateGoogleUpdate3(IGoogleUpdate3** update3) {
268 ScopedComPtr<IGoogleUpdate3> temp_update3;
269 HRESULT hr = temp_update3.CreateInstance(CLSID_GoogleUpdate3UserClass);
270 if (FAILED(hr)) {
miket_OOO 2012/08/23 23:51:01 It's slightly easier to read if the SUCCEEDED() ca
erikwright (departed) 2012/08/31 21:04:48 Done.
271 // TODO(erikwright): Try in-proc to support running elevated? According
272 // to update3_utils.cc (CreateGoogleUpdate3UserClass):
273 // The primary reason for the LocalServer activation failing on Vista/Win7
274 // is that COM does not look at HKCU registration when the code is running
275 // elevated. We fall back to an in-proc mode. The in-proc mode is limited to
276 // one install at a time, so we use it only as a backup mechanism.
277 LOG(ERROR) << "Failed to instantiate GoogleUpdate3: " << hr;
278 } else {
279 *update3 = temp_update3.Detach();
280 }
281 return hr;
282 }
283
284 HRESULT SelectBinariesApValue(IGoogleUpdate3* update3, BSTR* ap_value) {
285 HRESULT hr = GetAppHostAPValue(update3, ap_value);
286 if (FAILED(hr)) {
287 // TODO(erikwright): distinguish between AppHost not installed and an
288 // error in GetAppHostAPValue.
289 // TODO(erikwright): Use stable by default when App Host support is in
290 // stable.
291 ScopedBstr temp_ap_value;
292 if (NULL == temp_ap_value.Allocate(L"2.0-dev-multi-apphost")) {
293 LOG(ERROR) << "Unexpected error in ScopedBstr::Allocate.";
294 hr = E_FAIL;
295 } else {
296 *ap_value = temp_ap_value.Release();
297 hr = S_OK;
298 }
299 }
300
301 return hr;
302 }
303
304 } // namespace internal
305 } // namespace app_host
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698