Bug 1657404 - Gamepad: Make a singleton to hold monitoring observers r=handyman

Currently, the list of monitoring observers is stored in the
GamepadPlatformService. But it's possible for testing to start before an
event channel has been created, or to exist longer. That could result in the
GamepadPlatformManager being created-destroyed multiple times along with
this list.

Probably the simplest thing to do here is just have the list be its own
indepedent entity

Differential Revision: https://phabricator.services.mozilla.com/D96663
This commit is contained in:
Chris Martin 2020-12-02 22:32:30 +00:00
Родитель 14d936a94d
Коммит 6ecf1f1858
3 изменённых файлов: 58 добавлений и 55 удалений

Просмотреть файл

@ -28,33 +28,44 @@ StaticRefPtr<GamepadPlatformService> 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<GamepadTestChannelParent> 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<GamepadTestChannelParent>* 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();

Просмотреть файл

@ -12,6 +12,7 @@
#include <map>
#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<WeakPtr<GamepadTestChannelParent>> 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<GamepadTestChannelParent> 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<WeakPtr<GamepadTestChannelParent>> mObservers;
friend class GamepadPlatformService;
};
// Get the singleton service
static already_AddRefed<GamepadPlatformService> 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<uint32_t, GamepadAdded> mGamepadAdded;
MonitoringState mMonitoringState;
};
} // namespace dom

Просмотреть файл

@ -19,20 +19,12 @@ already_AddRefed<GamepadTestChannelParent> GamepadTestChannelParent::Create() {
GamepadTestChannelParent::GamepadTestChannelParent() {
::mozilla::ipc::AssertIsOnBackgroundThread();
RefPtr<GamepadPlatformService> service =
GamepadPlatformService::GetParentService();
MOZ_ASSERT(service);
service->GetMonitoringState().AddObserver(this);
GamepadMonitoringState::GetSingleton().AddObserver(this);
}
GamepadTestChannelParent::~GamepadTestChannelParent() {
::mozilla::ipc::AssertIsOnBackgroundThread();
RefPtr<GamepadPlatformService> 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");
}