// Copyright (c) 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chrome/browser/extensions/api/power/power_api_manager.h" #include "base/bind.h" #include "chrome/browser/chrome_notification_types.h" #include "content/public/browser/notification_service.h" #include "extensions/common/extension.h" namespace extensions { namespace { const char kPowerSaveBlockerReason[] = "extension"; content::PowerSaveBlocker::PowerSaveBlockerType LevelToPowerSaveBlockerType(api::power::Level level) { switch (level) { case api::power::LEVEL_SYSTEM: return content::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension; case api::power::LEVEL_DISPLAY: // fallthrough case api::power::LEVEL_NONE: return content::PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep; } NOTREACHED() << "Unhandled level " << level; return content::PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep; } } // namespace // static PowerApiManager* PowerApiManager::GetInstance() { return Singleton::get(); } void PowerApiManager::AddRequest(const std::string& extension_id, api::power::Level level) { extension_levels_[extension_id] = level; UpdatePowerSaveBlocker(); } void PowerApiManager::RemoveRequest(const std::string& extension_id) { extension_levels_.erase(extension_id); UpdatePowerSaveBlocker(); } void PowerApiManager::SetCreateBlockerFunctionForTesting( CreateBlockerFunction function) { create_blocker_function_ = !function.is_null() ? function : base::Bind(&content::PowerSaveBlocker::Create); } void PowerApiManager::Observe(int type, const content::NotificationSource& source, const content::NotificationDetails& details) { switch (type) { case chrome::NOTIFICATION_EXTENSION_UNLOADED: RemoveRequest(content::Details( details)->extension->id()); UpdatePowerSaveBlocker(); break; case chrome::NOTIFICATION_APP_TERMINATING: power_save_blocker_.reset(); break; default: NOTREACHED() << "Unexpected notification " << type; } } PowerApiManager::PowerApiManager() : create_blocker_function_(base::Bind(&content::PowerSaveBlocker::Create)), current_level_(api::power::LEVEL_SYSTEM) { registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, content::NotificationService::AllSources()); registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING, content::NotificationService::AllSources()); } PowerApiManager::~PowerApiManager() {} void PowerApiManager::UpdatePowerSaveBlocker() { if (extension_levels_.empty()) { power_save_blocker_.reset(); return; } api::power::Level new_level = api::power::LEVEL_SYSTEM; for (ExtensionLevelMap::const_iterator it = extension_levels_.begin(); it != extension_levels_.end(); ++it) { if (it->second == api::power::LEVEL_DISPLAY) new_level = it->second; } // If the level changed and we need to create a new blocker, do a swap // to ensure that there isn't a brief period where power management is // unblocked. if (!power_save_blocker_ || new_level != current_level_) { content::PowerSaveBlocker::PowerSaveBlockerType type = LevelToPowerSaveBlockerType(new_level); scoped_ptr new_blocker( create_blocker_function_.Run(type, kPowerSaveBlockerReason)); power_save_blocker_.swap(new_blocker); current_level_ = new_level; } } } // namespace extensions