From 51042398ff8940427fda139867e940a67dc5b73c Mon Sep 17 00:00:00 2001 From: Chih-Yi Leu Date: Sun, 23 Oct 2016 19:32:00 +0200 Subject: [PATCH] Bug 1283193 - Add buffer mechanism in GamepadPlatformService to prevent dispatch failure in Mochitest. r=ted --- dom/gamepad/GamepadPlatformService.cpp | 29 ++++++++++++++++++++++++++ dom/gamepad/GamepadPlatformService.h | 9 ++++++++ 2 files changed, 38 insertions(+) diff --git a/dom/gamepad/GamepadPlatformService.cpp b/dom/gamepad/GamepadPlatformService.cpp index 564458605ac9..4a2ecb6e9729 100644 --- a/dom/gamepad/GamepadPlatformService.cpp +++ b/dom/gamepad/GamepadPlatformService.cpp @@ -70,6 +70,14 @@ GamepadPlatformService::NotifyGamepadChange(const T& aInfo) // mChannelParents may be accessed by background thread in the // same time, we use mutex to prevent possible race condtion MutexAutoLock autoLock(mMutex); + + // Buffer all events if we have no Channel to dispatch, which + // may happen when performing Mochitest. + if (mChannelParents.IsEmpty()) { + mPendingEvents.AppendElement(e); + return; + } + for(uint32_t i = 0; i < mChannelParents.Length(); ++i) { mChannelParents[i]->DispatchUpdateEvent(e); } @@ -163,6 +171,27 @@ GamepadPlatformService::AddChannelParent(GamepadEventChannelParent* aParent) // We use mutex here to prevent race condition with monitor thread MutexAutoLock autoLock(mMutex); mChannelParents.AppendElement(aParent); + FlushPendingEvents(); +} + +void +GamepadPlatformService::FlushPendingEvents() +{ + AssertIsOnBackgroundThread(); + MOZ_ASSERT(!mChannelParents.IsEmpty()); + + if (mPendingEvents.IsEmpty()) { + return; + } + + // NOTE: This method must be called with mMutex held because it accesses + // mChannelParents. + for (uint32_t i=0; iDispatchUpdateEvent(mPendingEvents[j]); + } + } + mPendingEvents.Clear(); } void diff --git a/dom/gamepad/GamepadPlatformService.h b/dom/gamepad/GamepadPlatformService.h index 5e4a3eb1d51b..0a61281e4275 100644 --- a/dom/gamepad/GamepadPlatformService.h +++ b/dom/gamepad/GamepadPlatformService.h @@ -74,6 +74,10 @@ class GamepadPlatformService final GamepadPlatformService(); ~GamepadPlatformService(); template void NotifyGamepadChange(const T& aInfo); + + // Flush all pending events buffered in mPendingEvents, must be called + // with mMutex held + void FlushPendingEvents(); void Cleanup(); // mGamepadIndex can only be accessed by monitor thread @@ -87,6 +91,11 @@ class GamepadPlatformService final // This mutex protects mChannelParents from race condition // between background and monitor thread Mutex mMutex; + + // In mochitest, it is possible that the test Events is synthesized + // before GamepadEventChannel created, we need to buffer all events + // until the channel is created if that happens. + nsTArray mPendingEvents; }; } // namespace dom