tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

GamepadServiceTest.cpp (12465B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
      5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "GamepadServiceTest.h"
      8 
      9 #include "mozilla/ErrorResult.h"
     10 #include "mozilla/dom/GamepadManager.h"
     11 #include "mozilla/dom/GamepadPlatformService.h"
     12 #include "mozilla/dom/GamepadServiceTestBinding.h"
     13 #include "mozilla/dom/GamepadTestChannelChild.h"
     14 #include "mozilla/ipc/BackgroundChild.h"
     15 #include "mozilla/ipc/PBackgroundChild.h"
     16 
     17 namespace mozilla::dom {
     18 
     19 /*
     20 * Implementation of the test service. This is just to provide a simple binding
     21 * of the GamepadService to JavaScript via WebIDL so that we can write
     22 * Mochitests that add and remove fake gamepads, avoiding the platform-specific
     23 * backends.
     24 */
     25 
     26 constexpr uint32_t kMaxButtons = 20;
     27 constexpr uint32_t kMaxAxes = 10;
     28 constexpr uint32_t kMaxHaptics = 2;
     29 constexpr uint32_t kMaxLightIndicator = 2;
     30 constexpr uint32_t kMaxTouchEvents = 4;
     31 
     32 NS_IMPL_CYCLE_COLLECTION_INHERITED(GamepadServiceTest, DOMEventTargetHelper,
     33                                   mWindow)
     34 
     35 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(GamepadServiceTest)
     36 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
     37 
     38 NS_IMPL_ADDREF_INHERITED(GamepadServiceTest, DOMEventTargetHelper)
     39 NS_IMPL_RELEASE_INHERITED(GamepadServiceTest, DOMEventTargetHelper)
     40 
     41 // static
     42 already_AddRefed<GamepadServiceTest> GamepadServiceTest::CreateTestService(
     43    nsPIDOMWindowInner* aWindow) {
     44  MOZ_ASSERT(aWindow);
     45  RefPtr<GamepadServiceTest> service = new GamepadServiceTest(aWindow);
     46  service->InitPBackgroundActor();
     47  return service.forget();
     48 }
     49 
     50 void GamepadServiceTest::Shutdown() {
     51  MOZ_ASSERT(!mShuttingDown);
     52  mShuttingDown = true;
     53  DestroyPBackgroundActor();
     54  mWindow = nullptr;
     55 }
     56 
     57 GamepadServiceTest::GamepadServiceTest(nsPIDOMWindowInner* aWindow)
     58    : mService(GamepadManager::GetService()),
     59      mWindow(aWindow),
     60      mEventNumber(0),
     61      mShuttingDown(false),
     62      mChild(nullptr) {}
     63 
     64 GamepadServiceTest::~GamepadServiceTest() {
     65  MOZ_ASSERT(mPromiseList.IsEmpty());
     66 }
     67 
     68 void GamepadServiceTest::InitPBackgroundActor() {
     69  MOZ_ASSERT(!mChild);
     70 
     71  ::mozilla::ipc::PBackgroundChild* actor =
     72      ::mozilla::ipc::BackgroundChild::GetOrCreateForCurrentThread();
     73  if (NS_WARN_IF(!actor)) {
     74    MOZ_CRASH("Failed to create a PBackgroundChild actor!");
     75  }
     76 
     77  mChild = GamepadTestChannelChild::Create(this);
     78  PGamepadTestChannelChild* initedChild =
     79      actor->SendPGamepadTestChannelConstructor(mChild.get());
     80  if (NS_WARN_IF(!initedChild)) {
     81    MOZ_CRASH("Failed to create a PBackgroundChild actor!");
     82  }
     83 }
     84 
     85 void GamepadServiceTest::ReplyGamepadHandle(uint32_t aPromiseId,
     86                                            const GamepadHandle& aHandle) {
     87  uint32_t handleSlot = AddGamepadHandle(aHandle);
     88 
     89  RefPtr<Promise> p;
     90  if (!mPromiseList.Get(aPromiseId, getter_AddRefs(p))) {
     91    MOZ_CRASH("We should always have a promise.");
     92  }
     93 
     94  p->MaybeResolve(handleSlot);
     95  mPromiseList.Remove(aPromiseId);
     96 }
     97 
     98 void GamepadServiceTest::DestroyPBackgroundActor() {
     99  MOZ_ASSERT(mChild);
    100  PGamepadTestChannelChild::Send__delete__(mChild);
    101  mChild = nullptr;
    102 }
    103 
    104 already_AddRefed<Promise> GamepadServiceTest::AddGamepad(
    105    const nsAString& aID, GamepadMappingType aMapping, GamepadHand aHand,
    106    uint32_t aNumButtons, uint32_t aNumAxes, uint32_t aNumHaptics,
    107    uint32_t aNumLightIndicator, uint32_t aNumTouchEvents, ErrorResult& aRv) {
    108  if (aNumButtons > kMaxButtons || aNumAxes > kMaxAxes ||
    109      aNumHaptics > kMaxHaptics || aNumLightIndicator > kMaxLightIndicator ||
    110      aNumTouchEvents > kMaxTouchEvents) {
    111    aRv.ThrowNotSupportedError("exceeded maximum hardware dimensions");
    112    return nullptr;
    113  }
    114 
    115  if (mShuttingDown) {
    116    aRv.ThrowInvalidStateError("Shutting down");
    117    return nullptr;
    118  }
    119 
    120  // The values here are ignored, the value just can't be zero to avoid an
    121  // assertion
    122  GamepadHandle gamepadHandle{1, GamepadHandleKind::GamepadPlatformManager};
    123 
    124  GamepadAdded a(nsString(aID), aMapping, aHand, aNumButtons, aNumAxes,
    125                 aNumHaptics, aNumLightIndicator, aNumTouchEvents);
    126  GamepadChangeEventBody body(a);
    127  GamepadChangeEvent e(gamepadHandle, body);
    128 
    129  RefPtr<Promise> p = Promise::Create(mWindow->AsGlobal(), aRv);
    130  if (aRv.Failed()) {
    131    return nullptr;
    132  }
    133 
    134  uint32_t id = ++mEventNumber;
    135 
    136  MOZ_ASSERT(!mPromiseList.Contains(id));
    137  mPromiseList.InsertOrUpdate(id, RefPtr{p});
    138 
    139  mChild->SendGamepadTestEvent(id, e);
    140 
    141  return p.forget();
    142 }
    143 
    144 already_AddRefed<Promise> GamepadServiceTest::RemoveGamepad(
    145    uint32_t aHandleSlot, ErrorResult& aRv) {
    146  if (mShuttingDown) {
    147    aRv.ThrowInvalidStateError("Shutting down");
    148    return nullptr;
    149  }
    150 
    151  GamepadHandle gamepadHandle = GetHandleInSlot(aHandleSlot);
    152 
    153  GamepadRemoved a;
    154  GamepadChangeEventBody body(a);
    155  GamepadChangeEvent e(gamepadHandle, body);
    156 
    157  uint32_t id = ++mEventNumber;
    158 
    159  RefPtr<Promise> p = Promise::Create(mWindow->AsGlobal(), aRv);
    160  if (aRv.Failed()) {
    161    return nullptr;
    162  }
    163 
    164  MOZ_ASSERT(!mPromiseList.Contains(id));
    165  mPromiseList.InsertOrUpdate(id, RefPtr{p});
    166 
    167  mChild->SendGamepadTestEvent(id, e);
    168  return p.forget();
    169 }
    170 
    171 already_AddRefed<Promise> GamepadServiceTest::NewButtonEvent(
    172    uint32_t aHandleSlot, uint32_t aButton, bool aPressed, bool aTouched,
    173    ErrorResult& aRv) {
    174  if (mShuttingDown) {
    175    aRv.ThrowInvalidStateError("Shutting down");
    176    return nullptr;
    177  }
    178 
    179  GamepadHandle gamepadHandle = GetHandleInSlot(aHandleSlot);
    180 
    181  GamepadButtonInformation a(aButton, aPressed ? 1.0 : 0, aPressed, aTouched);
    182  GamepadChangeEventBody body(a);
    183  GamepadChangeEvent e(gamepadHandle, body);
    184 
    185  uint32_t id = ++mEventNumber;
    186  RefPtr<Promise> p = Promise::Create(mWindow->AsGlobal(), aRv);
    187  if (aRv.Failed()) {
    188    return nullptr;
    189  }
    190 
    191  MOZ_ASSERT(!mPromiseList.Contains(id));
    192  mPromiseList.InsertOrUpdate(id, RefPtr{p});
    193  mChild->SendGamepadTestEvent(id, e);
    194  return p.forget();
    195 }
    196 
    197 already_AddRefed<Promise> GamepadServiceTest::NewButtonValueEvent(
    198    uint32_t aHandleSlot, uint32_t aButton, bool aPressed, bool aTouched,
    199    double aValue, ErrorResult& aRv) {
    200  if (mShuttingDown) {
    201    aRv.ThrowInvalidStateError("Shutting down");
    202    return nullptr;
    203  }
    204 
    205  GamepadHandle gamepadHandle = GetHandleInSlot(aHandleSlot);
    206 
    207  GamepadButtonInformation a(aButton, aValue, aPressed, aTouched);
    208  GamepadChangeEventBody body(a);
    209  GamepadChangeEvent e(gamepadHandle, body);
    210 
    211  uint32_t id = ++mEventNumber;
    212  RefPtr<Promise> p = Promise::Create(mWindow->AsGlobal(), aRv);
    213  if (aRv.Failed()) {
    214    return nullptr;
    215  }
    216 
    217  MOZ_ASSERT(!mPromiseList.Contains(id));
    218  mPromiseList.InsertOrUpdate(id, RefPtr{p});
    219  mChild->SendGamepadTestEvent(id, e);
    220  return p.forget();
    221 }
    222 
    223 already_AddRefed<Promise> GamepadServiceTest::NewAxisMoveEvent(
    224    uint32_t aHandleSlot, uint32_t aAxis, double aValue, ErrorResult& aRv) {
    225  if (mShuttingDown) {
    226    aRv.ThrowInvalidStateError("Shutting down");
    227    return nullptr;
    228  }
    229 
    230  GamepadHandle gamepadHandle = GetHandleInSlot(aHandleSlot);
    231 
    232  GamepadAxisInformation a(aAxis, aValue);
    233  GamepadChangeEventBody body(a);
    234  GamepadChangeEvent e(gamepadHandle, body);
    235 
    236  uint32_t id = ++mEventNumber;
    237  RefPtr<Promise> p = Promise::Create(mWindow->AsGlobal(), aRv);
    238  if (aRv.Failed()) {
    239    return nullptr;
    240  }
    241 
    242  MOZ_ASSERT(!mPromiseList.Contains(id));
    243  mPromiseList.InsertOrUpdate(id, RefPtr{p});
    244  mChild->SendGamepadTestEvent(id, e);
    245  return p.forget();
    246 }
    247 
    248 already_AddRefed<Promise> GamepadServiceTest::NewPoseMove(
    249    uint32_t aHandleSlot, const Nullable<Float32Array>& aOrient,
    250    const Nullable<Float32Array>& aPos,
    251    const Nullable<Float32Array>& aAngVelocity,
    252    const Nullable<Float32Array>& aAngAcceleration,
    253    const Nullable<Float32Array>& aLinVelocity,
    254    const Nullable<Float32Array>& aLinAcceleration, ErrorResult& aRv) {
    255  if (mShuttingDown) {
    256    aRv.ThrowInvalidStateError("Shutting down");
    257    return nullptr;
    258  }
    259 
    260  GamepadHandle gamepadHandle = GetHandleInSlot(aHandleSlot);
    261 
    262  GamepadPoseState poseState;
    263  poseState.flags = GamepadCapabilityFlags::Cap_Orientation |
    264                    GamepadCapabilityFlags::Cap_Position |
    265                    GamepadCapabilityFlags::Cap_AngularAcceleration |
    266                    GamepadCapabilityFlags::Cap_LinearAcceleration;
    267  if (!aOrient.IsNull()) {
    268    DebugOnly<bool> ok = aOrient.Value().CopyDataTo(poseState.orientation);
    269    MOZ_ASSERT(ok,
    270               "aOrient.Value().Length() != std::size(poseState.orientation)");
    271    poseState.isOrientationValid = true;
    272  }
    273  if (!aPos.IsNull()) {
    274    DebugOnly<bool> ok = aPos.Value().CopyDataTo(poseState.position);
    275    MOZ_ASSERT(ok, "aPos.Value().Length() != std::size(poseState.position)");
    276    poseState.isPositionValid = true;
    277  }
    278  if (!aAngVelocity.IsNull()) {
    279    DebugOnly<bool> ok =
    280        aAngVelocity.Value().CopyDataTo(poseState.angularVelocity);
    281    MOZ_ASSERT(ok,
    282               "aAngVelocity.Value().Length() != "
    283               "std::size(poseState.angularVelocity)");
    284  }
    285  if (!aAngAcceleration.IsNull()) {
    286    DebugOnly<bool> ok =
    287        aAngAcceleration.Value().CopyDataTo(poseState.angularAcceleration);
    288    MOZ_ASSERT(ok,
    289               "aAngAcceleration.Value().Length() != "
    290               "std::size(poseState.angularAcceleration)");
    291  }
    292  if (!aLinVelocity.IsNull()) {
    293    DebugOnly<bool> ok =
    294        aLinVelocity.Value().CopyDataTo(poseState.linearVelocity);
    295    MOZ_ASSERT(ok,
    296               "aLinVelocity.Value().Length() != "
    297               "std::size(poseState.linearVelocity)");
    298  }
    299  if (!aLinAcceleration.IsNull()) {
    300    DebugOnly<bool> ok =
    301        aLinAcceleration.Value().CopyDataTo(poseState.linearAcceleration);
    302    MOZ_ASSERT(ok,
    303               "aLinAcceleration.Value().Length() != "
    304               "std::size(poseState.linearAcceleration)");
    305  }
    306 
    307  GamepadPoseInformation a(poseState);
    308  GamepadChangeEventBody body(a);
    309  GamepadChangeEvent e(gamepadHandle, body);
    310 
    311  uint32_t id = ++mEventNumber;
    312  RefPtr<Promise> p = Promise::Create(mWindow->AsGlobal(), aRv);
    313  if (aRv.Failed()) {
    314    return nullptr;
    315  }
    316 
    317  MOZ_ASSERT(!mPromiseList.Contains(id));
    318  mPromiseList.InsertOrUpdate(id, RefPtr{p});
    319  mChild->SendGamepadTestEvent(id, e);
    320  return p.forget();
    321 }
    322 
    323 already_AddRefed<Promise> GamepadServiceTest::NewTouch(
    324    uint32_t aHandleSlot, uint32_t aTouchArrayIndex, uint32_t aTouchId,
    325    uint8_t aSurfaceId, const Float32Array& aPos,
    326    const Nullable<Float32Array>& aSurfDim, ErrorResult& aRv) {
    327  if (mShuttingDown) {
    328    aRv.ThrowInvalidStateError("Shutting down");
    329    return nullptr;
    330  }
    331 
    332  GamepadHandle gamepadHandle = GetHandleInSlot(aHandleSlot);
    333 
    334  GamepadTouchState touchState;
    335  touchState.touchId = aTouchId;
    336  touchState.surfaceId = aSurfaceId;
    337  DebugOnly<bool> ok = aPos.CopyDataTo(touchState.position);
    338  MOZ_ASSERT(ok, "aPos.Length() != std::size(touchState.position)");
    339 
    340  if (!aSurfDim.IsNull()) {
    341    ok = aSurfDim.Value().CopyDataTo(touchState.surfaceDimensions);
    342    MOZ_ASSERT(ok,
    343               "aSurfDim.Length() != std::size(touchState.surfaceDimensions)");
    344    touchState.isSurfaceDimensionsValid = true;
    345  }
    346 
    347  GamepadTouchInformation a(aTouchArrayIndex, touchState);
    348  GamepadChangeEventBody body(a);
    349  GamepadChangeEvent e(gamepadHandle, body);
    350 
    351  uint32_t id = ++mEventNumber;
    352  RefPtr<Promise> p = Promise::Create(mWindow->AsGlobal(), aRv);
    353  if (aRv.Failed()) {
    354    return nullptr;
    355  }
    356 
    357  MOZ_ASSERT(!mPromiseList.Contains(id));
    358  mPromiseList.InsertOrUpdate(id, RefPtr{p});
    359  mChild->SendGamepadTestEvent(id, e);
    360  return p.forget();
    361 }
    362 
    363 JSObject* GamepadServiceTest::WrapObject(JSContext* aCx,
    364                                         JS::Handle<JSObject*> aGivenProto) {
    365  return GamepadServiceTest_Binding::Wrap(aCx, this, aGivenProto);
    366 }
    367 
    368 uint32_t GamepadServiceTest::AddGamepadHandle(GamepadHandle aHandle) {
    369  uint32_t handleSlot = mGamepadHandles.Length();
    370  mGamepadHandles.AppendElement(aHandle);
    371  return handleSlot;
    372 }
    373 
    374 void GamepadServiceTest::RemoveGamepadHandle(uint32_t aHandleSlot) {
    375  MOZ_ASSERT(aHandleSlot < mGamepadHandles.Length());
    376  return mGamepadHandles.RemoveElementAt(aHandleSlot);
    377 }
    378 
    379 GamepadHandle GamepadServiceTest::GetHandleInSlot(uint32_t aHandleSlot) const {
    380  MOZ_ASSERT(aHandleSlot < mGamepadHandles.Length());
    381  return mGamepadHandles.ElementAt(aHandleSlot);
    382 }
    383 
    384 }  // namespace mozilla::dom