summaryrefslogtreecommitdiffstats
path: root/dom/power/PowerManagerService.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dom/power/PowerManagerService.cpp')
-rw-r--r--dom/power/PowerManagerService.cpp170
1 files changed, 170 insertions, 0 deletions
diff --git a/dom/power/PowerManagerService.cpp b/dom/power/PowerManagerService.cpp
new file mode 100644
index 0000000000..e957643d00
--- /dev/null
+++ b/dom/power/PowerManagerService.cpp
@@ -0,0 +1,170 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/dom/ContentParent.h"
+#include "mozilla/Hal.h"
+#include "mozilla/HalWakeLock.h"
+#include "mozilla/ClearOnShutdown.h"
+#include "mozilla/ModuleUtils.h"
+#include "mozilla/Preferences.h"
+#include "nsIDOMWakeLockListener.h"
+#include "PowerManagerService.h"
+#include "WakeLock.h"
+
+// For _exit().
+#ifdef XP_WIN
+# include <process.h>
+#else
+# include <unistd.h>
+#endif
+
+namespace mozilla::dom::power {
+
+using namespace hal;
+
+NS_IMPL_ISUPPORTS(PowerManagerService, nsIPowerManagerService)
+
+/* static */
+StaticRefPtr<PowerManagerService> PowerManagerService::sSingleton;
+
+/* static */
+already_AddRefed<PowerManagerService> PowerManagerService::GetInstance() {
+ if (!sSingleton) {
+ sSingleton = new PowerManagerService();
+ sSingleton->Init();
+ ClearOnShutdown(&sSingleton);
+ }
+
+ RefPtr<PowerManagerService> service = sSingleton.get();
+ return service.forget();
+}
+
+void PowerManagerService::Init() { RegisterWakeLockObserver(this); }
+
+PowerManagerService::~PowerManagerService() {
+ UnregisterWakeLockObserver(this);
+}
+
+void PowerManagerService::ComputeWakeLockState(
+ const WakeLockInformation& aWakeLockInfo, nsAString& aState) {
+ WakeLockState state = hal::ComputeWakeLockState(aWakeLockInfo.numLocks(),
+ aWakeLockInfo.numHidden());
+ switch (state) {
+ case WAKE_LOCK_STATE_UNLOCKED:
+ aState.AssignLiteral("unlocked");
+ break;
+ case WAKE_LOCK_STATE_HIDDEN:
+ aState.AssignLiteral("locked-background");
+ break;
+ case WAKE_LOCK_STATE_VISIBLE:
+ aState.AssignLiteral("locked-foreground");
+ break;
+ }
+}
+
+void PowerManagerService::Notify(const WakeLockInformation& aWakeLockInfo) {
+ nsAutoString state;
+ ComputeWakeLockState(aWakeLockInfo, state);
+
+ /**
+ * Copy the listeners list before we walk through the callbacks
+ * because the callbacks may install new listeners. We expect no
+ * more than one listener per window, so it shouldn't be too long.
+ */
+ const CopyableAutoTArray<nsCOMPtr<nsIDOMMozWakeLockListener>, 2> listeners =
+ mWakeLockListeners;
+
+ for (uint32_t i = 0; i < listeners.Length(); ++i) {
+ listeners[i]->Callback(aWakeLockInfo.topic(), state);
+ }
+}
+
+NS_IMETHODIMP
+PowerManagerService::AddWakeLockListener(nsIDOMMozWakeLockListener* aListener) {
+ if (mWakeLockListeners.Contains(aListener)) return NS_OK;
+
+ mWakeLockListeners.AppendElement(aListener);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PowerManagerService::RemoveWakeLockListener(
+ nsIDOMMozWakeLockListener* aListener) {
+ mWakeLockListeners.RemoveElement(aListener);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PowerManagerService::GetWakeLockState(const nsAString& aTopic,
+ nsAString& aState) {
+ WakeLockInformation info;
+ GetWakeLockInfo(aTopic, &info);
+
+ ComputeWakeLockState(info, aState);
+
+ return NS_OK;
+}
+
+already_AddRefed<WakeLock> PowerManagerService::NewWakeLock(
+ const nsAString& aTopic, nsPIDOMWindowInner* aWindow,
+ mozilla::ErrorResult& aRv) {
+ RefPtr<WakeLock> wakelock = new WakeLock();
+ aRv = wakelock->Init(aTopic, aWindow);
+ if (aRv.Failed()) {
+ return nullptr;
+ }
+
+ return wakelock.forget();
+}
+
+NS_IMETHODIMP
+PowerManagerService::NewWakeLock(const nsAString& aTopic,
+ mozIDOMWindow* aWindow,
+ nsIWakeLock** aWakeLock) {
+ mozilla::ErrorResult rv;
+ RefPtr<WakeLock> wakelock =
+ NewWakeLock(aTopic, nsPIDOMWindowInner::From(aWindow), rv);
+ if (rv.Failed()) {
+ return rv.StealNSResult();
+ }
+
+ wakelock.forget(aWakeLock);
+ return NS_OK;
+}
+
+} // namespace mozilla::dom::power
+
+NS_DEFINE_NAMED_CID(NS_POWERMANAGERSERVICE_CID);
+
+NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(
+ nsIPowerManagerService,
+ mozilla::dom::power::PowerManagerService::GetInstance)
+
+static const mozilla::Module::CIDEntry kPowerManagerCIDs[] = {
+ // clang-format off
+ { &kNS_POWERMANAGERSERVICE_CID, false, nullptr, nsIPowerManagerServiceConstructor, mozilla::Module::ALLOW_IN_GPU_RDD_AND_SOCKET_PROCESS },
+ { nullptr }
+ // clang-format on
+};
+
+static const mozilla::Module::ContractIDEntry kPowerManagerContracts[] = {
+ // clang-format off
+ { POWERMANAGERSERVICE_CONTRACTID, &kNS_POWERMANAGERSERVICE_CID, mozilla::Module::ALLOW_IN_GPU_RDD_AND_SOCKET_PROCESS },
+ { nullptr }
+ // clang-format on
+};
+
+// We mark the power module as being available in the GPU process because the
+// appshell depends on the power manager service.
+extern const mozilla::Module kPowerManagerModule = {
+ mozilla::Module::kVersion,
+ kPowerManagerCIDs,
+ kPowerManagerContracts,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ mozilla::Module::ALLOW_IN_GPU_RDD_AND_SOCKET_PROCESS};