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/. */
8 #include "mozilla/dom/ContentParent.h"
9 #include "mozilla/dom/Event.h" // for Event
10 #include "mozilla/Hal.h"
11 #include "mozilla/HalWakeLock.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
)
28 NS_IMPL_ADDREF(WakeLock
)
29 NS_IMPL_RELEASE(WakeLock
)
31 WakeLock::~WakeLock() {
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
);
49 * Null windows are allowed. A wake lock without associated window
50 * is always considered invisible.
53 nsCOMPtr
<Document
> doc
= aWindow
->GetExtantDoc();
55 mHidden
= doc
->Hidden();
58 AttachEventListener();
64 void WakeLock::DoLock() {
66 // Change the flag immediately to prevent recursive reentering
70 mTopic
, hal::WAKE_LOCK_ADD_ONE
,
71 mHidden
? hal::WAKE_LOCK_ADD_ONE
: hal::WAKE_LOCK_NO_CHANGE
);
75 void WakeLock::DoUnlock() {
77 // Change the flag immediately to prevent recursive reentering
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();
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();
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.
125 aRv
.Throw(NS_ERROR_DOM_INVALID_STATE_ERR
);
130 DetachEventListener();
133 void WakeLock::GetTopic(nsAString
& aTopic
) { aTopic
.Assign(mTopic
); }
136 WakeLock::HandleEvent(Event
* aEvent
) {
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
) {
149 mTopic
, hal::WAKE_LOCK_NO_CHANGE
,
150 mHidden
? hal::WAKE_LOCK_ADD_ONE
: hal::WAKE_LOCK_REMOVE_ONE
);
156 if (type
.EqualsLiteral("pagehide")) {
161 if (type
.EqualsLiteral("pageshow")) {
173 return error
.StealNSResult();
176 nsPIDOMWindowInner
* WakeLock::GetParentObject() const {
177 nsCOMPtr
<nsPIDOMWindowInner
> window
= do_QueryInterface(mWindow
);
181 } // namespace mozilla::dom