summaryrefslogtreecommitdiffstats
path: root/dom/power
diff options
context:
space:
mode:
Diffstat (limited to 'dom/power')
-rw-r--r--dom/power/PowerManagerService.cpp138
-rw-r--r--dom/power/PowerManagerService.h57
-rw-r--r--dom/power/WakeLock.cpp228
-rw-r--r--dom/power/WakeLock.h84
-rw-r--r--dom/power/components.conf17
-rw-r--r--dom/power/moz.build37
-rw-r--r--dom/power/nsIDOMWakeLockListener.idl29
-rw-r--r--dom/power/nsIPowerManagerService.idl32
-rw-r--r--dom/power/nsIWakeLock.idl12
9 files changed, 634 insertions, 0 deletions
diff --git a/dom/power/PowerManagerService.cpp b/dom/power/PowerManagerService.cpp
new file mode 100644
index 0000000000..ad3eadce8e
--- /dev/null
+++ b/dom/power/PowerManagerService.cpp
@@ -0,0 +1,138 @@
+/* -*- 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
diff --git a/dom/power/PowerManagerService.h b/dom/power/PowerManagerService.h
new file mode 100644
index 0000000000..1522342201
--- /dev/null
+++ b/dom/power/PowerManagerService.h
@@ -0,0 +1,57 @@
+/* -*- 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/. */
+#ifndef mozilla_dom_power_PowerManagerService_h
+#define mozilla_dom_power_PowerManagerService_h
+
+#include "nsCOMPtr.h"
+#include "nsHashKeys.h"
+#include "nsTArray.h"
+#include "nsIDOMWakeLockListener.h"
+#include "nsIPowerManagerService.h"
+#include "mozilla/HalWakeLockInformation.h"
+#include "mozilla/StaticPtr.h"
+#include "mozilla/dom/WakeLock.h"
+
+namespace mozilla::dom {
+
+class ContentParent;
+
+namespace power {
+
+class PowerManagerService : public nsIPowerManagerService,
+ public hal::WakeLockObserver {
+ public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIPOWERMANAGERSERVICE
+
+ PowerManagerService() = default;
+
+ static already_AddRefed<PowerManagerService> GetInstance();
+
+ void Init();
+
+ // Implement WakeLockObserver
+ void Notify(const hal::WakeLockInformation& aWakeLockInfo) override;
+
+ already_AddRefed<WakeLock> NewWakeLock(const nsAString& aTopic,
+ nsPIDOMWindowInner* aWindow,
+ mozilla::ErrorResult& aRv);
+
+ private:
+ ~PowerManagerService();
+
+ void ComputeWakeLockState(const hal::WakeLockInformation& aWakeLockInfo,
+ nsAString& aState);
+
+ static StaticRefPtr<PowerManagerService> sSingleton;
+
+ nsTArray<nsCOMPtr<nsIDOMMozWakeLockListener>> mWakeLockListeners;
+};
+
+} // namespace power
+} // namespace mozilla::dom
+
+#endif // mozilla_dom_power_PowerManagerService_h
diff --git a/dom/power/WakeLock.cpp b/dom/power/WakeLock.cpp
new file mode 100644
index 0000000000..bdfcfeaccd
--- /dev/null
+++ b/dom/power/WakeLock.cpp
@@ -0,0 +1,228 @@
+/* -*- 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 "WakeLock.h"
+#include "mozilla/dom/ContentParent.h"
+#include "mozilla/dom/Event.h" // for Event
+#include "mozilla/Hal.h"
+#include "mozilla/HalWakeLock.h"
+#include "nsError.h"
+#include "mozilla/dom/Document.h"
+#include "nsPIDOMWindow.h"
+#include "nsIPropertyBag2.h"
+
+using namespace mozilla::hal;
+
+namespace mozilla::dom {
+
+NS_INTERFACE_MAP_BEGIN(WakeLock)
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMEventListener)
+ NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
+ NS_INTERFACE_MAP_ENTRY(nsIObserver)
+ NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
+ NS_INTERFACE_MAP_ENTRY(nsIWakeLock)
+NS_INTERFACE_MAP_END
+
+NS_IMPL_ADDREF(WakeLock)
+NS_IMPL_RELEASE(WakeLock)
+
+WakeLock::WakeLock()
+ : mLocked(false),
+ mHidden(true),
+ mContentParentID(CONTENT_PROCESS_ID_UNKNOWN) {}
+
+WakeLock::~WakeLock() {
+ DoUnlock();
+ DetachEventListener();
+}
+
+nsresult WakeLock::Init(const nsAString& aTopic, nsPIDOMWindowInner* aWindow) {
+ // Don't Init() a WakeLock twice.
+ MOZ_ASSERT(mTopic.IsEmpty());
+
+ if (aTopic.IsEmpty()) {
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ mTopic.Assign(aTopic);
+
+ mWindow = do_GetWeakReference(aWindow);
+
+ /**
+ * Null windows are allowed. A wake lock without associated window
+ * is always considered invisible.
+ */
+ if (aWindow) {
+ nsCOMPtr<Document> doc = aWindow->GetExtantDoc();
+ NS_ENSURE_STATE(doc);
+ mHidden = IsDocumentInvisible(*doc);
+ }
+
+ AttachEventListener();
+ DoLock();
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+WakeLock::Observe(nsISupports* aSubject, const char* aTopic,
+ const char16_t* data) {
+ // If this wake lock was acquired on behalf of another process, unlock it
+ // when that process dies.
+ //
+ // Note that we do /not/ call DoUnlock() here! The wake lock back-end is
+ // already listening for ipc:content-shutdown messages and will clear out its
+ // tally for the process when it dies. All we need to do here is ensure that
+ // unlock() becomes a nop.
+
+ MOZ_ASSERT(!strcmp(aTopic, "ipc:content-shutdown"));
+
+ nsCOMPtr<nsIPropertyBag2> props = do_QueryInterface(aSubject);
+ if (!props) {
+ NS_WARNING("ipc:content-shutdown message without property bag as subject");
+ return NS_OK;
+ }
+
+ uint64_t childID = 0;
+ nsresult rv = props->GetPropertyAsUint64(u"childID"_ns, &childID);
+ if (NS_SUCCEEDED(rv)) {
+ if (childID == mContentParentID) {
+ mLocked = false;
+ }
+ } else {
+ NS_WARNING("ipc:content-shutdown message without childID property");
+ }
+ return NS_OK;
+}
+
+void WakeLock::DoLock() {
+ if (!mLocked) {
+ // Change the flag immediately to prevent recursive reentering
+ mLocked = true;
+
+ hal::ModifyWakeLock(
+ mTopic, hal::WAKE_LOCK_ADD_ONE,
+ mHidden ? hal::WAKE_LOCK_ADD_ONE : hal::WAKE_LOCK_NO_CHANGE,
+ mContentParentID);
+ }
+}
+
+void WakeLock::DoUnlock() {
+ if (mLocked) {
+ // Change the flag immediately to prevent recursive reentering
+ mLocked = false;
+
+ hal::ModifyWakeLock(
+ mTopic, hal::WAKE_LOCK_REMOVE_ONE,
+ mHidden ? hal::WAKE_LOCK_REMOVE_ONE : hal::WAKE_LOCK_NO_CHANGE,
+ mContentParentID);
+ }
+}
+
+void WakeLock::AttachEventListener() {
+ if (nsCOMPtr<nsPIDOMWindowInner> window = do_QueryReferent(mWindow)) {
+ nsCOMPtr<Document> doc = window->GetExtantDoc();
+ if (doc) {
+ doc->AddSystemEventListener(u"visibilitychange"_ns, this,
+ /* useCapture = */ true,
+ /* wantsUntrusted = */ false);
+
+ nsCOMPtr<EventTarget> target = do_QueryInterface(window);
+ target->AddSystemEventListener(u"pagehide"_ns, this,
+ /* useCapture = */ true,
+ /* wantsUntrusted = */ false);
+ target->AddSystemEventListener(u"pageshow"_ns, this,
+ /* useCapture = */ true,
+ /* wantsUntrusted = */ false);
+ }
+ }
+}
+
+void WakeLock::DetachEventListener() {
+ if (nsCOMPtr<nsPIDOMWindowInner> window = do_QueryReferent(mWindow)) {
+ nsCOMPtr<Document> doc = window->GetExtantDoc();
+ if (doc) {
+ doc->RemoveSystemEventListener(u"visibilitychange"_ns, this,
+ /* useCapture = */ true);
+ nsCOMPtr<EventTarget> target = do_QueryInterface(window);
+ target->RemoveSystemEventListener(u"pagehide"_ns, this,
+ /* useCapture = */ true);
+ target->RemoveSystemEventListener(u"pageshow"_ns, this,
+ /* useCapture = */ true);
+ }
+ }
+}
+
+void WakeLock::Unlock(ErrorResult& aRv) {
+ /*
+ * We throw NS_ERROR_DOM_INVALID_STATE_ERR on double unlock.
+ */
+ if (!mLocked) {
+ aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
+ return;
+ }
+
+ DoUnlock();
+ DetachEventListener();
+}
+
+void WakeLock::GetTopic(nsAString& aTopic) { aTopic.Assign(mTopic); }
+
+bool WakeLock::IsDocumentInvisible(const Document& aDocument) const {
+ // If document has a child element being used in the picture in picture
+ // mode, which is always visible to users, then we would consider the
+ // document as visible as well.
+ return aDocument.Hidden() && !aDocument.HasPictureInPictureChildElement();
+}
+
+NS_IMETHODIMP
+WakeLock::HandleEvent(Event* aEvent) {
+ nsAutoString type;
+ aEvent->GetType(type);
+
+ if (type.EqualsLiteral("visibilitychange")) {
+ nsCOMPtr<Document> doc = do_QueryInterface(aEvent->GetTarget());
+ NS_ENSURE_STATE(doc);
+
+ bool oldHidden = mHidden;
+ mHidden = IsDocumentInvisible(*doc);
+
+ if (mLocked && oldHidden != mHidden) {
+ hal::ModifyWakeLock(
+ mTopic, hal::WAKE_LOCK_NO_CHANGE,
+ mHidden ? hal::WAKE_LOCK_ADD_ONE : hal::WAKE_LOCK_REMOVE_ONE,
+ mContentParentID);
+ }
+
+ return NS_OK;
+ }
+
+ if (type.EqualsLiteral("pagehide")) {
+ DoUnlock();
+ return NS_OK;
+ }
+
+ if (type.EqualsLiteral("pageshow")) {
+ DoLock();
+ return NS_OK;
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+WakeLock::Unlock() {
+ ErrorResult error;
+ Unlock(error);
+ return error.StealNSResult();
+}
+
+nsPIDOMWindowInner* WakeLock::GetParentObject() const {
+ nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(mWindow);
+ return window;
+}
+
+} // namespace mozilla::dom
diff --git a/dom/power/WakeLock.h b/dom/power/WakeLock.h
new file mode 100644
index 0000000000..0ccf5c81fd
--- /dev/null
+++ b/dom/power/WakeLock.h
@@ -0,0 +1,84 @@
+/* -*- 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/. */
+
+#ifndef mozilla_dom_power_WakeLock_h
+#define mozilla_dom_power_WakeLock_h
+
+#include "nsCOMPtr.h"
+#include "nsIDOMEventListener.h"
+#include "nsIObserver.h"
+#include "nsIWakeLock.h"
+#include "nsString.h"
+#include "nsWeakReference.h"
+#include "nsWrapperCache.h"
+
+class nsPIDOMWindowInner;
+
+namespace mozilla {
+class ErrorResult;
+
+namespace dom {
+class Document;
+
+class WakeLock final : public nsIDOMEventListener,
+ public nsIObserver,
+ public nsSupportsWeakReference,
+ public nsIWakeLock {
+ public:
+ NS_DECL_NSIDOMEVENTLISTENER
+ NS_DECL_NSIOBSERVER
+ NS_DECL_NSIWAKELOCK
+
+ NS_DECL_ISUPPORTS
+
+ // Note: WakeLock lives for the lifetime of the document in order to avoid
+ // exposing GC behavior to pages. This means that
+ // |var foo = navigator.requestWakeLock('cpu'); foo = null;|
+ // doesn't unlock the 'cpu' resource.
+
+ WakeLock();
+
+ // Initialize this wake lock on behalf of the given window. Null windows are
+ // allowed; a lock without an associated window is always considered
+ // invisible.
+ nsresult Init(const nsAString& aTopic, nsPIDOMWindowInner* aWindow);
+
+ // WebIDL methods
+
+ nsPIDOMWindowInner* GetParentObject() const;
+
+ void GetTopic(nsAString& aTopic);
+
+ void Unlock(ErrorResult& aRv);
+
+ private:
+ virtual ~WakeLock();
+
+ void DoUnlock();
+ void DoLock();
+ void AttachEventListener();
+ void DetachEventListener();
+
+ // Return true if all parts of the given document are regarded as invisible.
+ bool IsDocumentInvisible(const Document& aDocument) const;
+
+ bool mLocked;
+ bool mHidden;
+
+ // The ID of the ContentParent on behalf of whom we acquired this lock, or
+ // CONTENT_PROCESS_UNKNOWN_ID if this lock was acquired on behalf of the
+ // current process.
+ uint64_t mContentParentID;
+ nsString mTopic;
+
+ // window that this was created for. Weak reference.
+ nsWeakPtr mWindow;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_power_WakeLock_h
diff --git a/dom/power/components.conf b/dom/power/components.conf
new file mode 100644
index 0000000000..0d09757f8d
--- /dev/null
+++ b/dom/power/components.conf
@@ -0,0 +1,17 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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/.
+
+Classes = [
+ {
+ 'cid': '{18c2e238-3a0a-4153-89fc-166b3b1465a1}',
+ 'contract_ids': ['@mozilla.org/power/powermanagerservice;1'],
+ 'type': 'mozilla::dom::power::PowerManagerService',
+ 'constructor': 'mozilla::dom::power::PowerManagerService::GetInstance',
+ 'headers': ['mozilla/dom/power/PowerManagerService.h'],
+ 'singleton': True,
+ 'processes': ProcessSelector.ALLOW_IN_GPU_RDD_AND_SOCKET_PROCESS,
+ },
+]
diff --git a/dom/power/moz.build b/dom/power/moz.build
new file mode 100644
index 0000000000..9c9bae638b
--- /dev/null
+++ b/dom/power/moz.build
@@ -0,0 +1,37 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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/.
+
+with Files("**"):
+ BUG_COMPONENT = ("Core", "DOM: Core & HTML")
+
+XPIDL_SOURCES += [
+ "nsIDOMWakeLockListener.idl",
+ "nsIPowerManagerService.idl",
+ "nsIWakeLock.idl",
+]
+
+XPIDL_MODULE = "dom_power"
+
+XPCOM_MANIFESTS += [
+ "components.conf",
+]
+
+EXPORTS.mozilla.dom += [
+ "WakeLock.h",
+]
+
+EXPORTS.mozilla.dom.power += [
+ "PowerManagerService.h",
+]
+
+UNIFIED_SOURCES += [
+ "PowerManagerService.cpp",
+ "WakeLock.cpp",
+]
+
+include("/ipc/chromium/chromium-config.mozbuild")
+
+FINAL_LIBRARY = "xul"
diff --git a/dom/power/nsIDOMWakeLockListener.idl b/dom/power/nsIDOMWakeLockListener.idl
new file mode 100644
index 0000000000..366e9cf594
--- /dev/null
+++ b/dom/power/nsIDOMWakeLockListener.idl
@@ -0,0 +1,29 @@
+/* -*- Mode: C++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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 "nsISupports.idl"
+
+[scriptable, function, uuid(4e258af8-cffb-47bc-b16d-e8241243426e)]
+interface nsIDOMMozWakeLockListener : nsISupports
+{
+ /**
+ * The callback will be called when a lock topic changes its lock
+ * state.
+ *
+ * Possible states are:
+ *
+ * - "unlocked" - nobody holds the wake lock.
+ *
+ * - "locked-foreground" - at least one window holds the wake lock,
+ * and it is visible.
+ *
+ * - "locked-background" - at least one window holds the wake lock,
+ * but all of them are hidden.
+ *
+ * @param aTopic The resource name related to the wake lock.
+ * @param aState The wake lock state
+ */
+ void callback(in AString aTopic, in AString aState);
+};
diff --git a/dom/power/nsIPowerManagerService.idl b/dom/power/nsIPowerManagerService.idl
new file mode 100644
index 0000000000..3fef3de9a3
--- /dev/null
+++ b/dom/power/nsIPowerManagerService.idl
@@ -0,0 +1,32 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* 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 "nsISupports.idl"
+
+%{C++
+#define POWERMANAGERSERVICE_CONTRACTID "@mozilla.org/power/powermanagerservice;1"
+%}
+
+interface nsIDOMMozWakeLockListener;
+interface mozIDOMWindow;
+interface nsIWakeLock;
+
+/**
+ * For use with non-content code.
+ */
+[scriptable, builtinclass, uuid(ba7ca4c1-9d92-4425-a83b-85dd7fa953f7)]
+interface nsIPowerManagerService : nsISupports
+{
+ void addWakeLockListener(in nsIDOMMozWakeLockListener aListener);
+ void removeWakeLockListener(in nsIDOMMozWakeLockListener aListener);
+ AString getWakeLockState(in AString aTopic);
+
+ /**
+ * Return a wake lock (MozWakeLock) object of aTopic associated with aWindow.
+ * A wake lock without associated window, e.g. used in chrome, is
+ * always considered invisible.
+ */
+ nsIWakeLock newWakeLock(in AString aTopic, [optional] in mozIDOMWindow aWindow);
+};
diff --git a/dom/power/nsIWakeLock.idl b/dom/power/nsIWakeLock.idl
new file mode 100644
index 0000000000..5ebc158109
--- /dev/null
+++ b/dom/power/nsIWakeLock.idl
@@ -0,0 +1,12 @@
+/* -*- Mode: C++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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 "nsISupports.idl"
+
+[scriptable, builtinclass, uuid(e27e57ce-fa63-4035-b9ef-27c5dc0cc3ae)]
+interface nsIWakeLock : nsISupports
+{
+ void unlock();
+};