1 : /* -*- Mode: C++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* This Source Code Form is subject to the terms of the Mozilla Public
3 : * License, v. 2.0. If a copy of the MPL was not distributed with this file,
4 : * You can obtain one at http://mozilla.org/MPL/2.0/. */
5 :
6 : #include "mozilla/Hal.h"
7 : #include "mozilla/HalWakeLock.h"
8 : #include "nsDOMClassInfoID.h"
9 : #include "nsDOMError.h"
10 : #include "nsIDOMWindow.h"
11 : #include "nsIDOMEvent.h"
12 : #include "nsIDOMDocument.h"
13 : #include "nsIDOMEventTarget.h"
14 : #include "nsPIDOMWindow.h"
15 : #include "PowerManager.h"
16 : #include "WakeLock.h"
17 :
18 : DOMCI_DATA(MozWakeLock, mozilla::dom::power::WakeLock)
19 :
20 : namespace mozilla {
21 : namespace dom {
22 : namespace power {
23 :
24 0 : NS_INTERFACE_MAP_BEGIN(WakeLock)
25 0 : NS_INTERFACE_MAP_ENTRY(nsIDOMMozWakeLock)
26 0 : NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMMozWakeLock)
27 0 : NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
28 0 : NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(MozWakeLock)
29 0 : NS_INTERFACE_MAP_END
30 :
31 0 : NS_IMPL_ADDREF(WakeLock)
32 0 : NS_IMPL_RELEASE(WakeLock)
33 :
34 0 : WakeLock::WakeLock()
35 : : mLocked(false)
36 0 : , mHidden(true)
37 : {
38 0 : }
39 :
40 0 : WakeLock::~WakeLock()
41 : {
42 0 : DoUnlock();
43 0 : DetachEventListener();
44 0 : }
45 :
46 : nsresult
47 0 : WakeLock::Init(const nsAString &aTopic, nsIDOMWindow *aWindow)
48 : {
49 0 : mTopic.Assign(aTopic);
50 :
51 0 : mWindow = do_GetWeakReference(aWindow);
52 0 : nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aWindow);
53 :
54 : /**
55 : * Null windows are allowed. A wake lock without associated window
56 : * is always considered invisible.
57 : */
58 0 : if (window) {
59 0 : nsCOMPtr<nsIDOMDocument> domDoc = window->GetExtantDocument();
60 0 : NS_ENSURE_STATE(domDoc);
61 0 : domDoc->GetMozHidden(&mHidden);
62 : }
63 :
64 0 : AttachEventListener();
65 0 : DoLock();
66 :
67 0 : return NS_OK;
68 : }
69 :
70 : void
71 0 : WakeLock::DoLock()
72 : {
73 0 : if (!mLocked) {
74 : // Change the flag immediately to prevent recursive reentering
75 0 : mLocked = true;
76 : hal::ModifyWakeLock(mTopic,
77 : hal::WAKE_LOCK_ADD_ONE,
78 0 : mHidden ? hal::WAKE_LOCK_ADD_ONE : hal::WAKE_LOCK_NO_CHANGE);
79 : }
80 0 : }
81 :
82 : void
83 0 : WakeLock::DoUnlock()
84 : {
85 0 : if (mLocked) {
86 : // Change the flag immediately to prevent recursive reentering
87 0 : mLocked = false;
88 : hal::ModifyWakeLock(mTopic,
89 : hal::WAKE_LOCK_REMOVE_ONE,
90 0 : mHidden ? hal::WAKE_LOCK_REMOVE_ONE : hal::WAKE_LOCK_NO_CHANGE);
91 : }
92 0 : }
93 :
94 : void
95 0 : WakeLock::AttachEventListener()
96 : {
97 0 : nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
98 :
99 0 : if (window) {
100 0 : nsCOMPtr<nsIDOMDocument> domDoc = window->GetExtantDocument();
101 0 : if (domDoc) {
102 0 : nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(domDoc);
103 0 : target->AddSystemEventListener(NS_LITERAL_STRING("mozvisibilitychange"),
104 : this,
105 : /* useCapture = */ true,
106 0 : /* wantsUntrusted = */ false);
107 :
108 0 : target = do_QueryInterface(window);
109 0 : target->AddSystemEventListener(NS_LITERAL_STRING("pagehide"),
110 : this,
111 : /* useCapture = */ true,
112 0 : /* wantsUntrusted = */ false);
113 0 : target->AddSystemEventListener(NS_LITERAL_STRING("pageshow"),
114 : this,
115 : /* useCapture = */ true,
116 0 : /* wantsUntrusted = */ false);
117 : }
118 : }
119 0 : }
120 :
121 : void
122 0 : WakeLock::DetachEventListener()
123 : {
124 0 : nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
125 :
126 0 : if (window) {
127 0 : nsCOMPtr<nsIDOMDocument> domDoc = window->GetExtantDocument();
128 0 : if (domDoc) {
129 0 : nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(domDoc);
130 0 : target->RemoveSystemEventListener(NS_LITERAL_STRING("mozvisibilitychange"),
131 : this,
132 0 : /* useCapture = */ true);
133 0 : target = do_QueryInterface(window);
134 0 : target->RemoveSystemEventListener(NS_LITERAL_STRING("pagehide"),
135 : this,
136 0 : /* useCapture = */ true);
137 0 : target->RemoveSystemEventListener(NS_LITERAL_STRING("pageshow"),
138 : this,
139 0 : /* useCapture = */ true);
140 : }
141 : }
142 0 : }
143 :
144 : NS_IMETHODIMP
145 0 : WakeLock::Unlock()
146 : {
147 : /*
148 : * We throw NS_ERROR_DOM_INVALID_STATE_ERR on double unlock.
149 : */
150 0 : if (!mLocked) {
151 0 : return NS_ERROR_DOM_INVALID_STATE_ERR;
152 : }
153 :
154 0 : DoUnlock();
155 0 : DetachEventListener();
156 :
157 0 : return NS_OK;
158 : }
159 :
160 : NS_IMETHODIMP
161 0 : WakeLock::GetTopic(nsAString &aTopic)
162 : {
163 0 : aTopic.Assign(mTopic);
164 0 : return NS_OK;
165 : }
166 :
167 : NS_IMETHODIMP
168 0 : WakeLock::HandleEvent(nsIDOMEvent *aEvent)
169 : {
170 0 : nsAutoString type;
171 0 : aEvent->GetType(type);
172 :
173 0 : if (type.EqualsLiteral("mozvisibilitychange")) {
174 0 : nsCOMPtr<nsIDOMEventTarget> target;
175 0 : aEvent->GetTarget(getter_AddRefs(target));
176 0 : nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(target);
177 0 : NS_ENSURE_STATE(domDoc);
178 0 : domDoc->GetMozHidden(&mHidden);
179 :
180 0 : if (mLocked) {
181 : hal::ModifyWakeLock(mTopic,
182 : hal::WAKE_LOCK_NO_CHANGE,
183 0 : mHidden ? hal::WAKE_LOCK_ADD_ONE : hal::WAKE_LOCK_REMOVE_ONE);
184 : }
185 :
186 0 : return NS_OK;
187 : }
188 :
189 0 : if (type.EqualsLiteral("pagehide")) {
190 0 : DoUnlock();
191 0 : return NS_OK;
192 : }
193 :
194 0 : if (type.EqualsLiteral("pageshow")) {
195 0 : DoLock();
196 0 : return NS_OK;
197 : }
198 :
199 0 : return NS_OK;
200 : }
201 :
202 : } // power
203 : } // dom
204 : } // mozilla
|