Home | History | Annotate | Download | only in app_mode
      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 
     23 namespace chromeos {
     24 
     25 namespace {
     26 
     27 // How low to wait after an update is available before we force a restart.
     28 const int kForceRestartWaitTimeMs = 24 * 3600 * 1000;  // 24 hours.
     29 
     30 }  // namespace
     31 
     32 KioskAppUpdateService::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 
     46 KioskAppUpdateService::~KioskAppUpdateService() {
     47 }
     48 
     49 void 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 
     59 void 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 
     65 void KioskAppUpdateService::Shutdown() {
     66   ExtensionService* service = profile_->GetExtensionService();
     67   if (service)
     68     service->RemoveUpdateObserver(this);
     69 }
     70 
     71 void 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 
     90 void 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 
    111 void KioskAppUpdateService::WillDestroyAutomaticRebootManager() {
    112   automatic_reboot_manager_->RemoveObserver(this);
    113   automatic_reboot_manager_ = NULL;
    114 }
    115 
    116 KioskAppUpdateServiceFactory::KioskAppUpdateServiceFactory()
    117     : BrowserContextKeyedServiceFactory(
    118         "KioskAppUpdateService",
    119         BrowserContextDependencyManager::GetInstance()) {
    120   DependsOn(
    121       extensions::ExtensionsBrowserClient::Get()->GetExtensionSystemFactory());
    122 }
    123 
    124 KioskAppUpdateServiceFactory::~KioskAppUpdateServiceFactory() {
    125 }
    126 
    127 // static
    128 KioskAppUpdateService* 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
    140 KioskAppUpdateServiceFactory* KioskAppUpdateServiceFactory::GetInstance() {
    141   return Singleton<KioskAppUpdateServiceFactory>::get();
    142 }
    143 
    144 KeyedService* 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