1 // Copyright (c) 2012 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/screensaver/screensaver_controller.h" 6 7 #include "ash/screensaver/screensaver_view.h" 8 #include "ash/shell.h" 9 #include "ash/wm/user_activity_detector.h" 10 #include "base/bind.h" 11 #include "base/callback.h" 12 #include "base/logging.h" 13 #include "chrome/browser/chrome_notification_types.h" 14 #include "chrome/browser/extensions/extension_service.h" 15 #include "chrome/browser/extensions/extension_system.h" 16 #include "chrome/browser/profiles/profile_manager.h" 17 #include "chrome/common/extensions/extension.h" 18 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h" 19 #include "chromeos/dbus/dbus_thread_manager.h" 20 #include "chromeos/dbus/power_manager_client.h" 21 #include "content/public/browser/notification_service.h" 22 23 namespace { 24 25 const int kScreensaverTimeoutMinutes = 2; 26 27 ExtensionService* GetDefaultExtensionService() { 28 Profile* default_profile = ProfileManager::GetDefaultProfile(); 29 DCHECK(default_profile); 30 ExtensionService* service = 31 extensions::ExtensionSystem::Get(default_profile)->extension_service(); 32 DCHECK(service); 33 34 return service; 35 } 36 37 // Find the screensaver extension for the given service, excluding 38 // the one with exclude_id. 39 std::string FindScreensaverExtension(ExtensionService* service, 40 const std::string& exclude_id) { 41 const ExtensionSet* extensions = service->extensions(); 42 if (!extensions) 43 return std::string(); 44 45 for (ExtensionSet::const_iterator it = extensions->begin(); 46 it != extensions->end(); 47 ++it) { 48 const extensions::Extension* extension = it->get(); 49 if (extension && 50 extension->id() != exclude_id && 51 extension->HasAPIPermission(extensions::APIPermission::kScreensaver)) { 52 return extension->id(); 53 } 54 } 55 56 return std::string(); 57 } 58 59 void UninstallPreviousScreensavers(const extensions::Extension* current) { 60 Profile* default_profile = ProfileManager::GetDefaultProfile(); 61 DCHECK(default_profile); 62 ExtensionService* service = 63 extensions::ExtensionSystem::Get(default_profile)->extension_service(); 64 DCHECK(service); 65 66 std::string screensaver_id; 67 while ((screensaver_id = FindScreensaverExtension(service, current->id())) 68 != "") { 69 string16 error; 70 if (!service->UninstallExtension(screensaver_id, false, &error)) 71 LOG(ERROR) 72 << "Couldn't uninstall previous screensaver extension with id: " 73 << screensaver_id << " \nError: " << error; 74 } 75 } 76 77 } // namespace 78 79 namespace chromeos { 80 81 ScreensaverController::ScreensaverController() 82 : threshold_(base::TimeDelta::FromMinutes(kScreensaverTimeoutMinutes)), 83 weak_ptr_factory_(this) { 84 // Register for extension changes. 85 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED, 86 content::NotificationService::AllSources()); 87 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, 88 content::NotificationService::AllSources()); 89 90 std::string screensaver_extension_id = 91 FindScreensaverExtension(GetDefaultExtensionService(), std::string()); 92 if (!screensaver_extension_id.empty()) 93 SetupScreensaver(screensaver_extension_id); 94 } 95 96 ScreensaverController::~ScreensaverController() { 97 TeardownScreensaver(); 98 } 99 100 void ScreensaverController::Observe( 101 int type, 102 const content::NotificationSource& source, 103 const content::NotificationDetails& details) { 104 switch (type) { 105 case chrome::NOTIFICATION_EXTENSION_INSTALLED: { 106 const extensions::Extension* extension = 107 content::Details<const extensions::InstalledExtensionInfo>(details)-> 108 extension; 109 // Uninstall any previously installed screensaver extensions if a new 110 // screensaver extension is installed. 111 if (extension->HasAPIPermission(extensions::APIPermission::kScreensaver)) 112 UninstallPreviousScreensavers(extension); 113 break; 114 } 115 case chrome::NOTIFICATION_EXTENSION_LOADED: { 116 const extensions::Extension* extension = 117 content::Details<const extensions::Extension>(details).ptr(); 118 if (extension->HasAPIPermission(extensions::APIPermission::kScreensaver)) 119 SetupScreensaver(extension->id()); 120 break; 121 } 122 case chrome::NOTIFICATION_EXTENSION_UNLOADED: { 123 const extensions::Extension* extension = 124 content::Details<extensions::UnloadedExtensionInfo>( 125 details)->extension; 126 if (extension->id() == screensaver_extension_id_) 127 TeardownScreensaver(); 128 break; 129 } 130 } 131 } 132 133 void ScreensaverController::IdleNotify(int64 threshold) { 134 ExtensionService* service = GetDefaultExtensionService(); 135 const extensions::Extension* screensaver_extension = 136 service->GetExtensionById(screensaver_extension_id_, 137 ExtensionService::INCLUDE_ENABLED); 138 ash::ShowScreensaver( 139 extensions::AppLaunchInfo::GetFullLaunchURL(screensaver_extension)); 140 141 if (!ash::Shell::GetInstance()->user_activity_detector()->HasObserver(this)) 142 ash::Shell::GetInstance()->user_activity_detector()->AddObserver(this); 143 } 144 145 void ScreensaverController::OnUserActivity(const ui::Event* event) { 146 // We don't want to handle further user notifications; we'll either login 147 // the user and close out or or at least close the screensaver. 148 if (ash::Shell::GetInstance()->user_activity_detector()->HasObserver(this)) 149 ash::Shell::GetInstance()->user_activity_detector()->RemoveObserver(this); 150 ash::CloseScreensaver(); 151 152 RequestNextIdleNotification(); 153 } 154 155 void ScreensaverController::SetupScreensaver( 156 const std::string& screensaver_extension_id) { 157 screensaver_extension_id_ = screensaver_extension_id; 158 159 PowerManagerClient* power_manager = 160 DBusThreadManager::Get()->GetPowerManagerClient(); 161 if (!power_manager->HasObserver(this)) 162 power_manager->AddObserver(this); 163 164 RequestNextIdleNotification(); 165 } 166 167 void ScreensaverController::TeardownScreensaver() { 168 PowerManagerClient* power_manager = 169 DBusThreadManager::Get()->GetPowerManagerClient(); 170 if (power_manager && power_manager->HasObserver(this)) 171 power_manager->RemoveObserver(this); 172 173 if (ash::Shell::GetInstance() && 174 ash::Shell::GetInstance()->user_activity_detector()->HasObserver(this)) { 175 ash::Shell::GetInstance()->user_activity_detector()->RemoveObserver(this); 176 } 177 178 ash::CloseScreensaver(); 179 screensaver_extension_id_ = ""; 180 } 181 182 void ScreensaverController::RequestNextIdleNotification() { 183 DBusThreadManager::Get()->GetPowerManagerClient()-> 184 RequestIdleNotification(threshold_.InMilliseconds()); 185 } 186 187 } // namespace chromeos 188