Index: extensions/browser/api/power/power_api.cc |
diff --git a/extensions/browser/api/power/power_api.cc b/extensions/browser/api/power/power_api.cc |
index d731b9f6796e02260beff9166b22cdec9ea711f9..13dbbab161d6f12205e1408178e7535d008e91c2 100644 |
--- a/extensions/browser/api/power/power_api.cc |
+++ b/extensions/browser/api/power/power_api.cc |
@@ -4,24 +4,128 @@ |
#include "extensions/browser/api/power/power_api.h" |
-#include "extensions/browser/api/power/power_api_manager.h" |
+#include "base/bind.h" |
+#include "base/lazy_instance.h" |
+#include "extensions/browser/extension_registry.h" |
#include "extensions/common/api/power.h" |
+#include "extensions/common/extension.h" |
namespace extensions { |
+namespace { |
+ |
+const char kPowerSaveBlockerDescription[] = "extension"; |
+ |
+content::PowerSaveBlocker::PowerSaveBlockerType LevelToPowerSaveBlockerType( |
+ core_api::power::Level level) { |
+ switch (level) { |
+ case core_api::power::LEVEL_SYSTEM: |
+ return content::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension; |
+ case core_api::power::LEVEL_DISPLAY: // fallthrough |
+ case core_api::power::LEVEL_NONE: |
+ return content::PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep; |
+ } |
+ NOTREACHED() << "Unhandled level " << level; |
+ return content::PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep; |
+} |
+ |
+base::LazyInstance<BrowserContextKeyedAPIFactory<PowerAPI>> g_factory = |
+ LAZY_INSTANCE_INITIALIZER; |
+ |
+} // namespace |
+ |
bool PowerRequestKeepAwakeFunction::RunSync() { |
scoped_ptr<core_api::power::RequestKeepAwake::Params> params( |
core_api::power::RequestKeepAwake::Params::Create(*args_)); |
EXTENSION_FUNCTION_VALIDATE(params); |
EXTENSION_FUNCTION_VALIDATE(params->level != core_api::power::LEVEL_NONE); |
- PowerApiManager::Get(browser_context())->AddRequest( |
- extension_id(), params->level); |
+ PowerAPI::Get(browser_context())->AddRequest(extension_id(), params->level); |
return true; |
} |
bool PowerReleaseKeepAwakeFunction::RunSync() { |
- PowerApiManager::Get(browser_context())->RemoveRequest(extension_id()); |
+ PowerAPI::Get(browser_context())->RemoveRequest(extension_id()); |
return true; |
} |
+// static |
+PowerAPI* PowerAPI::Get(content::BrowserContext* context) { |
+ return BrowserContextKeyedAPIFactory<PowerAPI>::Get(context); |
+} |
+ |
+// static |
+BrowserContextKeyedAPIFactory<PowerAPI>* PowerAPI::GetFactoryInstance() { |
+ return g_factory.Pointer(); |
+} |
+ |
+void PowerAPI::AddRequest(const std::string& extension_id, |
+ core_api::power::Level level) { |
+ extension_levels_[extension_id] = level; |
+ UpdatePowerSaveBlocker(); |
+} |
+ |
+void PowerAPI::RemoveRequest(const std::string& extension_id) { |
+ extension_levels_.erase(extension_id); |
+ UpdatePowerSaveBlocker(); |
+} |
+ |
+void PowerAPI::SetCreateBlockerFunctionForTesting( |
+ CreateBlockerFunction function) { |
+ create_blocker_function_ = |
+ !function.is_null() ? function |
+ : base::Bind(&content::PowerSaveBlocker::Create); |
+} |
+ |
+void PowerAPI::OnExtensionUnloaded(content::BrowserContext* browser_context, |
+ const Extension* extension, |
+ UnloadedExtensionInfo::Reason reason) { |
+ RemoveRequest(extension->id()); |
+ UpdatePowerSaveBlocker(); |
+} |
+ |
+PowerAPI::PowerAPI(content::BrowserContext* context) |
+ : browser_context_(context), |
+ create_blocker_function_(base::Bind(&content::PowerSaveBlocker::Create)), |
+ current_level_(core_api::power::LEVEL_SYSTEM) { |
+ ExtensionRegistry::Get(browser_context_)->AddObserver(this); |
+} |
+ |
+PowerAPI::~PowerAPI() { |
+} |
+ |
+void PowerAPI::UpdatePowerSaveBlocker() { |
+ if (extension_levels_.empty()) { |
+ power_save_blocker_.reset(); |
+ return; |
+ } |
+ |
+ core_api::power::Level new_level = core_api::power::LEVEL_SYSTEM; |
+ for (ExtensionLevelMap::const_iterator it = extension_levels_.begin(); |
+ it != extension_levels_.end(); ++it) { |
+ if (it->second == core_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<content::PowerSaveBlocker> new_blocker( |
+ create_blocker_function_.Run(type, |
+ content::PowerSaveBlocker::kReasonOther, |
+ kPowerSaveBlockerDescription)); |
+ power_save_blocker_.swap(new_blocker); |
+ current_level_ = new_level; |
+ } |
+} |
+ |
+void PowerAPI::Shutdown() { |
+ // Unregister here rather than in the d'tor; otherwise this call will recreate |
+ // the already-deleted ExtensionRegistry. |
+ ExtensionRegistry::Get(browser_context_)->RemoveObserver(this); |
+ power_save_blocker_.reset(); |
+} |
+ |
} // namespace extensions |