diff --git a/dom/gamepad/GamepadPlatformService.cpp b/dom/gamepad/GamepadPlatformService.cpp index a4d92d84bfa1..0397646dd977 100644 --- a/dom/gamepad/GamepadPlatformService.cpp +++ b/dom/gamepad/GamepadPlatformService.cpp @@ -28,33 +28,44 @@ StaticRefPtr gGamepadPlatformServiceSingleton; } // namespace -GamepadPlatformService::MonitoringState::~MonitoringState() { - AssertIsOnBackgroundThread(); - MOZ_RELEASE_ASSERT(mObservers.IsEmpty()); +// static +GamepadMonitoringState& GamepadMonitoringState::GetSingleton() { + static GamepadMonitoringState sInstance{}; + return sInstance; } -void GamepadPlatformService::MonitoringState::AddObserver( - WeakPtr aParent) { +void GamepadMonitoringState::AddObserver(GamepadTestChannelParent* aParent) { AssertIsOnBackgroundThread(); MOZ_ASSERT(aParent); - MOZ_ASSERT(!mObservers.Contains(aParent)); - mObservers.AppendElement(std::move(aParent)); + MOZ_ALWAYS_TRUE(mObservers.append(aParent)); } -void GamepadPlatformService::MonitoringState::RemoveObserver( - GamepadTestChannelParent* aParent) { +void GamepadMonitoringState::RemoveObserver(GamepadTestChannelParent* aParent) { AssertIsOnBackgroundThread(); MOZ_ASSERT(aParent); - MOZ_ASSERT(mObservers.Contains(aParent)); - mObservers.RemoveElement(aParent); + + WeakPtr* observer = nullptr; + + for (auto& item : mObservers) { + if (item == aParent) { + observer = &item; + } + } + + MOZ_ASSERT( + observer, + "Attempted to remove a GamepadTestChannelParent that was never added"); + + std::swap(*observer, mObservers.back()); + mObservers.popBack(); } -bool GamepadPlatformService::MonitoringState::IsMonitoring() const { +bool GamepadMonitoringState::IsMonitoring() const { AssertIsOnBackgroundThread(); return mIsMonitoring; } -void GamepadPlatformService::MonitoringState::Set(bool aIsMonitoring) { +void GamepadMonitoringState::Set(bool aIsMonitoring) { AssertIsOnBackgroundThread(); if (mIsMonitoring != aIsMonitoring) { @@ -258,7 +269,7 @@ void GamepadPlatformService::AddChannelParent( StartGamepadMonitoring(); - mMonitoringState.Set(true); + GamepadMonitoringState::GetSingleton().Set(true); } void GamepadPlatformService::RemoveChannelParent( @@ -278,7 +289,7 @@ void GamepadPlatformService::RemoveChannelParent( } } - mMonitoringState.Set(false); + GamepadMonitoringState::GetSingleton().Set(false); StopGamepadMonitoring(); ResetGamepadIndexes(); diff --git a/dom/gamepad/GamepadPlatformService.h b/dom/gamepad/GamepadPlatformService.h index 608f27db8e76..70a86b14518d 100644 --- a/dom/gamepad/GamepadPlatformService.h +++ b/dom/gamepad/GamepadPlatformService.h @@ -12,6 +12,7 @@ #include #include "mozilla/Mutex.h" #include "mozilla/StaticPtr.h" +#include "mozilla/Vector.h" #include "mozilla/WeakPtr.h" namespace mozilla { @@ -23,6 +24,33 @@ enum class GamepadLightIndicatorType : uint8_t; struct GamepadPoseState; class GamepadTestChannelParent; struct GamepadTouchState; +class GamepadPlatformService; + +class GamepadMonitoringState { + public: + static GamepadMonitoringState& GetSingleton(); + + void AddObserver(GamepadTestChannelParent* aParent); + void RemoveObserver(GamepadTestChannelParent* aParent); + + bool IsMonitoring() const; + + GamepadMonitoringState(const GamepadMonitoringState&) = delete; + GamepadMonitoringState(GamepadMonitoringState&&) = delete; + GamepadMonitoringState& operator=(const GamepadMonitoringState) = delete; + GamepadMonitoringState& operator=(GamepadMonitoringState&&) = delete; + + private: + GamepadMonitoringState() = default; + ~GamepadMonitoringState() = default; + + void Set(bool aIsMonitoring); + + bool mIsMonitoring{false}; + Vector> mObservers; + + friend class mozilla::dom::GamepadPlatformService; +}; // Platform Service for building and transmitting IPDL messages // through the HAL sandbox. Used by platform specific @@ -39,30 +67,6 @@ struct GamepadTouchState; class GamepadPlatformService final { NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GamepadPlatformService) public: - class MonitoringState { - public: - MonitoringState() = default; - ~MonitoringState(); - - void AddObserver(WeakPtr aParent); - void RemoveObserver(GamepadTestChannelParent* aParent); - - bool IsMonitoring() const; - - MonitoringState(const MonitoringState&) = delete; - MonitoringState(MonitoringState&&) = delete; - MonitoringState& operator=(const MonitoringState) = delete; - MonitoringState& operator=(MonitoringState&&) = delete; - - private: - void Set(bool aIsMonitoring); - - bool mIsMonitoring{false}; - nsTArray> mObservers; - - friend class GamepadPlatformService; - }; - // Get the singleton service static already_AddRefed GetParentService(); @@ -117,8 +121,6 @@ class GamepadPlatformService final { void MaybeShutdown(); - MonitoringState& GetMonitoringState() { return mMonitoringState; } - private: GamepadPlatformService(); ~GamepadPlatformService(); @@ -140,8 +142,6 @@ class GamepadPlatformService final { Mutex mMutex; std::map mGamepadAdded; - - MonitoringState mMonitoringState; }; } // namespace dom diff --git a/dom/gamepad/ipc/GamepadTestChannelParent.cpp b/dom/gamepad/ipc/GamepadTestChannelParent.cpp index dc66454400a1..267a1b968b93 100644 --- a/dom/gamepad/ipc/GamepadTestChannelParent.cpp +++ b/dom/gamepad/ipc/GamepadTestChannelParent.cpp @@ -19,20 +19,12 @@ already_AddRefed GamepadTestChannelParent::Create() { GamepadTestChannelParent::GamepadTestChannelParent() { ::mozilla::ipc::AssertIsOnBackgroundThread(); - RefPtr service = - GamepadPlatformService::GetParentService(); - MOZ_ASSERT(service); - - service->GetMonitoringState().AddObserver(this); + GamepadMonitoringState::GetSingleton().AddObserver(this); } GamepadTestChannelParent::~GamepadTestChannelParent() { ::mozilla::ipc::AssertIsOnBackgroundThread(); - RefPtr service = - GamepadPlatformService::GetParentService(); - MOZ_ASSERT(service); - - service->GetMonitoringState().RemoveObserver(this); + GamepadMonitoringState::GetSingleton().RemoveObserver(this); } void GamepadTestChannelParent::AddGamepadToPlatformService( @@ -80,7 +72,7 @@ mozilla::ipc::IPCResult GamepadTestChannelParent::RecvGamepadTestEvent( // started. Everything else won't be deferred and will fail if monitoring // isn't running if (body.type() == GamepadChangeEventBody::TGamepadAdded) { - if (service->GetMonitoringState().IsMonitoring()) { + if (GamepadMonitoringState::GetSingleton().IsMonitoring()) { AddGamepadToPlatformService(aID, body.get_GamepadAdded()); } else { mDeferredGamepadAdded.AppendElement( @@ -89,7 +81,7 @@ mozilla::ipc::IPCResult GamepadTestChannelParent::RecvGamepadTestEvent( return IPC_OK(); } - if (!service->GetMonitoringState().IsMonitoring()) { + if (!GamepadMonitoringState::GetSingleton().IsMonitoring()) { return IPC_FAIL(this, "Simulated message received while not monitoring"); }