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
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #include "mozilla/dom/ContentParent.h"
8 #include "mozilla/Hal.h"
9 #include "mozilla/HalWakeLock.h"
10 #include "mozilla/ClearOnShutdown.h"
11 #include "mozilla/ModuleUtils.h"
12 #include "mozilla/Preferences.h"
13 #include "nsIDOMWakeLockListener.h"
14 #include "PowerManagerService.h"
15 #include "WakeLock.h"
16
17 // For _exit().
18 #ifdef XP_WIN
19 # include <process.h>
20 #else
21 # include <unistd.h>
22 #endif
23
24 namespace mozilla::dom::power {
25
26 using namespace hal;
27
28 NS_IMPL_ISUPPORTS(PowerManagerService, nsIPowerManagerService)
29
30 /* static */
31 StaticRefPtr<PowerManagerService> PowerManagerService::sSingleton;
32
33 /* static */
GetInstance()34 already_AddRefed<PowerManagerService> PowerManagerService::GetInstance() {
35 if (!sSingleton) {
36 sSingleton = new PowerManagerService();
37 sSingleton->Init();
38 ClearOnShutdown(&sSingleton);
39 }
40
41 RefPtr<PowerManagerService> service = sSingleton.get();
42 return service.forget();
43 }
44
Init()45 void PowerManagerService::Init() { RegisterWakeLockObserver(this); }
46
~PowerManagerService()47 PowerManagerService::~PowerManagerService() {
48 UnregisterWakeLockObserver(this);
49 }
50
ComputeWakeLockState(const WakeLockInformation & aWakeLockInfo,nsAString & aState)51 void PowerManagerService::ComputeWakeLockState(
52 const WakeLockInformation& aWakeLockInfo, nsAString& aState) {
53 WakeLockState state = hal::ComputeWakeLockState(aWakeLockInfo.numLocks(),
54 aWakeLockInfo.numHidden());
55 switch (state) {
56 case WAKE_LOCK_STATE_UNLOCKED:
57 aState.AssignLiteral("unlocked");
58 break;
59 case WAKE_LOCK_STATE_HIDDEN:
60 aState.AssignLiteral("locked-background");
61 break;
62 case WAKE_LOCK_STATE_VISIBLE:
63 aState.AssignLiteral("locked-foreground");
64 break;
65 }
66 }
67
Notify(const WakeLockInformation & aWakeLockInfo)68 void PowerManagerService::Notify(const WakeLockInformation& aWakeLockInfo) {
69 nsAutoString state;
70 ComputeWakeLockState(aWakeLockInfo, state);
71
72 /**
73 * Copy the listeners list before we walk through the callbacks
74 * because the callbacks may install new listeners. We expect no
75 * more than one listener per window, so it shouldn't be too long.
76 */
77 const CopyableAutoTArray<nsCOMPtr<nsIDOMMozWakeLockListener>, 2> listeners =
78 mWakeLockListeners;
79
80 for (uint32_t i = 0; i < listeners.Length(); ++i) {
81 listeners[i]->Callback(aWakeLockInfo.topic(), state);
82 }
83 }
84
85 NS_IMETHODIMP
AddWakeLockListener(nsIDOMMozWakeLockListener * aListener)86 PowerManagerService::AddWakeLockListener(nsIDOMMozWakeLockListener* aListener) {
87 if (mWakeLockListeners.Contains(aListener)) return NS_OK;
88
89 mWakeLockListeners.AppendElement(aListener);
90 return NS_OK;
91 }
92
93 NS_IMETHODIMP
RemoveWakeLockListener(nsIDOMMozWakeLockListener * aListener)94 PowerManagerService::RemoveWakeLockListener(
95 nsIDOMMozWakeLockListener* aListener) {
96 mWakeLockListeners.RemoveElement(aListener);
97 return NS_OK;
98 }
99
100 NS_IMETHODIMP
GetWakeLockState(const nsAString & aTopic,nsAString & aState)101 PowerManagerService::GetWakeLockState(const nsAString& aTopic,
102 nsAString& aState) {
103 WakeLockInformation info;
104 GetWakeLockInfo(aTopic, &info);
105
106 ComputeWakeLockState(info, aState);
107
108 return NS_OK;
109 }
110
NewWakeLock(const nsAString & aTopic,nsPIDOMWindowInner * aWindow,mozilla::ErrorResult & aRv)111 already_AddRefed<WakeLock> PowerManagerService::NewWakeLock(
112 const nsAString& aTopic, nsPIDOMWindowInner* aWindow,
113 mozilla::ErrorResult& aRv) {
114 RefPtr<WakeLock> wakelock = new WakeLock();
115 aRv = wakelock->Init(aTopic, aWindow);
116 if (aRv.Failed()) {
117 return nullptr;
118 }
119
120 return wakelock.forget();
121 }
122
123 NS_IMETHODIMP
NewWakeLock(const nsAString & aTopic,mozIDOMWindow * aWindow,nsIWakeLock ** aWakeLock)124 PowerManagerService::NewWakeLock(const nsAString& aTopic,
125 mozIDOMWindow* aWindow,
126 nsIWakeLock** aWakeLock) {
127 mozilla::ErrorResult rv;
128 RefPtr<WakeLock> wakelock =
129 NewWakeLock(aTopic, nsPIDOMWindowInner::From(aWindow), rv);
130 if (rv.Failed()) {
131 return rv.StealNSResult();
132 }
133
134 wakelock.forget(aWakeLock);
135 return NS_OK;
136 }
137
138 } // namespace mozilla::dom::power
139
140 NS_DEFINE_NAMED_CID(NS_POWERMANAGERSERVICE_CID);
141
142 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(
143 nsIPowerManagerService,
144 mozilla::dom::power::PowerManagerService::GetInstance)
145
146 static const mozilla::Module::CIDEntry kPowerManagerCIDs[] = {
147 // clang-format off
148 { &kNS_POWERMANAGERSERVICE_CID, false, nullptr, nsIPowerManagerServiceConstructor, mozilla::Module::ALLOW_IN_GPU_RDD_AND_SOCKET_PROCESS },
149 { nullptr }
150 // clang-format on
151 };
152
153 static const mozilla::Module::ContractIDEntry kPowerManagerContracts[] = {
154 // clang-format off
155 { POWERMANAGERSERVICE_CONTRACTID, &kNS_POWERMANAGERSERVICE_CID, mozilla::Module::ALLOW_IN_GPU_RDD_AND_SOCKET_PROCESS },
156 { nullptr }
157 // clang-format on
158 };
159
160 // We mark the power module as being available in the GPU process because the
161 // appshell depends on the power manager service.
162 extern const mozilla::Module kPowerManagerModule = {
163 mozilla::Module::kVersion,
164 kPowerManagerCIDs,
165 kPowerManagerContracts,
166 nullptr,
167 nullptr,
168 nullptr,
169 nullptr,
170 mozilla::Module::ALLOW_IN_GPU_RDD_AND_SOCKET_PROCESS};
171