Home | History | Annotate | Download | only in screensaver
      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