summaryrefslogtreecommitdiffstats
path: root/dom/gamepad/GamepadServiceTest.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dom/gamepad/GamepadServiceTest.cpp')
-rw-r--r--dom/gamepad/GamepadServiceTest.cpp283
1 files changed, 283 insertions, 0 deletions
diff --git a/dom/gamepad/GamepadServiceTest.cpp b/dom/gamepad/GamepadServiceTest.cpp
new file mode 100644
index 000000000..a6fde58f0
--- /dev/null
+++ b/dom/gamepad/GamepadServiceTest.cpp
@@ -0,0 +1,283 @@
+/* -*- 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 "GamepadServiceTest.h"
+
+#include "mozilla/ErrorResult.h"
+#include "mozilla/Unused.h"
+
+#include "mozilla/dom/GamepadManager.h"
+#include "mozilla/dom/GamepadPlatformService.h"
+#include "mozilla/dom/GamepadServiceTestBinding.h"
+#include "mozilla/dom/GamepadTestChannelChild.h"
+
+#include "mozilla/ipc/BackgroundChild.h"
+#include "mozilla/ipc/PBackgroundChild.h"
+
+#include "mozilla/Unused.h"
+
+#include "nsIObserver.h"
+#include "nsIObserverService.h"
+
+namespace mozilla {
+namespace dom {
+
+/*
+ * Implementation of the test service. This is just to provide a simple binding
+ * of the GamepadService to JavaScript via WebIDL so that we can write Mochitests
+ * that add and remove fake gamepads, avoiding the platform-specific backends.
+ */
+
+NS_IMPL_CYCLE_COLLECTION_CLASS(GamepadServiceTest)
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(GamepadServiceTest,
+ DOMEventTargetHelper)
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(GamepadServiceTest,
+ DOMEventTargetHelper)
+ NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(GamepadServiceTest)
+ NS_INTERFACE_MAP_ENTRY(nsIIPCBackgroundChildCreateCallback)
+NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
+
+NS_IMPL_ADDREF_INHERITED(GamepadServiceTest, DOMEventTargetHelper)
+NS_IMPL_RELEASE_INHERITED(GamepadServiceTest, DOMEventTargetHelper)
+
+// static
+already_AddRefed<GamepadServiceTest>
+GamepadServiceTest::CreateTestService(nsPIDOMWindowInner* aWindow)
+{
+ MOZ_ASSERT(aWindow);
+ RefPtr<GamepadServiceTest> service = new GamepadServiceTest(aWindow);
+ service->InitPBackgroundActor();
+ return service.forget();
+}
+
+void
+GamepadServiceTest::Shutdown()
+{
+ MOZ_ASSERT(!mShuttingDown);
+ mShuttingDown = true;
+ DestroyPBackgroundActor();
+ mWindow = nullptr;
+}
+
+GamepadServiceTest::GamepadServiceTest(nsPIDOMWindowInner* aWindow)
+ : mService(GamepadManager::GetService()),
+ mWindow(aWindow),
+ mEventNumber(0),
+ mShuttingDown(false),
+ mChild(nullptr)
+{}
+
+GamepadServiceTest::~GamepadServiceTest() {}
+
+void
+GamepadServiceTest::InitPBackgroundActor()
+{
+ MOZ_ASSERT(!mChild);
+ PBackgroundChild *actor = BackgroundChild::GetForCurrentThread();
+ //Try to get the PBackground Child actor
+ if (actor) {
+ ActorCreated(actor);
+ } else {
+ Unused << BackgroundChild::GetOrCreateForCurrentThread(this);
+ }
+}
+
+void
+GamepadServiceTest::DestroyPBackgroundActor()
+{
+ if (mChild) {
+ // If mChild exists, which means that IPDL channel
+ // has been created, our pending operations should
+ // be empty.
+ MOZ_ASSERT(mPendingOperations.IsEmpty());
+ mChild->SendShutdownChannel();
+ mChild = nullptr;
+ } else {
+ // If the IPDL channel has not been created and we
+ // want to destroy it now, just cancel all pending
+ // operations.
+ mPendingOperations.Clear();
+ }
+}
+
+already_AddRefed<Promise>
+GamepadServiceTest::AddGamepad(const nsAString& aID,
+ uint32_t aMapping,
+ uint32_t aNumButtons,
+ uint32_t aNumAxes,
+ ErrorResult& aRv)
+{
+ if (mShuttingDown) {
+ return nullptr;
+ }
+
+ GamepadAdded a(nsString(aID), 0,
+ aMapping,
+ GamepadServiceType::Standard,
+ aNumButtons, aNumAxes);
+ GamepadChangeEvent e(a);
+ nsCOMPtr<nsIGlobalObject> go = do_QueryInterface(mWindow);
+
+ RefPtr<Promise> p = Promise::Create(go, aRv);
+ if (aRv.Failed()) {
+ return nullptr;
+ }
+
+ uint32_t id = ++mEventNumber;
+ if (mChild) {
+ mChild->AddPromise(id, p);
+ mChild->SendGamepadTestEvent(id, e);
+ } else {
+ PendingOperation op(id, e, p);
+ mPendingOperations.AppendElement(op);
+ }
+ return p.forget();
+}
+
+void
+GamepadServiceTest::RemoveGamepad(uint32_t aIndex)
+{
+ if (mShuttingDown) {
+ return;
+ }
+
+ GamepadRemoved a(aIndex, GamepadServiceType::Standard);
+ GamepadChangeEvent e(a);
+
+ uint32_t id = ++mEventNumber;
+ if (mChild) {
+ mChild->SendGamepadTestEvent(id, e);
+ } else {
+ PendingOperation op(id, e);
+ mPendingOperations.AppendElement(op);
+ }
+}
+
+void
+GamepadServiceTest::NewButtonEvent(uint32_t aIndex,
+ uint32_t aButton,
+ bool aPressed)
+{
+ if (mShuttingDown) {
+ return;
+ }
+
+ GamepadButtonInformation a(aIndex, GamepadServiceType::Standard,
+ aButton, aPressed, aPressed ? 1.0 : 0);
+ GamepadChangeEvent e(a);
+
+ uint32_t id = ++mEventNumber;
+ if (mChild) {
+ mChild->SendGamepadTestEvent(id, e);
+ } else {
+ PendingOperation op(id, e);
+ mPendingOperations.AppendElement(op);
+ }
+}
+
+void
+GamepadServiceTest::NewButtonValueEvent(uint32_t aIndex,
+ uint32_t aButton,
+ bool aPressed,
+ double aValue)
+{
+ if (mShuttingDown) {
+ return;
+ }
+
+ GamepadButtonInformation a(aIndex, GamepadServiceType::Standard,
+ aButton, aPressed, aValue);
+ GamepadChangeEvent e(a);
+
+ uint32_t id = ++mEventNumber;
+ if (mChild) {
+ mChild->SendGamepadTestEvent(id, e);
+ } else {
+ PendingOperation op(id, e);
+ mPendingOperations.AppendElement(op);
+ }
+}
+
+void
+GamepadServiceTest::NewAxisMoveEvent(uint32_t aIndex,
+ uint32_t aAxis,
+ double aValue)
+{
+ if (mShuttingDown) {
+ return;
+ }
+
+ GamepadAxisInformation a(aIndex, GamepadServiceType::Standard,
+ aAxis, aValue);
+ GamepadChangeEvent e(a);
+
+ uint32_t id = ++mEventNumber;
+ if (mChild) {
+ mChild->SendGamepadTestEvent(id, e);
+ } else {
+ PendingOperation op(id, e);
+ mPendingOperations.AppendElement(op);
+ }
+}
+
+void
+GamepadServiceTest::FlushPendingOperations()
+{
+ for (uint32_t i=0; i < mPendingOperations.Length(); ++i) {
+ PendingOperation op = mPendingOperations[i];
+ if (op.mPromise) {
+ mChild->AddPromise(op.mID, op.mPromise);
+ }
+ mChild->SendGamepadTestEvent(op.mID, op.mEvent);
+ }
+ mPendingOperations.Clear();
+}
+
+void
+GamepadServiceTest::ActorCreated(PBackgroundChild* aActor)
+{
+ MOZ_ASSERT(aActor);
+ // If we are shutting down, we don't need to create the
+ // IPDL child/parent pair anymore.
+ if (mShuttingDown) {
+ // mPendingOperations should be cleared in
+ // DestroyPBackgroundActor()
+ MOZ_ASSERT(mPendingOperations.IsEmpty());
+ return;
+ }
+
+ mChild = new GamepadTestChannelChild();
+ PGamepadTestChannelChild* initedChild =
+ aActor->SendPGamepadTestChannelConstructor(mChild);
+ if (NS_WARN_IF(!initedChild)) {
+ ActorFailed();
+ return;
+ }
+ FlushPendingOperations();
+}
+
+void
+GamepadServiceTest::ActorFailed()
+{
+ MOZ_CRASH("Failed to create background child actor!");
+}
+
+JSObject*
+GamepadServiceTest::WrapObject(JSContext* aCx, JS::HandleObject aGivenProto)
+{
+ return GamepadServiceTestBinding::Wrap(aCx, this, aGivenProto);
+}
+
+} // dom
+} // mozilla