OLD | NEW |
| (Empty) |
1 // Copyright 2009-2010 Google Inc. | |
2 // | |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | |
4 // you may not use this file except in compliance with the License. | |
5 // You may obtain a copy of the License at | |
6 // | |
7 // http://www.apache.org/licenses/LICENSE-2.0 | |
8 // | |
9 // Unless required by applicable law or agreed to in writing, software | |
10 // distributed under the License is distributed on an "AS IS" BASIS, | |
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
12 // See the License for the specific language governing permissions and | |
13 // limitations under the License. | |
14 // ======================================================================== | |
15 | |
16 #include"omaha/goopdate/app_bundle.h" | |
17 #include <atlsafe.h> | |
18 #include "omaha/base/debug.h" | |
19 #include "omaha/base/error.h" | |
20 #include "omaha/base/logging.h" | |
21 #include "omaha/base/scoped_impersonation.h" | |
22 #include "omaha/base/user_rights.h" | |
23 #include "omaha/base/utils.h" | |
24 #include "omaha/common/config_manager.h" | |
25 #include "omaha/common/lang.h" | |
26 #include "omaha/common/ping.h" | |
27 #include "omaha/common/update_request.h" | |
28 #include "omaha/common/update_response.h" | |
29 #include "omaha/common/web_services_client.h" | |
30 #include "omaha/goopdate/app_bundle_state_init.h" | |
31 #include "omaha/goopdate/app_manager.h" | |
32 #include "omaha/goopdate/model.h" | |
33 #include "omaha/goopdate/update_request_utils.h" | |
34 | |
35 namespace omaha { | |
36 | |
37 namespace { | |
38 | |
39 const TCHAR* const kDefaultInstallSource = _T("unknown"); | |
40 | |
41 } // namespace | |
42 | |
43 AppBundle::AppBundle(bool is_machine, Model* model) | |
44 : ModelObject(model), | |
45 install_source_(kDefaultInstallSource), | |
46 is_machine_(is_machine), | |
47 is_auto_update_(false), | |
48 priority_(INSTALL_PRIORITY_HIGH), | |
49 parent_hwnd_(NULL), | |
50 user_work_item_(NULL), | |
51 display_language_(lang::GetDefaultLanguage(is_machine)) { | |
52 CORE_LOG(L3, (_T("[AppBundle::AppBundle][0x%p]"), this)); | |
53 app_bundle_state_.reset(new fsm::AppBundleStateInit); | |
54 } | |
55 | |
56 AppBundle::~AppBundle() { | |
57 CORE_LOG(L3, (_T("[AppBundle::~AppBundle][0x%p]"), this)); | |
58 | |
59 // Destruction of this object is not serialized. The lifetime of AppBundle | |
60 // objects is controlled by the client and multiple objects can destruct at | |
61 // the same time. | |
62 ASSERT1(!model()->IsLockedByCaller()); | |
63 | |
64 HRESULT hr = SendPingEvents(); | |
65 CORE_LOG(L3, (_T("[SendPingEvents returned 0x%x]"), hr)); | |
66 | |
67 __mutexScope(model()->lock()); | |
68 for (size_t i = 0; i < apps_.size(); ++i) { | |
69 delete apps_[i]; | |
70 } | |
71 | |
72 // If the thread running this AppBundle does not exit before the | |
73 // NetworkConfigManager::DeleteInstance() happens in GoopdateImpl::Main, the | |
74 // update_check_client_ destructor will crash. Resetting here explicitly. | |
75 update_check_client_.reset(); | |
76 | |
77 // Garbage-collect everything that has expired, including this object. | |
78 // The model holds weak references to AppBundle objects. Those weak | |
79 // references expire before the destructor for the object runs. Therefore, it | |
80 // is not possible to associate this object with any of the weak references | |
81 // in the model. Those weak references must be garbage collected. | |
82 model()->CleanupExpiredAppBundles(); | |
83 } | |
84 | |
85 ControllingPtr AppBundle::controlling_ptr() { | |
86 __mutexScope(model()->lock()); | |
87 return shared_from_this(); | |
88 } | |
89 | |
90 bool AppBundle::is_pending_non_blocking_call() const { | |
91 __mutexScope(model()->lock()); | |
92 return user_work_item_ != NULL; | |
93 } | |
94 | |
95 void AppBundle::set_user_work_item(UserWorkItem* user_work_item) { | |
96 ASSERT(user_work_item, (_T("Use CompleteAsyncCall() instead."))); | |
97 __mutexScope(model()->lock()); | |
98 | |
99 user_work_item_ = user_work_item; | |
100 } | |
101 | |
102 HANDLE AppBundle::impersonation_token() const { | |
103 __mutexScope(model()->lock()); | |
104 return alt_impersonation_token_.GetHandle() ? | |
105 alt_impersonation_token_.GetHandle() : | |
106 impersonation_token_.GetHandle(); | |
107 } | |
108 | |
109 HANDLE AppBundle::primary_token() const { | |
110 __mutexScope(model()->lock()); | |
111 return alt_primary_token_.GetHandle() ? alt_primary_token_.GetHandle() : | |
112 primary_token_.GetHandle(); | |
113 } | |
114 | |
115 HRESULT AppBundle::CaptureCallerImpersonationToken() { | |
116 __mutexScope(model()->lock()); | |
117 | |
118 if (!is_machine_) { | |
119 return S_OK; | |
120 } | |
121 | |
122 if (impersonation_token_.GetHandle()) { | |
123 ::CloseHandle(impersonation_token_.Detach()); | |
124 } | |
125 | |
126 HRESULT hr = UserRights::GetCallerToken(&impersonation_token_); | |
127 if (FAILED(hr)) { | |
128 CORE_LOG(LE, (_T("[CaptureCallerImpersonationToken failed][0x%x]"), hr)); | |
129 return hr; | |
130 } | |
131 | |
132 return S_OK; | |
133 } | |
134 | |
135 HRESULT AppBundle::CaptureCallerPrimaryToken() { | |
136 __mutexScope(model()->lock()); | |
137 | |
138 if (!is_machine_) { | |
139 return S_OK; | |
140 } | |
141 | |
142 ASSERT1(impersonation_token_.GetHandle()); | |
143 if (!UserRights::TokenIsAdmin(impersonation_token_.GetHandle())) { | |
144 ASSERT1(false); | |
145 return E_UNEXPECTED; | |
146 } | |
147 | |
148 if (primary_token_.GetHandle()) { | |
149 ::CloseHandle(primary_token_.Detach()); | |
150 } | |
151 | |
152 if (!impersonation_token_.CreatePrimaryToken(&primary_token_)) { | |
153 HRESULT hr = HRESULTFromLastError(); | |
154 CORE_LOG(LE, (_T("[CreatePrimaryToken failed][0x%x]"), hr)); | |
155 return hr; | |
156 } | |
157 | |
158 return S_OK; | |
159 } | |
160 | |
161 size_t AppBundle::GetNumberOfApps() const { | |
162 __mutexScope(model()->lock()); | |
163 return apps_.size(); | |
164 } | |
165 | |
166 App* AppBundle::GetApp(size_t index) { | |
167 __mutexScope(model()->lock()); | |
168 | |
169 if (index >= GetNumberOfApps()) { | |
170 ASSERT1(false); | |
171 return NULL; | |
172 } | |
173 | |
174 App* app = apps_[index]; | |
175 ASSERT1(app); | |
176 return app; | |
177 } | |
178 | |
179 CString AppBundle::FetchAndResetLogText() { | |
180 __mutexScope(model()->lock()); | |
181 | |
182 CString event_log_text; | |
183 for (size_t i = 0; i < apps_.size(); ++i) { | |
184 event_log_text += apps_[i]->FetchAndResetLogText(); | |
185 } | |
186 | |
187 return event_log_text; | |
188 } | |
189 | |
190 HRESULT AppBundle::SendPingEvents() { | |
191 CORE_LOG(L3, (_T("[AppBundle::SendPingEvents]"))); | |
192 | |
193 scoped_impersonation impersonate_user(impersonation_token()); | |
194 | |
195 if (!ConfigManager::Instance()->CanUseNetwork(is_machine_)) { | |
196 CORE_LOG(L1, (_T("[Ping not sent because network use prohibited]"))); | |
197 return S_OK; | |
198 } | |
199 | |
200 Ping ping(is_machine_, session_id_, install_source_); | |
201 | |
202 __mutexBlock(model()->lock()) { | |
203 for (size_t i = 0; i != apps_.size(); ++i) { | |
204 if (apps_[i]->is_eula_accepted()) { | |
205 ping.BuildRequest(apps_[i], false); | |
206 } | |
207 } | |
208 | |
209 for (size_t i = 0; i != uninstalled_apps_.size(); ++i) { | |
210 if (uninstalled_apps_[i]->is_eula_accepted()) { | |
211 ping.BuildRequest(uninstalled_apps_[i], false); | |
212 } | |
213 } | |
214 } | |
215 | |
216 CORE_LOG(L3, (_T("[AppBundle::SendPingEvents][sending ping events]") | |
217 _T("[%d uninstalled apps]"), uninstalled_apps_.size())); | |
218 | |
219 // TODO(Omaha): Add sample to metric_ping_succeeded_ms or | |
220 // metric_ping_failed_ms based on the result of Send(). | |
221 return ping.Send(false); | |
222 } | |
223 | |
224 // IAppBundle. | |
225 STDMETHODIMP AppBundle::get_displayName(BSTR* display_name) { | |
226 ASSERT1(display_name); | |
227 __mutexScope(model()->lock()); | |
228 *display_name = display_name_.AllocSysString(); | |
229 return S_OK; | |
230 } | |
231 | |
232 STDMETHODIMP AppBundle::put_displayName(BSTR display_name) { | |
233 __mutexScope(model()->lock()); | |
234 display_name_ = display_name; | |
235 return S_OK; | |
236 } | |
237 | |
238 STDMETHODIMP AppBundle::get_installSource(BSTR* install_source) { | |
239 ASSERT1(install_source); | |
240 __mutexScope(model()->lock()); | |
241 *install_source = install_source_.AllocSysString(); | |
242 return S_OK; | |
243 } | |
244 | |
245 STDMETHODIMP AppBundle::put_installSource(BSTR install_source) { | |
246 __mutexScope(model()->lock()); | |
247 install_source_ = install_source; | |
248 return S_OK; | |
249 } | |
250 | |
251 STDMETHODIMP AppBundle::get_originURL(BSTR* origin_url) { | |
252 ASSERT1(origin_url); | |
253 __mutexScope(model()->lock()); | |
254 *origin_url = origin_url_.AllocSysString(); | |
255 return S_OK; | |
256 } | |
257 | |
258 STDMETHODIMP AppBundle::put_originURL(BSTR origin_url) { | |
259 __mutexScope(model()->lock()); | |
260 origin_url_ = origin_url; | |
261 return S_OK; | |
262 } | |
263 | |
264 STDMETHODIMP AppBundle::get_offlineDirectory(BSTR* offline_dir) { | |
265 ASSERT1(offline_dir); | |
266 __mutexScope(model()->lock()); | |
267 *offline_dir = offline_dir_.AllocSysString(); | |
268 return S_OK; | |
269 } | |
270 | |
271 STDMETHODIMP AppBundle::put_offlineDirectory(BSTR offline_dir) { | |
272 CORE_LOG(L3, (_T("[AppBundle::put_offlineDirectory][%s]"), offline_dir)); | |
273 __mutexScope(model()->lock()); | |
274 offline_dir_ = offline_dir; | |
275 return S_OK; | |
276 } | |
277 | |
278 STDMETHODIMP AppBundle::get_sessionId(BSTR* session_id) { | |
279 ASSERT1(session_id); | |
280 __mutexScope(model()->lock()); | |
281 *session_id = session_id_.AllocSysString(); | |
282 return S_OK; | |
283 } | |
284 | |
285 STDMETHODIMP AppBundle::put_sessionId(BSTR session_id) { | |
286 CORE_LOG(L3, (_T("[AppBundle::put_sessionId][%s]"), session_id)); | |
287 __mutexScope(model()->lock()); | |
288 return app_bundle_state_->put_sessionId(this, session_id); | |
289 } | |
290 | |
291 STDMETHODIMP AppBundle::get_priority(long* priority) { // NOLINT | |
292 ASSERT1(priority); | |
293 __mutexScope(model()->lock()); | |
294 *priority = priority_; | |
295 return S_OK; | |
296 } | |
297 | |
298 STDMETHODIMP AppBundle::put_priority(long priority) { // NOLINT | |
299 if ((priority < INSTALL_PRIORITY_LOW) || (priority > INSTALL_PRIORITY_HIGH)) { | |
300 return E_INVALIDARG; | |
301 } | |
302 __mutexScope(model()->lock()); | |
303 priority_ = priority; | |
304 return S_OK; | |
305 } | |
306 | |
307 STDMETHODIMP AppBundle::put_altTokens(ULONG_PTR impersonation_token, | |
308 ULONG_PTR primary_token, | |
309 DWORD caller_proc_id) { | |
310 ASSERT1(impersonation_token); | |
311 ASSERT1(primary_token); | |
312 ASSERT1(caller_proc_id); | |
313 __mutexScope(model()->lock()); | |
314 | |
315 return app_bundle_state_->put_altTokens(this, | |
316 impersonation_token, | |
317 primary_token, | |
318 caller_proc_id); | |
319 } | |
320 | |
321 STDMETHODIMP AppBundle::put_parentHWND(ULONG_PTR hwnd) { | |
322 CORE_LOG(L3, (_T("[AppBundle::put_parentHWND][0x%x]"), hwnd)); | |
323 | |
324 __mutexScope(model()->lock()); | |
325 parent_hwnd_ = reinterpret_cast<HWND>(hwnd); | |
326 update_check_client_->set_proxy_auth_config(GetProxyAuthConfig()); | |
327 return S_OK; | |
328 } | |
329 | |
330 CString AppBundle::display_language() const { | |
331 __mutexScope(model()->lock()); | |
332 return display_language_; | |
333 } | |
334 | |
335 STDMETHODIMP AppBundle::get_displayLanguage(BSTR* language) { | |
336 ASSERT1(language); | |
337 __mutexScope(model()->lock()); | |
338 *language = display_language_.AllocSysString(); | |
339 return S_OK; | |
340 } | |
341 | |
342 STDMETHODIMP AppBundle::put_displayLanguage(BSTR language) { | |
343 __mutexScope(model()->lock()); | |
344 if (::SysStringLen(language) == 0) { | |
345 return E_INVALIDARG; | |
346 } | |
347 | |
348 if (!lang::IsLanguageSupported(language)) { | |
349 return E_INVALIDARG; | |
350 } | |
351 | |
352 display_language_ = language; | |
353 return S_OK; | |
354 } | |
355 | |
356 bool AppBundle::is_machine() const { | |
357 __mutexScope(model()->lock()); | |
358 return is_machine_; | |
359 } | |
360 | |
361 bool AppBundle::is_auto_update() const { | |
362 __mutexScope(model()->lock()); | |
363 return is_auto_update_; | |
364 } | |
365 | |
366 void AppBundle::set_is_auto_update(bool is_auto_update) { | |
367 __mutexScope(model()->lock()); | |
368 is_auto_update_ = is_auto_update; | |
369 } | |
370 | |
371 bool AppBundle::is_offline_install() const { | |
372 __mutexScope(model()->lock()); | |
373 return !offline_dir_.IsEmpty(); | |
374 } | |
375 | |
376 const CString& AppBundle::offline_dir() const { | |
377 __mutexScope(model()->lock()); | |
378 return offline_dir_; | |
379 } | |
380 | |
381 const CString& AppBundle::session_id() const { | |
382 __mutexScope(model()->lock()); | |
383 return session_id_; | |
384 } | |
385 | |
386 int AppBundle::priority() const { | |
387 __mutexScope(model()->lock()); | |
388 return priority_; | |
389 } | |
390 | |
391 ProxyAuthConfig AppBundle::GetProxyAuthConfig() const { | |
392 __mutexScope(model()->lock()); | |
393 return ProxyAuthConfig(parent_hwnd_, display_name_); | |
394 } | |
395 | |
396 STDMETHODIMP AppBundle::initialize() { | |
397 __mutexScope(model()->lock()); | |
398 | |
399 // Ensure that clients that run as Local System were designed with alt tokens | |
400 // in mind. The alt tokens might not always be a different user, but at least | |
401 // the client considered the need to set the alt tokens. | |
402 // TODO(omaha): The /ua process should not need to call put_altTokens() | |
403 // when there is no logged in user. This may be causing issues on Windows 7. | |
404 bool alt_tokens_set(alt_impersonation_token_.GetHandle() && | |
405 alt_primary_token_.GetHandle()); | |
406 ASSERT1(!is_machine_ || | |
407 alt_tokens_set || | |
408 !UserRights::VerifyCallerIsSystem()); | |
409 | |
410 return app_bundle_state_->Initialize(this); | |
411 } | |
412 | |
413 // App is created with is_update=false because the caller is not using | |
414 // information about any installed app. It is either a new or over-install. | |
415 STDMETHODIMP AppBundle::createApp(BSTR app_id, App** app) { | |
416 CORE_LOG(L1, (_T("[AppBundle::createApp][%s][0x%p]"), app_id, this)); | |
417 ASSERT1(app_id); | |
418 ASSERT1(app); | |
419 | |
420 __mutexScope(model()->lock()); | |
421 | |
422 scoped_impersonation impersonate_user(impersonation_token()); | |
423 HRESULT hr = impersonate_user.result(); | |
424 if (FAILED(hr)) { | |
425 CORE_LOG(LE, (_T("[Impersonation failed][0x%08x]"), hr)); | |
426 return hr; | |
427 } | |
428 | |
429 return app_bundle_state_->CreateApp(this, app_id, app); | |
430 } | |
431 | |
432 STDMETHODIMP AppBundle::createInstalledApp(BSTR app_id, App** app) { | |
433 CORE_LOG(L1, (_T("[AppBundle::createInstalledApp][%s][0x%p]"), app_id, this)); | |
434 ASSERT1(app); | |
435 | |
436 __mutexScope(model()->lock()); | |
437 | |
438 | |
439 scoped_impersonation impersonate_user(impersonation_token()); | |
440 HRESULT hr = impersonate_user.result(); | |
441 if (FAILED(hr)) { | |
442 CORE_LOG(LE, (_T("[Impersonation failed][0x%08x]"), hr)); | |
443 return hr; | |
444 } | |
445 | |
446 return app_bundle_state_->CreateInstalledApp(this, app_id, app); | |
447 } | |
448 | |
449 STDMETHODIMP AppBundle::createAllInstalledApps() { | |
450 CORE_LOG(L1, (_T("[AppBundle::createAllInstalledApps][0x%p]"), this)); | |
451 | |
452 __mutexScope(model()->lock()); | |
453 | |
454 scoped_impersonation impersonate_user(impersonation_token()); | |
455 HRESULT hr = impersonate_user.result(); | |
456 if (FAILED(hr)) { | |
457 CORE_LOG(LE, (_T("[Impersonation failed][0x%08x]"), hr)); | |
458 return hr; | |
459 } | |
460 | |
461 return app_bundle_state_->CreateAllInstalledApps(this); | |
462 } | |
463 | |
464 STDMETHODIMP AppBundle::get_Count(long* count) { // NOLINT | |
465 ASSERT1(count); | |
466 | |
467 __mutexScope(model()->lock()); | |
468 | |
469 *count = apps_.size(); | |
470 | |
471 return S_OK; | |
472 } | |
473 | |
474 STDMETHODIMP AppBundle::get_Item(long index, App** app) { // NOLINT | |
475 ASSERT1(app); | |
476 | |
477 __mutexScope(model()->lock()); | |
478 | |
479 if (index < 0 || static_cast<size_t>(index) >= apps_.size()) { | |
480 return HRESULT_FROM_WIN32(ERROR_INVALID_INDEX); | |
481 } | |
482 | |
483 *app = apps_[index]; | |
484 return S_OK; | |
485 } | |
486 | |
487 WebServicesClientInterface* AppBundle::update_check_client() { | |
488 __mutexScope(model()->lock()); | |
489 ASSERT1(update_check_client_.get()); | |
490 return update_check_client_.get(); | |
491 } | |
492 | |
493 STDMETHODIMP AppBundle::checkForUpdate() { | |
494 CORE_LOG(L1, (_T("[AppBundle::checkForUpdate][0x%p]"), this)); | |
495 | |
496 __mutexScope(model()->lock()); | |
497 | |
498 scoped_impersonation impersonate_user(impersonation_token()); | |
499 HRESULT hr = impersonate_user.result(); | |
500 if (FAILED(hr)) { | |
501 CORE_LOG(LE, (_T("[Impersonation failed][0x%08x]"), hr)); | |
502 return hr; | |
503 } | |
504 | |
505 return app_bundle_state_->CheckForUpdate(this); | |
506 } | |
507 | |
508 STDMETHODIMP AppBundle::download() { | |
509 CORE_LOG(L1, (_T("[AppBundle::download][0x%p]"), this)); | |
510 | |
511 __mutexScope(model()->lock()); | |
512 | |
513 scoped_impersonation impersonate_user(impersonation_token()); | |
514 HRESULT hr = impersonate_user.result(); | |
515 if (FAILED(hr)) { | |
516 CORE_LOG(LE, (_T("[Impersonation failed][0x%08x]"), hr)); | |
517 return hr; | |
518 } | |
519 | |
520 return app_bundle_state_->Download(this); | |
521 } | |
522 | |
523 // Captures the primary token since it is the only function that needs it, and | |
524 // to prevent any scenarios where one user sets up a bundle and another installs | |
525 // the app(s) with the other user's credentials. | |
526 STDMETHODIMP AppBundle::install() { | |
527 CORE_LOG(L1, (_T("[AppBundle::install][0x%p]"), this)); | |
528 | |
529 __mutexScope(model()->lock()); | |
530 | |
531 HRESULT hr = CaptureCallerPrimaryToken(); | |
532 if (FAILED(hr)) { | |
533 return hr; | |
534 } | |
535 | |
536 scoped_impersonation impersonate_user(impersonation_token()); | |
537 hr = impersonate_user.result(); | |
538 if (FAILED(hr)) { | |
539 CORE_LOG(LE, (_T("[Impersonation failed][0x%08x]"), hr)); | |
540 return hr; | |
541 } | |
542 | |
543 return app_bundle_state_->Install(this); | |
544 } | |
545 | |
546 STDMETHODIMP AppBundle::updateAllApps() { | |
547 CORE_LOG(L1, (_T("[AppBundle::updateAllApps][0x%p]"), this)); | |
548 | |
549 __mutexScope(model()->lock()); | |
550 | |
551 scoped_impersonation impersonate_user(impersonation_token()); | |
552 HRESULT hr = impersonate_user.result(); | |
553 if (FAILED(hr)) { | |
554 CORE_LOG(LE, (_T("[Impersonation failed][0x%08x]"), hr)); | |
555 return hr; | |
556 } | |
557 | |
558 return app_bundle_state_->UpdateAllApps(this); | |
559 } | |
560 | |
561 STDMETHODIMP AppBundle::stop() { | |
562 CORE_LOG(L1, (_T("[AppBundle::stop][0x%p]"), this)); | |
563 | |
564 __mutexScope(model()->lock()); | |
565 | |
566 return app_bundle_state_->Stop(this); | |
567 } | |
568 | |
569 STDMETHODIMP AppBundle::pause() { | |
570 CORE_LOG(L1, (_T("[AppBundle::pause][0x%p]"), this)); | |
571 | |
572 __mutexScope(model()->lock()); | |
573 | |
574 return app_bundle_state_->Pause(this); | |
575 } | |
576 | |
577 STDMETHODIMP AppBundle::resume() { | |
578 CORE_LOG(L1, (_T("[AppBundle::resume][0x%p]"), this)); | |
579 | |
580 __mutexScope(model()->lock()); | |
581 | |
582 return app_bundle_state_->Resume(this); | |
583 } | |
584 | |
585 STDMETHODIMP AppBundle::isBusy(VARIANT_BOOL* is_busy) { | |
586 CORE_LOG(L3, (_T("[AppBundle::isBusy][0x%p]"), this)); | |
587 ASSERT1(is_busy); | |
588 | |
589 __mutexScope(model()->lock()); | |
590 | |
591 *is_busy = IsBusy() ? VARIANT_TRUE : VARIANT_FALSE; | |
592 return S_OK; | |
593 } | |
594 | |
595 STDMETHODIMP AppBundle::downloadPackage(BSTR app_id, BSTR package_name) { | |
596 CORE_LOG(L1, (_T("[AppBundle::downloadPackage][%s][%s]"), | |
597 app_id, package_name)); | |
598 | |
599 __mutexScope(model()->lock()); | |
600 | |
601 scoped_impersonation impersonate_user(impersonation_token()); | |
602 HRESULT hr = impersonate_user.result(); | |
603 if (FAILED(hr)) { | |
604 CORE_LOG(LE, (_T("[Impersonation failed][0x%08x]"), hr)); | |
605 return hr; | |
606 } | |
607 | |
608 return app_bundle_state_->DownloadPackage(this, app_id, package_name); | |
609 } | |
610 | |
611 // TODO(omaha3): May need to provide aggregate status. See TODO in IDL file. | |
612 STDMETHODIMP AppBundle::get_currentState(VARIANT* current_state) { | |
613 CORE_LOG(L3, (_T("[AppBundle::get_currentState][0x%p]"), this)); | |
614 ASSERT1(current_state); | |
615 UNREFERENCED_PARAMETER(current_state); | |
616 ASSERT(false, (_T("Not implemented. Should not call at this time."))); | |
617 return E_NOTIMPL; | |
618 } | |
619 | |
620 // This function is only called internal to the COM server and affects a | |
621 // separate vector of Apps, so it can be called in any state. | |
622 // It assumes all calls have a unique app_id. | |
623 HRESULT AppBundle::CreateUninstalledApp(const CString& app_id, App** app) { | |
624 CORE_LOG(L1, (_T("[AppBundle::CreateUninstalledApp][%s][0x%p]"), | |
625 app_id, this)); | |
626 ASSERT1(app); | |
627 | |
628 __mutexScope(model()->lock()); | |
629 | |
630 GUID app_guid = {0}; | |
631 HRESULT hr = StringToGuidSafe(app_id, &app_guid); | |
632 if (FAILED(hr)) { | |
633 CORE_LOG(LE, (_T("[invalid app id][%s]"), app_id)); | |
634 return hr; | |
635 } | |
636 | |
637 scoped_ptr<App> local_app(new App(app_guid, true, this)); | |
638 | |
639 hr = AppManager::Instance()->ReadUninstalledAppPersistentData( | |
640 local_app.get()); | |
641 if (FAILED(hr)) { | |
642 CORE_LOG(LE, (_T("[ReadUninstalledAppPersistentData failed][0x%x][%s]"), | |
643 hr, app_id)); | |
644 return hr; | |
645 } | |
646 | |
647 uninstalled_apps_.push_back(local_app.get()); | |
648 | |
649 *app = local_app.release(); | |
650 return S_OK; | |
651 } | |
652 | |
653 void AppBundle::CompleteAsyncCall() { | |
654 __mutexScope(model()->lock()); | |
655 | |
656 ASSERT1(is_pending_non_blocking_call()); | |
657 | |
658 VERIFY1(SUCCEEDED(app_bundle_state_->CompleteAsyncCall(this))); | |
659 | |
660 user_work_item_ = NULL; | |
661 } | |
662 | |
663 bool AppBundle::IsBusy() const { | |
664 __mutexScope(model()->lock()); | |
665 const bool is_busy = app_bundle_state_->IsBusy(); | |
666 CORE_LOG(L3, (_T("[AppBundle::isBusy returned][0x%p][%u]"), this, is_busy)); | |
667 return is_busy; | |
668 } | |
669 | |
670 void AppBundle::ChangeState(fsm::AppBundleState* app_bundle_state) { | |
671 ASSERT1(app_bundle_state); | |
672 ASSERT1(model()->IsLockedByCaller()); | |
673 | |
674 app_bundle_state_.reset(app_bundle_state); | |
675 } | |
676 | |
677 | |
678 // | |
679 // AppBundleWrapper implementation. | |
680 // | |
681 | |
682 AppBundleWrapper::AppBundleWrapper() { | |
683 CORE_LOG(L3, (_T("[AppBundleWrapper::AppBundleWrapper][0x%p]"), this)); | |
684 } | |
685 | |
686 AppBundleWrapper::~AppBundleWrapper() { | |
687 CORE_LOG(L3, (_T("[AppBundleWrapper::~AppBundleWrapper][0x%p]"), this)); | |
688 } | |
689 | |
690 // | |
691 // IAppBundle. | |
692 // | |
693 | |
694 STDMETHODIMP AppBundleWrapper::get_displayName(BSTR* display_name) { | |
695 __mutexScope(model()->lock()); | |
696 return wrapped_obj()->get_displayName(display_name); | |
697 } | |
698 | |
699 STDMETHODIMP AppBundleWrapper::put_displayName(BSTR display_name) { | |
700 __mutexScope(model()->lock()); | |
701 return wrapped_obj()->put_displayName(display_name); | |
702 } | |
703 | |
704 STDMETHODIMP AppBundleWrapper::get_installSource(BSTR* install_source) { | |
705 __mutexScope(model()->lock()); | |
706 return wrapped_obj()->get_installSource(install_source); | |
707 } | |
708 | |
709 STDMETHODIMP AppBundleWrapper::put_installSource(BSTR install_source) { | |
710 __mutexScope(model()->lock()); | |
711 return wrapped_obj()->put_installSource(install_source); | |
712 } | |
713 | |
714 STDMETHODIMP AppBundleWrapper::get_originURL(BSTR* origin_url) { | |
715 __mutexScope(model()->lock()); | |
716 return wrapped_obj()->get_originURL(origin_url); | |
717 } | |
718 | |
719 STDMETHODIMP AppBundleWrapper::put_originURL(BSTR origin_url) { | |
720 __mutexScope(model()->lock()); | |
721 return wrapped_obj()->put_originURL(origin_url); | |
722 } | |
723 | |
724 STDMETHODIMP AppBundleWrapper::get_offlineDirectory(BSTR* offline_dir) { | |
725 __mutexScope(model()->lock()); | |
726 return wrapped_obj()->get_offlineDirectory(offline_dir); | |
727 } | |
728 | |
729 STDMETHODIMP AppBundleWrapper::put_offlineDirectory(BSTR offline_dir) { | |
730 __mutexScope(model()->lock()); | |
731 return wrapped_obj()->put_offlineDirectory(offline_dir); | |
732 } | |
733 | |
734 STDMETHODIMP AppBundleWrapper::get_sessionId(BSTR* session_id) { | |
735 __mutexScope(model()->lock()); | |
736 return wrapped_obj()->get_sessionId(session_id); | |
737 } | |
738 | |
739 STDMETHODIMP AppBundleWrapper::put_sessionId(BSTR session_id) { | |
740 __mutexScope(model()->lock()); | |
741 return wrapped_obj()->put_sessionId(session_id); | |
742 } | |
743 | |
744 STDMETHODIMP AppBundleWrapper::get_priority(long* priority) { // NOLINT | |
745 __mutexScope(model()->lock()); | |
746 return wrapped_obj()->get_priority(priority); | |
747 } | |
748 | |
749 STDMETHODIMP AppBundleWrapper::put_priority(long priority) { // NOLINT | |
750 __mutexScope(model()->lock()); | |
751 return wrapped_obj()->put_priority(priority); | |
752 } | |
753 | |
754 STDMETHODIMP AppBundleWrapper::put_altTokens(ULONG_PTR impersonation_token, | |
755 ULONG_PTR primary_token, | |
756 DWORD caller_proc_id) { | |
757 __mutexScope(model()->lock()); | |
758 return wrapped_obj()->put_altTokens(impersonation_token, | |
759 primary_token, | |
760 caller_proc_id); | |
761 } | |
762 | |
763 STDMETHODIMP AppBundleWrapper::put_parentHWND(ULONG_PTR hwnd) { | |
764 __mutexScope(model()->lock()); | |
765 return wrapped_obj()->put_parentHWND(hwnd); | |
766 } | |
767 | |
768 STDMETHODIMP AppBundleWrapper::get_displayLanguage(BSTR* language) { | |
769 __mutexScope(model()->lock()); | |
770 return wrapped_obj()->get_displayLanguage(language); | |
771 } | |
772 STDMETHODIMP AppBundleWrapper::put_displayLanguage(BSTR language) { | |
773 __mutexScope(model()->lock()); | |
774 return wrapped_obj()->put_displayLanguage(language); | |
775 } | |
776 | |
777 STDMETHODIMP AppBundleWrapper::initialize() { | |
778 __mutexScope(model()->lock()); | |
779 return wrapped_obj()->initialize(); | |
780 } | |
781 | |
782 STDMETHODIMP AppBundleWrapper::createApp(BSTR app_id, IDispatch** app_disp) { | |
783 __mutexScope(model()->lock()); | |
784 | |
785 App* app = NULL; | |
786 HRESULT hr = wrapped_obj()->createApp(app_id, &app); | |
787 if (FAILED(hr)) { | |
788 return hr; | |
789 } | |
790 | |
791 return AppWrapper::Create(controlling_ptr(), app, app_disp); | |
792 } | |
793 | |
794 STDMETHODIMP AppBundleWrapper::createInstalledApp(BSTR appId, | |
795 IDispatch** app_disp) { | |
796 __mutexScope(model()->lock()); | |
797 | |
798 App* app = NULL; | |
799 HRESULT hr = wrapped_obj()->createInstalledApp(appId, &app); | |
800 if (FAILED(hr)) { | |
801 return hr; | |
802 } | |
803 | |
804 return AppWrapper::Create(controlling_ptr(), app, app_disp); | |
805 } | |
806 | |
807 STDMETHODIMP AppBundleWrapper::createAllInstalledApps() { | |
808 __mutexScope(model()->lock()); | |
809 return wrapped_obj()->createAllInstalledApps(); | |
810 } | |
811 | |
812 STDMETHODIMP AppBundleWrapper::get_Count(long* count) { // NOLINT | |
813 __mutexScope(model()->lock()); | |
814 return wrapped_obj()->get_Count(count); | |
815 } | |
816 | |
817 STDMETHODIMP AppBundleWrapper::get_Item(long index, IDispatch** app_disp) { //
NOLINT | |
818 __mutexScope(model()->lock()); | |
819 | |
820 App* app = NULL; | |
821 HRESULT hr = wrapped_obj()->get_Item(index, &app); | |
822 if (FAILED(hr)) { | |
823 return hr; | |
824 } | |
825 | |
826 return AppWrapper::Create(controlling_ptr(), app, app_disp); | |
827 } | |
828 | |
829 STDMETHODIMP AppBundleWrapper::checkForUpdate() { | |
830 __mutexScope(model()->lock()); | |
831 return wrapped_obj()->checkForUpdate(); | |
832 } | |
833 | |
834 STDMETHODIMP AppBundleWrapper::download() { | |
835 __mutexScope(model()->lock()); | |
836 return wrapped_obj()->download(); | |
837 } | |
838 | |
839 STDMETHODIMP AppBundleWrapper::install() { | |
840 if (wrapped_obj()->is_machine() && !UserRights::VerifyCallerIsAdmin()) { | |
841 ASSERT(false, (_T("AppBundle::install - Caller not an admin"))); | |
842 return E_ACCESSDENIED; | |
843 } | |
844 | |
845 __mutexScope(model()->lock()); | |
846 return wrapped_obj()->install(); | |
847 } | |
848 | |
849 STDMETHODIMP AppBundleWrapper::updateAllApps() { | |
850 __mutexScope(model()->lock()); | |
851 return wrapped_obj()->updateAllApps(); | |
852 } | |
853 | |
854 STDMETHODIMP AppBundleWrapper::stop() { | |
855 __mutexScope(model()->lock()); | |
856 return wrapped_obj()->stop(); | |
857 } | |
858 | |
859 STDMETHODIMP AppBundleWrapper::pause() { | |
860 __mutexScope(model()->lock()); | |
861 return wrapped_obj()->pause(); | |
862 } | |
863 | |
864 STDMETHODIMP AppBundleWrapper::resume() { | |
865 __mutexScope(model()->lock()); | |
866 return wrapped_obj()->resume(); | |
867 } | |
868 | |
869 STDMETHODIMP AppBundleWrapper::isBusy(VARIANT_BOOL* is_busy) { | |
870 __mutexScope(model()->lock()); | |
871 return wrapped_obj()->isBusy(is_busy); | |
872 } | |
873 | |
874 STDMETHODIMP AppBundleWrapper::downloadPackage(BSTR app_id, BSTR package_name) { | |
875 __mutexScope(model()->lock()); | |
876 return wrapped_obj()->downloadPackage(app_id, package_name); | |
877 } | |
878 | |
879 STDMETHODIMP AppBundleWrapper::get_currentState(VARIANT* current_state) { | |
880 __mutexScope(model()->lock()); | |
881 return wrapped_obj()->get_currentState(current_state); | |
882 } | |
883 | |
884 | |
885 // Sets app bundle's app_state to state. Used by unit tests to set up the state | |
886 // to the correct precondition for the test case. AppBundle friends this | |
887 // function, allowing it to call the private member function. | |
888 void SetAppBundleStateForUnitTest(AppBundle* app_bundle, | |
889 fsm::AppBundleState* state) { | |
890 ASSERT1(app_bundle); | |
891 ASSERT1(state); | |
892 __mutexScope(app_bundle->model()->lock()); | |
893 app_bundle->ChangeState(state); | |
894 } | |
895 | |
896 } // namespace omaha | |
OLD | NEW |