Bug 1494162 - Part 52: Don't show the empty message in the CssRuleView constructor...
[gecko.git] / hal / Hal.cpp
bloba52dcae32d447e056af722682d91313bffa4177e
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set sw=2 ts=8 et ft=cpp : */
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 "Hal.h"
9 #include "HalImpl.h"
10 #include "HalLog.h"
11 #include "HalSandbox.h"
12 #include "HalWakeLockInternal.h"
13 #include "nsIDOMWindow.h"
14 #include "nsIDocument.h"
15 #include "nsIDocShell.h"
16 #include "nsITabChild.h"
17 #include "nsIWebNavigation.h"
18 #include "nsThreadUtils.h"
19 #include "nsXULAppAPI.h"
20 #include "nsPIDOMWindow.h"
21 #include "nsJSUtils.h"
22 #include "mozilla/ClearOnShutdown.h"
23 #include "mozilla/Observer.h"
24 #include "mozilla/dom/ContentChild.h"
25 #include "WindowIdentifier.h"
27 #ifdef XP_WIN
28 #include <process.h>
29 #define getpid _getpid
30 #endif
32 using namespace mozilla::services;
33 using namespace mozilla::dom;
35 #define PROXY_IF_SANDBOXED(_call) \
36 do { \
37 if (InSandbox()) { \
38 if (!hal_sandbox::HalChildDestroyed()) { \
39 hal_sandbox::_call; \
40 } \
41 } else { \
42 hal_impl::_call; \
43 } \
44 } while (0)
46 #define RETURN_PROXY_IF_SANDBOXED(_call, defValue)\
47 do { \
48 if (InSandbox()) { \
49 if (hal_sandbox::HalChildDestroyed()) { \
50 return defValue; \
51 } \
52 return hal_sandbox::_call; \
53 } else { \
54 return hal_impl::_call; \
55 } \
56 } while (0)
58 namespace mozilla {
59 namespace hal {
61 static bool sInitialized = false;
63 mozilla::LogModule *
64 GetHalLog()
66 static mozilla::LazyLogModule sHalLog("hal");
67 return sHalLog;
70 namespace {
72 void
73 AssertMainThread()
75 MOZ_ASSERT(NS_IsMainThread());
78 bool
79 InSandbox()
81 return GeckoProcessType_Content == XRE_GetProcessType();
84 bool
85 WindowIsActive(nsPIDOMWindowInner* aWindow)
87 nsIDocument* document = aWindow->GetDoc();
88 NS_ENSURE_TRUE(document, false);
90 return !document->Hidden();
93 StaticAutoPtr<WindowIdentifier::IDArrayType> gLastIDToVibrate;
95 static void
96 RecordLastIDToVibrate(const WindowIdentifier& aId)
98 if (!InSandbox()) {
99 *gLastIDToVibrate = aId.AsArray();
103 static bool
104 MayCancelVibration(const WindowIdentifier& aId)
106 // Although only active windows may start vibrations, a window may
107 // cancel its own vibration even if it's no longer active.
109 // After a window is marked as inactive, it sends a CancelVibrate
110 // request. We want this request to cancel a playing vibration
111 // started by that window, so we certainly don't want to reject the
112 // cancellation request because the window is now inactive.
114 // But it could be the case that, after this window became inactive,
115 // some other window came along and started a vibration. We don't
116 // want this window's cancellation request to cancel that window's
117 // actively-playing vibration!
119 // To solve this problem, we keep track of the id of the last window
120 // to start a vibration, and only accepts cancellation requests from
121 // the same window. All other cancellation requests are ignored.
123 return InSandbox() || (*gLastIDToVibrate == aId.AsArray());
126 } // namespace
128 void
129 Vibrate(const nsTArray<uint32_t>& pattern, nsPIDOMWindowInner* window)
131 Vibrate(pattern, WindowIdentifier(window));
134 void
135 Vibrate(const nsTArray<uint32_t>& pattern, const WindowIdentifier &id)
137 AssertMainThread();
139 // Only active windows may start vibrations. If |id| hasn't gone
140 // through the IPC layer -- that is, if our caller is the outside
141 // world, not hal_proxy -- check whether the window is active. If
142 // |id| has gone through IPC, don't check the window's visibility;
143 // only the window corresponding to the bottommost process has its
144 // visibility state set correctly.
145 if (!id.HasTraveledThroughIPC() && !WindowIsActive(id.GetWindow())) {
146 HAL_LOG("Vibrate: Window is inactive, dropping vibrate.");
147 return;
150 RecordLastIDToVibrate(id);
152 // Don't forward our ID if we are not in the sandbox, because hal_impl
153 // doesn't need it, and we don't want it to be tempted to read it. The
154 // empty identifier will assert if it's used.
155 PROXY_IF_SANDBOXED(Vibrate(pattern, InSandbox() ? id : WindowIdentifier()));
158 void
159 CancelVibrate(nsPIDOMWindowInner* window)
161 CancelVibrate(WindowIdentifier(window));
164 void
165 CancelVibrate(const WindowIdentifier &id)
167 AssertMainThread();
169 if (MayCancelVibration(id)) {
170 // Don't forward our ID if we are not in the sandbox, because hal_impl
171 // doesn't need it, and we don't want it to be tempted to read it. The
172 // empty identifier will assert if it's used.
173 PROXY_IF_SANDBOXED(CancelVibrate(InSandbox() ? id : WindowIdentifier()));
177 template <class InfoType>
178 class ObserversManager
180 public:
181 void AddObserver(Observer<InfoType>* aObserver) {
182 mObservers.AddObserver(aObserver);
184 if (mObservers.Length() == 1) {
185 EnableNotifications();
189 void RemoveObserver(Observer<InfoType>* aObserver) {
190 bool removed = mObservers.RemoveObserver(aObserver);
191 if (!removed) {
192 return;
195 if (mObservers.Length() == 0) {
196 DisableNotifications();
197 OnNotificationsDisabled();
201 void BroadcastInformation(const InfoType& aInfo) {
202 mObservers.Broadcast(aInfo);
205 protected:
206 ~ObserversManager() {
207 MOZ_ASSERT(mObservers.Length() == 0);
210 virtual void EnableNotifications() = 0;
211 virtual void DisableNotifications() = 0;
212 virtual void OnNotificationsDisabled() {}
214 private:
215 mozilla::ObserverList<InfoType> mObservers;
218 template <class InfoType>
219 class CachingObserversManager : public ObserversManager<InfoType>
221 public:
222 InfoType GetCurrentInformation() {
223 if (mHasValidCache) {
224 return mInfo;
227 GetCurrentInformationInternal(&mInfo);
228 mHasValidCache = true;
229 return mInfo;
232 void CacheInformation(const InfoType& aInfo) {
233 mHasValidCache = true;
234 mInfo = aInfo;
237 void BroadcastCachedInformation() {
238 this->BroadcastInformation(mInfo);
241 protected:
242 virtual void GetCurrentInformationInternal(InfoType*) = 0;
244 void OnNotificationsDisabled() override {
245 mHasValidCache = false;
248 private:
249 InfoType mInfo;
250 bool mHasValidCache;
253 class BatteryObserversManager final
254 : public CachingObserversManager<BatteryInformation>
256 protected:
257 void EnableNotifications() override {
258 PROXY_IF_SANDBOXED(EnableBatteryNotifications());
261 void DisableNotifications() override {
262 PROXY_IF_SANDBOXED(DisableBatteryNotifications());
265 void GetCurrentInformationInternal(BatteryInformation* aInfo) override {
266 PROXY_IF_SANDBOXED(GetCurrentBatteryInformation(aInfo));
270 class NetworkObserversManager final
271 : public CachingObserversManager<NetworkInformation>
273 protected:
274 void EnableNotifications() override {
275 PROXY_IF_SANDBOXED(EnableNetworkNotifications());
278 void DisableNotifications() override {
279 PROXY_IF_SANDBOXED(DisableNetworkNotifications());
282 void GetCurrentInformationInternal(NetworkInformation* aInfo) override {
283 PROXY_IF_SANDBOXED(GetCurrentNetworkInformation(aInfo));
287 class WakeLockObserversManager final
288 : public ObserversManager<WakeLockInformation>
290 protected:
291 void EnableNotifications() override {
292 PROXY_IF_SANDBOXED(EnableWakeLockNotifications());
295 void DisableNotifications() override {
296 PROXY_IF_SANDBOXED(DisableWakeLockNotifications());
300 class ScreenConfigurationObserversManager final
301 : public CachingObserversManager<ScreenConfiguration>
303 protected:
304 void EnableNotifications() override {
305 PROXY_IF_SANDBOXED(EnableScreenConfigurationNotifications());
308 void DisableNotifications() override {
309 PROXY_IF_SANDBOXED(DisableScreenConfigurationNotifications());
312 void GetCurrentInformationInternal(ScreenConfiguration* aInfo) override {
313 PROXY_IF_SANDBOXED(GetCurrentScreenConfiguration(aInfo));
317 typedef mozilla::ObserverList<SensorData> SensorObserverList;
318 StaticAutoPtr<SensorObserverList> sSensorObservers[NUM_SENSOR_TYPE];
320 static SensorObserverList*
321 GetSensorObservers(SensorType sensor_type) {
322 AssertMainThread();
323 MOZ_ASSERT(sensor_type < NUM_SENSOR_TYPE);
325 if (!sSensorObservers[sensor_type]) {
326 sSensorObservers[sensor_type] = new SensorObserverList();
329 return sSensorObservers[sensor_type];
332 #define MOZ_IMPL_HAL_OBSERVER(name_) \
333 StaticAutoPtr<name_##ObserversManager> s##name_##Observers; \
335 static name_##ObserversManager* \
336 name_##Observers() \
338 AssertMainThread(); \
340 if (!s##name_##Observers) { \
341 MOZ_ASSERT(sInitialized); \
342 s##name_##Observers = new name_##ObserversManager(); \
345 return s##name_##Observers; \
348 void \
349 Register##name_##Observer(name_##Observer* aObserver) \
351 AssertMainThread(); \
352 name_##Observers()->AddObserver(aObserver); \
355 void \
356 Unregister##name_##Observer(name_##Observer* aObserver) \
358 AssertMainThread(); \
359 name_##Observers()->RemoveObserver(aObserver); \
362 MOZ_IMPL_HAL_OBSERVER(Battery)
364 void
365 GetCurrentBatteryInformation(BatteryInformation* aInfo)
367 *aInfo = BatteryObservers()->GetCurrentInformation();
370 void
371 NotifyBatteryChange(const BatteryInformation& aInfo)
373 BatteryObservers()->CacheInformation(aInfo);
374 BatteryObservers()->BroadcastCachedInformation();
377 void
378 EnableSensorNotifications(SensorType aSensor) {
379 AssertMainThread();
380 PROXY_IF_SANDBOXED(EnableSensorNotifications(aSensor));
383 void
384 DisableSensorNotifications(SensorType aSensor) {
385 AssertMainThread();
386 PROXY_IF_SANDBOXED(DisableSensorNotifications(aSensor));
389 void
390 RegisterSensorObserver(SensorType aSensor, ISensorObserver *aObserver) {
391 SensorObserverList* observers = GetSensorObservers(aSensor);
393 observers->AddObserver(aObserver);
394 if (observers->Length() == 1) {
395 EnableSensorNotifications(aSensor);
399 void
400 UnregisterSensorObserver(SensorType aSensor, ISensorObserver *aObserver) {
401 SensorObserverList* observers = GetSensorObservers(aSensor);
402 if (!observers->RemoveObserver(aObserver) || observers->Length() > 0) {
403 return;
405 DisableSensorNotifications(aSensor);
408 void
409 NotifySensorChange(const SensorData &aSensorData) {
410 SensorObserverList* observers = GetSensorObservers(aSensorData.sensor());
412 observers->Broadcast(aSensorData);
415 MOZ_IMPL_HAL_OBSERVER(Network)
417 void
418 GetCurrentNetworkInformation(NetworkInformation* aInfo)
420 *aInfo = NetworkObservers()->GetCurrentInformation();
423 void
424 NotifyNetworkChange(const NetworkInformation& aInfo)
426 NetworkObservers()->CacheInformation(aInfo);
427 NetworkObservers()->BroadcastCachedInformation();
430 MOZ_IMPL_HAL_OBSERVER(WakeLock)
432 void
433 ModifyWakeLock(const nsAString& aTopic,
434 WakeLockControl aLockAdjust,
435 WakeLockControl aHiddenAdjust,
436 uint64_t aProcessID /* = CONTENT_PROCESS_ID_UNKNOWN */)
438 AssertMainThread();
440 if (aProcessID == CONTENT_PROCESS_ID_UNKNOWN) {
441 aProcessID = InSandbox() ? ContentChild::GetSingleton()->GetID() :
442 CONTENT_PROCESS_ID_MAIN;
445 PROXY_IF_SANDBOXED(ModifyWakeLock(aTopic, aLockAdjust,
446 aHiddenAdjust, aProcessID));
449 void
450 GetWakeLockInfo(const nsAString& aTopic, WakeLockInformation* aWakeLockInfo)
452 AssertMainThread();
453 PROXY_IF_SANDBOXED(GetWakeLockInfo(aTopic, aWakeLockInfo));
456 void
457 NotifyWakeLockChange(const WakeLockInformation& aInfo)
459 AssertMainThread();
460 WakeLockObservers()->BroadcastInformation(aInfo);
463 MOZ_IMPL_HAL_OBSERVER(ScreenConfiguration)
465 void
466 GetCurrentScreenConfiguration(ScreenConfiguration* aScreenConfiguration)
468 *aScreenConfiguration =
469 ScreenConfigurationObservers()->GetCurrentInformation();
472 void
473 NotifyScreenConfigurationChange(const ScreenConfiguration& aScreenConfiguration)
475 ScreenConfigurationObservers()->CacheInformation(aScreenConfiguration);
476 ScreenConfigurationObservers()->BroadcastCachedInformation();
479 bool
480 LockScreenOrientation(const ScreenOrientation& aOrientation)
482 AssertMainThread();
483 RETURN_PROXY_IF_SANDBOXED(LockScreenOrientation(aOrientation), false);
486 void
487 UnlockScreenOrientation()
489 AssertMainThread();
490 PROXY_IF_SANDBOXED(UnlockScreenOrientation());
493 bool
494 SetProcessPrioritySupported()
496 RETURN_PROXY_IF_SANDBOXED(SetProcessPrioritySupported(), false);
499 void
500 SetProcessPriority(int aPid, ProcessPriority aPriority)
502 // n.b. The sandboxed implementation crashes; SetProcessPriority works only
503 // from the main process.
504 PROXY_IF_SANDBOXED(SetProcessPriority(aPid, aPriority));
507 // From HalTypes.h.
508 const char*
509 ProcessPriorityToString(ProcessPriority aPriority)
511 switch (aPriority) {
512 case PROCESS_PRIORITY_MASTER:
513 return "MASTER";
514 case PROCESS_PRIORITY_PREALLOC:
515 return "PREALLOC";
516 case PROCESS_PRIORITY_FOREGROUND_HIGH:
517 return "FOREGROUND_HIGH";
518 case PROCESS_PRIORITY_FOREGROUND:
519 return "FOREGROUND";
520 case PROCESS_PRIORITY_FOREGROUND_KEYBOARD:
521 return "FOREGROUND_KEYBOARD";
522 case PROCESS_PRIORITY_BACKGROUND_PERCEIVABLE:
523 return "BACKGROUND_PERCEIVABLE";
524 case PROCESS_PRIORITY_BACKGROUND:
525 return "BACKGROUND";
526 case PROCESS_PRIORITY_UNKNOWN:
527 return "UNKNOWN";
528 default:
529 MOZ_ASSERT(false);
530 return "???";
534 void
535 Init()
537 MOZ_ASSERT(!sInitialized);
539 if (!InSandbox()) {
540 gLastIDToVibrate = new WindowIdentifier::IDArrayType();
543 WakeLockInit();
545 sInitialized = true;
548 void
549 Shutdown()
551 MOZ_ASSERT(sInitialized);
553 gLastIDToVibrate = nullptr;
555 sBatteryObservers = nullptr;
556 sNetworkObservers = nullptr;
557 sWakeLockObservers = nullptr;
558 sScreenConfigurationObservers = nullptr;
560 for (auto& sensorObserver : sSensorObservers) {
561 sensorObserver = nullptr;
564 sInitialized = false;
567 } // namespace hal
568 } // namespace mozilla