kiosk_app_update_service.cc revision 010d83a9304c5a91596085d917d248abff47903a
1// Copyright 2013 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/chromeos/app_mode/kiosk_app_update_service.h"
6
7#include "base/logging.h"
8#include "chrome/browser/app_mode/app_mode_utils.h"
9#include "chrome/browser/browser_process.h"
10#include "chrome/browser/browser_process_platform_part_chromeos.h"
11#include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h"
12#include "chrome/browser/chromeos/system/automatic_reboot_manager.h"
13#include "chrome/browser/extensions/extension_service.h"
14#include "chrome/browser/lifetime/application_lifetime.h"
15#include "chrome/browser/profiles/profile.h"
16#include "components/keyed_service/content/browser_context_dependency_manager.h"
17#include "extensions/browser/api/runtime/runtime_api.h"
18#include "extensions/browser/extension_system.h"
19#include "extensions/browser/extension_system_provider.h"
20#include "extensions/browser/extensions_browser_client.h"
21#include "extensions/common/extension.h"
22
23namespace chromeos {
24
25namespace {
26
27// How low to wait after an update is available before we force a restart.
28const int kForceRestartWaitTimeMs = 24 * 3600 * 1000;  // 24 hours.
29
30}  // namespace
31
32KioskAppUpdateService::KioskAppUpdateService(
33    Profile* profile,
34    system::AutomaticRebootManager* automatic_reboot_manager)
35    : profile_(profile),
36      automatic_reboot_manager_(automatic_reboot_manager) {
37  ExtensionService* service =
38      extensions::ExtensionSystem::Get(profile_)->extension_service();
39  if (service)
40    service->AddUpdateObserver(this);
41
42  if (automatic_reboot_manager_)
43    automatic_reboot_manager_->AddObserver(this);
44}
45
46KioskAppUpdateService::~KioskAppUpdateService() {
47}
48
49void KioskAppUpdateService::StartAppUpdateRestartTimer() {
50  if (restart_timer_.IsRunning())
51    return;
52
53  // Setup timer to force restart once the wait period expires.
54  restart_timer_.Start(
55      FROM_HERE, base::TimeDelta::FromMilliseconds(kForceRestartWaitTimeMs),
56      this, &KioskAppUpdateService::ForceAppUpdateRestart);
57}
58
59void KioskAppUpdateService::ForceAppUpdateRestart() {
60  // Force a chrome restart (not a logout or reboot) by closing all browsers.
61  LOG(WARNING) << "Force closing all browsers to update kiosk app.";
62  chrome::CloseAllBrowsersAndQuit();
63}
64
65void KioskAppUpdateService::Shutdown() {
66  ExtensionService* service = profile_->GetExtensionService();
67  if (service)
68    service->RemoveUpdateObserver(this);
69}
70
71void KioskAppUpdateService::OnAppUpdateAvailable(
72    const extensions::Extension* extension) {
73  if (extension->id() != app_id_)
74    return;
75
76  // Clears cached app data so that it will be reloaded if update from app
77  // does not finish in this run.
78  KioskAppManager::Get()->ClearAppData(app_id_);
79  KioskAppManager::Get()->UpdateAppDataFromProfile(
80      app_id_, profile_, extension);
81
82  extensions::RuntimeEventRouter::DispatchOnRestartRequiredEvent(
83      profile_,
84      app_id_,
85      extensions::core_api::runtime::OnRestartRequired::REASON_APP_UPDATE);
86
87  StartAppUpdateRestartTimer();
88}
89
90void KioskAppUpdateService::OnRebootScheduled(Reason reason) {
91  extensions::core_api::runtime::OnRestartRequired::Reason restart_reason =
92      extensions::core_api::runtime::OnRestartRequired::REASON_NONE;
93  switch (reason) {
94    case REBOOT_REASON_OS_UPDATE:
95      restart_reason =
96          extensions::core_api::runtime::OnRestartRequired::REASON_OS_UPDATE;
97      break;
98    case REBOOT_REASON_PERIODIC:
99      restart_reason =
100          extensions::core_api::runtime::OnRestartRequired::REASON_PERIODIC;
101      break;
102    default:
103      NOTREACHED() << "Unknown reboot reason=" << reason;
104      return;
105  }
106
107  extensions::RuntimeEventRouter::DispatchOnRestartRequiredEvent(
108      profile_, app_id_, restart_reason);
109}
110
111void KioskAppUpdateService::WillDestroyAutomaticRebootManager() {
112  automatic_reboot_manager_->RemoveObserver(this);
113  automatic_reboot_manager_ = NULL;
114}
115
116KioskAppUpdateServiceFactory::KioskAppUpdateServiceFactory()
117    : BrowserContextKeyedServiceFactory(
118        "KioskAppUpdateService",
119        BrowserContextDependencyManager::GetInstance()) {
120  DependsOn(
121      extensions::ExtensionsBrowserClient::Get()->GetExtensionSystemFactory());
122}
123
124KioskAppUpdateServiceFactory::~KioskAppUpdateServiceFactory() {
125}
126
127// static
128KioskAppUpdateService* KioskAppUpdateServiceFactory::GetForProfile(
129    Profile* profile) {
130  // This should never be called unless we are running in forced app mode.
131  DCHECK(chrome::IsRunningInForcedAppMode());
132  if (!chrome::IsRunningInForcedAppMode())
133    return NULL;
134
135  return static_cast<KioskAppUpdateService*>(
136      GetInstance()->GetServiceForBrowserContext(profile, true));
137}
138
139// static
140KioskAppUpdateServiceFactory* KioskAppUpdateServiceFactory::GetInstance() {
141  return Singleton<KioskAppUpdateServiceFactory>::get();
142}
143
144KeyedService* KioskAppUpdateServiceFactory::BuildServiceInstanceFor(
145    content::BrowserContext* context) const {
146  return new KioskAppUpdateService(
147      Profile::FromBrowserContext(context),
148      g_browser_process->platform_part()->automatic_reboot_manager());
149}
150
151}  // namespace chromeos
152