diff options
Diffstat (limited to 'dom/gamepad/ipc')
-rw-r--r-- | dom/gamepad/ipc/GamepadEventChannelChild.cpp | 63 | ||||
-rw-r--r-- | dom/gamepad/ipc/GamepadEventChannelChild.h | 41 | ||||
-rw-r--r-- | dom/gamepad/ipc/GamepadEventChannelParent.cpp | 116 | ||||
-rw-r--r-- | dom/gamepad/ipc/GamepadEventChannelParent.h | 51 | ||||
-rw-r--r-- | dom/gamepad/ipc/GamepadEventTypes.ipdlh | 78 | ||||
-rw-r--r-- | dom/gamepad/ipc/GamepadMessageUtils.h | 157 | ||||
-rw-r--r-- | dom/gamepad/ipc/GamepadTestChannelChild.cpp | 34 | ||||
-rw-r--r-- | dom/gamepad/ipc/GamepadTestChannelChild.h | 47 | ||||
-rw-r--r-- | dom/gamepad/ipc/GamepadTestChannelParent.cpp | 120 | ||||
-rw-r--r-- | dom/gamepad/ipc/GamepadTestChannelParent.h | 51 | ||||
-rw-r--r-- | dom/gamepad/ipc/PGamepadEventChannel.ipdl | 30 | ||||
-rw-r--r-- | dom/gamepad/ipc/PGamepadTestChannel.ipdl | 23 |
12 files changed, 811 insertions, 0 deletions
diff --git a/dom/gamepad/ipc/GamepadEventChannelChild.cpp b/dom/gamepad/ipc/GamepadEventChannelChild.cpp new file mode 100644 index 0000000000..9d1a07a662 --- /dev/null +++ b/dom/gamepad/ipc/GamepadEventChannelChild.cpp @@ -0,0 +1,63 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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 "GamepadEventChannelChild.h" +#include "mozilla/dom/GamepadManager.h" +#include "mozilla/dom/Promise.h" + +namespace mozilla::dom { + +namespace { + +class GamepadUpdateRunnable final : public Runnable { + public: + explicit GamepadUpdateRunnable(const GamepadChangeEvent& aGamepadEvent) + : Runnable("dom::GamepadUpdateRunnable"), mEvent(aGamepadEvent) {} + NS_IMETHOD Run() override { + RefPtr<GamepadManager> svc(GamepadManager::GetService()); + if (svc) { + svc->Update(mEvent); + } + return NS_OK; + } + + protected: + GamepadChangeEvent mEvent; +}; + +} // namespace + +already_AddRefed<GamepadEventChannelChild> GamepadEventChannelChild::Create() { + return RefPtr<GamepadEventChannelChild>(new GamepadEventChannelChild()) + .forget(); +} + +mozilla::ipc::IPCResult GamepadEventChannelChild::RecvGamepadUpdate( + const GamepadChangeEvent& aGamepadEvent) { + DebugOnly<nsresult> rv = + NS_DispatchToMainThread(new GamepadUpdateRunnable(aGamepadEvent)); + NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "NS_DispatchToMainThread failed"); + return IPC_OK(); +} + +void GamepadEventChannelChild::AddPromise(const uint32_t& aID, + dom::Promise* aPromise) { + MOZ_ASSERT(!mPromiseList.Get(aID, nullptr)); + mPromiseList.Put(aID, RefPtr{aPromise}); +} + +mozilla::ipc::IPCResult GamepadEventChannelChild::RecvReplyGamepadPromise( + const uint32_t& aPromiseID) { + RefPtr<dom::Promise> p; + if (!mPromiseList.Get(aPromiseID, getter_AddRefs(p))) { + MOZ_CRASH("We should always have a promise."); + } + + p->MaybeResolve(true); + mPromiseList.Remove(aPromiseID); + return IPC_OK(); +} + +} // namespace mozilla::dom diff --git a/dom/gamepad/ipc/GamepadEventChannelChild.h b/dom/gamepad/ipc/GamepadEventChannelChild.h new file mode 100644 index 0000000000..78d337e29c --- /dev/null +++ b/dom/gamepad/ipc/GamepadEventChannelChild.h @@ -0,0 +1,41 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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 "mozilla/dom/PGamepadEventChannelChild.h" +#include "nsRefPtrHashtable.h" + +#ifndef mozilla_dom_GamepadEventChannelChild_h_ +# define mozilla_dom_GamepadEventChannelChild_h_ + +namespace mozilla { +namespace dom { + +class GamepadEventChannelChild final : public PGamepadEventChannelChild { + public: + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GamepadEventChannelChild, override) + + static already_AddRefed<GamepadEventChannelChild> Create(); + + mozilla::ipc::IPCResult RecvGamepadUpdate( + const GamepadChangeEvent& aGamepadEvent); + mozilla::ipc::IPCResult RecvReplyGamepadPromise(const uint32_t& aPromiseID); + void AddPromise(const uint32_t& aID, dom::Promise* aPromise); + + GamepadEventChannelChild(const GamepadEventChannelChild&) = delete; + GamepadEventChannelChild(GamepadEventChannelChild&&) = delete; + GamepadEventChannelChild& operator=(const GamepadEventChannelChild&) = delete; + GamepadEventChannelChild& operator=(GamepadEventChannelChild&&) = delete; + + private: + GamepadEventChannelChild() = default; + ~GamepadEventChannelChild() = default; + + nsRefPtrHashtable<nsUint32HashKey, dom::Promise> mPromiseList; +}; + +} // namespace dom +} // namespace mozilla + +#endif diff --git a/dom/gamepad/ipc/GamepadEventChannelParent.cpp b/dom/gamepad/ipc/GamepadEventChannelParent.cpp new file mode 100644 index 0000000000..910650529f --- /dev/null +++ b/dom/gamepad/ipc/GamepadEventChannelParent.cpp @@ -0,0 +1,116 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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 "GamepadEventChannelParent.h" +#include "GamepadPlatformService.h" +#include "mozilla/dom/GamepadMonitoring.h" +#include "mozilla/ipc/BackgroundParent.h" +#include "nsThreadUtils.h" + +namespace mozilla::dom { + +using namespace mozilla::ipc; + +namespace { + +class SendGamepadUpdateRunnable final : public Runnable { + private: + ~SendGamepadUpdateRunnable() = default; + RefPtr<GamepadEventChannelParent> mParent; + GamepadChangeEvent mEvent; + + public: + SendGamepadUpdateRunnable(GamepadEventChannelParent* aParent, + GamepadChangeEvent aEvent) + : Runnable("dom::SendGamepadUpdateRunnable"), + mParent(aParent), + mEvent(aEvent) { + MOZ_ASSERT(mParent); + } + NS_IMETHOD Run() override { + AssertIsOnBackgroundThread(); + Unused << mParent->SendGamepadUpdate(mEvent); + return NS_OK; + } +}; + +} // namespace + +already_AddRefed<GamepadEventChannelParent> +GamepadEventChannelParent::Create() { + return RefPtr<GamepadEventChannelParent>(new GamepadEventChannelParent()) + .forget(); +} + +GamepadEventChannelParent::GamepadEventChannelParent() : mIsShutdown{false} { + MOZ_DIAGNOSTIC_ASSERT(IsOnBackgroundThread()); + + mBackgroundEventTarget = GetCurrentEventTarget(); + + RefPtr<GamepadPlatformService> service = + GamepadPlatformService::GetParentService(); + MOZ_ASSERT(service); + + service->AddChannelParent(this); +} + +void GamepadEventChannelParent::ActorDestroy(ActorDestroyReason aWhy) { + MOZ_DIAGNOSTIC_ASSERT(IsOnBackgroundThread()); + MOZ_DIAGNOSTIC_ASSERT(!mIsShutdown); + + mIsShutdown = true; + + RefPtr<GamepadPlatformService> service = + GamepadPlatformService::GetParentService(); + MOZ_ASSERT(service); + service->RemoveChannelParent(this); +} + +mozilla::ipc::IPCResult GamepadEventChannelParent::RecvVibrateHaptic( + const Tainted<GamepadHandle>& aHandle, + const Tainted<uint32_t>& aHapticIndex, const Tainted<double>& aIntensity, + const Tainted<double>& aDuration, const Tainted<uint32_t>& aPromiseID) { + // TODO: Bug 680289, implement for standard gamepads + + // TODO: simplify tainted validation, see 1610570 + if (SendReplyGamepadPromise(MOZ_NO_VALIDATE( + aPromiseID, + "This value is unused aside from being passed back to the child."))) { + return IPC_OK(); + } + + return IPC_FAIL(this, "SendReplyGamepadPromise fail."); +} + +mozilla::ipc::IPCResult GamepadEventChannelParent::RecvStopVibrateHaptic( + const Tainted<GamepadHandle>& aHandle) { + // TODO: Bug 680289, implement for standard gamepads + return IPC_OK(); +} + +mozilla::ipc::IPCResult GamepadEventChannelParent::RecvLightIndicatorColor( + const Tainted<GamepadHandle>& aHandle, + const Tainted<uint32_t>& aLightColorIndex, const Tainted<uint8_t>& aRed, + const Tainted<uint8_t>& aGreen, const Tainted<uint8_t>& aBlue, + const Tainted<uint32_t>& aPromiseID) { + SetGamepadLightIndicatorColor(aHandle, aLightColorIndex, aRed, aGreen, aBlue); + + // TODO: simplify tainted validation, see 1610570 + if (SendReplyGamepadPromise(MOZ_NO_VALIDATE( + aPromiseID, + "This value is unused aside from being passed back to the child."))) { + return IPC_OK(); + } + + return IPC_FAIL(this, "SendReplyGamepadPromise fail."); +} + +void GamepadEventChannelParent::DispatchUpdateEvent( + const GamepadChangeEvent& aEvent) { + mBackgroundEventTarget->Dispatch(new SendGamepadUpdateRunnable(this, aEvent), + NS_DISPATCH_NORMAL); +} + +} // namespace mozilla::dom diff --git a/dom/gamepad/ipc/GamepadEventChannelParent.h b/dom/gamepad/ipc/GamepadEventChannelParent.h new file mode 100644 index 0000000000..748b243172 --- /dev/null +++ b/dom/gamepad/ipc/GamepadEventChannelParent.h @@ -0,0 +1,51 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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 "mozilla/dom/PGamepadEventChannelParent.h" + +#ifndef mozilla_dom_GamepadEventChannelParent_h_ +# define mozilla_dom_GamepadEventChannelParent_h_ + +namespace mozilla { +namespace dom { + +class GamepadEventChannelParent final : public PGamepadEventChannelParent { + public: + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GamepadEventChannelParent, override) + + static already_AddRefed<GamepadEventChannelParent> Create(); + void ActorDestroy(ActorDestroyReason aWhy) override; + + mozilla::ipc::IPCResult RecvVibrateHaptic( + const Tainted<GamepadHandle>& aHandle, + const Tainted<uint32_t>& aHapticIndex, const Tainted<double>& aIntensity, + const Tainted<double>& aDuration, const Tainted<uint32_t>& aPromiseID); + mozilla::ipc::IPCResult RecvStopVibrateHaptic( + const Tainted<GamepadHandle>& aHandle); + mozilla::ipc::IPCResult RecvLightIndicatorColor( + const Tainted<GamepadHandle>& aHandle, + const Tainted<uint32_t>& aLightColorIndex, const Tainted<uint8_t>& aRed, + const Tainted<uint8_t>& aGreen, const Tainted<uint8_t>& aBlue, + const Tainted<uint32_t>& aPromiseID); + void DispatchUpdateEvent(const GamepadChangeEvent& aEvent); + + GamepadEventChannelParent(const GamepadEventChannelParent&) = delete; + GamepadEventChannelParent(GamepadEventChannelParent&&) = delete; + GamepadEventChannelParent& operator=(const GamepadEventChannelParent&) = + delete; + GamepadEventChannelParent& operator=(GamepadEventChannelParent&&) = delete; + + private: + GamepadEventChannelParent(); + ~GamepadEventChannelParent() = default; + + bool mIsShutdown; + nsCOMPtr<nsIEventTarget> mBackgroundEventTarget; +}; + +} // namespace dom +} // namespace mozilla + +#endif diff --git a/dom/gamepad/ipc/GamepadEventTypes.ipdlh b/dom/gamepad/ipc/GamepadEventTypes.ipdlh new file mode 100644 index 0000000000..4ac1d7dc93 --- /dev/null +++ b/dom/gamepad/ipc/GamepadEventTypes.ipdlh @@ -0,0 +1,78 @@ +/* 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 "mozilla/dom/GamepadMessageUtils.h"; + +using mozilla::dom::GamepadPoseState from "mozilla/dom/GamepadPoseState.h"; +using mozilla::dom::GamepadTouchState from "mozilla/dom/GamepadTouchState.h"; +using mozilla::dom::GamepadLightIndicatorType from "mozilla/dom/GamepadLightIndicatorBinding.h"; +using mozilla::dom::GamepadMappingType from "mozilla/dom/GamepadBinding.h"; +using mozilla::dom::GamepadHand from "mozilla/dom/GamepadBinding.h"; +using mozilla::dom::GamepadHandle from "mozilla/dom/GamepadHandle.h"; + +namespace mozilla { +namespace dom { + +struct GamepadAdded { + nsString id; + GamepadMappingType mapping; + GamepadHand hand; + uint32_t display_id; + uint32_t num_buttons; + uint32_t num_axes; + uint32_t num_haptics; + uint32_t num_lights; + uint32_t num_touches; +}; + +struct GamepadRemoved {}; + +struct GamepadAxisInformation { + uint32_t axis; + double value; +}; + +struct GamepadButtonInformation { + uint32_t button; + double value; + bool pressed; + bool touched; +}; + +struct GamepadPoseInformation { + GamepadPoseState pose_state; +}; + +struct GamepadLightIndicatorTypeInformation { + uint32_t light; + GamepadLightIndicatorType type; +}; + +struct GamepadHandInformation { + GamepadHand hand; +}; + +struct GamepadTouchInformation { + uint32_t index; + GamepadTouchState touch_state; +}; + +union GamepadChangeEventBody { + GamepadAdded; + GamepadRemoved; + GamepadAxisInformation; + GamepadButtonInformation; + GamepadHandInformation; + GamepadLightIndicatorTypeInformation; + GamepadPoseInformation; + GamepadTouchInformation; +}; + +struct GamepadChangeEvent { + GamepadHandle handle; + GamepadChangeEventBody body; +}; + +} // namespace dom +} // namespace mozilla
\ No newline at end of file diff --git a/dom/gamepad/ipc/GamepadMessageUtils.h b/dom/gamepad/ipc/GamepadMessageUtils.h new file mode 100644 index 0000000000..0332548a76 --- /dev/null +++ b/dom/gamepad/ipc/GamepadMessageUtils.h @@ -0,0 +1,157 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#ifndef mozilla_dom_gamepad_GamepadMessageUtils_h +#define mozilla_dom_gamepad_GamepadMessageUtils_h + +#include "ipc/EnumSerializer.h" +#include "mozilla/dom/GamepadBinding.h" +#include "mozilla/dom/GamepadHandle.h" +#include "mozilla/dom/GamepadLightIndicatorBinding.h" +#include "mozilla/dom/GamepadPoseState.h" +#include "mozilla/dom/GamepadTouchState.h" + +namespace IPC { + +template <> +struct ParamTraits<mozilla::dom::GamepadLightIndicatorType> + : public ContiguousEnumSerializer< + mozilla::dom::GamepadLightIndicatorType, + mozilla::dom::GamepadLightIndicatorType(0), + mozilla::dom::GamepadLightIndicatorType( + mozilla::dom::GamepadLightIndicatorType::EndGuard_)> {}; + +template <> +struct ParamTraits<mozilla::dom::GamepadMappingType> + : public ContiguousEnumSerializer< + mozilla::dom::GamepadMappingType, mozilla::dom::GamepadMappingType(0), + mozilla::dom::GamepadMappingType( + mozilla::dom::GamepadMappingType::EndGuard_)> {}; + +template <> +struct ParamTraits<mozilla::dom::GamepadHand> + : public ContiguousEnumSerializer< + mozilla::dom::GamepadHand, mozilla::dom::GamepadHand(0), + mozilla::dom::GamepadHand(mozilla::dom::GamepadHand::EndGuard_)> {}; + +template <> +struct ParamTraits<mozilla::dom::GamepadCapabilityFlags> + : public BitFlagsEnumSerializer< + mozilla::dom::GamepadCapabilityFlags, + mozilla::dom::GamepadCapabilityFlags::Cap_All> {}; + +template <> +struct ParamTraits<mozilla::dom::GamepadPoseState> { + typedef mozilla::dom::GamepadPoseState paramType; + + static void Write(Message* aMsg, const paramType& aParam) { + WriteParam(aMsg, aParam.flags); + WriteParam(aMsg, aParam.orientation[0]); + WriteParam(aMsg, aParam.orientation[1]); + WriteParam(aMsg, aParam.orientation[2]); + WriteParam(aMsg, aParam.orientation[3]); + WriteParam(aMsg, aParam.position[0]); + WriteParam(aMsg, aParam.position[1]); + WriteParam(aMsg, aParam.position[2]); + WriteParam(aMsg, aParam.angularVelocity[0]); + WriteParam(aMsg, aParam.angularVelocity[1]); + WriteParam(aMsg, aParam.angularVelocity[2]); + WriteParam(aMsg, aParam.angularAcceleration[0]); + WriteParam(aMsg, aParam.angularAcceleration[1]); + WriteParam(aMsg, aParam.angularAcceleration[2]); + WriteParam(aMsg, aParam.linearVelocity[0]); + WriteParam(aMsg, aParam.linearVelocity[1]); + WriteParam(aMsg, aParam.linearVelocity[2]); + WriteParam(aMsg, aParam.linearAcceleration[0]); + WriteParam(aMsg, aParam.linearAcceleration[1]); + WriteParam(aMsg, aParam.linearAcceleration[2]); + WriteParam(aMsg, aParam.isPositionValid); + WriteParam(aMsg, aParam.isOrientationValid); + } + + static bool Read(const Message* aMsg, PickleIterator* aIter, + paramType* aResult) { + if (!ReadParam(aMsg, aIter, &(aResult->flags)) || + !ReadParam(aMsg, aIter, &(aResult->orientation[0])) || + !ReadParam(aMsg, aIter, &(aResult->orientation[1])) || + !ReadParam(aMsg, aIter, &(aResult->orientation[2])) || + !ReadParam(aMsg, aIter, &(aResult->orientation[3])) || + !ReadParam(aMsg, aIter, &(aResult->position[0])) || + !ReadParam(aMsg, aIter, &(aResult->position[1])) || + !ReadParam(aMsg, aIter, &(aResult->position[2])) || + !ReadParam(aMsg, aIter, &(aResult->angularVelocity[0])) || + !ReadParam(aMsg, aIter, &(aResult->angularVelocity[1])) || + !ReadParam(aMsg, aIter, &(aResult->angularVelocity[2])) || + !ReadParam(aMsg, aIter, &(aResult->angularAcceleration[0])) || + !ReadParam(aMsg, aIter, &(aResult->angularAcceleration[1])) || + !ReadParam(aMsg, aIter, &(aResult->angularAcceleration[2])) || + !ReadParam(aMsg, aIter, &(aResult->linearVelocity[0])) || + !ReadParam(aMsg, aIter, &(aResult->linearVelocity[1])) || + !ReadParam(aMsg, aIter, &(aResult->linearVelocity[2])) || + !ReadParam(aMsg, aIter, &(aResult->linearAcceleration[0])) || + !ReadParam(aMsg, aIter, &(aResult->linearAcceleration[1])) || + !ReadParam(aMsg, aIter, &(aResult->linearAcceleration[2])) || + !ReadParam(aMsg, aIter, &(aResult->isPositionValid)) || + !ReadParam(aMsg, aIter, &(aResult->isOrientationValid))) { + return false; + } + return true; + } +}; + +template <> +struct ParamTraits<mozilla::dom::GamepadTouchState> { + typedef mozilla::dom::GamepadTouchState paramType; + + static void Write(Message* aMsg, const paramType& aParam) { + WriteParam(aMsg, aParam.touchId); + WriteParam(aMsg, aParam.surfaceId); + WriteParam(aMsg, aParam.position[0]); + WriteParam(aMsg, aParam.position[1]); + WriteParam(aMsg, aParam.surfaceDimensions[0]); + WriteParam(aMsg, aParam.surfaceDimensions[1]); + WriteParam(aMsg, aParam.isSurfaceDimensionsValid); + } + + static bool Read(const Message* aMsg, PickleIterator* aIter, + paramType* aResult) { + if (!ReadParam(aMsg, aIter, &(aResult->touchId)) || + !ReadParam(aMsg, aIter, &(aResult->surfaceId)) || + !ReadParam(aMsg, aIter, &(aResult->position[0])) || + !ReadParam(aMsg, aIter, &(aResult->position[1])) || + !ReadParam(aMsg, aIter, &(aResult->surfaceDimensions[0])) || + !ReadParam(aMsg, aIter, &(aResult->surfaceDimensions[1])) || + !ReadParam(aMsg, aIter, &(aResult->isSurfaceDimensionsValid))) { + return false; + } + return true; + } +}; + +template <> +struct ParamTraits<mozilla::dom::GamepadHandleKind> + : public ContiguousEnumSerializerInclusive< + mozilla::dom::GamepadHandleKind, + mozilla::dom::GamepadHandleKind::GamepadPlatformManager, + mozilla::dom::GamepadHandleKind::VR> {}; + +template <> +struct ParamTraits<mozilla::dom::GamepadHandle> { + typedef mozilla::dom::GamepadHandle paramType; + static void Write(Message* aMsg, const paramType& aParam) { + WriteParam(aMsg, aParam.mValue); + WriteParam(aMsg, aParam.mKind); + } + static bool Read(const Message* aMsg, PickleIterator* aIter, + paramType* aParam) { + return ReadParam(aMsg, aIter, &aParam->mValue) && + ReadParam(aMsg, aIter, &aParam->mKind); + } +}; + +} // namespace IPC + +#endif // mozilla_dom_gamepad_GamepadMessageUtils_h diff --git a/dom/gamepad/ipc/GamepadTestChannelChild.cpp b/dom/gamepad/ipc/GamepadTestChannelChild.cpp new file mode 100644 index 0000000000..d74e0736ce --- /dev/null +++ b/dom/gamepad/ipc/GamepadTestChannelChild.cpp @@ -0,0 +1,34 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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 "GamepadTestChannelChild.h" + +#include "mozilla/dom/GamepadServiceTest.h" + +namespace mozilla::dom { + +already_AddRefed<GamepadTestChannelChild> GamepadTestChannelChild::Create( + GamepadServiceTest* aGamepadServiceTest) { + return RefPtr<GamepadTestChannelChild>( + new GamepadTestChannelChild(aGamepadServiceTest)) + .forget(); +} + +GamepadTestChannelChild::GamepadTestChannelChild( + GamepadServiceTest* aGamepadServiceTest) + : mGamepadServiceTest(aGamepadServiceTest) {} + +mozilla::ipc::IPCResult GamepadTestChannelChild::RecvReplyGamepadHandle( + const uint32_t& aID, const GamepadHandle& aHandle) { + MOZ_RELEASE_ASSERT( + mGamepadServiceTest, + "Test channel should never outlive the owning GamepadServiceTest"); + + mGamepadServiceTest->ReplyGamepadHandle(aID, aHandle); + return IPC_OK(); +} + +} // namespace mozilla::dom diff --git a/dom/gamepad/ipc/GamepadTestChannelChild.h b/dom/gamepad/ipc/GamepadTestChannelChild.h new file mode 100644 index 0000000000..056b0d038c --- /dev/null +++ b/dom/gamepad/ipc/GamepadTestChannelChild.h @@ -0,0 +1,47 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#ifndef mozilla_dom_GamepadTestChannelChild_h_ +#define mozilla_dom_GamepadTestChannelChild_h_ + +#include "mozilla/dom/PGamepadTestChannelChild.h" +#include "mozilla/dom/Promise.h" +#include "mozilla/WeakPtr.h" +#include "nsRefPtrHashtable.h" + +namespace mozilla { +namespace dom { + +class GamepadServiceTest; + +class GamepadTestChannelChild final : public PGamepadTestChannelChild { + public: + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GamepadTestChannelChild) + + static already_AddRefed<GamepadTestChannelChild> Create( + GamepadServiceTest* aGamepadServiceTest); + + GamepadTestChannelChild(const GamepadTestChannelChild&) = delete; + GamepadTestChannelChild(GamepadTestChannelChild&&) = delete; + GamepadTestChannelChild& operator=(const GamepadTestChannelChild&) = delete; + GamepadTestChannelChild& operator=(GamepadTestChannelChild&&) = delete; + + private: + explicit GamepadTestChannelChild(GamepadServiceTest* aGamepadServiceTest); + ~GamepadTestChannelChild() = default; + + mozilla::ipc::IPCResult RecvReplyGamepadHandle(const uint32_t& aID, + const GamepadHandle& aHandle); + + WeakPtr<GamepadServiceTest> mGamepadServiceTest; + + friend class PGamepadTestChannelChild; +}; + +} // namespace dom +} // namespace mozilla + +#endif diff --git a/dom/gamepad/ipc/GamepadTestChannelParent.cpp b/dom/gamepad/ipc/GamepadTestChannelParent.cpp new file mode 100644 index 0000000000..ca6ab7cf00 --- /dev/null +++ b/dom/gamepad/ipc/GamepadTestChannelParent.cpp @@ -0,0 +1,120 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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 "GamepadTestChannelParent.h" + +#include "mozilla/dom/GamepadPlatformService.h" +#include "mozilla/ipc/BackgroundParent.h" +#include "mozilla/Unused.h" + +namespace mozilla::dom { + +already_AddRefed<GamepadTestChannelParent> GamepadTestChannelParent::Create() { + return RefPtr<GamepadTestChannelParent>(new GamepadTestChannelParent()) + .forget(); +} + +GamepadTestChannelParent::GamepadTestChannelParent() { + ::mozilla::ipc::AssertIsOnBackgroundThread(); + GamepadMonitoringState::GetSingleton().AddObserver(this); +} + +GamepadTestChannelParent::~GamepadTestChannelParent() { + ::mozilla::ipc::AssertIsOnBackgroundThread(); + GamepadMonitoringState::GetSingleton().RemoveObserver(this); +} + +void GamepadTestChannelParent::AddGamepadToPlatformService( + uint32_t aPromiseId, const GamepadAdded& aGamepadAdded) { + mozilla::ipc::AssertIsOnBackgroundThread(); + + RefPtr<GamepadPlatformService> service = + GamepadPlatformService::GetParentService(); + MOZ_ASSERT(service); + + const GamepadAdded& a = aGamepadAdded; + nsCString gamepadID; + LossyCopyUTF16toASCII(a.id(), gamepadID); + GamepadHandle handle = service->AddGamepad( + gamepadID.get(), static_cast<GamepadMappingType>(a.mapping()), a.hand(), + a.num_buttons(), a.num_axes(), a.num_haptics(), a.num_lights(), + a.num_touches()); + + Unused << SendReplyGamepadHandle(aPromiseId, handle); +} + +void GamepadTestChannelParent::OnMonitoringStateChanged(bool aNewState) { + mozilla::ipc::AssertIsOnBackgroundThread(); + + if (aNewState) { + for (auto& deferredGamepadAdd : mDeferredGamepadAdded) { + AddGamepadToPlatformService(deferredGamepadAdd.promiseId, + deferredGamepadAdd.gamepadAdded); + } + mDeferredGamepadAdded.Clear(); + } +} + +mozilla::ipc::IPCResult GamepadTestChannelParent::RecvGamepadTestEvent( + const uint32_t& aID, const GamepadChangeEvent& aEvent) { + mozilla::ipc::AssertIsOnBackgroundThread(); + + RefPtr<GamepadPlatformService> service = + GamepadPlatformService::GetParentService(); + MOZ_ASSERT(service); + + const GamepadChangeEventBody& body = aEvent.body(); + + // GamepadAdded is special because it will be deferred if monitoring hasn't + // started. Everything else won't be deferred and will fail if monitoring + // isn't running + if (body.type() == GamepadChangeEventBody::TGamepadAdded) { + if (GamepadMonitoringState::GetSingleton().IsMonitoring()) { + AddGamepadToPlatformService(aID, body.get_GamepadAdded()); + } else { + mDeferredGamepadAdded.AppendElement( + DeferredGamepadAdded{aID, body.get_GamepadAdded()}); + } + return IPC_OK(); + } + + if (!GamepadMonitoringState::GetSingleton().IsMonitoring()) { + return IPC_FAIL(this, "Simulated message received while not monitoring"); + } + + GamepadHandle handle = aEvent.handle(); + + if (body.type() == GamepadChangeEventBody::TGamepadRemoved) { + service->RemoveGamepad(handle); + return IPC_OK(); + } + if (body.type() == GamepadChangeEventBody::TGamepadButtonInformation) { + const GamepadButtonInformation& a = body.get_GamepadButtonInformation(); + service->NewButtonEvent(handle, a.button(), a.pressed(), a.touched(), + a.value()); + return IPC_OK(); + } + if (body.type() == GamepadChangeEventBody::TGamepadAxisInformation) { + const GamepadAxisInformation& a = body.get_GamepadAxisInformation(); + service->NewAxisMoveEvent(handle, a.axis(), a.value()); + return IPC_OK(); + } + if (body.type() == GamepadChangeEventBody::TGamepadPoseInformation) { + const GamepadPoseInformation& a = body.get_GamepadPoseInformation(); + service->NewPoseEvent(handle, a.pose_state()); + return IPC_OK(); + } + if (body.type() == GamepadChangeEventBody::TGamepadTouchInformation) { + const GamepadTouchInformation& a = body.get_GamepadTouchInformation(); + service->NewMultiTouchEvent(handle, a.index(), a.touch_state()); + return IPC_OK(); + } + + NS_WARNING("Unknown event type."); + return IPC_FAIL_NO_REASON(this); +} + +} // namespace mozilla::dom diff --git a/dom/gamepad/ipc/GamepadTestChannelParent.h b/dom/gamepad/ipc/GamepadTestChannelParent.h new file mode 100644 index 0000000000..a89077ffc7 --- /dev/null +++ b/dom/gamepad/ipc/GamepadTestChannelParent.h @@ -0,0 +1,51 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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 "mozilla/dom/PGamepadTestChannelParent.h" +#include "mozilla/WeakPtr.h" + +#ifndef mozilla_dom_GamepadTestChannelParent_h_ +# define mozilla_dom_GamepadTestChannelParent_h_ + +namespace mozilla { +namespace dom { + +class GamepadTestChannelParent final : public PGamepadTestChannelParent, + public SupportsWeakPtr { + public: + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GamepadTestChannelParent) + + static already_AddRefed<GamepadTestChannelParent> Create(); + + mozilla::ipc::IPCResult RecvGamepadTestEvent( + const uint32_t& aID, const GamepadChangeEvent& aGamepadEvent); + + void OnMonitoringStateChanged(bool aNewState); + + GamepadTestChannelParent(const GamepadTestChannelParent&) = delete; + GamepadTestChannelParent(GamepadTestChannelParent&&) = delete; + GamepadTestChannelParent& operator=(const GamepadTestChannelParent&) = delete; + GamepadTestChannelParent& operator=(GamepadTestChannelParent&&) = delete; + + private: + struct DeferredGamepadAdded { + uint32_t promiseId; + GamepadAdded gamepadAdded; + }; + + GamepadTestChannelParent(); + ~GamepadTestChannelParent(); + + void AddGamepadToPlatformService(uint32_t aPromiseId, + const GamepadAdded& aGamepadAdded); + + nsTArray<DeferredGamepadAdded> mDeferredGamepadAdded; +}; + +} // namespace dom +} // namespace mozilla + +#endif diff --git a/dom/gamepad/ipc/PGamepadEventChannel.ipdl b/dom/gamepad/ipc/PGamepadEventChannel.ipdl new file mode 100644 index 0000000000..b2f056fa5b --- /dev/null +++ b/dom/gamepad/ipc/PGamepadEventChannel.ipdl @@ -0,0 +1,30 @@ +/* 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 protocol PBackground; +include "mozilla/dom/GamepadMessageUtils.h"; +include GamepadEventTypes; + +using mozilla::dom::GamepadHandle from "mozilla/dom/GamepadHandle.h"; + +namespace mozilla { +namespace dom { + +refcounted protocol PGamepadEventChannel { + manager PBackground; + parent: + async __delete__(); + + async VibrateHaptic(GamepadHandle aHandle, uint32_t aHapticIndex, + double aIntensity, double aDuration, uint32_t aPromiseID) tainted; + async StopVibrateHaptic(GamepadHandle aHandle) tainted; + async LightIndicatorColor(GamepadHandle aHandle, uint32_t aLightColorIndex, + uint8_t aRed, uint8_t aGreen, uint8_t aBlue, uint32_t aPromiseID) tainted; + + child: + async GamepadUpdate(GamepadChangeEvent aGamepadEvent); + async ReplyGamepadPromise(uint32_t aPromiseID); +}; + +} +} diff --git a/dom/gamepad/ipc/PGamepadTestChannel.ipdl b/dom/gamepad/ipc/PGamepadTestChannel.ipdl new file mode 100644 index 0000000000..2d0d25d782 --- /dev/null +++ b/dom/gamepad/ipc/PGamepadTestChannel.ipdl @@ -0,0 +1,23 @@ +/* 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 protocol PBackground; +include "mozilla/dom/GamepadMessageUtils.h"; +include GamepadEventTypes; + +using mozilla::dom::GamepadHandle from "mozilla/dom/GamepadHandle.h"; + +namespace mozilla { +namespace dom { + +refcounted protocol PGamepadTestChannel { + manager PBackground; + parent: + async GamepadTestEvent(uint32_t aID, GamepadChangeEvent aGamepadEvent); + async __delete__(); + child: + async ReplyGamepadHandle(uint32_t aID, GamepadHandle aHandle); +}; + +} +} |