GamepadServiceTest.cpp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  4. * You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #include "GamepadServiceTest.h"
  6. #include "mozilla/ErrorResult.h"
  7. #include "mozilla/Unused.h"
  8. #include "mozilla/dom/GamepadManager.h"
  9. #include "mozilla/dom/GamepadPlatformService.h"
  10. #include "mozilla/dom/GamepadServiceTestBinding.h"
  11. #include "mozilla/dom/GamepadTestChannelChild.h"
  12. #include "mozilla/ipc/BackgroundChild.h"
  13. #include "mozilla/ipc/PBackgroundChild.h"
  14. #include "mozilla/Unused.h"
  15. #include "nsIObserver.h"
  16. #include "nsIObserverService.h"
  17. using namespace mozilla::ipc;
  18. namespace mozilla {
  19. namespace dom {
  20. /*
  21. * Implementation of the test service. This is just to provide a simple binding
  22. * of the GamepadService to JavaScript via WebIDL so that we can write Mochitests
  23. * that add and remove fake gamepads, avoiding the platform-specific backends.
  24. */
  25. NS_IMPL_CYCLE_COLLECTION_CLASS(GamepadServiceTest)
  26. NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(GamepadServiceTest,
  27. DOMEventTargetHelper)
  28. NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow)
  29. NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
  30. NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(GamepadServiceTest,
  31. DOMEventTargetHelper)
  32. NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow)
  33. NS_IMPL_CYCLE_COLLECTION_UNLINK_END
  34. NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(GamepadServiceTest)
  35. NS_INTERFACE_MAP_ENTRY(nsIIPCBackgroundChildCreateCallback)
  36. NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
  37. NS_IMPL_ADDREF_INHERITED(GamepadServiceTest, DOMEventTargetHelper)
  38. NS_IMPL_RELEASE_INHERITED(GamepadServiceTest, DOMEventTargetHelper)
  39. // static
  40. already_AddRefed<GamepadServiceTest>
  41. GamepadServiceTest::CreateTestService(nsPIDOMWindowInner* aWindow)
  42. {
  43. MOZ_ASSERT(aWindow);
  44. RefPtr<GamepadServiceTest> service = new GamepadServiceTest(aWindow);
  45. service->InitPBackgroundActor();
  46. return service.forget();
  47. }
  48. void
  49. GamepadServiceTest::Shutdown()
  50. {
  51. MOZ_ASSERT(!mShuttingDown);
  52. mShuttingDown = true;
  53. DestroyPBackgroundActor();
  54. mWindow = nullptr;
  55. }
  56. GamepadServiceTest::GamepadServiceTest(nsPIDOMWindowInner* aWindow)
  57. : mService(GamepadManager::GetService()),
  58. mWindow(aWindow),
  59. mEventNumber(0),
  60. mShuttingDown(false),
  61. mChild(nullptr)
  62. {}
  63. GamepadServiceTest::~GamepadServiceTest() {}
  64. void
  65. GamepadServiceTest::InitPBackgroundActor()
  66. {
  67. MOZ_ASSERT(!mChild);
  68. PBackgroundChild *actor = BackgroundChild::GetForCurrentThread();
  69. //Try to get the PBackground Child actor
  70. if (actor) {
  71. ActorCreated(actor);
  72. } else {
  73. Unused << BackgroundChild::GetOrCreateForCurrentThread(this);
  74. }
  75. }
  76. void
  77. GamepadServiceTest::DestroyPBackgroundActor()
  78. {
  79. if (mChild) {
  80. // If mChild exists, which means that IPDL channel
  81. // has been created, our pending operations should
  82. // be empty.
  83. MOZ_ASSERT(mPendingOperations.IsEmpty());
  84. mChild->SendShutdownChannel();
  85. mChild = nullptr;
  86. } else {
  87. // If the IPDL channel has not been created and we
  88. // want to destroy it now, just cancel all pending
  89. // operations.
  90. mPendingOperations.Clear();
  91. }
  92. }
  93. already_AddRefed<Promise>
  94. GamepadServiceTest::AddGamepad(const nsAString& aID,
  95. uint32_t aMapping,
  96. uint32_t aNumButtons,
  97. uint32_t aNumAxes,
  98. ErrorResult& aRv)
  99. {
  100. if (mShuttingDown) {
  101. return nullptr;
  102. }
  103. GamepadAdded a(nsString(aID), 0,
  104. aMapping,
  105. GamepadServiceType::Standard,
  106. aNumButtons, aNumAxes);
  107. GamepadChangeEvent e(a);
  108. nsCOMPtr<nsIGlobalObject> go = do_QueryInterface(mWindow);
  109. RefPtr<Promise> p = Promise::Create(go, aRv);
  110. if (aRv.Failed()) {
  111. return nullptr;
  112. }
  113. uint32_t id = ++mEventNumber;
  114. if (mChild) {
  115. mChild->AddPromise(id, p);
  116. mChild->SendGamepadTestEvent(id, e);
  117. } else {
  118. PendingOperation op(id, e, p);
  119. mPendingOperations.AppendElement(op);
  120. }
  121. return p.forget();
  122. }
  123. void
  124. GamepadServiceTest::RemoveGamepad(uint32_t aIndex)
  125. {
  126. if (mShuttingDown) {
  127. return;
  128. }
  129. GamepadRemoved a(aIndex, GamepadServiceType::Standard);
  130. GamepadChangeEvent e(a);
  131. uint32_t id = ++mEventNumber;
  132. if (mChild) {
  133. mChild->SendGamepadTestEvent(id, e);
  134. } else {
  135. PendingOperation op(id, e);
  136. mPendingOperations.AppendElement(op);
  137. }
  138. }
  139. void
  140. GamepadServiceTest::NewButtonEvent(uint32_t aIndex,
  141. uint32_t aButton,
  142. bool aPressed)
  143. {
  144. if (mShuttingDown) {
  145. return;
  146. }
  147. GamepadButtonInformation a(aIndex, GamepadServiceType::Standard,
  148. aButton, aPressed, aPressed ? 1.0 : 0);
  149. GamepadChangeEvent e(a);
  150. uint32_t id = ++mEventNumber;
  151. if (mChild) {
  152. mChild->SendGamepadTestEvent(id, e);
  153. } else {
  154. PendingOperation op(id, e);
  155. mPendingOperations.AppendElement(op);
  156. }
  157. }
  158. void
  159. GamepadServiceTest::NewButtonValueEvent(uint32_t aIndex,
  160. uint32_t aButton,
  161. bool aPressed,
  162. double aValue)
  163. {
  164. if (mShuttingDown) {
  165. return;
  166. }
  167. GamepadButtonInformation a(aIndex, GamepadServiceType::Standard,
  168. aButton, aPressed, aValue);
  169. GamepadChangeEvent e(a);
  170. uint32_t id = ++mEventNumber;
  171. if (mChild) {
  172. mChild->SendGamepadTestEvent(id, e);
  173. } else {
  174. PendingOperation op(id, e);
  175. mPendingOperations.AppendElement(op);
  176. }
  177. }
  178. void
  179. GamepadServiceTest::NewAxisMoveEvent(uint32_t aIndex,
  180. uint32_t aAxis,
  181. double aValue)
  182. {
  183. if (mShuttingDown) {
  184. return;
  185. }
  186. GamepadAxisInformation a(aIndex, GamepadServiceType::Standard,
  187. aAxis, aValue);
  188. GamepadChangeEvent e(a);
  189. uint32_t id = ++mEventNumber;
  190. if (mChild) {
  191. mChild->SendGamepadTestEvent(id, e);
  192. } else {
  193. PendingOperation op(id, e);
  194. mPendingOperations.AppendElement(op);
  195. }
  196. }
  197. void
  198. GamepadServiceTest::FlushPendingOperations()
  199. {
  200. for (uint32_t i=0; i < mPendingOperations.Length(); ++i) {
  201. PendingOperation op = mPendingOperations[i];
  202. if (op.mPromise) {
  203. mChild->AddPromise(op.mID, op.mPromise);
  204. }
  205. mChild->SendGamepadTestEvent(op.mID, op.mEvent);
  206. }
  207. mPendingOperations.Clear();
  208. }
  209. void
  210. GamepadServiceTest::ActorCreated(PBackgroundChild* aActor)
  211. {
  212. MOZ_ASSERT(aActor);
  213. // If we are shutting down, we don't need to create the
  214. // IPDL child/parent pair anymore.
  215. if (mShuttingDown) {
  216. // mPendingOperations should be cleared in
  217. // DestroyPBackgroundActor()
  218. MOZ_ASSERT(mPendingOperations.IsEmpty());
  219. return;
  220. }
  221. mChild = new GamepadTestChannelChild();
  222. PGamepadTestChannelChild* initedChild =
  223. aActor->SendPGamepadTestChannelConstructor(mChild);
  224. if (NS_WARN_IF(!initedChild)) {
  225. ActorFailed();
  226. return;
  227. }
  228. FlushPendingOperations();
  229. }
  230. void
  231. GamepadServiceTest::ActorFailed()
  232. {
  233. MOZ_CRASH("Failed to create background child actor!");
  234. }
  235. JSObject*
  236. GamepadServiceTest::WrapObject(JSContext* aCx, JS::HandleObject aGivenProto)
  237. {
  238. return GamepadServiceTestBinding::Wrap(aCx, this, aGivenProto);
  239. }
  240. } // dom
  241. } // mozilla