Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/gfx/vr/ipc/VRManagerChild.cpp
Line
Count
Source (jump to first uncovered line)
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
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#include "VRManagerChild.h"
8
#include "VRManagerParent.h"
9
#include "VRThread.h"
10
#include "VRDisplayClient.h"
11
#include "nsGlobalWindow.h"
12
#include "mozilla/StaticPtr.h"
13
#include "mozilla/layers/CompositorThread.h" // for CompositorThread
14
#include "mozilla/dom/Navigator.h"
15
#include "mozilla/dom/VREventObserver.h"
16
#include "mozilla/dom/WindowBinding.h" // for FrameRequestCallback
17
#include "mozilla/dom/ContentChild.h"
18
#include "nsContentUtils.h"
19
#include "mozilla/dom/GamepadManager.h"
20
#include "mozilla/dom/VRServiceTest.h"
21
#include "mozilla/layers/SyncObject.h"
22
23
using namespace mozilla::dom;
24
25
namespace {
26
const nsTArray<RefPtr<dom::VREventObserver>>::index_type kNoIndex =
27
  nsTArray<RefPtr<dom::VREventObserver> >::NoIndex;
28
} // namespace
29
30
namespace mozilla {
31
namespace gfx {
32
33
static StaticRefPtr<VRManagerChild> sVRManagerChildSingleton;
34
static StaticRefPtr<VRManagerParent> sVRManagerParentSingleton;
35
36
0
void ReleaseVRManagerParentSingleton() {
37
0
  sVRManagerParentSingleton = nullptr;
38
0
}
39
40
VRManagerChild::VRManagerChild()
41
  : mDisplaysInitialized(false)
42
  , mMessageLoop(MessageLoop::current())
43
  , mFrameRequestCallbackCounter(0)
44
  , mBackend(layers::LayersBackend::LAYERS_NONE)
45
  , mPromiseID(0)
46
  , mVRMockDisplay(nullptr)
47
  , mLastControllerState{}
48
0
{
49
0
  MOZ_ASSERT(NS_IsMainThread());
50
0
51
0
  mStartTimeStamp = TimeStamp::Now();
52
0
}
53
54
VRManagerChild::~VRManagerChild()
55
0
{
56
0
  MOZ_ASSERT(NS_IsMainThread());
57
0
}
58
59
/*static*/ void
60
VRManagerChild::IdentifyTextureHost(const TextureFactoryIdentifier& aIdentifier)
61
0
{
62
0
  if (sVRManagerChildSingleton) {
63
0
    sVRManagerChildSingleton->mBackend = aIdentifier.mParentBackend;
64
0
    sVRManagerChildSingleton->mSyncObject =
65
0
        layers::SyncObjectClient::CreateSyncObjectClient(aIdentifier.mSyncHandle);
66
0
  }
67
0
}
68
69
layers::LayersBackend
70
VRManagerChild::GetBackendType() const
71
0
{
72
0
  return mBackend;
73
0
}
74
75
/*static*/ VRManagerChild*
76
VRManagerChild::Get()
77
0
{
78
0
  MOZ_ASSERT(sVRManagerChildSingleton);
79
0
  return sVRManagerChildSingleton;
80
0
}
81
82
/* static */ bool
83
VRManagerChild::IsCreated()
84
0
{
85
0
  return !!sVRManagerChildSingleton;
86
0
}
87
88
/* static */ bool
89
VRManagerChild::InitForContent(Endpoint<PVRManagerChild>&& aEndpoint)
90
0
{
91
0
  MOZ_ASSERT(NS_IsMainThread());
92
0
  MOZ_ASSERT(!sVRManagerChildSingleton);
93
0
94
0
  RefPtr<VRManagerChild> child(new VRManagerChild());
95
0
  if (!aEndpoint.Bind(child)) {
96
0
    return false;
97
0
  }
98
0
  sVRManagerChildSingleton = child;
99
0
  return true;
100
0
}
101
102
/* static */ bool
103
VRManagerChild::ReinitForContent(Endpoint<PVRManagerChild>&& aEndpoint)
104
0
{
105
0
  MOZ_ASSERT(NS_IsMainThread());
106
0
107
0
  ShutDown();
108
0
109
0
  return InitForContent(std::move(aEndpoint));
110
0
}
111
112
/*static*/ void
113
VRManagerChild::InitSameProcess()
114
0
{
115
0
  MOZ_ASSERT(NS_IsMainThread());
116
0
  MOZ_ASSERT(!sVRManagerChildSingleton);
117
0
118
0
  sVRManagerChildSingleton = new VRManagerChild();
119
0
  sVRManagerParentSingleton = VRManagerParent::CreateSameProcess();
120
0
  sVRManagerChildSingleton->Open(sVRManagerParentSingleton->GetIPCChannel(),
121
0
                                 VRListenerThreadHolder::Loop(),
122
0
                                 mozilla::ipc::ChildSide);
123
0
}
124
125
/* static */ void
126
VRManagerChild::InitWithGPUProcess(Endpoint<PVRManagerChild>&& aEndpoint)
127
0
{
128
0
  MOZ_ASSERT(NS_IsMainThread());
129
0
  MOZ_ASSERT(!sVRManagerChildSingleton);
130
0
131
0
  sVRManagerChildSingleton = new VRManagerChild();
132
0
  if (!aEndpoint.Bind(sVRManagerChildSingleton)) {
133
0
    MOZ_CRASH("Couldn't Open() Compositor channel.");
134
0
  }
135
0
}
136
137
/*static*/ void
138
VRManagerChild::ShutDown()
139
0
{
140
0
  MOZ_ASSERT(NS_IsMainThread());
141
0
  if (sVRManagerChildSingleton) {
142
0
    sVRManagerChildSingleton->Destroy();
143
0
    sVRManagerChildSingleton = nullptr;
144
0
  }
145
0
}
146
147
/*static*/ void
148
VRManagerChild::DeferredDestroy(RefPtr<VRManagerChild> aVRManagerChild)
149
0
{
150
0
  aVRManagerChild->Close();
151
0
}
152
153
void
154
VRManagerChild::Destroy()
155
0
{
156
0
  // Keep ourselves alive until everything has been shut down
157
0
  RefPtr<VRManagerChild> selfRef = this;
158
0
159
0
  // The DeferredDestroyVRManager task takes ownership of
160
0
  // the VRManagerChild and will release it when it runs.
161
0
  MessageLoop::current()->PostTask(
162
0
             NewRunnableFunction("VRManagerChildDestroyRunnable",
163
0
                                 DeferredDestroy, selfRef));
164
0
}
165
166
PVRLayerChild*
167
VRManagerChild::AllocPVRLayerChild(const uint32_t& aDisplayID,
168
                                   const uint32_t& aGroup)
169
0
{
170
0
  return VRLayerChild::CreateIPDLActor();
171
0
}
172
173
bool
174
VRManagerChild::DeallocPVRLayerChild(PVRLayerChild* actor)
175
0
{
176
0
  return VRLayerChild::DestroyIPDLActor(actor);
177
0
}
178
179
void
180
VRManagerChild::UpdateDisplayInfo(nsTArray<VRDisplayInfo>& aDisplayUpdates)
181
0
{
182
0
  nsTArray<uint32_t> disconnectedDisplays;
183
0
  nsTArray<uint32_t> connectedDisplays;
184
0
185
0
  nsTArray<RefPtr<VRDisplayClient>> prevDisplays;
186
0
  prevDisplays = mDisplays;
187
0
188
0
  // Check if any displays have been disconnected
189
0
  for (auto& display : prevDisplays) {
190
0
    bool found = false;
191
0
    for (auto& displayUpdate : aDisplayUpdates) {
192
0
      if (display->GetDisplayInfo().GetDisplayID() == displayUpdate.GetDisplayID()) {
193
0
        found = true;
194
0
        break;
195
0
      }
196
0
    }
197
0
    if (!found) {
198
0
      display->NotifyDisconnected();
199
0
      disconnectedDisplays.AppendElement(display->GetDisplayInfo().GetDisplayID());
200
0
    }
201
0
  }
202
0
203
0
  // mDisplays could be a hashed container for more scalability, but not worth
204
0
  // it now as we expect < 10 entries.
205
0
  nsTArray<RefPtr<VRDisplayClient>> displays;
206
0
  for (VRDisplayInfo& displayUpdate : aDisplayUpdates) {
207
0
    bool isNewDisplay = true;
208
0
    for (auto& display : prevDisplays) {
209
0
      const VRDisplayInfo& prevInfo = display->GetDisplayInfo();
210
0
      if (prevInfo.GetDisplayID() == displayUpdate.GetDisplayID()) {
211
0
        if (displayUpdate.GetIsConnected() && !prevInfo.GetIsConnected()) {
212
0
          connectedDisplays.AppendElement(displayUpdate.GetDisplayID());
213
0
        }
214
0
        if (!displayUpdate.GetIsConnected() && prevInfo.GetIsConnected()) {
215
0
          disconnectedDisplays.AppendElement(displayUpdate.GetDisplayID());
216
0
        }
217
0
        display->UpdateDisplayInfo(displayUpdate);
218
0
        displays.AppendElement(display);
219
0
        isNewDisplay = false;
220
0
        break;
221
0
      }
222
0
    }
223
0
    if (isNewDisplay) {
224
0
      displays.AppendElement(new VRDisplayClient(displayUpdate));
225
0
      connectedDisplays.AppendElement(displayUpdate.GetDisplayID());
226
0
    }
227
0
  }
228
0
229
0
  mDisplays = displays;
230
0
231
0
  // We wish to fire the events only after mDisplays is updated
232
0
  for (uint32_t displayID : disconnectedDisplays) {
233
0
    FireDOMVRDisplayDisconnectEvent(displayID);
234
0
  }
235
0
236
0
  for (uint32_t displayID : connectedDisplays) {
237
0
    FireDOMVRDisplayConnectEvent(displayID);
238
0
  }
239
0
240
0
  mDisplaysInitialized = true;
241
0
}
242
243
mozilla::ipc::IPCResult
244
VRManagerChild::RecvUpdateDisplayInfo(nsTArray<VRDisplayInfo>&& aDisplayUpdates)
245
0
{
246
0
  UpdateDisplayInfo(aDisplayUpdates);
247
0
  for (auto& windowId : mNavigatorCallbacks) {
248
0
    /** We must call NotifyVRDisplaysUpdated for every
249
0
     * window's Navigator in mNavigatorCallbacks to ensure that
250
0
     * the promise returned by Navigator.GetVRDevices
251
0
     * can resolve.  This must happen even if no changes
252
0
     * to VRDisplays have been detected here.
253
0
     */
254
0
    nsGlobalWindowInner* window =
255
0
      nsGlobalWindowInner::GetInnerWindowWithId(windowId);
256
0
    if (!window) {
257
0
      continue;
258
0
    }
259
0
    dom::Navigator* nav = window->Navigator();
260
0
    if (!nav) {
261
0
      continue;
262
0
    }
263
0
    nav->NotifyVRDisplaysUpdated();
264
0
  }
265
0
  mNavigatorCallbacks.Clear();
266
0
  return IPC_OK();
267
0
}
268
269
bool
270
VRManagerChild::GetVRDisplays(nsTArray<RefPtr<VRDisplayClient>>& aDisplays)
271
0
{
272
0
  aDisplays = mDisplays;
273
0
  return true;
274
0
}
275
276
bool
277
VRManagerChild::RefreshVRDisplaysWithCallback(uint64_t aWindowId)
278
0
{
279
0
  bool success = SendRefreshDisplays();
280
0
  if (success) {
281
0
    mNavigatorCallbacks.AppendElement(aWindowId);
282
0
  }
283
0
  return success;
284
0
}
285
286
void
287
VRManagerChild::CreateVRServiceTestDisplay(const nsCString& aID, dom::Promise* aPromise)
288
0
{
289
0
  SendCreateVRServiceTestDisplay(aID, mPromiseID);
290
0
  mPromiseList.Put(mPromiseID, aPromise);
291
0
  ++mPromiseID;
292
0
}
293
294
void
295
VRManagerChild::CreateVRServiceTestController(const nsCString& aID, dom::Promise* aPromise)
296
0
{
297
0
  SendCreateVRServiceTestController(aID, mPromiseID);
298
0
  mPromiseList.Put(mPromiseID, aPromise);
299
0
  ++mPromiseID;
300
0
}
301
302
PVRLayerChild*
303
VRManagerChild::CreateVRLayer(uint32_t aDisplayID,
304
                              nsIEventTarget* aTarget,
305
                              uint32_t aGroup)
306
0
{
307
0
  PVRLayerChild* vrLayerChild = AllocPVRLayerChild(aDisplayID, aGroup);
308
0
  // Do the DOM labeling.
309
0
  if (aTarget) {
310
0
    SetEventTargetForActor(vrLayerChild, aTarget);
311
0
    MOZ_ASSERT(vrLayerChild->GetActorEventTarget());
312
0
  }
313
0
  return SendPVRLayerConstructor(vrLayerChild, aDisplayID, aGroup);
314
0
}
315
316
317
// XXX TODO - VRManagerChild::FrameRequest is the same as nsIDocument::FrameRequest, should we consolodate these?
318
struct VRManagerChild::FrameRequest
319
{
320
  FrameRequest(mozilla::dom::FrameRequestCallback& aCallback,
321
    int32_t aHandle) :
322
    mCallback(&aCallback),
323
    mHandle(aHandle)
324
0
  {}
325
326
  // Conversion operator so that we can append these to a
327
  // FrameRequestCallbackList
328
0
  operator const RefPtr<mozilla::dom::FrameRequestCallback>& () const {
329
0
    return mCallback;
330
0
  }
331
332
  // Comparator operators to allow RemoveElementSorted with an
333
  // integer argument on arrays of FrameRequest
334
0
  bool operator==(int32_t aHandle) const {
335
0
    return mHandle == aHandle;
336
0
  }
337
0
  bool operator<(int32_t aHandle) const {
338
0
    return mHandle < aHandle;
339
0
  }
340
341
  RefPtr<mozilla::dom::FrameRequestCallback> mCallback;
342
  int32_t mHandle;
343
};
344
345
nsresult
346
VRManagerChild::ScheduleFrameRequestCallback(mozilla::dom::FrameRequestCallback& aCallback,
347
                                             int32_t *aHandle)
348
0
{
349
0
  if (mFrameRequestCallbackCounter == INT32_MAX) {
350
0
    // Can't increment without overflowing; bail out
351
0
    return NS_ERROR_NOT_AVAILABLE;
352
0
  }
353
0
  int32_t newHandle = ++mFrameRequestCallbackCounter;
354
0
355
0
  DebugOnly<FrameRequest*> request =
356
0
    mFrameRequestCallbacks.AppendElement(FrameRequest(aCallback, newHandle));
357
0
  NS_ASSERTION(request, "This is supposed to be infallible!");
358
0
359
0
  *aHandle = newHandle;
360
0
  return NS_OK;
361
0
}
362
363
void
364
VRManagerChild::CancelFrameRequestCallback(int32_t aHandle)
365
0
{
366
0
  // mFrameRequestCallbacks is stored sorted by handle
367
0
  mFrameRequestCallbacks.RemoveElementSorted(aHandle);
368
0
}
369
370
mozilla::ipc::IPCResult
371
VRManagerChild::RecvGamepadUpdate(const GamepadChangeEvent& aGamepadEvent)
372
0
{
373
0
  // VRManagerChild could be at other processes, but GamepadManager
374
0
  // only exists at the content process or the same process
375
0
  // in non-e10s mode.
376
0
  MOZ_ASSERT(XRE_IsContentProcess() || IsSameProcess());
377
0
378
0
  RefPtr<GamepadManager> gamepadManager(GamepadManager::GetService());
379
0
  if (gamepadManager) {
380
0
    gamepadManager->Update(aGamepadEvent);
381
0
  }
382
0
383
0
  return IPC_OK();
384
0
}
385
386
mozilla::ipc::IPCResult
387
VRManagerChild::RecvReplyCreateVRServiceTestDisplay(const nsCString& aID,
388
                                                    const uint32_t& aPromiseID,
389
                                                    const uint32_t& aDeviceID)
390
0
{
391
0
  RefPtr<dom::Promise> p;
392
0
  if (!mPromiseList.Get(aPromiseID, getter_AddRefs(p))) {
393
0
    MOZ_CRASH("We should always have a promise.");
394
0
  }
395
0
396
0
  // We only allow one VRMockDisplay in VR tests.
397
0
  if (!mVRMockDisplay) {
398
0
    mVRMockDisplay = new VRMockDisplay(aID, aDeviceID);
399
0
  }
400
0
  p->MaybeResolve(mVRMockDisplay);
401
0
  mPromiseList.Remove(aPromiseID);
402
0
  return IPC_OK();
403
0
}
404
405
mozilla::ipc::IPCResult
406
VRManagerChild::RecvReplyCreateVRServiceTestController(const nsCString& aID,
407
                                                       const uint32_t& aPromiseID,
408
                                                       const uint32_t& aDeviceID)
409
0
{
410
0
  RefPtr<dom::Promise> p;
411
0
  if (!mPromiseList.Get(aPromiseID, getter_AddRefs(p))) {
412
0
    MOZ_CRASH("We should always have a promise.");
413
0
  }
414
0
415
0
  if (aDeviceID == 0) {
416
0
    // A value of 0 indicates that the controller could not
417
0
    // be created.  Most likely due to having no VR display
418
0
    // to associate it with.
419
0
    p->MaybeRejectWithUndefined();
420
0
  } else {
421
0
    p->MaybeResolve(new VRMockController(aID, aDeviceID));
422
0
  }
423
0
  mPromiseList.Remove(aPromiseID);
424
0
  return IPC_OK();
425
0
}
426
427
void
428
VRManagerChild::RunFrameRequestCallbacks()
429
0
{
430
0
  AUTO_PROFILER_TRACING("VR", "RunFrameRequestCallbacks");
431
0
432
0
  TimeStamp nowTime = TimeStamp::Now();
433
0
  mozilla::TimeDuration duration = nowTime - mStartTimeStamp;
434
0
  DOMHighResTimeStamp timeStamp = duration.ToMilliseconds();
435
0
436
0
437
0
  nsTArray<FrameRequest> callbacks;
438
0
  callbacks.AppendElements(mFrameRequestCallbacks);
439
0
  mFrameRequestCallbacks.Clear();
440
0
  for (auto& callback : callbacks) {
441
0
    callback.mCallback->Call(timeStamp);
442
0
  }
443
0
}
444
445
void
446
0
VRManagerChild::NotifyPresentationGenerationChanged(uint32_t aDisplayID) {
447
0
  nsContentUtils::AddScriptRunner(NewRunnableMethod<uint32_t>(
448
0
    "gfx::VRManagerChild::NotifyPresentationGenerationChangedInternal",
449
0
    this,
450
0
    &VRManagerChild::NotifyPresentationGenerationChangedInternal,
451
0
    aDisplayID));
452
0
}
453
454
void
455
VRManagerChild::FireDOMVRDisplayMountedEvent(uint32_t aDisplayID)
456
0
{
457
0
  nsContentUtils::AddScriptRunner(NewRunnableMethod<uint32_t>(
458
0
    "gfx::VRManagerChild::FireDOMVRDisplayMountedEventInternal",
459
0
    this,
460
0
    &VRManagerChild::FireDOMVRDisplayMountedEventInternal,
461
0
    aDisplayID));
462
0
}
463
464
void
465
VRManagerChild::FireDOMVRDisplayUnmountedEvent(uint32_t aDisplayID)
466
0
{
467
0
  nsContentUtils::AddScriptRunner(NewRunnableMethod<uint32_t>(
468
0
    "gfx::VRManagerChild::FireDOMVRDisplayUnmountedEventInternal",
469
0
    this,
470
0
    &VRManagerChild::FireDOMVRDisplayUnmountedEventInternal,
471
0
    aDisplayID));
472
0
}
473
474
void
475
VRManagerChild::FireDOMVRDisplayConnectEvent(uint32_t aDisplayID)
476
0
{
477
0
  nsContentUtils::AddScriptRunner(NewRunnableMethod<uint32_t>(
478
0
    "gfx::VRManagerChild::FireDOMVRDisplayConnectEventInternal",
479
0
    this,
480
0
    &VRManagerChild::FireDOMVRDisplayConnectEventInternal,
481
0
    aDisplayID));
482
0
}
483
484
void
485
VRManagerChild::FireDOMVRDisplayDisconnectEvent(uint32_t aDisplayID)
486
0
{
487
0
  nsContentUtils::AddScriptRunner(NewRunnableMethod<uint32_t>(
488
0
    "gfx::VRManagerChild::FireDOMVRDisplayDisconnectEventInternal",
489
0
    this,
490
0
    &VRManagerChild::FireDOMVRDisplayDisconnectEventInternal,
491
0
    aDisplayID));
492
0
}
493
494
void
495
VRManagerChild::FireDOMVRDisplayPresentChangeEvent(uint32_t aDisplayID)
496
0
{
497
0
  nsContentUtils::AddScriptRunner(NewRunnableMethod<uint32_t>(
498
0
    "gfx::VRManagerChild::FireDOMVRDisplayPresentChangeEventInternal",
499
0
    this,
500
0
    &VRManagerChild::FireDOMVRDisplayPresentChangeEventInternal,
501
0
    aDisplayID));
502
0
}
503
504
void
505
VRManagerChild::FireDOMVRDisplayMountedEventInternal(uint32_t aDisplayID)
506
0
{
507
0
  // Iterate over a copy of mListeners, as dispatched events may modify it.
508
0
  nsTArray<RefPtr<dom::VREventObserver>> listeners;
509
0
  listeners = mListeners;
510
0
  for (auto& listener : listeners) {
511
0
    listener->NotifyVRDisplayMounted(aDisplayID);
512
0
  }
513
0
}
514
515
void
516
VRManagerChild::FireDOMVRDisplayUnmountedEventInternal(uint32_t aDisplayID)
517
0
{
518
0
  // Iterate over a copy of mListeners, as dispatched events may modify it.
519
0
  nsTArray<RefPtr<dom::VREventObserver>> listeners;
520
0
  listeners = mListeners;
521
0
  for (auto& listener : listeners) {
522
0
    listener->NotifyVRDisplayUnmounted(aDisplayID);
523
0
  }
524
0
}
525
526
void
527
VRManagerChild::FireDOMVRDisplayConnectEventInternal(uint32_t aDisplayID)
528
0
{
529
0
  // Iterate over a copy of mListeners, as dispatched events may modify it.
530
0
  nsTArray<RefPtr<dom::VREventObserver>> listeners;
531
0
  listeners = mListeners;
532
0
  for (auto& listener : listeners) {
533
0
    listener->NotifyVRDisplayConnect(aDisplayID);
534
0
  }
535
0
}
536
537
void
538
VRManagerChild::FireDOMVRDisplayDisconnectEventInternal(uint32_t aDisplayID)
539
0
{
540
0
  // Iterate over a copy of mListeners, as dispatched events may modify it.
541
0
  nsTArray<RefPtr<dom::VREventObserver>> listeners;
542
0
  listeners = mListeners;
543
0
  for (auto& listener : listeners) {
544
0
    listener->NotifyVRDisplayDisconnect(aDisplayID);
545
0
  }
546
0
}
547
548
void
549
VRManagerChild::FireDOMVRDisplayPresentChangeEventInternal(uint32_t aDisplayID)
550
0
{
551
0
  // Iterate over a copy of mListeners, as dispatched events may modify it.
552
0
  nsTArray<RefPtr<dom::VREventObserver>> listeners;
553
0
  listeners = mListeners;
554
0
  for (auto& listener : listeners) {
555
0
    listener->NotifyVRDisplayPresentChange(aDisplayID);
556
0
  }
557
0
}
558
559
void
560
VRManagerChild::FireDOMVRDisplayConnectEventsForLoadInternal(uint32_t aDisplayID,
561
                                                            dom::VREventObserver* aObserver)
562
0
{
563
0
  aObserver->NotifyVRDisplayConnect(aDisplayID);
564
0
}
565
566
void
567
0
VRManagerChild::NotifyPresentationGenerationChangedInternal(uint32_t aDisplayID) {
568
0
  nsTArray<RefPtr<dom::VREventObserver>> listeners;
569
0
  listeners = mListeners;
570
0
  for (auto& listener : listeners) {
571
0
    listener->NotifyPresentationGenerationChanged(aDisplayID);
572
0
  }
573
0
}
574
575
void
576
VRManagerChild::FireDOMVRDisplayConnectEventsForLoad(dom::VREventObserver* aObserver)
577
0
{
578
0
  // We need to fire the VRDisplayConnect event when a page is loaded
579
0
  // for each VR Display that has already been enumerated
580
0
  nsTArray<RefPtr<VRDisplayClient>> displays;
581
0
  displays = mDisplays;
582
0
  for (auto& display : displays) {
583
0
    const VRDisplayInfo& info = display->GetDisplayInfo();
584
0
    if (info.GetIsConnected()) {
585
0
        nsContentUtils::AddScriptRunner(NewRunnableMethod<uint32_t, RefPtr<dom::VREventObserver>>(
586
0
      "gfx::VRManagerChild::FireDOMVRDisplayConnectEventsForLoadInternal",
587
0
      this,
588
0
      &VRManagerChild::FireDOMVRDisplayConnectEventsForLoadInternal,
589
0
      info.GetDisplayID(),
590
0
      aObserver));
591
0
    }
592
0
  }
593
0
}
594
595
void
596
VRManagerChild::AddListener(dom::VREventObserver* aObserver)
597
0
{
598
0
  MOZ_ASSERT(aObserver);
599
0
600
0
  if (mListeners.IndexOf(aObserver) != kNoIndex) {
601
0
    return; // already exists
602
0
  }
603
0
604
0
  mListeners.AppendElement(aObserver);
605
0
  if (mListeners.Length() == 1) {
606
0
    Unused << SendSetHaveEventListener(true);
607
0
  }
608
0
}
609
610
void
611
VRManagerChild::RemoveListener(dom::VREventObserver* aObserver)
612
0
{
613
0
  MOZ_ASSERT(aObserver);
614
0
615
0
  mListeners.RemoveElement(aObserver);
616
0
  if (mListeners.IsEmpty()) {
617
0
    Unused << SendSetHaveEventListener(false);
618
0
  }
619
0
}
620
621
void
622
VRManagerChild::HandleFatalError(const char* aMsg) const
623
0
{
624
0
  dom::ContentChild::FatalErrorIfNotUsingGPUProcess(aMsg, OtherPid());
625
0
}
626
627
void
628
VRManagerChild::AddPromise(const uint32_t& aID, dom::Promise* aPromise)
629
0
{
630
0
  MOZ_ASSERT(!mGamepadPromiseList.Get(aID, nullptr));
631
0
  mGamepadPromiseList.Put(aID, aPromise);
632
0
}
633
634
mozilla::ipc::IPCResult
635
VRManagerChild::RecvReplyGamepadVibrateHaptic(const uint32_t& aPromiseID)
636
0
{
637
0
  // VRManagerChild could be at other processes, but GamepadManager
638
0
  // only exists at the content process or the same process
639
0
  // in non-e10s mode.
640
0
  MOZ_ASSERT(XRE_IsContentProcess() || IsSameProcess());
641
0
642
0
  RefPtr<dom::Promise> p;
643
0
  if (!mGamepadPromiseList.Get(aPromiseID, getter_AddRefs(p))) {
644
0
    MOZ_CRASH("We should always have a promise.");
645
0
  }
646
0
647
0
  p->MaybeResolve(true);
648
0
  mGamepadPromiseList.Remove(aPromiseID);
649
0
  return IPC_OK();
650
0
}
651
652
mozilla::ipc::IPCResult
653
VRManagerChild::RecvDispatchSubmitFrameResult(const uint32_t& aDisplayID,
654
                                              const VRSubmitFrameResultInfo& aResult)
655
0
{
656
0
  nsTArray<RefPtr<VRDisplayClient>> displays;
657
0
  displays = mDisplays;
658
0
  for (auto& display : displays) {
659
0
    if (display->GetDisplayInfo().GetDisplayID() == aDisplayID) {
660
0
      display->UpdateSubmitFrameResult(aResult);
661
0
    }
662
0
  }
663
0
664
0
  return IPC_OK();
665
0
}
666
667
} // namespace gfx
668
} // namespace mozilla