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 if (KioskAppManager::Get()) 46 KioskAppManager::Get()->AddObserver(this); 47} 48 49KioskAppUpdateService::~KioskAppUpdateService() { 50} 51 52void KioskAppUpdateService::StartAppUpdateRestartTimer() { 53 if (restart_timer_.IsRunning()) 54 return; 55 56 // Setup timer to force restart once the wait period expires. 57 restart_timer_.Start( 58 FROM_HERE, base::TimeDelta::FromMilliseconds(kForceRestartWaitTimeMs), 59 this, &KioskAppUpdateService::ForceAppUpdateRestart); 60} 61 62void KioskAppUpdateService::ForceAppUpdateRestart() { 63 // Force a chrome restart (not a logout or reboot) by closing all browsers. 64 LOG(WARNING) << "Force closing all browsers to update kiosk app."; 65 chrome::CloseAllBrowsersAndQuit(); 66} 67 68void KioskAppUpdateService::Shutdown() { 69 ExtensionService* service = 70 extensions::ExtensionSystem::Get(profile_)->extension_service(); 71 if (service) 72 service->RemoveUpdateObserver(this); 73 if (KioskAppManager::Get()) 74 KioskAppManager::Get()->RemoveObserver(this); 75} 76 77void KioskAppUpdateService::OnAppUpdateAvailable( 78 const extensions::Extension* extension) { 79 if (extension->id() != app_id_) 80 return; 81 82 // Clears cached app data so that it will be reloaded if update from app 83 // does not finish in this run. 84 KioskAppManager::Get()->ClearAppData(app_id_); 85 KioskAppManager::Get()->UpdateAppDataFromProfile( 86 app_id_, profile_, extension); 87 88 extensions::RuntimeEventRouter::DispatchOnRestartRequiredEvent( 89 profile_, 90 app_id_, 91 extensions::core_api::runtime::OnRestartRequired::REASON_APP_UPDATE); 92 93 StartAppUpdateRestartTimer(); 94} 95 96void KioskAppUpdateService::OnRebootScheduled(Reason reason) { 97 extensions::core_api::runtime::OnRestartRequired::Reason restart_reason = 98 extensions::core_api::runtime::OnRestartRequired::REASON_NONE; 99 switch (reason) { 100 case REBOOT_REASON_OS_UPDATE: 101 restart_reason = 102 extensions::core_api::runtime::OnRestartRequired::REASON_OS_UPDATE; 103 break; 104 case REBOOT_REASON_PERIODIC: 105 restart_reason = 106 extensions::core_api::runtime::OnRestartRequired::REASON_PERIODIC; 107 break; 108 default: 109 NOTREACHED() << "Unknown reboot reason=" << reason; 110 return; 111 } 112 113 extensions::RuntimeEventRouter::DispatchOnRestartRequiredEvent( 114 profile_, app_id_, restart_reason); 115} 116 117void KioskAppUpdateService::WillDestroyAutomaticRebootManager() { 118 automatic_reboot_manager_->RemoveObserver(this); 119 automatic_reboot_manager_ = NULL; 120} 121 122void KioskAppUpdateService::OnKioskAppCacheUpdated(const std::string& app_id) { 123 if (app_id != app_id_) 124 return; 125 126 extensions::RuntimeEventRouter::DispatchOnRestartRequiredEvent( 127 profile_, 128 app_id_, 129 extensions::core_api::runtime::OnRestartRequired::REASON_APP_UPDATE); 130 131 StartAppUpdateRestartTimer(); 132} 133 134KioskAppUpdateServiceFactory::KioskAppUpdateServiceFactory() 135 : BrowserContextKeyedServiceFactory( 136 "KioskAppUpdateService", 137 BrowserContextDependencyManager::GetInstance()) { 138 DependsOn( 139 extensions::ExtensionsBrowserClient::Get()->GetExtensionSystemFactory()); 140} 141 142KioskAppUpdateServiceFactory::~KioskAppUpdateServiceFactory() { 143} 144 145// static 146KioskAppUpdateService* KioskAppUpdateServiceFactory::GetForProfile( 147 Profile* profile) { 148 // This should never be called unless we are running in forced app mode. 149 DCHECK(chrome::IsRunningInForcedAppMode()); 150 if (!chrome::IsRunningInForcedAppMode()) 151 return NULL; 152 153 return static_cast<KioskAppUpdateService*>( 154 GetInstance()->GetServiceForBrowserContext(profile, true)); 155} 156 157// static 158KioskAppUpdateServiceFactory* KioskAppUpdateServiceFactory::GetInstance() { 159 return Singleton<KioskAppUpdateServiceFactory>::get(); 160} 161 162KeyedService* KioskAppUpdateServiceFactory::BuildServiceInstanceFor( 163 content::BrowserContext* context) const { 164 return new KioskAppUpdateService( 165 Profile::FromBrowserContext(context), 166 g_browser_process->platform_part()->automatic_reboot_manager()); 167} 168 169} // namespace chromeos 170