Bug 1885489 - Part 5: Add SnapshotIterator::readInt32(). r=iain
[gecko.git] / dom / power / WakeLock.cpp
blobb381b3c6272cadbdcf83b6d52d34afb73e0a12d7
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "WakeLock.h"
8 #include "mozilla/dom/ContentParent.h"
9 #include "mozilla/dom/Event.h" // for Event
10 #include "mozilla/Hal.h"
11 #include "mozilla/HalWakeLock.h"
12 #include "nsError.h"
13 #include "mozilla/dom/Document.h"
14 #include "nsPIDOMWindow.h"
15 #include "nsIPropertyBag2.h"
17 using namespace mozilla::hal;
19 namespace mozilla::dom {
21 NS_INTERFACE_MAP_BEGIN(WakeLock)
22 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMEventListener)
23 NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
24 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
25 NS_INTERFACE_MAP_ENTRY(nsIWakeLock)
26 NS_INTERFACE_MAP_END
28 NS_IMPL_ADDREF(WakeLock)
29 NS_IMPL_RELEASE(WakeLock)
31 WakeLock::~WakeLock() {
32 DoUnlock();
33 DetachEventListener();
36 nsresult WakeLock::Init(const nsAString& aTopic, nsPIDOMWindowInner* aWindow) {
37 // Don't Init() a WakeLock twice.
38 MOZ_ASSERT(mTopic.IsEmpty());
40 if (aTopic.IsEmpty()) {
41 return NS_ERROR_INVALID_ARG;
44 mTopic.Assign(aTopic);
46 mWindow = do_GetWeakReference(aWindow);
48 /**
49 * Null windows are allowed. A wake lock without associated window
50 * is always considered invisible.
52 if (aWindow) {
53 nsCOMPtr<Document> doc = aWindow->GetExtantDoc();
54 NS_ENSURE_STATE(doc);
55 mHidden = doc->Hidden();
58 AttachEventListener();
59 DoLock();
61 return NS_OK;
64 void WakeLock::DoLock() {
65 if (!mLocked) {
66 // Change the flag immediately to prevent recursive reentering
67 mLocked = true;
69 hal::ModifyWakeLock(
70 mTopic, hal::WAKE_LOCK_ADD_ONE,
71 mHidden ? hal::WAKE_LOCK_ADD_ONE : hal::WAKE_LOCK_NO_CHANGE);
75 void WakeLock::DoUnlock() {
76 if (mLocked) {
77 // Change the flag immediately to prevent recursive reentering
78 mLocked = false;
80 hal::ModifyWakeLock(
81 mTopic, hal::WAKE_LOCK_REMOVE_ONE,
82 mHidden ? hal::WAKE_LOCK_REMOVE_ONE : hal::WAKE_LOCK_NO_CHANGE);
86 void WakeLock::AttachEventListener() {
87 if (nsCOMPtr<nsPIDOMWindowInner> window = do_QueryReferent(mWindow)) {
88 nsCOMPtr<Document> doc = window->GetExtantDoc();
89 if (doc) {
90 doc->AddSystemEventListener(u"visibilitychange"_ns, this,
91 /* useCapture = */ true,
92 /* wantsUntrusted = */ false);
94 nsCOMPtr<EventTarget> target = do_QueryInterface(window);
95 target->AddSystemEventListener(u"pagehide"_ns, this,
96 /* useCapture = */ true,
97 /* wantsUntrusted = */ false);
98 target->AddSystemEventListener(u"pageshow"_ns, this,
99 /* useCapture = */ true,
100 /* wantsUntrusted = */ false);
105 void WakeLock::DetachEventListener() {
106 if (nsCOMPtr<nsPIDOMWindowInner> window = do_QueryReferent(mWindow)) {
107 nsCOMPtr<Document> doc = window->GetExtantDoc();
108 if (doc) {
109 doc->RemoveSystemEventListener(u"visibilitychange"_ns, this,
110 /* useCapture = */ true);
111 nsCOMPtr<EventTarget> target = do_QueryInterface(window);
112 target->RemoveSystemEventListener(u"pagehide"_ns, this,
113 /* useCapture = */ true);
114 target->RemoveSystemEventListener(u"pageshow"_ns, this,
115 /* useCapture = */ true);
120 void WakeLock::Unlock(ErrorResult& aRv) {
122 * We throw NS_ERROR_DOM_INVALID_STATE_ERR on double unlock.
124 if (!mLocked) {
125 aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
126 return;
129 DoUnlock();
130 DetachEventListener();
133 void WakeLock::GetTopic(nsAString& aTopic) { aTopic.Assign(mTopic); }
135 NS_IMETHODIMP
136 WakeLock::HandleEvent(Event* aEvent) {
137 nsAutoString type;
138 aEvent->GetType(type);
140 if (type.EqualsLiteral("visibilitychange")) {
141 nsCOMPtr<Document> doc = do_QueryInterface(aEvent->GetTarget());
142 NS_ENSURE_STATE(doc);
144 bool oldHidden = mHidden;
145 mHidden = doc->Hidden();
147 if (mLocked && oldHidden != mHidden) {
148 hal::ModifyWakeLock(
149 mTopic, hal::WAKE_LOCK_NO_CHANGE,
150 mHidden ? hal::WAKE_LOCK_ADD_ONE : hal::WAKE_LOCK_REMOVE_ONE);
153 return NS_OK;
156 if (type.EqualsLiteral("pagehide")) {
157 DoUnlock();
158 return NS_OK;
161 if (type.EqualsLiteral("pageshow")) {
162 DoLock();
163 return NS_OK;
166 return NS_OK;
169 NS_IMETHODIMP
170 WakeLock::Unlock() {
171 ErrorResult error;
172 Unlock(error);
173 return error.StealNSResult();
176 nsPIDOMWindowInner* WakeLock::GetParentObject() const {
177 nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(mWindow);
178 return window;
181 } // namespace mozilla::dom