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