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

Side by Side Diff: client/install_apps.cc

Issue 624713003: Keep only base/extractor.[cc|h]. (Closed) Base URL: https://chromium.googlesource.com/external/omaha.git@master
Patch Set: Created 6 years, 2 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
« no previous file with comments | « client/install_apps.h ('k') | client/install_apps_internal.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 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/client/install_apps.h"
17 #include <atlsafe.h>
18 #include "base/scoped_ptr.h"
19 #include "omaha/base/const_object_names.h"
20 #include "omaha/base/debug.h"
21 #include "omaha/base/error.h"
22 #include "omaha/base/logging.h"
23 #include "omaha/base/reactor.h"
24 #include "omaha/base/scope_guard.h"
25 #include "omaha/base/scoped_ptr_address.h"
26 #include "omaha/base/shutdown_callback.h"
27 #include "omaha/base/shutdown_handler.h"
28 #include "omaha/base/string.h"
29 #include "omaha/base/time.h"
30 #include "omaha/base/utils.h"
31 #include "omaha/base/vista_utils.h"
32 #include "omaha/client/bundle_creator.h"
33 #include "omaha/client/bundle_installer.h"
34 #include "omaha/client/client_metrics.h"
35 #include "omaha/client/client_utils.h"
36 #include "omaha/client/help_url_builder.h"
37 #include "omaha/client/install_apps_internal.h"
38 #include "omaha/client/install_progress_observer.h"
39 #include "omaha/client/resource.h"
40 #include "omaha/common/command_line.h"
41 #include "omaha/common/config_manager.h"
42 #include "omaha/common/const_cmd_line.h"
43 #include "omaha/common/goopdate_utils.h"
44 #include "omaha/common/lang.h"
45 #include "omaha/common/ping.h"
46 #include "omaha/common/update3_utils.h"
47 #include "goopdate/omaha3_idl.h"
48 #include "omaha/ui/progress_wnd.h"
49
50 namespace omaha {
51
52 namespace {
53
54 // Implements the UI progress window.
55 class SilentProgressObserver : public InstallProgressObserver {
56 public:
57 explicit SilentProgressObserver(BundleInstaller* installer)
58 : installer_(installer) {
59 ASSERT1(installer);
60 }
61
62 virtual void OnCheckingForUpdate() {
63 CORE_LOG(L3, (_T("[SilentProgressObserver::OnCheckingForUpdate]")));
64 }
65
66 virtual void OnUpdateAvailable(const CString& app_name,
67 const CString& version_string) {
68 CORE_LOG(L3, (_T("[SilentProgressObserver::OnUpdateAvailable][%s][%s]"),
69 app_name, version_string));
70 UNREFERENCED_PARAMETER(app_name);
71 UNREFERENCED_PARAMETER(version_string);
72 }
73
74 virtual void OnWaitingToDownload(const CString& app_name) {
75 CORE_LOG(L3, (_T("[SilentProgressObserver::OnWaitingToDownload][%s]"),
76 app_name));
77 UNREFERENCED_PARAMETER(app_name);
78 }
79
80 virtual void OnDownloading(const CString& app_name,
81 int time_remaining_ms,
82 int pos) {
83 CORE_LOG(L5, (_T("[SilentProgressObserver::OnDownloading]")
84 _T("[%s][remaining ms=%d][pos=%d]"),
85 app_name, time_remaining_ms, pos));
86 UNREFERENCED_PARAMETER(app_name);
87 UNREFERENCED_PARAMETER(time_remaining_ms);
88 UNREFERENCED_PARAMETER(pos);
89 }
90
91 virtual void OnWaitingRetryDownload(const CString& app_name,
92 time64 next_retry_time) {
93 CORE_LOG(L5, (_T("[SilentProgressObserver::OnWaitingRetryDownload]")
94 _T("[%s][next retry time=%llu]"),
95 app_name, next_retry_time));
96 UNREFERENCED_PARAMETER(app_name);
97 UNREFERENCED_PARAMETER(next_retry_time);
98 }
99
100 virtual void OnWaitingToInstall(const CString& app_name,
101 bool* can_start_install) {
102 CORE_LOG(L3, (_T("[SilentProgressObserver::OnWaitingToInstall][%s]"),
103 app_name));
104 ASSERT1(can_start_install);
105 UNREFERENCED_PARAMETER(app_name);
106 UNREFERENCED_PARAMETER(can_start_install);
107 }
108
109 virtual void OnInstalling(const CString& app_name) {
110 CORE_LOG(L5, (_T("[SilentProgressObserver::OnInstalling][%s]"), app_name));
111 UNREFERENCED_PARAMETER(app_name);
112 }
113
114 virtual void OnPause() {
115 CORE_LOG(L3, (_T("[SilentProgressObserver::OnPause]")));
116 }
117
118 // Terminates the message loop.
119 virtual void OnComplete(const ObserverCompletionInfo& observer_info) {
120 CORE_LOG(L3, (_T("[SilentProgressObserver::OnComplete][%s]"),
121 observer_info.ToString()));
122 UNREFERENCED_PARAMETER(observer_info);
123
124 installer_->DoExit();
125 CORE_LOG(L1, (_T("[SilentProgressObserver][DoExit() called]")));
126 }
127
128 private:
129 BundleInstaller *const installer_;
130 };
131
132 class OnDemandEvents : public OnDemandEventsInterface {
133 public:
134 explicit OnDemandEvents(BundleInstaller* installer)
135 : installer_(installer) {
136 ASSERT1(installer);
137 }
138 virtual void DoClose() {
139 installer_->DoClose();
140 }
141 virtual void DoExit() {
142 installer_->DoExit();
143 }
144
145 private:
146 BundleInstaller *const installer_;
147 };
148
149 // This ATL module is used for BundleInstaller message loop shutdown intrinsics.
150 // It is also needed for cases where the Update3 server COM objects are created
151 // inproc.
152 class BundleAtlModule : public CAtlExeModuleT<BundleAtlModule> {
153 public:
154 explicit BundleAtlModule() : allow_post_quit_(false) {
155 // Disable the delay on shutdown mechanism in CAtlExeModuleT.
156 m_bDelayShutdown = false;
157 }
158 ~BundleAtlModule() {}
159
160 LONG Unlock() throw() {
161 LONG lRet = CComGlobalsThreadModel::Decrement(&m_nLockCnt);
162
163 if (lRet == 0 && allow_post_quit_) {
164 ::PostThreadMessage(m_dwMainThreadID, WM_QUIT, 0, 0);
165 }
166
167 return lRet;
168 }
169
170 // BundleAtlModule will only post WM_QUIT if enable_quit() is called, to avoid
171 // spurious WM_QUITs during bundle initialization.
172 void enable_quit() {
173 allow_post_quit_ = true;
174 }
175
176 private:
177 bool allow_post_quit_;
178
179 DISALLOW_COPY_AND_ASSIGN(BundleAtlModule);
180 };
181
182 } // namespace
183
184 namespace internal {
185
186 bool IsBrowserRestartSupported(BrowserType browser_type) {
187 return (browser_type != BROWSER_UNKNOWN &&
188 browser_type != BROWSER_DEFAULT &&
189 browser_type < BROWSER_MAX);
190 }
191
192 InstallAppsWndEvents::InstallAppsWndEvents(bool is_machine,
193 BundleInstaller* installer,
194 BrowserType browser_type)
195 : is_machine_(is_machine),
196 installer_(installer),
197 browser_type_(browser_type) {
198 ASSERT1(installer_);
199 }
200
201 void InstallAppsWndEvents::DoClose() {
202 ASSERT1(installer_);
203 installer_->DoClose();
204 }
205
206 void InstallAppsWndEvents::DoExit() {
207 ASSERT1(installer_);
208 installer_->DoExit();
209 }
210
211 void InstallAppsWndEvents::DoCancel() {
212 ASSERT1(installer_);
213 installer_->DoCancel();
214 }
215
216 // TODO(omaha3): Need to address elevated Vista installs. Since we are doing
217 // a handoff, we know that Omaha is installed and can do de-elevation.
218 // However, BuildGetHelpUrl will return an empty string right now. Best to
219 // just solve the general problem.
220 bool InstallAppsWndEvents::DoLaunchBrowser(const CString& url) {
221 CORE_LOG(L2, (_T("[InstallAppsWndEvents::DoLaunchBrowser %s]"), url));
222 const BrowserType browser = BROWSER_UNKNOWN == browser_type_ ?
223 BROWSER_DEFAULT :
224 browser_type_;
225 return SUCCEEDED(goopdate_utils::LaunchBrowser(is_machine_, browser, url));
226 }
227
228 // Restarts the browser(s) and returns whether the browser was successfully
229 // restarted.
230 bool InstallAppsWndEvents::DoRestartBrowser(bool terminate_all_browsers,
231 const std::vector<CString>& urls) {
232 // UI should not trigger this call back if the browser type is unknown.
233 // Instead it should ask user to restart the browser(s) manually.
234 ASSERT1(IsBrowserRestartSupported(browser_type_));
235
236 BrowserType browser = browser_type_;
237 if (browser == BROWSER_DEFAULT) {
238 GetDefaultBrowserType(&browser);
239 }
240
241 TerminateBrowserResult browser_res;
242 TerminateBrowserResult default_res;
243 if (terminate_all_browsers) {
244 VERIFY1(SUCCEEDED(goopdate_utils::TerminateAllBrowsers(browser,
245 &browser_res,
246 &default_res)));
247 } else {
248 VERIFY1(SUCCEEDED(goopdate_utils::TerminateBrowserProcesses(browser,
249 &browser_res,
250 &default_res)));
251 }
252
253 BrowserType default_browser_type = BROWSER_UNKNOWN;
254 HRESULT hr = GetDefaultBrowserType(&default_browser_type);
255 if (FAILED(hr)) {
256 CORE_LOG(LE, (_T("[GetDefaultBrowserType failed][0x%08x]"), hr));
257 }
258
259 BrowserType browser_to_restart = BROWSER_UNKNOWN;
260 if (!goopdate_utils::GetBrowserToRestart(browser,
261 default_browser_type,
262 browser_res,
263 default_res,
264 &browser_to_restart)) {
265 CORE_LOG(LE, (_T("[GetBrowserToRestart returned false. Not launching.]")));
266 return false;
267 }
268 ASSERT1(IsBrowserRestartSupported(browser_to_restart));
269
270 bool succeeded = true;
271 for (size_t i = 0; i < urls.size(); ++i) {
272 succeeded &= SUCCEEDED(goopdate_utils::LaunchBrowser(is_machine_,
273 browser_to_restart,
274 urls[i]));
275 }
276
277 return succeeded;
278 }
279
280 // Initiates a reboot and returns whether it was iniated successfully.
281 bool InstallAppsWndEvents::DoReboot() {
282 ASSERT(false, (_T("Not implemented.")));
283 return false;
284 }
285
286 CString GetBundleDisplayName(IAppBundle* app_bundle) {
287 if (!app_bundle) {
288 return client_utils::GetDefaultBundleName();
289 }
290
291 CComBSTR bundle_name;
292 HRESULT hr = app_bundle->get_displayName(&bundle_name);
293 if (FAILED(hr)) {
294 CORE_LOG(LW, (_T("[get_displayName failed][0x%08x]"), hr));
295 }
296
297 return (SUCCEEDED(hr) && bundle_name.Length()) ?
298 CString(bundle_name) : client_utils::GetDefaultBundleName();
299 }
300
301 HRESULT CreateClientUI(bool is_machine,
302 BrowserType browser_type,
303 BundleInstaller* installer,
304 IAppBundle* app_bundle,
305 InstallProgressObserver** observer,
306 OmahaWndEvents** ui_sink) {
307 ASSERT1(installer);
308 ASSERT1(observer);
309 ASSERT1(!*observer);
310 ASSERT1(ui_sink);
311 ASSERT1(!*ui_sink);
312
313 scoped_ptr<ProgressWnd> progress_wnd(
314 new ProgressWnd(installer->message_loop(), NULL));
315 ScopeGuard destroy_window_guard = MakeObjGuard(*progress_wnd,
316 &ProgressWnd::DestroyWindow);
317
318 progress_wnd->set_is_machine(is_machine);
319 progress_wnd->set_bundle_name(internal::GetBundleDisplayName(app_bundle));
320
321 HRESULT hr = progress_wnd->Initialize();
322 if (FAILED(hr)) {
323 return hr;
324 }
325
326 scoped_ptr<internal::InstallAppsWndEvents> progress_wnd_events(
327 new internal::InstallAppsWndEvents(is_machine, installer, browser_type));
328 progress_wnd->SetEventSink(progress_wnd_events.get());
329
330 progress_wnd->Show();
331 installer->SetBundleParentWindow(progress_wnd->m_hWnd);
332
333 destroy_window_guard.Dismiss();
334 *observer = progress_wnd.release();
335 *ui_sink = progress_wnd_events.release();
336 return S_OK;
337 }
338
339 // The order of construction is important because it ensures the objects are
340 // deleted in a safe order (objects before their dependencies).
341 // Any early returns before the message loop is run must call
342 // progress_wnd.DestroyWindow(). Errors do not need to be reported in a UI
343 // because they are handled further up the call stack.
344 HRESULT DoInstallApps(BundleInstaller* installer,
345 IAppBundle* app_bundle,
346 bool is_machine,
347 bool is_interactive,
348 bool is_update_all_apps,
349 BrowserType browser_type,
350 bool* has_ui_been_displayed) {
351 CORE_LOG(L2, (_T("[DoInstallApps]")));
352 ASSERT1(installer);
353 ASSERT1(has_ui_been_displayed);
354
355 scoped_ptr<InstallProgressObserver> observer;
356 scoped_ptr<OmahaWndEvents> ui_sink;
357 bool listen_to_shutdown_event = false;
358
359 CComPtr<IAppBundle> app_bundle_ptr;
360 app_bundle_ptr.Attach(app_bundle);
361
362 HRESULT hr = S_OK;
363 if (is_interactive) {
364 hr = CreateClientUI(is_machine,
365 browser_type,
366 installer,
367 app_bundle,
368 address(observer),
369 address(ui_sink));
370 if (FAILED(hr)) {
371 CORE_LOG(LE, (_T("CreateClientUI failed][0x%08x]"), hr));
372 return hr;
373 }
374 *has_ui_been_displayed = true;
375 } else {
376 observer.reset(new SilentProgressObserver(installer));
377 if (is_update_all_apps) {
378 listen_to_shutdown_event = true;
379 }
380 }
381
382 hr = installer->InstallBundle(is_machine,
383 listen_to_shutdown_event,
384 app_bundle_ptr.Detach(),
385 observer.get());
386
387 observer.reset();
388
389 // ui_sink must be destroyed after observer and before installer.
390 ui_sink.reset();
391
392 CORE_LOG(L1, (_T("DoInstallApps returning][0x%08x]"), hr));
393 return hr;
394 }
395
396 void HandleInstallAppsError(HRESULT error,
397 int extra_code1,
398 bool is_machine,
399 bool is_interactive,
400 bool is_eula_accepted,
401 bool is_oem_install,
402 const CString& install_source,
403 const CommandLineExtraArgs& extra_args,
404 const CString& session_id,
405 bool* has_ui_been_displayed) {
406 ASSERT1(FAILED(error));
407 ASSERT1(has_ui_been_displayed);
408
409 const CString& bundle_name = extra_args.bundle_name;
410 ASSERT1(!bundle_name.IsEmpty());
411
412 CString error_text;
413
414 switch (error) {
415 case GOOPDATE_E_USER_AND_ELEVATED_WITH_UAC_ON:
416 error_text.FormatMessage(IDS_USER_SHOULD_NOT_RUN_ELEVATED_WITH_UAC_ON,
417 bundle_name);
418 break;
419 default: {
420 CString product_name;
421 VERIFY1(product_name.LoadString(IDS_PRODUCT_DISPLAY_NAME));
422 error_text.FormatMessage(IDS_SETUP_FAILED, product_name, error);
423 break;
424 }
425 }
426
427 OPT_LOG(LE, (_T("[Failed to install apps][0x%08x][%s]"), error, error_text));
428
429 if (is_interactive && !*has_ui_been_displayed) {
430 CString primary_app_id;
431 if (!extra_args.apps.empty()) {
432 primary_app_id = GuidToString(extra_args.apps[0].app_guid);
433 }
434
435 *has_ui_been_displayed = client_utils::DisplayError(
436 is_machine,
437 bundle_name,
438 error,
439 extra_code1,
440 error_text,
441 primary_app_id,
442 extra_args.language,
443 extra_args.installation_id,
444 extra_args.brand_code);
445 }
446
447 if (!is_eula_accepted || is_oem_install) {
448 return;
449 }
450
451 // Send an install complete ping and do not wait for the ping to be sent.
452 // Since Omaha has been installed at this point, it should be able to
453 // send this ping without blocking the user flow.
454 Ping ping(is_machine, session_id, install_source);
455 ping.LoadAppDataFromExtraArgs(extra_args);
456 PingEventPtr ping_event(
457 new PingEvent(PingEvent::EVENT_INSTALL_COMPLETE,
458 PingEvent::EVENT_RESULT_HANDOFF_ERROR,
459 error,
460 extra_code1));
461 ping.BuildAppsPing(ping_event);
462 HRESULT send_result = ping.Send(true);
463 if (FAILED(send_result)) {
464 CORE_LOG(LW, (_T("[Ping::Send failed][0x%x]"), send_result));
465 }
466 }
467
468 } // namespace internal
469
470 HRESULT UpdateAppOnDemand(bool is_machine,
471 const CString& app_id,
472 bool is_update_check_only,
473 const CString& session_id,
474 HANDLE impersonation_token,
475 HANDLE primary_token,
476 OnDemandObserver* observer) {
477 CORE_LOG(L2, (_T("[UpdateAppOnDemand][%d][%s][%d]"),
478 is_machine, app_id, is_update_check_only));
479
480 const TCHAR* install_source = is_update_check_only ?
481 kCmdLineInstallSource_OnDemandCheckForUpdate :
482 kCmdLineInstallSource_OnDemandUpdate;
483 CComPtr<IAppBundle> app_bundle;
484 HRESULT hr = bundle_creator::CreateForOnDemand(is_machine,
485 app_id,
486 install_source,
487 session_id,
488 impersonation_token,
489 primary_token,
490 &app_bundle);
491 if (SUCCEEDED(hr)) {
492 BundleInstaller installer(NULL, // No help URL for on-demand.
493 false, // Is not update all apps.
494 is_update_check_only,
495 false);
496 hr = installer.Initialize();
497 if (SUCCEEDED(hr)) {
498 OnDemandEvents install_events(&installer);
499 observer->SetEventSink(&install_events);
500
501 // TODO(omaha3): Listen to shutdown event during installation?
502 return installer.InstallBundle(is_machine,
503 false,
504 app_bundle.Detach(),
505 observer);
506 }
507 }
508
509 // The observer must be notified that the bundle has completed with an error
510 // since the bundle will not be processed.
511 observer->OnComplete(ObserverCompletionInfo(COMPLETION_CODE_ERROR));
512 return hr;
513 }
514
515 HRESULT InstallApps(bool is_machine,
516 bool is_interactive,
517 bool is_eula_accepted,
518 bool is_oem_install,
519 bool is_offline,
520 const CString& offline_directory,
521 const CommandLineExtraArgs& extra_args,
522 const CString& install_source,
523 const CString& session_id,
524 bool* has_ui_been_displayed) {
525 CORE_LOG(L2, (_T("[InstallApps][is_machine: %u][is_interactive: %u]")
526 _T("[is_eula_accepted: %u][is_oem_install: %u][is_offline: %u]")
527 _T("[offline_directory: %s]"), is_machine, is_interactive,
528 is_eula_accepted, is_oem_install, is_offline, offline_directory));
529 ASSERT1(has_ui_been_displayed);
530
531 BundleAtlModule atl_module;
532
533 CComPtr<IAppBundle> app_bundle;
534 HRESULT hr = bundle_creator::CreateFromCommandLine(is_machine,
535 is_eula_accepted,
536 is_offline,
537 offline_directory,
538 extra_args,
539 install_source,
540 session_id,
541 is_interactive,
542 &app_bundle);
543 if (FAILED(hr)) {
544 CORE_LOG(LE, (_T("[bundle_creator::CreateFromCommandLine][0x%08x]"), hr));
545 internal::HandleInstallAppsError(hr,
546 0,
547 is_machine,
548 is_interactive,
549 is_eula_accepted,
550 is_oem_install,
551 install_source,
552 extra_args,
553 session_id,
554 has_ui_been_displayed);
555 return hr;
556 }
557
558 BundleInstaller installer(
559 new HelpUrlBuilder(is_machine,
560 extra_args.language,
561 extra_args.installation_id,
562 extra_args.brand_code),
563 false, // is_update_all_apps
564 false, // is_update_check_only
565 internal::IsBrowserRestartSupported(extra_args.browser_type));
566 hr = installer.Initialize();
567 if (FAILED(hr)) {
568 return hr;
569 }
570
571 atl_module.enable_quit();
572 return internal::DoInstallApps(&installer,
573 app_bundle.Detach(),
574 is_machine,
575 is_interactive,
576 false, // Is not update all apps.
577 extra_args.browser_type,
578 has_ui_been_displayed);
579 }
580
581 HRESULT UpdateAllApps(bool is_machine,
582 bool is_interactive,
583 const CString& install_source,
584 const CString& display_language,
585 const CString& session_id,
586 bool* has_ui_been_displayed) {
587 CORE_LOG(L2, (_T("[UpdateAllApps][%u][%u]"), is_machine, is_interactive));
588 ASSERT1(has_ui_been_displayed);
589
590 BundleAtlModule atl_module;
591
592 CComPtr<IAppBundle> app_bundle;
593 HRESULT hr = bundle_creator::Create(is_machine,
594 display_language,
595 install_source,
596 session_id,
597 is_interactive,
598 &app_bundle);
599 if (FAILED(hr)) {
600 CORE_LOG(LE, (_T("[bundle_creator::Create failed][0x%08x]"), hr));
601 return hr;
602 }
603
604 BundleInstaller installer(new HelpUrlBuilder(is_machine,
605 display_language,
606 GUID_NULL,
607 CString()),
608 true, // is_update_all_apps
609 false, // is_update_check_only
610 BROWSER_UNKNOWN);
611 hr = installer.Initialize();
612 if (FAILED(hr)) {
613 return hr;
614 }
615
616 atl_module.enable_quit();
617 return internal::DoInstallApps(&installer,
618 app_bundle.Detach(),
619 is_machine,
620 is_interactive,
621 true, // Is update all apps.
622 BROWSER_UNKNOWN,
623 has_ui_been_displayed);
624 }
625
626 } // namespace omaha
OLDNEW
« no previous file with comments | « client/install_apps.h ('k') | client/install_apps_internal.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698