Bug 1406327 - Part 6: Avoid other threads to access the same member data simultaneously(wip). draft
authorDaosheng Mu <daoshengmu@gmail.com>
Thu, 02 Nov 2017 17:33:54 +0800
changeset 694069 6e5f6cde0573de9ef0fb6cb47286bcea97f0d1b3
parent 694068 0b518e5e025671b4261f6ebf8e0e9c99bc455bf2
child 739247 d878ec4c76d91b0f2653a7599c6cf5ce21c41f73
push id88034
push userbmo:dmu@mozilla.com
push dateTue, 07 Nov 2017 10:40:18 +0000
bugs1406327
milestone58.0a1
Bug 1406327 - Part 6: Avoid other threads to access the same member data simultaneously(wip). MozReview-Commit-ID: 2Sz3XPBrzID
dom/vr/test/reftest/draw_rect.html
gfx/ipc/GPUParent.cpp
gfx/layers/ipc/CompositorVsyncScheduler.cpp
gfx/thebes/gfxPlatform.cpp
gfx/vr/VRDisplayHost.cpp
gfx/vr/VRManager.cpp
gfx/vr/VRManager.h
gfx/vr/VRThread.cpp
gfx/vr/ipc/VRLayerParent.cpp
gfx/vr/ipc/VRLayerParent.h
gfx/vr/ipc/VRManagerParent.cpp
gfx/vr/ipc/VRManagerParent.h
--- a/dom/vr/test/reftest/draw_rect.html
+++ b/dom/vr/test/reftest/draw_rect.html
@@ -31,34 +31,34 @@ If this fails, something is seriously wr
     var img = null;
 
     function setStatus(text) {
       var elem = document.getElementById('status');
       elem.innerHTML = text;
     }
 
     function initVRMock() {
-      VRServiceTest = navigator.requestVRServiceTest();
-      if (!VRServiceTest) {
-        setStatus('VRServiceTest get failed.');
-        return;
-      }
-
-      VRSimulationDriver.AttachWebVRDisplay().then(() => {
-        // Looking for VR displays
-        if (navigator.getVRDisplays) {
-          submitResult = new VRSubmitFrameResult();
-          navigator.getVRDisplays().then(function (displays) {
-            if (displays.length > 0) {
-              vrDisplay = displays[0];
-              vrDisplay.requestPresent([{ source: webglCanvas }]);
-              vrDisplay.requestAnimationFrame(onAnimationFrame);
-            }
-          });
+      navigator.getVRDisplays().then(function (displays) {
+        VRServiceTest = navigator.requestVRServiceTest();
+        if (!VRServiceTest) {
+          setStatus('VRServiceTest get failed.');
+          return;
         }
+      }).then(function (displays) {
+          // Looking for VR displays
+          if (navigator.getVRDisplays) {
+            submitResult = new VRSubmitFrameResult();
+            navigator.getVRDisplays().then(function (displays) {
+              if (displays.length > 0) {
+                vrDisplay = displays[0];
+                vrDisplay.requestPresent([{ source: webglCanvas }]);
+                vrDisplay.requestAnimationFrame(onAnimationFrame);
+              }
+            });
+          }
       });
     }
 
     function onAnimationFrame() {
       if (!vrDisplay.isPresenting) {
         return;
       }
 
--- a/gfx/ipc/GPUParent.cpp
+++ b/gfx/ipc/GPUParent.cpp
@@ -426,18 +426,18 @@ GPUParent::ActorDestroy(ActorDestroyReas
   }
 #endif
 
   if (mVsyncBridge) {
     mVsyncBridge->Shutdown();
     mVsyncBridge = nullptr;
   }
   dom::VideoDecoderManagerParent::ShutdownVideoBridge();
+  VRListenerThreadHolder::Shutdown();
   CompositorThreadHolder::Shutdown();
-  VRListenerThreadHolder::Shutdown();
   if (gfxVars::UseWebRender()) {
     wr::RenderThread::ShutDown();
   }
   Factory::ShutDown();
 #if defined(XP_WIN)
   DeviceManagerDx::Shutdown();
 #endif
   LayerTreeOwnerTracker::Shutdown();
--- a/gfx/layers/ipc/CompositorVsyncScheduler.cpp
+++ b/gfx/layers/ipc/CompositorVsyncScheduler.cpp
@@ -138,22 +138,24 @@ CompositorVsyncScheduler::PostCompositeT
     VRManager* vm = VRManager::Get();
     TimeStamp activeTime(vm->GetLastVRListenerThreadActiveTime());
 
     // Shutdown VR listener thread when no VR content in 45 sec. Shutdown threads
     // only allows to be run at the main thread.
     if (!activeTime.IsNull() && ((aCompositeTimestamp - activeTime) > timeout)) {
       VRListenerThreadHolder::Shutdown();
     } else {
+      MonitorAutoLock lockVR(mCurrentVRListenerTaskMonitor);
       RefPtr<CancelableRunnable> task = NewCancelableRunnableMethod<TimeStamp>(
         "layers::CompositorVsyncScheduler::DispatchVREvents",
         this,
         &CompositorVsyncScheduler::DispatchVREvents,
         aCompositeTimestamp);
       mCurrentVRListenerTask = task;
+    //  vm->mCurrentVRListenerTaskCom = task;
       MOZ_ASSERT(VRListenerThreadHolder::Loop());
       VRListenerThreadHolder::Loop()->PostTask(Move(task.forget()));
     }
   }
 }
 
 void
 CompositorVsyncScheduler::ScheduleComposition()
@@ -240,21 +242,26 @@ CompositorVsyncScheduler::NotifyVsync(Ti
   PostCompositeTask(aVsyncTimestamp);
   return true;
 }
 
 void
 CompositorVsyncScheduler::CancelCurrentCompositeTask()
 {
   MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread() || NS_IsMainThread());
-  MonitorAutoLock lock(mCurrentCompositeTaskMonitor);
+  MonitorAutoLock lockComposite(mCurrentCompositeTaskMonitor);
   if (mCurrentCompositeTask) {
     mCurrentCompositeTask->Cancel();
     mCurrentCompositeTask = nullptr;
   }
+//  MonitorAutoLock lockVR(mCurrentVRListenerTaskMonitor);
+  if (mCurrentVRListenerTask) {
+    mCurrentVRListenerTask->Cancel();
+    mCurrentVRListenerTask = nullptr;
+  }
 }
 
 void
 CompositorVsyncScheduler::Composite(TimeStamp aVsyncTimestamp)
 {
   MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
   {
     MonitorAutoLock lock(mCurrentCompositeTaskMonitor);
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -1066,18 +1066,18 @@ gfxPlatform::ShutdownLayersIPC()
         if (gfxVars::UseOMTP()) {
           layers::PaintThread::Shutdown();
         }
     } else if (XRE_IsParentProcess()) {
         gfx::VRManagerChild::ShutDown();
         layers::CompositorManagerChild::Shutdown();
         layers::ImageBridgeChild::ShutDown();
         // This has to happen after shutting down the child protocols.
+        gfx::VRListenerThreadHolder::Shutdown();
         layers::CompositorThreadHolder::Shutdown();
-        gfx::VRListenerThreadHolder::Shutdown();
         if (gfxVars::UseWebRender()) {
           wr::RenderThread::ShutDown();
 
           Preferences::UnregisterCallback(WebRenderDebugPrefChangeCallback, WR_DEBUG_PREF);
         }
 
     } else {
       // TODO: There are other kind of processes and we should make sure gfx
--- a/gfx/vr/VRDisplayHost.cpp
+++ b/gfx/vr/VRDisplayHost.cpp
@@ -349,22 +349,23 @@ VRDisplayHost::SubmitFrame(VRLayerParent
    * the render loop, if we don't successfully call it, we shouldn't trigger
    * NotifyVRVsync immediately, as it will run unbounded.
    * If NotifyVRVsync is not called here due to SubmitFrame failing, the
    * fallback "watchdog" code in VRDisplayHost::NotifyVSync() will cause
    * frames to continue at a lower refresh rate until frame submission
    * succeeds again.
    */
   VRManager* vm = VRManager::Get();
-  MessageLoop* loop = VRListenerThreadHolder::Loop();
-
-  loop->PostTask(NewRunnableMethod<const uint32_t>(
-    "gfx::VRManager::NotifyVRVsync",
-    vm, &VRManager::NotifyVRVsync, mDisplayInfo.mDisplayID
-  ));
+  if (VRListenerThreadHolder::IsActive()) {
+    MessageLoop* loop = VRListenerThreadHolder::Loop();
+    loop->PostTask(NewRunnableMethod<const uint32_t>(
+      "gfx::VRManager::NotifyVRVsync",
+      vm, &VRManager::NotifyVRVsync, mDisplayInfo.mDisplayID
+    ));
+  }
 #endif
 }
 
 bool
 VRDisplayHost::CheckClearDisplayInfoDirty()
 {
   if (mDisplayInfo == mLastUpdateDisplayInfo) {
     return false;
--- a/gfx/vr/VRManager.cpp
+++ b/gfx/vr/VRManager.cpp
@@ -45,17 +45,20 @@ VRManager::ManagerInit()
 
   if (sVRManagerSingleton == nullptr) {
     sVRManagerSingleton = new VRManager();
     ClearOnShutdown(&sVRManagerSingleton);
   }
 }
 
 VRManager::VRManager()
-  : mInitialized(false)
+  : mCurrentVRListenerTaskMonitor("vrListenerMonitor")
+  , mCurrentVRListenerTask(nullptr)
+  , mMutex("VRManager.Mutex")
+  , mInitialized(false)
   , mVRTestSystemCreated(false)
 {
   MOZ_COUNT_CTOR(VRManager);
   MOZ_ASSERT(sVRManagerSingleton == nullptr);
 
   RefPtr<VRSystemManager> mgr;
 
   /**
@@ -97,36 +100,52 @@ VRManager::VRManager()
   // Preference only can be set at the Parent process.
   if (XRE_IsParentProcess() && gfxPrefs::VREnabled()) {
     Preferences::SetBool("dom.gamepad.extensions.enabled", true);
   }
 }
 
 VRManager::~VRManager()
 {
+  printf_stderr("~VRManager.................\n");
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(!mInitialized);
   MOZ_COUNT_DTOR(VRManager);
 }
 
 void
 VRManager::Destroy()
 {
+  // TODO::remove the refreshVRDisplayInternal cancelablerunnable.
+  printf_stderr("VRManager::Destroy().................\n");
+
+  mPuppetManager = nullptr;
   mVRDisplays.Clear();
   mVRControllers.Clear();
   for (uint32_t i = 0; i < mManagers.Length(); ++i) {
     mManagers[i]->Destroy();
   }
 
   mInitialized = false;
+
+  //MOZ_ASSERT(VRListenerThreadHolder::IsInVRListenerThread());
+  MonitorAutoLock lockVR(mCurrentVRListenerTaskMonitor);
+  if (mCurrentVRListenerTask) {
+    mCurrentVRListenerTask->Cancel();
+    mCurrentVRListenerTask = nullptr;
+  }
 }
 
 void
 VRManager::Shutdown()
 {
+  MOZ_ASSERT(VRListenerThreadHolder::IsInVRListenerThread());
+  return;
+  printf_stderr("VRManager::Shutdown().................\n");
+ // MutexAutoLock autoLock(mMutex);
   mVRDisplays.Clear();
   mVRControllers.Clear();
   for (uint32_t i = 0; i < mManagers.Length(); ++i) {
     mManagers[i]->Shutdown();
   }
 }
 
 void
@@ -252,35 +271,59 @@ VRManager::NotifyVRVsync(const uint32_t&
   if (display) {
     display->StartFrame();
   }
 
   RefreshVRDisplays();
 }
 
 void
+VRManager::RefreshPuppetDisplay()
+{
+  MutexAutoLock autoLock(mMutex);
+  MOZ_ASSERT(VRListenerThreadHolder::IsInVRListenerThread());
+  // Force to refresh VRPuppet display here
+  // because we need it to setup data early.
+  nsTArray<RefPtr<gfx::VRDisplayHost> > displays;
+  mPuppetManager->GetHMDs(displays);
+  for (const auto& display: displays) {
+    mVRDisplays.Put(display->GetDisplayInfo().GetDisplayID(), display);
+  }
+}
+
+void
 VRManager::RefreshVRDisplays(bool aMustDispatch)
 {
+  if (!VRListenerThreadHolder::IsActive()) {
+    return;
+  }
+
   if (VRListenerThreadHolder::IsInVRListenerThread()) {
     RefreshVRDisplaysInternal(aMustDispatch);
   } else {
-   if (VRListenerThreadHolder::IsActive()) {
-     MessageLoop* loop = VRListenerThreadHolder::Loop();
-      loop->PostTask(NewRunnableMethod<bool>(
-        "gfx::VRManager::RefreshVRDisplaysInternal",
-        this, &VRManager::RefreshVRDisplaysInternal, aMustDispatch
-      ));
-   }
+    MonitorAutoLock lock(mCurrentVRListenerTaskMonitor);
+    MessageLoop* loop = VRListenerThreadHolder::Loop();
+    RefPtr<CancelableRunnable> task = NewCancelableRunnableMethod<bool>(
+      "gfx::VRManager::RefreshVRDisplaysInternal",
+     this, &VRManager::RefreshVRDisplaysInternal, aMustDispatch
+    );
+    MOZ_ASSERT(loop);
+    mCurrentVRListenerTask = task;
+    loop->PostTask(task.forget());
   }
 }
 
 void
 VRManager::RefreshVRDisplaysInternal(bool aMustDispatch)
 {
   MOZ_ASSERT(VRListenerThreadHolder::IsInVRListenerThread());
+
+  MonitorAutoLock lock(mCurrentVRListenerTaskMonitor);
+  mCurrentVRListenerTask = nullptr;
+
   nsTArray<RefPtr<gfx::VRDisplayHost> > displays;
   mLastVRListenerThreadActiveTime = TimeStamp::Now();
   /** We don't wish to enumerate the same display from multiple managers,
    * so stop as soon as we get a display.
    * It is still possible to get multiple displays from a single manager,
    * but do not wish to mix-and-match for risk of reporting a duplicate.
    *
    * XXX - Perhaps there will be a better way to detect duplicate displays
@@ -323,89 +366,114 @@ VRManager::RefreshVRDisplaysInternal(boo
     for (const auto& display: displays) {
       mVRDisplays.Put(display->GetDisplayInfo().GetDisplayID(), display);
     }
   }
 
   if (displayInfoChanged || displaySetChanged || aMustDispatch) {
     // Due to PVRManager is at Compositor thread. We have to post tasks
     // to Compositor thread when sending to them the content processes.
+    nsTArray<VRDisplayInfo> update;
+    GetVRDisplayInfo(update);
     MessageLoop* loop = CompositorThreadHolder::Loop();
-    loop->PostTask(
-      NewRunnableMethod("gfx::VRManager::DispatchVRDisplayInfoUpdate",
-                        this,
-                        &VRManager::DispatchVRDisplayInfoUpdate));
+    if (loop) {
+      loop->PostTask(
+        NewRunnableMethod<nsTArray<VRDisplayInfo>&&>(
+          "gfx::VRManager::DispatchVRDisplayInfoUpdate",
+          this, &VRManager::DispatchVRDisplayInfoUpdate, Move(update)));
+    }
   }
 }
 
 void
-VRManager::DispatchVRDisplayInfoUpdate()
+VRManager::DispatchVRDisplayInfoUpdate(nsTArray<VRDisplayInfo>&& displays)
 {
   MOZ_ASSERT(NS_IsInCompositorThread());
-  nsTArray<VRDisplayInfo> update;
-  GetVRDisplayInfo(update);
-
   for (auto iter = mVRManagerParents.Iter(); !iter.Done(); iter.Next()) {
-    Unused << iter.Get()->GetKey()->SendUpdateDisplayInfo(update);
+    Unused << iter.Get()->GetKey()->SendUpdateDisplayInfo(displays);
   }
 }
 
 /**
  * Get any VR displays that have already been enumerated without
  * activating any new devices.
  */
 void
 VRManager::GetVRDisplayInfo(nsTArray<VRDisplayInfo>& aDisplayInfo)
 {
+  MOZ_ASSERT(VRListenerThreadHolder::IsInVRListenerThread());
   aDisplayInfo.Clear();
   for (auto iter = mVRDisplays.Iter(); !iter.Done(); iter.Next()) {
     gfx::VRDisplayHost* display = iter.UserData();
     aDisplayInfo.AppendElement(VRDisplayInfo(display->GetDisplayInfo()));
   }
 }
 
 RefPtr<gfx::VRDisplayHost>
 VRManager::GetDisplay(const uint32_t& aDisplayID)
 {
+  MOZ_ASSERT(VRListenerThreadHolder::IsInVRListenerThread());
   RefPtr<gfx::VRDisplayHost> display;
   if (mVRDisplays.Get(aDisplayID, getter_AddRefs(display))) {
     return display;
   }
   return nullptr;
 }
 
 RefPtr<gfx::VRControllerHost>
 VRManager::GetController(const uint32_t& aControllerID)
 {
+  MOZ_ASSERT(VRListenerThreadHolder::IsInVRListenerThread());
   RefPtr<gfx::VRControllerHost> controller;
   if (mVRControllers.Get(aControllerID, getter_AddRefs(controller))) {
     return controller;
   }
   return nullptr;
 }
 
 void
 VRManager::GetVRControllerInfo(nsTArray<VRControllerInfo>& aControllerInfo)
 {
+  MOZ_ASSERT(VRListenerThreadHolder::IsInVRListenerThread());
   aControllerInfo.Clear();
   for (auto iter = mVRControllers.Iter(); !iter.Done(); iter.Next()) {
     gfx::VRControllerHost* controller = iter.UserData();
     aControllerInfo.AppendElement(VRControllerInfo(controller->GetControllerInfo()));
   }
 }
 
 TimeStamp
 VRManager::GetLastVRListenerThreadActiveTime()
 {
   return mLastVRListenerThreadActiveTime;
 }
 
 void
 VRManager::RefreshVRControllers()
 {
+  if (!VRListenerThreadHolder::IsActive()) {
+    return;
+  }
+
+  if (VRListenerThreadHolder::IsInVRListenerThread()) {
+    RefreshVRControllersInternal();
+  } else {
+    MessageLoop* loop = VRListenerThreadHolder::Loop();
+    MOZ_ASSERT(loop);
+    loop->PostTask(
+      NewRunnableMethod(
+        "gfx::VRManager::RefreshVRControllersInternal",
+        this, &VRManager::RefreshVRControllersInternal));
+  }
+}
+
+void
+VRManager::RefreshVRControllersInternal()
+{
+  MOZ_ASSERT(VRListenerThreadHolder::IsInVRListenerThread());
   nsTArray<RefPtr<gfx::VRControllerHost>> controllers;
 
   ScanForControllers();
 
   for (uint32_t i = 0; i < mManagers.Length()
       && controllers.Length() == 0; ++i) {
     mManagers[i]->GetControllers(controllers);
   }
@@ -440,59 +508,73 @@ VRManager::ScanForControllers()
   for (uint32_t i = 0; i < mManagers.Length(); ++i) {
     mManagers[i]->ScanForControllers();
   }
 }
 
 void
 VRManager::RemoveControllers()
 {
+  if (VRListenerThreadHolder::IsActive()) {
+    MessageLoop* loop = VRListenerThreadHolder::Loop();
+    loop->PostTask(
+      NewRunnableMethod(
+        "gfx::VRManager::RemoveControllersInternal",
+        this, &VRManager::RemoveControllersInternal));
+  }
+}
+
+void
+VRManager::RemoveControllersInternal()
+{
+  MOZ_ASSERT(VRListenerThreadHolder::IsInVRListenerThread());
   for (uint32_t i = 0; i < mManagers.Length(); ++i) {
     mManagers[i]->RemoveControllers();
   }
   mVRControllers.Clear();
 }
 
 void
 VRManager::CreateVRTestSystem()
 {
   if (mVRTestSystemCreated) {
     return;
   }
 
-  RefPtr<VRSystemManager> mgr = VRSystemManagerPuppet::Create();
-  if (mgr) {
-    mManagers.AppendElement(mgr);
+  mPuppetManager = VRSystemManagerPuppet::Create();
+  if (mPuppetManager) {
+    mManagers.AppendElement(mPuppetManager);
     mVRTestSystemCreated = true;
-  }
 
-  // Force to refresh VRPuppet display here
-  // because we need it to setup data early.
-  nsTArray<RefPtr<gfx::VRDisplayHost> > displays;
-  mgr->GetHMDs(displays);
-  for (const auto& display: displays) {
-    mVRDisplays.Put(display->GetDisplayInfo().GetDisplayID(), display);
+    // Force to refresh VRPuppet display here
+    // because we need it to setup data early.
+    nsTArray<RefPtr<gfx::VRDisplayHost> > displays;
+    mPuppetManager->GetHMDs(displays);
+    for (const auto& display: displays) {
+      mVRDisplays.Put(display->GetDisplayInfo().GetDisplayID(), display);
+    }
   }
 }
 
 template<class T>
 void
 VRManager::NotifyGamepadChange(uint32_t aIndex, const T& aInfo)
 {
   dom::GamepadChangeEventBody body(aInfo);
   dom::GamepadChangeEvent e(aIndex, dom::GamepadServiceType::VR, body);
 
   // Due to PVRManager is at Compositor thread. We have to post
   // tasks to Compositor thread.
   MessageLoop* loop = CompositorThreadHolder::Loop();
-  loop->PostTask(
-    NewRunnableMethod<dom::GamepadChangeEvent>(
-                      "gfx::VRManager::NotifyGamepadChangeEventsToContent",
-                      this,
-                      &VRManager::NotifyGamepadChangeEventsToContent, e));
+  if (loop) {
+    loop->PostTask(
+      NewRunnableMethod<dom::GamepadChangeEvent>(
+        "gfx::VRManager::NotifyGamepadChangeEventsToContent",
+        this, &VRManager::NotifyGamepadChangeEventsToContent, e));
+  }
 }
 
 void
 VRManager::NotifyGamepadChangeEventsToContent(const dom::GamepadChangeEvent& aEvent)
 {
   MOZ_ASSERT(NS_IsInCompositorThread());
   for (auto iter = mVRManagerParents.Iter(); !iter.Done(); iter.Next()) {
     Unused << iter.Get()->GetKey()->SendGamepadUpdate(aEvent);
@@ -519,21 +601,22 @@ VRManager::StopVibrateHaptic(uint32_t aC
 }
 
 void
 VRManager::NotifyVibrateHapticCompleted(uint32_t aPromiseID)
 {
   // Due to PVRManager is at Compositor thread. We have to post
   // tasks to Compositor thread.
   MessageLoop* loop = CompositorThreadHolder::Loop();
-  loop->PostTask(
-    NewRunnableMethod<uint32_t>(
-                      "gfx::VRManager::NotifyVibrateHapticCompletedToContent",
-                      this,
-                      &VRManager::NotifyVibrateHapticCompletedToContent, aPromiseID));
+  if (loop) {
+    loop->PostTask(
+      NewRunnableMethod<uint32_t>(
+        "gfx::VRManager::NotifyVibrateHapticCompletedToContent",
+        this, &VRManager::NotifyVibrateHapticCompletedToContent, aPromiseID));
+  }
 }
 
 void
 VRManager::NotifyVibrateHapticCompletedToContent(uint32_t aPromiseID)
 {
   MOZ_ASSERT(NS_IsInCompositorThread());
   for (auto iter = mVRManagerParents.Iter(); !iter.Done(); iter.Next()) {
     Unused << iter.Get()->GetKey()->SendReplyGamepadVibrateHaptic(aPromiseID);
--- a/gfx/vr/VRManager.h
+++ b/gfx/vr/VRManager.h
@@ -33,59 +33,67 @@ public:
   static VRManager* Get();
 
   void AddVRManagerParent(VRManagerParent* aVRManagerParent);
   void RemoveVRManagerParent(VRManagerParent* aVRManagerParent);
 
   void NotifyVsync(const TimeStamp& aVsyncTimestamp);
   void NotifyVRVsync(const uint32_t& aDisplayID);
   void RefreshVRDisplays(bool aMustDispatch = false);
+  void RefreshPuppetDisplay();
   void RefreshVRControllers();
   void ScanForControllers();
   void RemoveControllers();
   template<class T> void NotifyGamepadChange(uint32_t aIndex, const T& aInfo);
   RefPtr<gfx::VRDisplayHost> GetDisplay(const uint32_t& aDisplayID);
   void GetVRDisplayInfo(nsTArray<VRDisplayInfo>& aDisplayInfo);
   RefPtr<gfx::VRControllerHost> GetController(const uint32_t& aControllerID);
   void GetVRControllerInfo(nsTArray<VRControllerInfo>& aControllerInfo);
   void CreateVRTestSystem();
   void VibrateHaptic(uint32_t aControllerIdx, uint32_t aHapticIndex,
                      double aIntensity, double aDuration, uint32_t aPromiseID);
   void StopVibrateHaptic(uint32_t aControllerIdx);
   void NotifyVibrateHapticCompleted(uint32_t aPromiseID);
   void DispatchSubmitFrameResult(uint32_t aDisplayID, const VRSubmitFrameResultInfo& aResult);
   TimeStamp GetLastVRListenerThreadActiveTime();
 
+  RefPtr<CancelableRunnable> mCurrentVRListenerTaskCom;
 protected:
   VRManager();
   ~VRManager();
 
 private:
 
   void Init();
   void Destroy();
   void Shutdown();
 
-  void DispatchVRDisplayInfoUpdate();
+  void DispatchVRDisplayInfoUpdate(nsTArray<VRDisplayInfo>&& displays);
   void RefreshVRDisplaysInternal(bool aMustDispatch);
+  void RefreshVRControllersInternal();
+  void RemoveControllersInternal();
   void NotifyGamepadChangeEventsToContent(const dom::GamepadChangeEvent& aEvent);
   void NotifyVibrateHapticCompletedToContent(uint32_t aPromiseID);
 
   typedef nsTHashtable<nsRefPtrHashKey<VRManagerParent>> VRManagerParentSet;
   VRManagerParentSet mVRManagerParents;
 
   typedef nsTArray<RefPtr<VRSystemManager>> VRSystemManagerArray;
   VRSystemManagerArray mManagers;
 
   typedef nsRefPtrHashtable<nsUint32HashKey, gfx::VRDisplayHost> VRDisplayHostHashMap;
   VRDisplayHostHashMap mVRDisplays;
 
   typedef nsRefPtrHashtable<nsUint32HashKey, gfx::VRControllerHost> VRControllerHostHashMap;
   VRControllerHostHashMap mVRControllers;
+  RefPtr<VRSystemManager> mPuppetManager;
+  mozilla::Monitor mCurrentVRListenerTaskMonitor;
+  RefPtr<CancelableRunnable> mCurrentVRListenerTask;
 
+  Mutex mMutex;
   Atomic<bool> mInitialized;
 
   TimeStamp mLastRefreshTime;
   TimeStamp mLastActiveTime;
   TimeStamp mLastVRListenerThreadActiveTime;
   bool mVRTestSystemCreated;
 };
 
--- a/gfx/vr/VRThread.cpp
+++ b/gfx/vr/VRThread.cpp
@@ -90,17 +90,17 @@ VRListenerThreadHolder::CreateThread()
   return vrThread;
 }
 
 void
 VRListenerThreadHolder::Start()
 {
   MOZ_ASSERT(NS_IsMainThread(), "Should be on the main thread!");
   MOZ_ASSERT(!sVRListenerThreadHolder, "The VR listener thread has already been started!");
-
+  printf_stderr("VRListenerThreadHolder::Start.................\n");
   sVRListenerThreadHolder = new VRListenerThreadHolder();
   sStartTime = TimeStamp::Now();
   sShutdowning = false;
 }
 
 TimeStamp
 VRListenerThreadHolder::GetStartTime()
 {
@@ -108,16 +108,17 @@ VRListenerThreadHolder::GetStartTime()
 }
 
 /* static */ void
 VRListenerThreadHolder::Shutdown()
 {
   if (!IsActive()) {
     return;
   }
+  printf_stderr("VRListenerThreadHolder::Shutdown.................\n");
   sShutdowning = true;
 
   RefPtr<Runnable> runnable = NewRunnableFunction(
     &VRListenerThreadHolder::ShutdownInternal);
   NS_DispatchToMainThread(runnable.forget());
 }
 
 /* static */ void
--- a/gfx/vr/ipc/VRLayerParent.cpp
+++ b/gfx/vr/ipc/VRLayerParent.cpp
@@ -36,52 +36,96 @@ void
 VRLayerParent::ActorDestroy(ActorDestroyReason aWhy)
 {
   mIPCOpen = false;
 }
 
 void
 VRLayerParent::Destroy()
 {
+  // if (mVRDisplayID) {
+  //   VRManager* vm = VRManager::Get();
+  //   RefPtr<gfx::VRDisplayHost> display = vm->GetDisplay(mVRDisplayID);
+  //   if (display) {
+  //     display->RemoveLayer(this);
+  //   }
+  //   // 0 will never be a valid VRDisplayID; we can use it to indicate that
+  //   // we are destroyed and no longer associated with a display.
+  //   mVRDisplayID = 0;
+  // }
+
+  if (!VRListenerThreadHolder::IsActive()) {
+    MessageLoop* loop = VRListenerThreadHolder::Loop();
+    loop->PostTask(NewRunnableMethod(
+      "gfx::VRLayerParent::DestroyInternal",
+      this, &VRLayerParent::DestroyInternal));
+  }
+
+  if (mIPCOpen) {
+    Unused << PVRLayerParent::Send__delete__(this);
+  }
+}
+
+void
+VRLayerParent::DestroyInternal()
+{
   if (mVRDisplayID) {
     VRManager* vm = VRManager::Get();
     RefPtr<gfx::VRDisplayHost> display = vm->GetDisplay(mVRDisplayID);
     if (display) {
       display->RemoveLayer(this);
     }
     // 0 will never be a valid VRDisplayID; we can use it to indicate that
     // we are destroyed and no longer associated with a display.
     mVRDisplayID = 0;
   }
-
-  if (mIPCOpen) {
-    Unused << PVRLayerParent::Send__delete__(this);
-  }
 }
 
 mozilla::ipc::IPCResult
 VRLayerParent::RecvSubmitFrame(const layers::SurfaceDescriptor &aTexture,
                                const uint64_t& aFrameId,
                                const gfx::Rect& aLeftEyeRect,
                                const gfx::Rect& aRightEyeRect)
 {
   if (mVRDisplayID) {
-    VRManager* vm = VRManager::Get();
-    RefPtr<VRDisplayHost> display = vm->GetDisplay(mVRDisplayID);
-    if (display) {
-      // TODO: Move SubmitFrame to VRSubmitFrame thread in Bug 1392217.
-      SubmitFrame(display, aTexture, aFrameId, aLeftEyeRect, aRightEyeRect);
+    if (VRListenerThreadHolder::IsActive()) {
+      MessageLoop* loop = VRListenerThreadHolder::Loop();
+      loop->PostTask(NewRunnableMethod<const layers::SurfaceDescriptor, uint64_t,
+        const gfx::Rect&, const gfx::Rect&>(
+        "gfx::VRLayerParent::SubmitFrame",
+        this,
+        &VRLayerParent::SubmitFrame, aTexture, aFrameId, aLeftEyeRect, aRightEyeRect));
     }
   }
 
   return IPC_OK();
 }
 
 void
-VRLayerParent::SubmitFrame(VRDisplayHost* aDisplay, const layers::SurfaceDescriptor& aTexture,
+VRLayerParent::SubmitFrame(const layers::SurfaceDescriptor& aTexture,
                            uint64_t aFrameId, const gfx::Rect& aLeftEyeRect, const gfx::Rect& aRightEyeRect)
 {
+  VRManager* vm = VRManager::Get();
+  RefPtr<VRDisplayHost> display = vm->GetDisplay(mVRDisplayID);
+  if (display) {
+    // TODO: Move SubmitFrame to VRSubmitFrame thread in Bug 1392217.
+    // SubmitFrame(display, aTexture, aFrameId, aLeftEyeRect, aRightEyeRect);
+
+    MessageLoop* loop = layers::CompositorThreadHolder::Loop();
+    loop->PostTask(NewRunnableMethod<VRDisplayHost*, const layers::SurfaceDescriptor, uint64_t,
+                  const gfx::Rect&, const gfx::Rect&>(
+              "gfx::VRLayerParent::SubmitFrameInternal",
+              this,
+              &VRLayerParent::SubmitFrameInternal, display, aTexture, aFrameId, aLeftEyeRect, aRightEyeRect));
+  //  display->SubmitFrame(this, aTexture, aFrameId, aLeftEyeRect, aRightEyeRect);
+  }
+}
+
+void
+VRLayerParent::SubmitFrameInternal(VRDisplayHost* aDisplay, const layers::SurfaceDescriptor& aTexture,
+                                   uint64_t aFrameId, const gfx::Rect& aLeftEyeRect, const gfx::Rect& aRightEyeRect)
+{
   aDisplay->SubmitFrame(this, aTexture, aFrameId,
                         aLeftEyeRect, aRightEyeRect);
 }
 
 } // namespace gfx
 } // namespace mozilla
--- a/gfx/vr/ipc/VRLayerParent.h
+++ b/gfx/vr/ipc/VRLayerParent.h
@@ -37,16 +37,19 @@ protected:
   bool mIPCOpen;
 
   uint32_t mVRDisplayID;
   gfx::Rect mLeftEyeRect;
   gfx::Rect mRightEyeRect;
   uint32_t mGroup;
 
 private:
-  void SubmitFrame(VRDisplayHost* aDisplay, const layers::SurfaceDescriptor& aTexture,
+  void SubmitFrame(const layers::SurfaceDescriptor& aTexture,
                    uint64_t aFrameId, const gfx::Rect& aLeftEyeRect, const gfx::Rect& aRightEyeRect);
+  void SubmitFrameInternal(VRDisplayHost* aDisplay, const layers::SurfaceDescriptor& aTexture,
+                    uint64_t aFrameId, const gfx::Rect& aLeftEyeRect, const gfx::Rect& aRightEyeRect);
+  void DestroyInternal();
 };
 
 } // namespace gfx
 } // namespace mozilla
 
 #endif
--- a/gfx/vr/ipc/VRManagerParent.cpp
+++ b/gfx/vr/ipc/VRManagerParent.cpp
@@ -41,22 +41,34 @@ VRManagerParent::~VRManagerParent()
 
 PVRLayerParent*
 VRManagerParent::AllocPVRLayerParent(const uint32_t& aDisplayID,
                                      const uint32_t& aGroup)
 {
   RefPtr<VRLayerParent> layer;
   layer = new VRLayerParent(aDisplayID,
                             aGroup);
+
+  if (!VRListenerThreadHolder::IsActive()) {
+    MessageLoop* loop = VRListenerThreadHolder::Loop();
+    loop->PostTask(NewRunnableMethod<RefPtr<VRLayerParent>, uint32_t>(
+      "gfx::VRManagerParent::GetDisplay",
+      this, &VRManagerParent::GetDisplay, layer, aDisplayID));
+  }
+  return layer.forget().take();
+}
+
+void
+VRManagerParent::GetDisplay(RefPtr<VRLayerParent> aLayer, uint32_t aDisplayID)
+{
   VRManager* vm = VRManager::Get();
   RefPtr<gfx::VRDisplayHost> display = vm->GetDisplay(aDisplayID);
   if (display) {
-    display->AddLayer(layer);
+    display->AddLayer(aLayer);
   }
-  return layer.forget().take();
 }
 
 bool
 VRManagerParent::DeallocPVRLayerParent(PVRLayerParent* actor)
 {
   delete actor;
   return true;
 }
@@ -149,21 +161,23 @@ VRManagerParent::DeferredDestroy()
 void
 VRManagerParent::RefreshDisplays()
 {
   // This is called to refresh the VR Displays for Navigator.GetVRDevices().
   // We must pass "true" to VRManager::RefreshVRDisplays()
   // to ensure that the promise returned by Navigator.GetVRDevices
   // can resolve even if there are no changes to the VR Displays.
   VRManager* vm = VRManager::Get();
-  MessageLoop* loop = VRListenerThreadHolder::Loop();
-  loop->PostTask(
-    NewRunnableMethod<bool>(
-      "gfx::VRManager::RefreshVRDisplays",
-      vm, &VRManager::RefreshVRDisplays, true));
+  if (VRListenerThreadHolder::IsActive()) {
+    MessageLoop* loop = VRListenerThreadHolder::Loop();
+    loop->PostTask(
+      NewRunnableMethod<bool>(
+        "gfx::VRManager::RefreshVRDisplays",
+        vm, &VRManager::RefreshVRDisplays, true));
+  }
 }
 
 void
 VRManagerParent::ActorDestroy(ActorDestroyReason why)
 {
   UnregisterFromManager();
   MessageLoop::current()->PostTask(
     NewRunnableMethod("gfx::VRManagerParent::DeferredDestroy",
@@ -195,36 +209,74 @@ VRManagerParent::RecvRefreshDisplays()
   }
 
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 VRManagerParent::RecvResetSensor(const uint32_t& aDisplayID)
 {
+  // VRManager* vm = VRManager::Get();
+  // RefPtr<gfx::VRDisplayHost> display = vm->GetDisplay(aDisplayID);
+  // if (display != nullptr) {
+  //   display->ZeroSensor();
+  // }
+
+  if (VRListenerThreadHolder::IsActive()) {
+    MessageLoop* loop = VRListenerThreadHolder::Loop();
+    loop->PostTask(
+      NewRunnableMethod<bool>(
+        "gfx::VRManagerParent::ResetSensor",
+        this, &VRManagerParent::ResetSensor, aDisplayID));
+  }
+
+  return IPC_OK();
+}
+
+void
+VRManagerParent::ResetSensor(uint32_t aDisplayID)
+{
   VRManager* vm = VRManager::Get();
   RefPtr<gfx::VRDisplayHost> display = vm->GetDisplay(aDisplayID);
   if (display != nullptr) {
     display->ZeroSensor();
   }
+}
+
+mozilla::ipc::IPCResult
+VRManagerParent::RecvSetGroupMask(const uint32_t& aDisplayID, const uint32_t& aGroupMask)
+{
+  // VRManager* vm = VRManager::Get();
+  // RefPtr<gfx::VRDisplayHost> display = vm->GetDisplay(aDisplayID);
+  // if (display != nullptr) {
+  //   display->SetGroupMask(aGroupMask);
+  // }
+
+  if (VRListenerThreadHolder::IsActive()) {
+    MessageLoop* loop = VRListenerThreadHolder::Loop();
+    loop->PostTask(
+      NewRunnableMethod<uint32_t, uint32_t>(
+        "gfx::VRManagerParent::SetGroupMask",
+        this, &VRManagerParent::SetGroupMask, aDisplayID, aGroupMask));
+  }
 
   return IPC_OK();
 }
 
-mozilla::ipc::IPCResult
-VRManagerParent::RecvSetGroupMask(const uint32_t& aDisplayID, const uint32_t& aGroupMask)
+void
+VRManagerParent::SetGroupMask(uint32_t aDisplayID, uint32_t aGroupMask)
 {
   VRManager* vm = VRManager::Get();
   RefPtr<gfx::VRDisplayHost> display = vm->GetDisplay(aDisplayID);
   if (display != nullptr) {
     display->SetGroupMask(aGroupMask);
   }
-  return IPC_OK();
 }
 
+
 void
 VRManagerParent::StartVRListenerThread()
 {
   VRListenerThreadHolder::Start();
   RefreshDisplays();
 }
 
 bool
@@ -268,88 +320,47 @@ VRManagerParent::RecvControllerListenerR
 
 mozilla::ipc::IPCResult
 VRManagerParent::RecvCreateVRTestSystem()
 {
   VRManager* vm = VRManager::Get();
   vm->CreateVRTestSystem();
   mDisplayTestID = 0;
   mControllerTestID = 0;
+  mVRDisplayTests.Clear();
+  mVRControllerTests.Clear();
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 VRManagerParent::RecvCreateVRServiceTestDisplay(const nsCString& aID, const uint32_t& aPromiseID)
 {
-  nsTArray<VRDisplayInfo> displayInfoArray;
-  impl::VRDisplayPuppet* displayPuppet = nullptr;
-  VRManager* vm = VRManager::Get();
+  MOZ_ASSERT(VRListenerThreadHolder::IsActive());
 
-  // Get VRDisplayPuppet from VRManager
-  vm->GetVRDisplayInfo(displayInfoArray);
-  for (auto& displayInfo : displayInfoArray) {
-    if (displayInfo.GetType() == VRDeviceType::Puppet) {
-        displayPuppet = static_cast<impl::VRDisplayPuppet*>(
-                        vm->GetDisplay(displayInfo.GetDisplayID()).get());
-        break;
-    }
-  }
+  MessageLoop* loop = VRListenerThreadHolder::Loop();
+  loop->PostTask(
+    NewRunnableMethod<nsCString, uint32_t>(
+      "gfx::VRManagerParent::RefreshPuppetDisplay",
+      this, &VRManagerParent::RefreshPuppetDisplay, aID, aPromiseID));
 
-  MOZ_ASSERT(displayPuppet);
-  MOZ_ASSERT(!mDisplayTestID); // We have only one display in VRSystemManagerPuppet.
-
-  if (!mVRDisplayTests.Get(mDisplayTestID, nullptr)) {
-    mVRDisplayTests.Put(mDisplayTestID, displayPuppet);
-  }
-
-  if (SendReplyCreateVRServiceTestDisplay(aID, aPromiseID, mDisplayTestID)) {
-    return IPC_OK();
-  }
-
-  return IPC_FAIL(this, "SendReplyCreateVRServiceTestController fail");
+  return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 VRManagerParent::RecvCreateVRServiceTestController(const nsCString& aID, const uint32_t& aPromiseID)
 {
-  uint32_t controllerIdx = 0;
-  nsTArray<VRControllerInfo> controllerInfoArray;
-  impl::VRControllerPuppet* controllerPuppet = nullptr;
-  VRManager* vm = VRManager::Get();
-
-  if (mHaveControllerListener) {
-    vm->RefreshVRControllers();
-  }
+  MOZ_ASSERT(VRListenerThreadHolder::IsActive());
+  
+  MessageLoop* loop = VRListenerThreadHolder::Loop();
+  loop->PostTask(
+    NewRunnableMethod<nsCString, uint32_t>(
+      "gfx::VRManagerParent::RefreshPuppetController",
+      this, &VRManagerParent::RefreshPuppetController, aID, aPromiseID));
 
-  // Get VRControllerPuppet from VRManager
-  vm->GetVRControllerInfo(controllerInfoArray);
-  for (auto& controllerInfo : controllerInfoArray) {
-    if (controllerInfo.GetType() == VRDeviceType::Puppet) {
-      if (controllerIdx == mControllerTestID) {
-        controllerPuppet = static_cast<impl::VRControllerPuppet*>(
-                           vm->GetController(controllerInfo.GetControllerID()).get());
-        break;
-      }
-      ++controllerIdx;
-    }
-  }
-
-  MOZ_ASSERT(controllerPuppet);
-  MOZ_ASSERT(mControllerTestID < 2); // We have only two controllers in VRSystemManagerPuppet.
-
-  if (!mVRControllerTests.Get(mControllerTestID, nullptr)) {
-    mVRControllerTests.Put(mControllerTestID, controllerPuppet);
-  }
-
-  if (SendReplyCreateVRServiceTestController(aID, aPromiseID, mControllerTestID)) {
-    ++mControllerTestID;
-    return IPC_OK();
-  }
-
-  return IPC_FAIL(this, "SendReplyCreateVRServiceTestController fail");
+  return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 VRManagerParent::RecvSetDisplayInfoToMockDisplay(const uint32_t& aDeviceID,
                                                  const VRDisplayInfo& aDisplayInfo)
 {
   RefPtr<impl::VRDisplayPuppet> displayPuppet;
   mVRDisplayTests.Get(aDeviceID,
@@ -423,16 +434,111 @@ VRManagerParent::RecvVibrateHaptic(const
 mozilla::ipc::IPCResult
 VRManagerParent::RecvStopVibrateHaptic(const uint32_t& aControllerIdx)
 {
   VRManager* vm = VRManager::Get();
   vm->StopVibrateHaptic(aControllerIdx);
   return IPC_OK();
 }
 
+void
+VRManagerParent::RefreshPuppetDisplay(nsCString aID, uint32_t aPromiseID)
+{
+  nsTArray<VRDisplayInfo> displayInfoArray;
+  impl::VRDisplayPuppet* displayPuppet = nullptr;
+  VRManager* vm = VRManager::Get();
+
+  // Get VRDisplayPuppet from VRManager
+  vm->GetVRDisplayInfo(displayInfoArray);
+  for (auto& displayInfo : displayInfoArray) {
+    if (displayInfo.GetType() == VRDeviceType::Puppet) {
+        displayPuppet = static_cast<impl::VRDisplayPuppet*>(
+                        vm->GetDisplay(displayInfo.GetDisplayID()).get());
+        break;
+    }
+  }
+
+  MOZ_ASSERT(displayPuppet);
+  MOZ_ASSERT(!mDisplayTestID); // We have only one display in VRSystemManagerPuppet.
+
+  if (!mVRDisplayTests.Get(mDisplayTestID, nullptr)) {
+    mVRDisplayTests.Put(mDisplayTestID, displayPuppet);
+  }
+
+  //SendReplyCreateVRServiceTestDisplay(aID, aPromiseID, mDisplayTestID);
+  MessageLoop* loop = CompositorThreadHolder::Loop();
+  if (loop) {
+    loop->PostTask(
+      NewRunnableMethod<nsCString, uint32_t, uint32_t>(
+        "gfx::VRManagerParent::ReplyCreateVRServiceTestDisplayToContent",
+        this, &VRManagerParent::ReplyCreateVRServiceTestDisplayToContent,
+        aID, aPromiseID, mDisplayTestID));
+  }
+}
+
+void
+VRManagerParent::ReplyCreateVRServiceTestDisplayToContent(nsCString aID,
+                                                          uint32_t aPromiseID,
+                                                          uint32_t aDisplayTestID)
+{
+  Unused << SendReplyCreateVRServiceTestDisplay(aID, aPromiseID, aDisplayTestID);
+}
+
+void
+VRManagerParent::RefreshPuppetController(nsCString aID, uint32_t aPromiseID)
+{
+  uint32_t controllerIdx = 0;
+  nsTArray<VRControllerInfo> controllerInfoArray;
+  impl::VRControllerPuppet* controllerPuppet = nullptr;
+  VRManager* vm = VRManager::Get();
+
+  if (mHaveControllerListener) {
+    vm->RefreshVRControllers();
+  }
+
+  // Get VRControllerPuppet from VRManager
+  vm->GetVRControllerInfo(controllerInfoArray);
+  for (auto& controllerInfo : controllerInfoArray) {
+    if (controllerInfo.GetType() == VRDeviceType::Puppet) {
+      if (controllerIdx == mControllerTestID) {
+        controllerPuppet = static_cast<impl::VRControllerPuppet*>(
+                           vm->GetController(controllerInfo.GetControllerID()).get());
+        break;
+      }
+      ++controllerIdx;
+    }
+  }
+
+  MOZ_ASSERT(controllerPuppet);
+  MOZ_ASSERT(mControllerTestID < 2); // We have only two controllers in VRSystemManagerPuppet.
+
+  if (!mVRControllerTests.Get(mControllerTestID, nullptr)) {
+    mVRControllerTests.Put(mControllerTestID, controllerPuppet);
+  }
+
+  MessageLoop* loop = CompositorThreadHolder::Loop();
+  if (loop) {
+    loop->PostTask(
+      NewRunnableMethod<nsCString, uint32_t, uint32_t>(
+        "gfx::VRManagerParent::ReplyCreateVRServiceTestControllerToContent",
+        this, &VRManagerParent::ReplyCreateVRServiceTestControllerToContent,
+        aID, aPromiseID, mControllerTestID));
+  }
+
+  ++mControllerTestID;
+}
+
+void
+VRManagerParent::ReplyCreateVRServiceTestControllerToContent(nsCString aID,
+                                                             uint32_t aPromiseID,
+                                                             uint32_t aControllerTestID)
+{
+  Unused << SendReplyCreateVRServiceTestController(aID, aPromiseID, aControllerTestID);
+}
+
 bool
 VRManagerParent::SendGamepadUpdate(const GamepadChangeEvent& aGamepadEvent)
 {
   // GamepadManager only exists at the content process
   // or the same process in non-e10s mode.
   if (mHaveControllerListener &&
       (mIsContentChild || IsSameProcess())) {
     return PVRManagerParent::SendGamepadUpdate(aGamepadEvent);
--- a/gfx/vr/ipc/VRManagerParent.h
+++ b/gfx/vr/ipc/VRManagerParent.h
@@ -79,16 +79,25 @@ private:
   void UnregisterFromManager();
 
   void Bind(Endpoint<PVRManagerParent>&& aEndpoint);
 
   static void RegisterVRManagerInCompositorThread(VRManagerParent* aVRManager);
 
   void DeferredDestroy();
   void RefreshDisplays();
+  void RefreshPuppetDisplay(nsCString aID, uint32_t aPromiseID);
+  void RefreshPuppetController(nsCString aID, uint32_t aPromiseID);
+  void GetDisplay(RefPtr<VRLayerParent> aLayer, uint32_t aDisplayID);
+  void ResetSensor(uint32_t aDisplayID);
+  void SetGroupMask(uint32_t aDisplayID, uint32_t aGroupMask);
+  void ReplyCreateVRServiceTestDisplayToContent(nsCString aID, uint32_t aPromiseID,
+                                                uint32_t aDisplayTestID);
+  void ReplyCreateVRServiceTestControllerToContent(nsCString aID, uint32_t aPromiseID,
+                                                   uint32_t aControllerTestID);
 
   // This keeps us alive until ActorDestroy(), at which point we do a
   // deferred destruction of ourselves.
   RefPtr<VRManagerParent> mSelfRef;
 
   // Keep the compositor thread alive, until we have destroyed ourselves.
   RefPtr<layers::CompositorThreadHolder> mCompositorThreadHolder;