diff options
author | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
---|---|---|
committer | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
commit | 5f8de423f190bbb79a62f804151bc24824fa32d8 (patch) | |
tree | 10027f336435511475e392454359edea8e25895d /hal/Hal.cpp | |
parent | 49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff) | |
download | UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip |
Add m-esr52 at 52.6.0
Diffstat (limited to 'hal/Hal.cpp')
-rw-r--r-- | hal/Hal.cpp | 1003 |
1 files changed, 1003 insertions, 0 deletions
diff --git a/hal/Hal.cpp b/hal/Hal.cpp new file mode 100644 index 000000000..44be2f510 --- /dev/null +++ b/hal/Hal.cpp @@ -0,0 +1,1003 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set sw=2 ts=8 et ft=cpp : */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "Hal.h" + +#include "HalImpl.h" +#include "HalLog.h" +#include "HalSandbox.h" +#include "nsIDOMDocument.h" +#include "nsIDOMWindow.h" +#include "nsIDocument.h" +#include "nsIDocShell.h" +#include "nsITabChild.h" +#include "nsIWebNavigation.h" +#include "nsThreadUtils.h" +#include "nsXULAppAPI.h" +#include "nsPIDOMWindow.h" +#include "nsJSUtils.h" +#include "mozilla/ClearOnShutdown.h" +#include "mozilla/Observer.h" +#include "mozilla/Services.h" +#include "mozilla/StaticPtr.h" +#include "mozilla/dom/ContentChild.h" +#include "mozilla/dom/ContentParent.h" +#include "mozilla/dom/ScreenOrientation.h" +#include "WindowIdentifier.h" + +#ifdef XP_WIN +#include <process.h> +#define getpid _getpid +#endif + +using namespace mozilla::services; +using namespace mozilla::dom; + +#define PROXY_IF_SANDBOXED(_call) \ + do { \ + if (InSandbox()) { \ + if (!hal_sandbox::HalChildDestroyed()) { \ + hal_sandbox::_call; \ + } \ + } else { \ + hal_impl::_call; \ + } \ + } while (0) + +#define RETURN_PROXY_IF_SANDBOXED(_call, defValue)\ + do { \ + if (InSandbox()) { \ + if (hal_sandbox::HalChildDestroyed()) { \ + return defValue; \ + } \ + return hal_sandbox::_call; \ + } else { \ + return hal_impl::_call; \ + } \ + } while (0) + +namespace mozilla { +namespace hal { + +mozilla::LogModule * +GetHalLog() +{ + static mozilla::LazyLogModule sHalLog("hal"); + return sHalLog; +} + +namespace { + +void +AssertMainThread() +{ + MOZ_ASSERT(NS_IsMainThread()); +} + +bool +InSandbox() +{ + return GeckoProcessType_Content == XRE_GetProcessType(); +} + +void +AssertMainProcess() +{ + MOZ_ASSERT(GeckoProcessType_Default == XRE_GetProcessType()); +} + +#if !defined(MOZ_WIDGET_GONK) + +bool +WindowIsActive(nsPIDOMWindowInner* aWindow) +{ + nsIDocument* document = aWindow->GetDoc(); + NS_ENSURE_TRUE(document, false); + + return !document->Hidden(); +} + +#endif // !defined(MOZ_WIDGET_GONK) + +StaticAutoPtr<WindowIdentifier::IDArrayType> gLastIDToVibrate; + +void InitLastIDToVibrate() +{ + gLastIDToVibrate = new WindowIdentifier::IDArrayType(); + ClearOnShutdown(&gLastIDToVibrate); +} + +} // namespace + +void +Vibrate(const nsTArray<uint32_t>& pattern, nsPIDOMWindowInner* window) +{ + Vibrate(pattern, WindowIdentifier(window)); +} + +void +Vibrate(const nsTArray<uint32_t>& pattern, const WindowIdentifier &id) +{ + AssertMainThread(); + +#if !defined(MOZ_WIDGET_GONK) + // Only active windows may start vibrations. If |id| hasn't gone + // through the IPC layer -- that is, if our caller is the outside + // world, not hal_proxy -- check whether the window is active. If + // |id| has gone through IPC, don't check the window's visibility; + // only the window corresponding to the bottommost process has its + // visibility state set correctly. + if (!id.HasTraveledThroughIPC() && !WindowIsActive(id.GetWindow())) { + HAL_LOG("Vibrate: Window is inactive, dropping vibrate."); + return; + } +#endif // !defined(MOZ_WIDGET_GONK) + + if (!InSandbox()) { + if (!gLastIDToVibrate) { + InitLastIDToVibrate(); + } + *gLastIDToVibrate = id.AsArray(); + } + + // Don't forward our ID if we are not in the sandbox, because hal_impl + // doesn't need it, and we don't want it to be tempted to read it. The + // empty identifier will assert if it's used. + PROXY_IF_SANDBOXED(Vibrate(pattern, InSandbox() ? id : WindowIdentifier())); +} + +void +CancelVibrate(nsPIDOMWindowInner* window) +{ + CancelVibrate(WindowIdentifier(window)); +} + +void +CancelVibrate(const WindowIdentifier &id) +{ + AssertMainThread(); + + // Although only active windows may start vibrations, a window may + // cancel its own vibration even if it's no longer active. + // + // After a window is marked as inactive, it sends a CancelVibrate + // request. We want this request to cancel a playing vibration + // started by that window, so we certainly don't want to reject the + // cancellation request because the window is now inactive. + // + // But it could be the case that, after this window became inactive, + // some other window came along and started a vibration. We don't + // want this window's cancellation request to cancel that window's + // actively-playing vibration! + // + // To solve this problem, we keep track of the id of the last window + // to start a vibration, and only accepts cancellation requests from + // the same window. All other cancellation requests are ignored. + + if (InSandbox() || (gLastIDToVibrate && *gLastIDToVibrate == id.AsArray())) { + // Don't forward our ID if we are not in the sandbox, because hal_impl + // doesn't need it, and we don't want it to be tempted to read it. The + // empty identifier will assert if it's used. + PROXY_IF_SANDBOXED(CancelVibrate(InSandbox() ? id : WindowIdentifier())); + } +} + +template <class InfoType> +class ObserversManager +{ +public: + void AddObserver(Observer<InfoType>* aObserver) { + if (!mObservers) { + mObservers = new mozilla::ObserverList<InfoType>(); + } + + mObservers->AddObserver(aObserver); + + if (mObservers->Length() == 1) { + EnableNotifications(); + } + } + + void RemoveObserver(Observer<InfoType>* aObserver) { + bool removed = mObservers && mObservers->RemoveObserver(aObserver); + if (!removed) { + return; + } + + if (mObservers->Length() == 0) { + DisableNotifications(); + + OnNotificationsDisabled(); + + delete mObservers; + mObservers = nullptr; + } + } + + void BroadcastInformation(const InfoType& aInfo) { + // It is possible for mObservers to be nullptr here on some platforms, + // because a call to BroadcastInformation gets queued up asynchronously + // while RemoveObserver is running (and before the notifications are + // disabled). The queued call can then get run after mObservers has + // been nulled out. See bug 757025. + if (!mObservers) { + return; + } + mObservers->Broadcast(aInfo); + } + +protected: + virtual void EnableNotifications() = 0; + virtual void DisableNotifications() = 0; + virtual void OnNotificationsDisabled() {} + +private: + mozilla::ObserverList<InfoType>* mObservers; +}; + +template <class InfoType> +class CachingObserversManager : public ObserversManager<InfoType> +{ +public: + InfoType GetCurrentInformation() { + if (mHasValidCache) { + return mInfo; + } + + GetCurrentInformationInternal(&mInfo); + mHasValidCache = true; + return mInfo; + } + + void CacheInformation(const InfoType& aInfo) { + mHasValidCache = true; + mInfo = aInfo; + } + + void BroadcastCachedInformation() { + this->BroadcastInformation(mInfo); + } + +protected: + virtual void GetCurrentInformationInternal(InfoType*) = 0; + + virtual void OnNotificationsDisabled() { + mHasValidCache = false; + } + +private: + InfoType mInfo; + bool mHasValidCache; +}; + +class BatteryObserversManager : public CachingObserversManager<BatteryInformation> +{ +protected: + void EnableNotifications() { + PROXY_IF_SANDBOXED(EnableBatteryNotifications()); + } + + void DisableNotifications() { + PROXY_IF_SANDBOXED(DisableBatteryNotifications()); + } + + void GetCurrentInformationInternal(BatteryInformation* aInfo) { + PROXY_IF_SANDBOXED(GetCurrentBatteryInformation(aInfo)); + } +}; + +static BatteryObserversManager& +BatteryObservers() +{ + static BatteryObserversManager sBatteryObservers; + AssertMainThread(); + return sBatteryObservers; +} + +class NetworkObserversManager : public CachingObserversManager<NetworkInformation> +{ +protected: + void EnableNotifications() { + PROXY_IF_SANDBOXED(EnableNetworkNotifications()); + } + + void DisableNotifications() { + PROXY_IF_SANDBOXED(DisableNetworkNotifications()); + } + + void GetCurrentInformationInternal(NetworkInformation* aInfo) { + PROXY_IF_SANDBOXED(GetCurrentNetworkInformation(aInfo)); + } +}; + +static NetworkObserversManager& +NetworkObservers() +{ + static NetworkObserversManager sNetworkObservers; + AssertMainThread(); + return sNetworkObservers; +} + +class WakeLockObserversManager : public ObserversManager<WakeLockInformation> +{ +protected: + void EnableNotifications() { + PROXY_IF_SANDBOXED(EnableWakeLockNotifications()); + } + + void DisableNotifications() { + PROXY_IF_SANDBOXED(DisableWakeLockNotifications()); + } +}; + +static WakeLockObserversManager& +WakeLockObservers() +{ + static WakeLockObserversManager sWakeLockObservers; + AssertMainThread(); + return sWakeLockObservers; +} + +class ScreenConfigurationObserversManager : public CachingObserversManager<ScreenConfiguration> +{ +protected: + void EnableNotifications() { + PROXY_IF_SANDBOXED(EnableScreenConfigurationNotifications()); + } + + void DisableNotifications() { + PROXY_IF_SANDBOXED(DisableScreenConfigurationNotifications()); + } + + void GetCurrentInformationInternal(ScreenConfiguration* aInfo) { + PROXY_IF_SANDBOXED(GetCurrentScreenConfiguration(aInfo)); + } +}; + +static ScreenConfigurationObserversManager& +ScreenConfigurationObservers() +{ + AssertMainThread(); + static ScreenConfigurationObserversManager sScreenConfigurationObservers; + return sScreenConfigurationObservers; +} + +void +RegisterBatteryObserver(BatteryObserver* aObserver) +{ + AssertMainThread(); + BatteryObservers().AddObserver(aObserver); +} + +void +UnregisterBatteryObserver(BatteryObserver* aObserver) +{ + AssertMainThread(); + BatteryObservers().RemoveObserver(aObserver); +} + +void +GetCurrentBatteryInformation(BatteryInformation* aInfo) +{ + AssertMainThread(); + *aInfo = BatteryObservers().GetCurrentInformation(); +} + +void +NotifyBatteryChange(const BatteryInformation& aInfo) +{ + AssertMainThread(); + BatteryObservers().CacheInformation(aInfo); + BatteryObservers().BroadcastCachedInformation(); +} + +bool GetScreenEnabled() +{ + AssertMainThread(); + RETURN_PROXY_IF_SANDBOXED(GetScreenEnabled(), false); +} + +void SetScreenEnabled(bool aEnabled) +{ + AssertMainThread(); + PROXY_IF_SANDBOXED(SetScreenEnabled(aEnabled)); +} + +bool GetKeyLightEnabled() +{ + AssertMainThread(); + RETURN_PROXY_IF_SANDBOXED(GetKeyLightEnabled(), false); +} + +void SetKeyLightEnabled(bool aEnabled) +{ + AssertMainThread(); + PROXY_IF_SANDBOXED(SetKeyLightEnabled(aEnabled)); +} + +bool GetCpuSleepAllowed() +{ + // Generally for interfaces that are accessible by normal web content + // we should cache the result and be notified on state changes, like + // what the battery API does. But since this is only used by + // privileged interface, the synchronous getter is OK here. + AssertMainThread(); + RETURN_PROXY_IF_SANDBOXED(GetCpuSleepAllowed(), true); +} + +void SetCpuSleepAllowed(bool aAllowed) +{ + AssertMainThread(); + PROXY_IF_SANDBOXED(SetCpuSleepAllowed(aAllowed)); +} + +double GetScreenBrightness() +{ + AssertMainThread(); + RETURN_PROXY_IF_SANDBOXED(GetScreenBrightness(), 0); +} + +void SetScreenBrightness(double aBrightness) +{ + AssertMainThread(); + PROXY_IF_SANDBOXED(SetScreenBrightness(clamped(aBrightness, 0.0, 1.0))); +} + +class SystemClockChangeObserversManager : public ObserversManager<int64_t> +{ +protected: + void EnableNotifications() { + PROXY_IF_SANDBOXED(EnableSystemClockChangeNotifications()); + } + + void DisableNotifications() { + PROXY_IF_SANDBOXED(DisableSystemClockChangeNotifications()); + } +}; + +static SystemClockChangeObserversManager& +SystemClockChangeObservers() +{ + static SystemClockChangeObserversManager sSystemClockChangeObservers; + AssertMainThread(); + return sSystemClockChangeObservers; +} + +void +RegisterSystemClockChangeObserver(SystemClockChangeObserver* aObserver) +{ + AssertMainThread(); + SystemClockChangeObservers().AddObserver(aObserver); +} + +void +UnregisterSystemClockChangeObserver(SystemClockChangeObserver* aObserver) +{ + AssertMainThread(); + SystemClockChangeObservers().RemoveObserver(aObserver); +} + +void +NotifySystemClockChange(const int64_t& aClockDeltaMS) +{ + SystemClockChangeObservers().BroadcastInformation(aClockDeltaMS); +} + +class SystemTimezoneChangeObserversManager : public ObserversManager<SystemTimezoneChangeInformation> +{ +protected: + void EnableNotifications() { + PROXY_IF_SANDBOXED(EnableSystemTimezoneChangeNotifications()); + } + + void DisableNotifications() { + PROXY_IF_SANDBOXED(DisableSystemTimezoneChangeNotifications()); + } +}; + +static SystemTimezoneChangeObserversManager& +SystemTimezoneChangeObservers() +{ + static SystemTimezoneChangeObserversManager sSystemTimezoneChangeObservers; + return sSystemTimezoneChangeObservers; +} + +void +RegisterSystemTimezoneChangeObserver(SystemTimezoneChangeObserver* aObserver) +{ + AssertMainThread(); + SystemTimezoneChangeObservers().AddObserver(aObserver); +} + +void +UnregisterSystemTimezoneChangeObserver(SystemTimezoneChangeObserver* aObserver) +{ + AssertMainThread(); + SystemTimezoneChangeObservers().RemoveObserver(aObserver); +} + +void +NotifySystemTimezoneChange(const SystemTimezoneChangeInformation& aSystemTimezoneChangeInfo) +{ + nsJSUtils::ResetTimeZone(); + SystemTimezoneChangeObservers().BroadcastInformation(aSystemTimezoneChangeInfo); +} + +void +AdjustSystemClock(int64_t aDeltaMilliseconds) +{ + AssertMainThread(); + PROXY_IF_SANDBOXED(AdjustSystemClock(aDeltaMilliseconds)); +} + +void +SetTimezone(const nsCString& aTimezoneSpec) +{ + AssertMainThread(); + PROXY_IF_SANDBOXED(SetTimezone(aTimezoneSpec)); +} + +int32_t +GetTimezoneOffset() +{ + AssertMainThread(); + RETURN_PROXY_IF_SANDBOXED(GetTimezoneOffset(), 0); +} + +nsCString +GetTimezone() +{ + AssertMainThread(); + RETURN_PROXY_IF_SANDBOXED(GetTimezone(), nsCString("")); +} + +void +EnableSensorNotifications(SensorType aSensor) { + AssertMainThread(); + PROXY_IF_SANDBOXED(EnableSensorNotifications(aSensor)); +} + +void +DisableSensorNotifications(SensorType aSensor) { + AssertMainThread(); + PROXY_IF_SANDBOXED(DisableSensorNotifications(aSensor)); +} + +typedef mozilla::ObserverList<SensorData> SensorObserverList; +static SensorObserverList* gSensorObservers = nullptr; + +static SensorObserverList & +GetSensorObservers(SensorType sensor_type) { + MOZ_ASSERT(sensor_type < NUM_SENSOR_TYPE); + + if(!gSensorObservers) { + gSensorObservers = new SensorObserverList[NUM_SENSOR_TYPE]; + } + return gSensorObservers[sensor_type]; +} + +void +RegisterSensorObserver(SensorType aSensor, ISensorObserver *aObserver) { + SensorObserverList &observers = GetSensorObservers(aSensor); + + AssertMainThread(); + + observers.AddObserver(aObserver); + if(observers.Length() == 1) { + EnableSensorNotifications(aSensor); + } +} + +void +UnregisterSensorObserver(SensorType aSensor, ISensorObserver *aObserver) { + AssertMainThread(); + + if (!gSensorObservers) { + return; + } + + SensorObserverList &observers = GetSensorObservers(aSensor); + if (!observers.RemoveObserver(aObserver) || observers.Length() > 0) { + return; + } + DisableSensorNotifications(aSensor); + + // Destroy sSensorObservers only if all observer lists are empty. + for (int i = 0; i < NUM_SENSOR_TYPE; i++) { + if (gSensorObservers[i].Length() > 0) { + return; + } + } + delete [] gSensorObservers; + gSensorObservers = nullptr; +} + +void +NotifySensorChange(const SensorData &aSensorData) { + SensorObserverList &observers = GetSensorObservers(aSensorData.sensor()); + + AssertMainThread(); + + observers.Broadcast(aSensorData); +} + +void +RegisterNetworkObserver(NetworkObserver* aObserver) +{ + AssertMainThread(); + NetworkObservers().AddObserver(aObserver); +} + +void +UnregisterNetworkObserver(NetworkObserver* aObserver) +{ + AssertMainThread(); + NetworkObservers().RemoveObserver(aObserver); +} + +void +GetCurrentNetworkInformation(NetworkInformation* aInfo) +{ + AssertMainThread(); + *aInfo = NetworkObservers().GetCurrentInformation(); +} + +void +NotifyNetworkChange(const NetworkInformation& aInfo) +{ + NetworkObservers().CacheInformation(aInfo); + NetworkObservers().BroadcastCachedInformation(); +} + +void Reboot() +{ + AssertMainProcess(); + AssertMainThread(); + PROXY_IF_SANDBOXED(Reboot()); +} + +void PowerOff() +{ + AssertMainProcess(); + AssertMainThread(); + PROXY_IF_SANDBOXED(PowerOff()); +} + +void StartForceQuitWatchdog(ShutdownMode aMode, int32_t aTimeoutSecs) +{ + AssertMainProcess(); + AssertMainThread(); + PROXY_IF_SANDBOXED(StartForceQuitWatchdog(aMode, aTimeoutSecs)); +} + +void +RegisterWakeLockObserver(WakeLockObserver* aObserver) +{ + AssertMainThread(); + WakeLockObservers().AddObserver(aObserver); +} + +void +UnregisterWakeLockObserver(WakeLockObserver* aObserver) +{ + AssertMainThread(); + WakeLockObservers().RemoveObserver(aObserver); +} + +void +ModifyWakeLock(const nsAString& aTopic, + WakeLockControl aLockAdjust, + WakeLockControl aHiddenAdjust, + uint64_t aProcessID /* = CONTENT_PROCESS_ID_UNKNOWN */) +{ + AssertMainThread(); + + if (aProcessID == CONTENT_PROCESS_ID_UNKNOWN) { + aProcessID = InSandbox() ? ContentChild::GetSingleton()->GetID() : + CONTENT_PROCESS_ID_MAIN; + } + + PROXY_IF_SANDBOXED(ModifyWakeLock(aTopic, aLockAdjust, + aHiddenAdjust, aProcessID)); +} + +void +GetWakeLockInfo(const nsAString& aTopic, WakeLockInformation* aWakeLockInfo) +{ + AssertMainThread(); + PROXY_IF_SANDBOXED(GetWakeLockInfo(aTopic, aWakeLockInfo)); +} + +void +NotifyWakeLockChange(const WakeLockInformation& aInfo) +{ + AssertMainThread(); + WakeLockObservers().BroadcastInformation(aInfo); +} + +void +RegisterScreenConfigurationObserver(ScreenConfigurationObserver* aObserver) +{ + AssertMainThread(); + ScreenConfigurationObservers().AddObserver(aObserver); +} + +void +UnregisterScreenConfigurationObserver(ScreenConfigurationObserver* aObserver) +{ + AssertMainThread(); + ScreenConfigurationObservers().RemoveObserver(aObserver); +} + +void +GetCurrentScreenConfiguration(ScreenConfiguration* aScreenConfiguration) +{ + AssertMainThread(); + *aScreenConfiguration = ScreenConfigurationObservers().GetCurrentInformation(); +} + +void +NotifyScreenConfigurationChange(const ScreenConfiguration& aScreenConfiguration) +{ + ScreenConfigurationObservers().CacheInformation(aScreenConfiguration); + ScreenConfigurationObservers().BroadcastCachedInformation(); +} + +bool +LockScreenOrientation(const dom::ScreenOrientationInternal& aOrientation) +{ + AssertMainThread(); + RETURN_PROXY_IF_SANDBOXED(LockScreenOrientation(aOrientation), false); +} + +void +UnlockScreenOrientation() +{ + AssertMainThread(); + PROXY_IF_SANDBOXED(UnlockScreenOrientation()); +} + +void +EnableSwitchNotifications(SwitchDevice aDevice) { + AssertMainThread(); + PROXY_IF_SANDBOXED(EnableSwitchNotifications(aDevice)); +} + +void +DisableSwitchNotifications(SwitchDevice aDevice) { + AssertMainThread(); + PROXY_IF_SANDBOXED(DisableSwitchNotifications(aDevice)); +} + +SwitchState GetCurrentSwitchState(SwitchDevice aDevice) +{ + AssertMainThread(); + RETURN_PROXY_IF_SANDBOXED(GetCurrentSwitchState(aDevice), SWITCH_STATE_UNKNOWN); +} + +void NotifySwitchStateFromInputDevice(SwitchDevice aDevice, SwitchState aState) +{ + AssertMainThread(); + PROXY_IF_SANDBOXED(NotifySwitchStateFromInputDevice(aDevice, aState)); +} + +typedef mozilla::ObserverList<SwitchEvent> SwitchObserverList; + +static SwitchObserverList *sSwitchObserverLists = nullptr; + +static SwitchObserverList& +GetSwitchObserverList(SwitchDevice aDevice) { + MOZ_ASSERT(0 <= aDevice && aDevice < NUM_SWITCH_DEVICE); + if (sSwitchObserverLists == nullptr) { + sSwitchObserverLists = new SwitchObserverList[NUM_SWITCH_DEVICE]; + } + return sSwitchObserverLists[aDevice]; +} + +static void +ReleaseObserversIfNeeded() { + for (int i = 0; i < NUM_SWITCH_DEVICE; i++) { + if (sSwitchObserverLists[i].Length() != 0) + return; + } + + //The length of every list is 0, no observer in the list. + delete [] sSwitchObserverLists; + sSwitchObserverLists = nullptr; +} + +void +RegisterSwitchObserver(SwitchDevice aDevice, SwitchObserver *aObserver) +{ + AssertMainThread(); + SwitchObserverList& observer = GetSwitchObserverList(aDevice); + observer.AddObserver(aObserver); + if (observer.Length() == 1) { + EnableSwitchNotifications(aDevice); + } +} + +void +UnregisterSwitchObserver(SwitchDevice aDevice, SwitchObserver *aObserver) +{ + AssertMainThread(); + + if (!sSwitchObserverLists) { + return; + } + + SwitchObserverList& observer = GetSwitchObserverList(aDevice); + if (!observer.RemoveObserver(aObserver) || observer.Length() > 0) { + return; + } + + DisableSwitchNotifications(aDevice); + ReleaseObserversIfNeeded(); +} + +void +NotifySwitchChange(const SwitchEvent& aEvent) +{ + // When callback this notification, main thread may call unregister function + // first. We should check if this pointer is valid. + if (!sSwitchObserverLists) + return; + + SwitchObserverList& observer = GetSwitchObserverList(aEvent.device()); + observer.Broadcast(aEvent); +} + +static AlarmObserver* sAlarmObserver; + +bool +RegisterTheOneAlarmObserver(AlarmObserver* aObserver) +{ + MOZ_ASSERT(!InSandbox()); + MOZ_ASSERT(!sAlarmObserver); + + sAlarmObserver = aObserver; + RETURN_PROXY_IF_SANDBOXED(EnableAlarm(), false); +} + +void +UnregisterTheOneAlarmObserver() +{ + if (sAlarmObserver) { + sAlarmObserver = nullptr; + PROXY_IF_SANDBOXED(DisableAlarm()); + } +} + +void +NotifyAlarmFired() +{ + if (sAlarmObserver) { + sAlarmObserver->Notify(void_t()); + } +} + +bool +SetAlarm(int32_t aSeconds, int32_t aNanoseconds) +{ + // It's pointless to program an alarm nothing is going to observe ... + MOZ_ASSERT(sAlarmObserver); + RETURN_PROXY_IF_SANDBOXED(SetAlarm(aSeconds, aNanoseconds), false); +} + +void +SetProcessPriority(int aPid, ProcessPriority aPriority, uint32_t aLRU) +{ + // n.b. The sandboxed implementation crashes; SetProcessPriority works only + // from the main process. + PROXY_IF_SANDBOXED(SetProcessPriority(aPid, aPriority, aLRU)); +} + +void +SetCurrentThreadPriority(hal::ThreadPriority aThreadPriority) +{ + PROXY_IF_SANDBOXED(SetCurrentThreadPriority(aThreadPriority)); +} + +void +SetThreadPriority(PlatformThreadId aThreadId, + hal::ThreadPriority aThreadPriority) +{ + PROXY_IF_SANDBOXED(SetThreadPriority(aThreadId, aThreadPriority)); +} + +// From HalTypes.h. +const char* +ProcessPriorityToString(ProcessPriority aPriority) +{ + switch (aPriority) { + case PROCESS_PRIORITY_MASTER: + return "MASTER"; + case PROCESS_PRIORITY_PREALLOC: + return "PREALLOC"; + case PROCESS_PRIORITY_FOREGROUND_HIGH: + return "FOREGROUND_HIGH"; + case PROCESS_PRIORITY_FOREGROUND: + return "FOREGROUND"; + case PROCESS_PRIORITY_FOREGROUND_KEYBOARD: + return "FOREGROUND_KEYBOARD"; + case PROCESS_PRIORITY_BACKGROUND_PERCEIVABLE: + return "BACKGROUND_PERCEIVABLE"; + case PROCESS_PRIORITY_BACKGROUND: + return "BACKGROUND"; + case PROCESS_PRIORITY_UNKNOWN: + return "UNKNOWN"; + default: + MOZ_ASSERT(false); + return "???"; + } +} + +const char * +ThreadPriorityToString(ThreadPriority aPriority) +{ + switch (aPriority) { + case THREAD_PRIORITY_COMPOSITOR: + return "COMPOSITOR"; + default: + MOZ_ASSERT(false); + return "???"; + } +} + +void FactoryReset(mozilla::dom::FactoryResetReason& aReason) +{ + AssertMainThread(); + PROXY_IF_SANDBOXED(FactoryReset(aReason)); +} + +void +StartDiskSpaceWatcher() +{ + AssertMainProcess(); + AssertMainThread(); + PROXY_IF_SANDBOXED(StartDiskSpaceWatcher()); +} + +void +StopDiskSpaceWatcher() +{ + AssertMainProcess(); + AssertMainThread(); + PROXY_IF_SANDBOXED(StopDiskSpaceWatcher()); +} + +uint32_t +GetTotalSystemMemory() +{ + return hal_impl::GetTotalSystemMemory(); +} + +bool IsHeadphoneEventFromInputDev() +{ + AssertMainThread(); + RETURN_PROXY_IF_SANDBOXED(IsHeadphoneEventFromInputDev(), false); +} + +nsresult StartSystemService(const char* aSvcName, const char* aArgs) +{ + AssertMainThread(); + RETURN_PROXY_IF_SANDBOXED(StartSystemService(aSvcName, aArgs), NS_ERROR_FAILURE); +} + +void StopSystemService(const char* aSvcName) +{ + AssertMainThread(); + PROXY_IF_SANDBOXED(StopSystemService(aSvcName)); +} + +bool SystemServiceIsRunning(const char* aSvcName) +{ + AssertMainThread(); + RETURN_PROXY_IF_SANDBOXED(SystemServiceIsRunning(aSvcName), false); +} + +} // namespace hal +} // namespace mozilla |