Chromium Code Reviews| Index: chrome/browser/chromeos/screensaver/screensaver_controller.cc |
| diff --git a/chrome/browser/chromeos/screensaver/screensaver_controller.cc b/chrome/browser/chromeos/screensaver/screensaver_controller.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..ca3c71e7a974c6e21baecf47b2eb9f3f28439b3b |
| --- /dev/null |
| +++ b/chrome/browser/chromeos/screensaver/screensaver_controller.cc |
| @@ -0,0 +1,181 @@ |
| +// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
|
Matt Perry
2013/01/31 00:37:23
We have other systems that only support 1 active e
rkc
2013/01/31 02:15:46
So I spoke with Josh (the PM for this feature) and
Matt Perry
2013/01/31 22:43:51
OK, that seems fair.
|
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "chrome/browser/chromeos/screensaver/screensaver_controller.h" |
| + |
| +#include "ash/screensaver/screensaver_view.h" |
| +#include "ash/shell.h" |
| +#include "ash/wm/user_activity_detector.h" |
| +#include "base/bind.h" |
| +#include "base/callback.h" |
| +#include "base/logging.h" |
| +#include "chrome/browser/extensions/extension_service.h" |
| +#include "chrome/browser/extensions/extension_system.h" |
| +#include "chrome/browser/profiles/profile_manager.h" |
| +#include "chrome/common/chrome_notification_types.h" |
| +#include "chrome/common/extensions/extension.h" |
| +#include "chromeos/dbus/dbus_thread_manager.h" |
| +#include "chromeos/dbus/power_manager_client.h" |
| +#include "content/public/browser/notification_service.h" |
| + |
| +namespace { |
| + |
| +const int kScreensaverTimeoutMs = 120000; |
|
Matt Perry
2013/01/31 00:37:23
nit: could specify this in minutes, and use TimeDe
rkc
2013/01/31 02:15:46
Done.
|
| + |
| +ExtensionService* GetDefaultExtensionService() { |
| + Profile* default_profile = ProfileManager::GetDefaultProfile(); |
|
Matt Perry
2013/01/31 00:37:23
This is generally a bad thing to do... But maybe i
rkc
2013/01/31 02:15:46
The default profile on ChromeOS will always be you
|
| + DCHECK(default_profile); |
| + ExtensionService* service = |
| + extensions::ExtensionSystem::Get(default_profile)->extension_service(); |
| + DCHECK(service); |
| + |
| + return service; |
| +} |
| + |
| +// Find the screensaver extension for the given service, excluding |
| +// the one with exclude_id. |
| +std::string FindScreensaverExtension(ExtensionService* service, |
| + const std::string& exclude_id) { |
| + const ExtensionSet* extensions = service->extensions(); |
| + if (!extensions) |
| + return std::string(); |
| + |
| + for (ExtensionSet::const_iterator it = extensions->begin(); |
| + it != extensions->end(); |
| + ++it) { |
| + const extensions::Extension* extension = *it; |
| + if (extension && |
| + extension->id() != exclude_id && |
| + extension->HasAPIPermission(extensions::APIPermission::kScreensaver)) |
| + return extension->id(); |
| + } |
| + |
| + return std::string(); |
| +} |
| + |
| +void UninstallPreviousScreensavers(const extensions::Extension* current) { |
| + Profile* default_profile = ProfileManager::GetDefaultProfile(); |
| + DCHECK(default_profile); |
| + ExtensionService* service = |
| + extensions::ExtensionSystem::Get(default_profile)->extension_service(); |
| + DCHECK(service); |
| + |
| + std::string screensaver_id; |
| + while (!(screensaver_id = FindScreensaverExtension(service, |
| + current->id())).empty()) { |
|
Matt Perry
2013/01/31 00:37:23
indent
rkc
2013/01/31 02:15:46
Done.
Matt Perry
2013/01/31 22:43:51
(FYI I just meant that curret_id should be 1 space
|
| + string16 error; |
| + if (!service->UninstallExtension(screensaver_id, false, &error)) |
| + LOG(ERROR) << |
| + "Couldn't uninstall previous screensaver extension with id: " << |
| + screensaver_id << " \nError: " << error; |
| + } |
| +} |
| + |
| +} // namespace |
| + |
| +namespace chromeos { |
| + |
| +ScreensaverController::ScreensaverController() |
| + : threshold_(base::TimeDelta::FromMilliseconds(kScreensaverTimeoutMs)), |
| + weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { |
| + // Register for extension changes. |
| + registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED, |
| + content::NotificationService::AllSources()); |
| + registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, |
| + content::NotificationService::AllSources()); |
| + |
| + std::string screensaver_extension_id = |
| + FindScreensaverExtension(GetDefaultExtensionService(), std::string()); |
| + if (!screensaver_extension_id.empty()) |
| + SetupScreensaver(screensaver_extension_id); |
| +} |
| + |
| +ScreensaverController::~ScreensaverController() { |
| + TeardownScreensaver(); |
| +} |
| + |
| +void ScreensaverController::Observe( |
| + int type, |
| + const content::NotificationSource& source, |
| + const content::NotificationDetails& details) { |
| + switch (type) { |
| + case chrome::NOTIFICATION_EXTENSION_INSTALLED: { |
| + const extensions::Extension* extension = |
| + content::Details<const extensions::Extension>(details).ptr(); |
| + |
| + // Uninstall any previously installed screensaver extensions. |
| + UninstallPreviousScreensavers(extension); |
|
Matt Perry
2013/01/31 00:37:23
I think you mean to do this only if |extension| is
rkc
2013/01/31 02:15:46
Whoops, yes, this will just unload any previous sc
|
| + break; |
| + } |
| + case chrome::NOTIFICATION_EXTENSION_LOADED: { |
| + const extensions::Extension* extension = |
| + content::Details<const extensions::Extension>(details).ptr(); |
| + if (!extension->HasAPIPermission(extensions::APIPermission::kScreensaver)) |
| + return; |
|
Matt Perry
2013/01/31 00:37:23
indent
rkc
2013/01/31 02:15:46
Done.
|
| + |
| + SetupScreensaver(extension->id()); |
| + break; |
| + } |
| + case chrome::NOTIFICATION_EXTENSION_UNLOADED: { |
| + const extensions::Extension* extension = |
| + content::Details<extensions::UnloadedExtensionInfo>( |
| + details)->extension; |
| + if (extension->HasAPIPermission(extensions::APIPermission::kScreensaver)) |
|
Matt Perry
2013/01/31 00:37:23
might be clearer to just test if the id matches sc
rkc
2013/01/31 02:15:46
Done.
|
| + TeardownScreensaver(); |
| + break; |
| + } |
| + } |
| +} |
| + |
| +void ScreensaverController::IdleNotify(int64 threshold) { |
| + ExtensionService* service = GetDefaultExtensionService(); |
| + const extensions::Extension* screensaver_extension = |
| + service->GetExtensionById(screensaver_extension_id_, |
| + ExtensionService::INCLUDE_ENABLED); |
| + ash::ShowScreensaver(screensaver_extension->GetFullLaunchURL()); |
|
Matt Perry
2013/01/31 00:37:23
interesting.. so a screensaver is just an app with
rkc
2013/01/31 02:15:46
Yep, that's how the screensaver is implemented in
|
| + |
| + ash::Shell::GetInstance()->user_activity_detector()->AddObserver(this); |
| +} |
| + |
| +void ScreensaverController::OnUserActivity() { |
| + // We don't want to handle further user notifications; we'll either login |
| + // the user and close out or or at least close the screensaver. |
| + ash::Shell::GetInstance()->user_activity_detector()->RemoveObserver(this); |
| + ash::CloseScreensaver(); |
| + |
| + RequestNextIdleNotification(); |
| +} |
| + |
| +void ScreensaverController::SetupScreensaver( |
| + const std::string& screensaver_extension_id) { |
| + screensaver_extension_id_ = screensaver_extension_id; |
| + |
| + PowerManagerClient* power_manager = |
| + DBusThreadManager::Get()->GetPowerManagerClient(); |
| + if (!power_manager->HasObserver(this)) |
| + power_manager->AddObserver(this); |
| + |
| + RequestNextIdleNotification(); |
| +} |
| + |
| +void ScreensaverController::TeardownScreensaver() { |
| + PowerManagerClient* power_manager = |
| + DBusThreadManager::Get()->GetPowerManagerClient(); |
| + if (power_manager && power_manager->HasObserver(this)) |
| + power_manager->RemoveObserver(this); |
| + |
| + if (ash::Shell::GetInstance() && |
| + ash::Shell::GetInstance()->user_activity_detector()->HasObserver(this)) |
| + ash::Shell::GetInstance()->user_activity_detector()->RemoveObserver(this); |
| + |
| + ash::CloseScreensaver(); |
| + screensaver_extension_id_ = ""; |
| +} |
| + |
| +void ScreensaverController::RequestNextIdleNotification() { |
| + DBusThreadManager::Get()->GetPowerManagerClient()-> |
| + RequestIdleNotification(kScreensaverTimeoutMs); |
| +} |
| + |
| +} // namespace chromeos |