summaryrefslogtreecommitdiffstats
path: root/dom/gamepad/ipc
diff options
context:
space:
mode:
Diffstat (limited to 'dom/gamepad/ipc')
-rw-r--r--dom/gamepad/ipc/GamepadEventChannelChild.cpp63
-rw-r--r--dom/gamepad/ipc/GamepadEventChannelChild.h39
-rw-r--r--dom/gamepad/ipc/GamepadEventChannelParent.cpp109
-rw-r--r--dom/gamepad/ipc/GamepadEventChannelParent.h48
-rw-r--r--dom/gamepad/ipc/GamepadEventTypes.ipdlh78
-rw-r--r--dom/gamepad/ipc/GamepadMessageUtils.h154
-rw-r--r--dom/gamepad/ipc/GamepadTestChannelChild.cpp34
-rw-r--r--dom/gamepad/ipc/GamepadTestChannelChild.h45
-rw-r--r--dom/gamepad/ipc/GamepadTestChannelParent.cpp129
-rw-r--r--dom/gamepad/ipc/GamepadTestChannelParent.h49
-rw-r--r--dom/gamepad/ipc/PGamepadEventChannel.ipdl31
-rw-r--r--dom/gamepad/ipc/PGamepadTestChannel.ipdl23
12 files changed, 802 insertions, 0 deletions
diff --git a/dom/gamepad/ipc/GamepadEventChannelChild.cpp b/dom/gamepad/ipc/GamepadEventChannelChild.cpp
new file mode 100644
index 0000000000..ef8528f565
--- /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.Contains(aID));
+ mPromiseList.InsertOrUpdate(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..97fd0576a4
--- /dev/null
+++ b/dom/gamepad/ipc/GamepadEventChannelChild.h
@@ -0,0 +1,39 @@
+/* -*- 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::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 mozilla::dom
+
+#endif
diff --git a/dom/gamepad/ipc/GamepadEventChannelParent.cpp b/dom/gamepad/ipc/GamepadEventChannelParent.cpp
new file mode 100644
index 0000000000..4a21948c06
--- /dev/null
+++ b/dom/gamepad/ipc/GamepadEventChannelParent.cpp
@@ -0,0 +1,109 @@
+/* -*- 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 = GetCurrentSerialEventTarget();
+
+ 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 uint32_t& aPromiseID) {
+ // TODO: Bug 680289, implement for standard gamepads
+
+ if (SendReplyGamepadPromise(aPromiseID)) {
+ 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 uint8_t& aRed,
+ const uint8_t& aGreen, const uint8_t& aBlue, const uint32_t& aPromiseID) {
+ SetGamepadLightIndicatorColor(aHandle, aLightColorIndex, aRed, aGreen, aBlue);
+
+ if (SendReplyGamepadPromise(aPromiseID)) {
+ 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..90bb7e7f4d
--- /dev/null
+++ b/dom/gamepad/ipc/GamepadEventChannelParent.h
@@ -0,0 +1,48 @@
+/* -*- 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::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 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 uint8_t& aRed,
+ const uint8_t& aGreen, const uint8_t& aBlue, const 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 mozilla::dom
+
+#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..c29293d3a5
--- /dev/null
+++ b/dom/gamepad/ipc/GamepadMessageUtils.h
@@ -0,0 +1,154 @@
+/* -*- 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(MessageWriter* aWriter, const paramType& aParam) {
+ WriteParam(aWriter, aParam.flags);
+ WriteParam(aWriter, aParam.orientation[0]);
+ WriteParam(aWriter, aParam.orientation[1]);
+ WriteParam(aWriter, aParam.orientation[2]);
+ WriteParam(aWriter, aParam.orientation[3]);
+ WriteParam(aWriter, aParam.position[0]);
+ WriteParam(aWriter, aParam.position[1]);
+ WriteParam(aWriter, aParam.position[2]);
+ WriteParam(aWriter, aParam.angularVelocity[0]);
+ WriteParam(aWriter, aParam.angularVelocity[1]);
+ WriteParam(aWriter, aParam.angularVelocity[2]);
+ WriteParam(aWriter, aParam.angularAcceleration[0]);
+ WriteParam(aWriter, aParam.angularAcceleration[1]);
+ WriteParam(aWriter, aParam.angularAcceleration[2]);
+ WriteParam(aWriter, aParam.linearVelocity[0]);
+ WriteParam(aWriter, aParam.linearVelocity[1]);
+ WriteParam(aWriter, aParam.linearVelocity[2]);
+ WriteParam(aWriter, aParam.linearAcceleration[0]);
+ WriteParam(aWriter, aParam.linearAcceleration[1]);
+ WriteParam(aWriter, aParam.linearAcceleration[2]);
+ WriteParam(aWriter, aParam.isPositionValid);
+ WriteParam(aWriter, aParam.isOrientationValid);
+ }
+
+ static bool Read(MessageReader* aReader, paramType* aResult) {
+ if (!ReadParam(aReader, &(aResult->flags)) ||
+ !ReadParam(aReader, &(aResult->orientation[0])) ||
+ !ReadParam(aReader, &(aResult->orientation[1])) ||
+ !ReadParam(aReader, &(aResult->orientation[2])) ||
+ !ReadParam(aReader, &(aResult->orientation[3])) ||
+ !ReadParam(aReader, &(aResult->position[0])) ||
+ !ReadParam(aReader, &(aResult->position[1])) ||
+ !ReadParam(aReader, &(aResult->position[2])) ||
+ !ReadParam(aReader, &(aResult->angularVelocity[0])) ||
+ !ReadParam(aReader, &(aResult->angularVelocity[1])) ||
+ !ReadParam(aReader, &(aResult->angularVelocity[2])) ||
+ !ReadParam(aReader, &(aResult->angularAcceleration[0])) ||
+ !ReadParam(aReader, &(aResult->angularAcceleration[1])) ||
+ !ReadParam(aReader, &(aResult->angularAcceleration[2])) ||
+ !ReadParam(aReader, &(aResult->linearVelocity[0])) ||
+ !ReadParam(aReader, &(aResult->linearVelocity[1])) ||
+ !ReadParam(aReader, &(aResult->linearVelocity[2])) ||
+ !ReadParam(aReader, &(aResult->linearAcceleration[0])) ||
+ !ReadParam(aReader, &(aResult->linearAcceleration[1])) ||
+ !ReadParam(aReader, &(aResult->linearAcceleration[2])) ||
+ !ReadParam(aReader, &(aResult->isPositionValid)) ||
+ !ReadParam(aReader, &(aResult->isOrientationValid))) {
+ return false;
+ }
+ return true;
+ }
+};
+
+template <>
+struct ParamTraits<mozilla::dom::GamepadTouchState> {
+ typedef mozilla::dom::GamepadTouchState paramType;
+
+ static void Write(MessageWriter* aWriter, const paramType& aParam) {
+ WriteParam(aWriter, aParam.touchId);
+ WriteParam(aWriter, aParam.surfaceId);
+ WriteParam(aWriter, aParam.position[0]);
+ WriteParam(aWriter, aParam.position[1]);
+ WriteParam(aWriter, aParam.surfaceDimensions[0]);
+ WriteParam(aWriter, aParam.surfaceDimensions[1]);
+ WriteParam(aWriter, aParam.isSurfaceDimensionsValid);
+ }
+
+ static bool Read(MessageReader* aReader, paramType* aResult) {
+ if (!ReadParam(aReader, &(aResult->touchId)) ||
+ !ReadParam(aReader, &(aResult->surfaceId)) ||
+ !ReadParam(aReader, &(aResult->position[0])) ||
+ !ReadParam(aReader, &(aResult->position[1])) ||
+ !ReadParam(aReader, &(aResult->surfaceDimensions[0])) ||
+ !ReadParam(aReader, &(aResult->surfaceDimensions[1])) ||
+ !ReadParam(aReader, &(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(MessageWriter* aWriter, const paramType& aParam) {
+ WriteParam(aWriter, aParam.mValue);
+ WriteParam(aWriter, aParam.mKind);
+ }
+ static bool Read(MessageReader* aReader, paramType* aParam) {
+ return ReadParam(aReader, &aParam->mValue) &&
+ ReadParam(aReader, &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..26d499ff8a
--- /dev/null
+++ b/dom/gamepad/ipc/GamepadTestChannelChild.h
@@ -0,0 +1,45 @@
+/* -*- 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::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 mozilla::dom
+
+#endif
diff --git a/dom/gamepad/ipc/GamepadTestChannelParent.cpp b/dom/gamepad/ipc/GamepadTestChannelParent.cpp
new file mode 100644
index 0000000000..1c8d67491e
--- /dev/null
+++ b/dom/gamepad/ipc/GamepadTestChannelParent.cpp
@@ -0,0 +1,129 @@
+/* -*- 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/StaticPrefs_dom.h"
+#include "mozilla/Unused.h"
+
+namespace mozilla::dom {
+
+already_AddRefed<GamepadTestChannelParent> GamepadTestChannelParent::Create() {
+ // Refuse to create the parent actor if this pref is disabled
+ if (!StaticPrefs::dom_gamepad_test_enabled()) {
+ return nullptr;
+ }
+
+ 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();
+
+ switch (body.type()) {
+ case GamepadChangeEventBody::TGamepadRemoved:
+ service->RemoveGamepad(handle);
+ break;
+ case GamepadChangeEventBody::TGamepadButtonInformation: {
+ const GamepadButtonInformation& a = body.get_GamepadButtonInformation();
+ service->NewButtonEvent(handle, a.button(), a.pressed(), a.touched(),
+ a.value());
+ break;
+ }
+ case GamepadChangeEventBody::TGamepadAxisInformation: {
+ const GamepadAxisInformation& a = body.get_GamepadAxisInformation();
+ service->NewAxisMoveEvent(handle, a.axis(), a.value());
+ break;
+ }
+ case GamepadChangeEventBody::TGamepadPoseInformation: {
+ const GamepadPoseInformation& a = body.get_GamepadPoseInformation();
+ service->NewPoseEvent(handle, a.pose_state());
+ break;
+ }
+ case GamepadChangeEventBody::TGamepadTouchInformation: {
+ const GamepadTouchInformation& a = body.get_GamepadTouchInformation();
+ service->NewMultiTouchEvent(handle, a.index(), a.touch_state());
+ break;
+ }
+ default:
+ NS_WARNING("Unknown event type.");
+ return IPC_FAIL_NO_REASON(this);
+ }
+ Unused << SendReplyGamepadHandle(aID, handle);
+ return IPC_OK();
+}
+
+} // namespace mozilla::dom
diff --git a/dom/gamepad/ipc/GamepadTestChannelParent.h b/dom/gamepad/ipc/GamepadTestChannelParent.h
new file mode 100644
index 0000000000..03567727e2
--- /dev/null
+++ b/dom/gamepad/ipc/GamepadTestChannelParent.h
@@ -0,0 +1,49 @@
+/* -*- 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::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 mozilla::dom
+
+#endif
diff --git a/dom/gamepad/ipc/PGamepadEventChannel.ipdl b/dom/gamepad/ipc/PGamepadEventChannel.ipdl
new file mode 100644
index 0000000000..dba6725bd4
--- /dev/null
+++ b/dom/gamepad/ipc/PGamepadEventChannel.ipdl
@@ -0,0 +1,31 @@
+/* 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 {
+
+protocol PGamepadEventChannel {
+ manager PBackground;
+ parent:
+ async __delete__();
+
+ [Tainted] async VibrateHaptic(GamepadHandle aHandle, uint32_t aHapticIndex,
+ double aIntensity, double aDuration, [NoTaint=passback] uint32_t aPromiseID);
+ [Tainted] async StopVibrateHaptic(GamepadHandle aHandle);
+ [Tainted] async LightIndicatorColor(GamepadHandle aHandle, uint32_t aLightColorIndex,
+ [NoTaint=allvalid] uint8_t aRed, [NoTaint=allvalid] uint8_t aGreen,
+ [NoTaint=allvalid] uint8_t aBlue, [NoTaint=passback] uint32_t aPromiseID);
+
+ 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..2be0819491
--- /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 {
+
+protocol PGamepadTestChannel {
+ manager PBackground;
+ parent:
+ async GamepadTestEvent(uint32_t aID, GamepadChangeEvent aGamepadEvent);
+ async __delete__();
+ child:
+ async ReplyGamepadHandle(uint32_t aID, GamepadHandle aHandle);
+};
+
+}
+}