Bug 1430040 - Part 4: Make the parent process keep the OpenVR controller manifest info when VR process is enabled. r=kip
authorDaosheng Mu <daoshengmu@gmail.com>
Fri, 28 Dec 2018 22:09:44 +0000
changeset 509582 ec8667678f3a7fa4d6259b070a35a4c4a5c14209
parent 509581 2f31f4f0cad3e652f8fa9b9f14016f8bd59fa48d
child 509583 95d275f757c3501fcdc8e00e84f8ae1a3be0cf48
push id10547
push userffxbld-merge
push dateMon, 21 Jan 2019 13:03:58 +0000
treeherdermozilla-beta@24ec1916bffe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskip
bugs1430040
milestone66.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1430040 - Part 4: Make the parent process keep the OpenVR controller manifest info when VR process is enabled. r=kip Differential Revision: https://phabricator.services.mozilla.com/D15419
gfx/vr/gfxVR.h
gfx/vr/ipc/PVR.ipdl
gfx/vr/ipc/VRChild.cpp
gfx/vr/ipc/VRChild.h
gfx/vr/ipc/VRGPUParent.h
gfx/vr/ipc/VRMessageUtils.h
gfx/vr/ipc/VRParent.cpp
gfx/vr/ipc/VRParent.h
gfx/vr/ipc/VRProcessChild.cpp
gfx/vr/ipc/VRProcessChild.h
gfx/vr/moz.build
gfx/vr/service/OpenVRSession.cpp
--- a/gfx/vr/gfxVR.h
+++ b/gfx/vr/gfxVR.h
@@ -47,16 +47,23 @@ enum class VRDeviceType : uint16_t {
   OpenVR,
   OSVR,
   GVR,
   Puppet,
   External,
   NumVRDeviceTypes
 };
 
+enum class OpenVRControllerType : uint16_t {
+  Vive,
+  WMR,
+  Knuckles,
+  NumOpenVRControllerTypes
+};
+
 struct VRDisplayInfo {
   uint32_t mDisplayID;
   VRDeviceType mType;
   uint32_t mPresentingGroups;
   uint32_t mGroupMask;
   uint64_t mFrameId;
   VRDisplayState mDisplayState;
   VRControllerState mControllerState[kVRControllerMaxCount];
--- a/gfx/vr/ipc/PVR.ipdl
+++ b/gfx/vr/ipc/PVR.ipdl
@@ -1,26 +1,33 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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/. */
 
 using mozilla::TimeStamp from "mozilla/TimeStamp.h";
+using mozilla::gfx::OpenVRControllerType from "gfxVR.h";
 
 include GraphicsMessages;
 include protocol PVRGPU;
 
 namespace mozilla {
 namespace gfx {
 
 async protocol PVR
 {
 parent:
   async NewGPUVRManager(Endpoint<PVRGPUParent> endpoint);
   async Init(GfxPrefSetting[] prefs, GfxVarUpdate[] vars, DevicePrefs devicePrefs);
   async NotifyVsync(TimeStamp vsyncTimestamp);
 
   async UpdatePref(GfxPrefSetting pref);
   async UpdateVar(GfxVarUpdate var);
+  async OpenVRControllerActionPathToVR(nsCString aPath);
+  async OpenVRControllerManifestPathToVR(OpenVRControllerType aType, nsCString aPath);
+
+child:
+  async OpenVRControllerActionPathToParent(nsCString aPath);
+  async OpenVRControllerManifestPathToParent(OpenVRControllerType aType, nsCString aPath);
 };
 
 } // namespace gfx
 } // namespace mozilla
\ No newline at end of file
--- a/gfx/vr/ipc/VRChild.cpp
+++ b/gfx/vr/ipc/VRChild.cpp
@@ -10,16 +10,65 @@
 
 #include "mozilla/gfx/gfxVars.h"
 #include "mozilla/SystemGroup.h"
 #include "mozilla/VsyncDispatcher.h"
 
 namespace mozilla {
 namespace gfx {
 
+class OpenVRControllerManifestManager {
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(OpenVRControllerManifestManager)
+ public:
+  explicit OpenVRControllerManifestManager() = default;
+
+  void SetOpenVRControllerActionPath(const nsCString& aPath) {
+    mAction = aPath;
+  }
+
+  void SetOpenVRControllerManifestPath(OpenVRControllerType aType,
+                                       const nsCString& aPath) {
+    mManifest.Put(static_cast<uint32_t>(aType), aPath);
+  }
+
+  bool GetActionPath(nsCString* aPath) {
+    if (!mAction.IsEmpty()) {
+      *aPath = mAction;
+      return true;
+    }
+    return false;
+  }
+
+  bool GetManifestPath(OpenVRControllerType aType, nsCString* aPath) {
+    return mManifest.Get(static_cast<uint32_t>(aType), aPath);
+  }
+
+ private:
+  ~OpenVRControllerManifestManager() {
+    if (!mAction.IsEmpty() && remove(mAction.BeginReading()) != 0) {
+      MOZ_ASSERT(false, "Delete controller action file failed.");
+    }
+    mAction = "";
+
+    for (auto iter = mManifest.Iter(); !iter.Done(); iter.Next()) {
+      nsCString path(iter.Data());
+      if (!path.IsEmpty() && remove(path.BeginReading()) != 0) {
+        MOZ_ASSERT(false, "Delete controller manifest file failed.");
+      }
+    }
+    mManifest.Clear();
+  }
+
+  nsCString mAction;
+  nsDataHashtable<nsUint32HashKey, nsCString> mManifest;
+  DISALLOW_COPY_AND_ASSIGN(OpenVRControllerManifestManager);
+};
+
+StaticRefPtr<OpenVRControllerManifestManager> sOpenVRControllerManifestManager;
+
 VRChild::VRChild(VRProcessParent* aHost) : mHost(aHost) {
   MOZ_ASSERT(XRE_IsParentProcess());
 }
 
 void VRChild::ActorDestroy(ActorDestroyReason aWhy) {
   gfxVars::RemoveReceiver(this);
   mHost->OnChannelClosed();
 }
@@ -49,19 +98,57 @@ void VRChild::Init() {
   devicePrefs.d3d11Compositing() =
       gfxConfig::GetValue(Feature::D3D11_COMPOSITING);
   devicePrefs.oglCompositing() =
       gfxConfig::GetValue(Feature::OPENGL_COMPOSITING);
   devicePrefs.advancedLayers() = gfxConfig::GetValue(Feature::ADVANCED_LAYERS);
   devicePrefs.useD2D1() = gfxConfig::GetValue(Feature::DIRECT2D);
 
   SendInit(prefs, updates, devicePrefs);
+
+  if (!sOpenVRControllerManifestManager) {
+    sOpenVRControllerManifestManager = new OpenVRControllerManifestManager();
+    NS_DispatchToMainThread(NS_NewRunnableFunction(
+        "ClearOnShutdown OpenVRControllerManifestManager",
+        []() { ClearOnShutdown(&sOpenVRControllerManifestManager); }));
+  }
+
+  nsCString output;
+  if (sOpenVRControllerManifestManager->GetActionPath(&output)) {
+    SendOpenVRControllerActionPathToVR(output);
+  }
+  if (sOpenVRControllerManifestManager->GetManifestPath(
+          OpenVRControllerType::Vive, &output)) {
+    SendOpenVRControllerManifestPathToVR(OpenVRControllerType::Vive, output);
+  }
+  if (sOpenVRControllerManifestManager->GetManifestPath(
+          OpenVRControllerType::WMR, &output)) {
+    SendOpenVRControllerManifestPathToVR(OpenVRControllerType::WMR, output);
+  }
+  if (sOpenVRControllerManifestManager->GetManifestPath(
+          OpenVRControllerType::Knuckles, &output)) {
+    SendOpenVRControllerManifestPathToVR(OpenVRControllerType::Knuckles,
+                                         output);
+  }
   gfxVars::AddReceiver(this);
 }
 
+mozilla::ipc::IPCResult VRChild::RecvOpenVRControllerActionPathToParent(
+    const nsCString& aPath) {
+  sOpenVRControllerManifestManager->SetOpenVRControllerActionPath(aPath);
+  return IPC_OK();
+}
+
+mozilla::ipc::IPCResult VRChild::RecvOpenVRControllerManifestPathToParent(
+    const OpenVRControllerType& aType, const nsCString& aPath) {
+  sOpenVRControllerManifestManager->SetOpenVRControllerManifestPath(aType,
+                                                                    aPath);
+  return IPC_OK();
+}
+
 void VRChild::OnVarChanged(const GfxVarUpdate& aVar) { SendUpdateVar(aVar); }
 
 class DeferredDeleteVRChild : public Runnable {
  public:
   explicit DeferredDeleteVRChild(UniquePtr<VRChild>&& aChild)
       : Runnable("gfx::DeferredDeleteVRChild"), mChild(std::move(aChild)) {}
 
   NS_IMETHODIMP Run() override { return NS_OK; }
--- a/gfx/vr/ipc/VRChild.h
+++ b/gfx/vr/ipc/VRChild.h
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef GFX_VR_CHILD_H
 #define GFX_VR_CHILD_H
 
 #include "mozilla/gfx/PVRChild.h"
 #include "mozilla/gfx/gfxVarReceiver.h"
 #include "mozilla/VsyncDispatcher.h"
+#include "gfxVR.h"
 
 namespace mozilla {
 namespace gfx {
 
 class VRProcessParent;
 class VRChild;
 
 class VRChild final : public PVRChild, public gfxVarReceiver {
@@ -23,16 +24,20 @@ class VRChild final : public PVRChild, p
   ~VRChild() = default;
 
   static void Destroy(UniquePtr<VRChild>&& aChild);
   void Init();
   virtual void OnVarChanged(const GfxVarUpdate& aVar) override;
 
  protected:
   virtual void ActorDestroy(ActorDestroyReason aWhy) override;
+  virtual mozilla::ipc::IPCResult RecvOpenVRControllerActionPathToParent(
+      const nsCString& aPath) override;
+  virtual mozilla::ipc::IPCResult RecvOpenVRControllerManifestPathToParent(
+      const OpenVRControllerType& aType, const nsCString& aPath) override;
 
  private:
   VRProcessParent* mHost;
 };
 
 }  // namespace gfx
 }  // namespace mozilla
 
--- a/gfx/vr/ipc/VRGPUParent.h
+++ b/gfx/vr/ipc/VRGPUParent.h
@@ -3,41 +3,43 @@
 /* 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/. */
 
 #ifndef GFX_VR_GPU_PARENT_H
 #define GFX_VR_GPU_PARENT_H
 
 #include "mozilla/gfx/PVRGPUParent.h"
+#include "VRService.h"
 
 namespace mozilla {
 namespace gfx {
 
 class VRGPUParent final : public PVRGPUParent {
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VRGPUParent)
 
  public:
   explicit VRGPUParent(ProcessId aChildProcessId);
 
   virtual void ActorDestroy(ActorDestroyReason aWhy) override;
   static RefPtr<VRGPUParent> CreateForGPU(Endpoint<PVRGPUParent>&& aEndpoint);
 
  protected:
-  ~VRGPUParent() {}
+  ~VRGPUParent() = default;
 
   void Bind(Endpoint<PVRGPUParent>&& aEndpoint);
   virtual mozilla::ipc::IPCResult RecvStartVRService() override;
   virtual mozilla::ipc::IPCResult RecvStopVRService() override;
 
  private:
   void DeferredDestroy();
 
   RefPtr<VRGPUParent> mSelfRef;
 #if !defined(MOZ_WIDGET_ANDROID)
   RefPtr<VRService> mVRService;
 #endif
+  DISALLOW_COPY_AND_ASSIGN(VRGPUParent);
 };
 
 }  // namespace gfx
 }  // namespace mozilla
 
 #endif  // GFX_VR_CONTENT_PARENT_H
--- a/gfx/vr/ipc/VRMessageUtils.h
+++ b/gfx/vr/ipc/VRMessageUtils.h
@@ -25,16 +25,23 @@ struct ParamTraits<mozilla::gfx::VRDevic
 
 template <>
 struct ParamTraits<mozilla::gfx::VRDisplayCapabilityFlags>
     : public BitFlagsEnumSerializer<
           mozilla::gfx::VRDisplayCapabilityFlags,
           mozilla::gfx::VRDisplayCapabilityFlags::Cap_All> {};
 
 template <>
+struct ParamTraits<mozilla::gfx::OpenVRControllerType>
+    : public ContiguousEnumSerializer<
+          mozilla::gfx::OpenVRControllerType,
+          mozilla::gfx::OpenVRControllerType::Vive,
+          mozilla::gfx::OpenVRControllerType::NumOpenVRControllerTypes> {};
+
+template <>
 struct ParamTraits<mozilla::gfx::VRDisplayState> {
   typedef mozilla::gfx::VRDisplayState paramType;
 
   static void Write(Message* aMsg, const paramType& aParam) {
     // TODO - VRDisplayState is asserted to be a POD type
     //        A simple memcpy may be sufficient here, or
     //        this code can be refactored out if we use
     //        shmem between the VR and content process.
--- a/gfx/vr/ipc/VRParent.cpp
+++ b/gfx/vr/ipc/VRParent.cpp
@@ -74,16 +74,28 @@ IPCResult VRParent::RecvUpdatePref(const
   return IPC_OK();
 }
 
 IPCResult VRParent::RecvUpdateVar(const GfxVarUpdate& aUpdate) {
   gfxVars::ApplyUpdate(aUpdate);
   return IPC_OK();
 }
 
+mozilla::ipc::IPCResult VRParent::RecvOpenVRControllerActionPathToVR(
+    const nsCString& aPath) {
+  mOpenVRControllerAction = aPath;
+  return IPC_OK();
+}
+
+mozilla::ipc::IPCResult VRParent::RecvOpenVRControllerManifestPathToVR(
+    const OpenVRControllerType& aType, const nsCString& aPath) {
+  mOpenVRControllerManifest.Put(static_cast<uint32_t>(aType), aPath);
+  return IPC_OK();
+}
+
 void VRParent::ActorDestroy(ActorDestroyReason aWhy) {
   if (AbnormalShutdown == aWhy) {
     NS_WARNING("Shutting down VR process early due to a crash!");
     ProcessChild::QuickExit();
   }
 
   mVRGPUParent = nullptr;
 #if defined(XP_WIN)
@@ -130,10 +142,24 @@ bool VRParent::Init(base::ProcessId aPar
 #endif
   if (NS_FAILED(NS_InitMinimalXPCOM())) {
     return false;
   }
 
   return true;
 }
 
+bool VRParent::GetOpenVRControllerActionPath(nsCString* aPath) {
+  if (!mOpenVRControllerAction.IsEmpty()) {
+    *aPath = mOpenVRControllerAction;
+    return true;
+  }
+
+  return false;
+}
+
+bool VRParent::GetOpenVRControllerManifestPath(OpenVRControllerType aType,
+                                               nsCString* aPath) {
+  return mOpenVRControllerManifest.Get(static_cast<uint32_t>(aType), aPath);
+}
+
 }  // namespace gfx
 }  // namespace mozilla
\ No newline at end of file
--- a/gfx/vr/ipc/VRParent.h
+++ b/gfx/vr/ipc/VRParent.h
@@ -3,44 +3,59 @@
 /* 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/. */
 
 #ifndef GFX_VR_PARENT_H
 #define GFX_VR_PARENT_H
 
 #include "mozilla/gfx/PVRParent.h"
+#include "VRGPUParent.h"
 
 namespace mozilla {
 namespace gfx {
 
-class VRGPUParent;
 class VRService;
 class VRSystemManagerExternal;
 
 class VRParent final : public PVRParent {
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VRParent);
+
  public:
-  VRParent();
+  explicit VRParent();
+
   bool Init(base::ProcessId aParentPid, const char* aParentBuildID,
             MessageLoop* aIOLoop, IPC::Channel* aChannel);
   virtual void ActorDestroy(ActorDestroyReason aWhy) override;
+  bool GetOpenVRControllerActionPath(nsCString* aPath);
+  bool GetOpenVRControllerManifestPath(OpenVRControllerType aType,
+                                       nsCString* aPath);
 
  protected:
+  ~VRParent() = default;
+
   virtual mozilla::ipc::IPCResult RecvNewGPUVRManager(
       Endpoint<PVRGPUParent>&& aEndpoint) override;
   virtual mozilla::ipc::IPCResult RecvInit(
       nsTArray<GfxPrefSetting>&& prefs, nsTArray<GfxVarUpdate>&& vars,
       const DevicePrefs& devicePrefs) override;
   virtual mozilla::ipc::IPCResult RecvNotifyVsync(
       const TimeStamp& vsyncTimestamp) override;
   virtual mozilla::ipc::IPCResult RecvUpdatePref(
       const GfxPrefSetting& setting) override;
   virtual mozilla::ipc::IPCResult RecvUpdateVar(
       const GfxVarUpdate& pref) override;
+  virtual mozilla::ipc::IPCResult RecvOpenVRControllerActionPathToVR(
+      const nsCString& aPath) override;
+  virtual mozilla::ipc::IPCResult RecvOpenVRControllerManifestPathToVR(
+      const OpenVRControllerType& aType, const nsCString& aPath) override;
 
  private:
+  nsCString mOpenVRControllerAction;
+  nsDataHashtable<nsUint32HashKey, nsCString> mOpenVRControllerManifest;
   RefPtr<VRGPUParent> mVRGPUParent;
+  DISALLOW_COPY_AND_ASSIGN(VRParent);
 };
 
 }  // namespace gfx
 }  // namespace mozilla
 
 #endif  // GFX_VR_PARENT_H
\ No newline at end of file
--- a/gfx/vr/ipc/VRProcessChild.cpp
+++ b/gfx/vr/ipc/VRProcessChild.cpp
@@ -8,39 +8,44 @@
 
 #include "mozilla/BackgroundHangMonitor.h"
 #include "mozilla/ipc/IOThreadChild.h"
 
 using namespace mozilla;
 using namespace mozilla::gfx;
 using mozilla::ipc::IOThreadChild;
 
+StaticRefPtr<VRParent> sVRParent;
+
 VRProcessChild::VRProcessChild(ProcessId aParentPid)
-    : ProcessChild(aParentPid)
-#if defined(aParentPid)
-      ,
-      mVR(nullptr)
-#endif
-{
+    : ProcessChild(aParentPid) {}
+
+VRProcessChild::~VRProcessChild() { sVRParent = nullptr; }
+
+/*static*/ VRParent* VRProcessChild::GetVRParent() {
+  MOZ_ASSERT(sVRParent);
+  return sVRParent;
 }
 
-VRProcessChild::~VRProcessChild() {}
-
 bool VRProcessChild::Init(int aArgc, char* aArgv[]) {
   BackgroundHangMonitor::Startup();
 
   char* parentBuildID = nullptr;
   for (int i = 1; i < aArgc; i++) {
     if (!aArgv[i]) {
       continue;
     }
     if (strcmp(aArgv[i], "-parentBuildID") == 0) {
       parentBuildID = aArgv[i + 1];
     }
   }
 
-  mVR.Init(ParentPid(), parentBuildID, IOThreadChild::message_loop(),
-           IOThreadChild::channel());
+  sVRParent = new VRParent();
+  sVRParent->Init(ParentPid(), parentBuildID, IOThreadChild::message_loop(),
+                  IOThreadChild::channel());
 
   return true;
 }
 
-void VRProcessChild::CleanUp() { NS_ShutdownXPCOM(nullptr); }
\ No newline at end of file
+void VRProcessChild::CleanUp() {
+  sVRParent = nullptr;
+  NS_ShutdownXPCOM(nullptr);
+}
\ No newline at end of file
--- a/gfx/vr/ipc/VRProcessChild.h
+++ b/gfx/vr/ipc/VRProcessChild.h
@@ -20,22 +20,23 @@ namespace gfx {
 class VRProcessChild final : public mozilla::ipc::ProcessChild {
  protected:
   typedef mozilla::ipc::ProcessChild ProcessChild;
 
  public:
   explicit VRProcessChild(ProcessId aParentPid);
   ~VRProcessChild();
 
+  // IPC channel for VR process talk to the parent process.
+  static VRParent* GetVRParent();
+
   // ProcessChild functions.
   virtual bool Init(int aArgc, char* aArgv[]) override;
   virtual void CleanUp() override;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(VRProcessChild);
-
-  VRParent mVR;
 };
 
 }  // namespace gfx
 }  // namespace mozilla
 
 #endif /* GFX_VR_PROCESS_CHILD_H */
\ No newline at end of file
--- a/gfx/vr/moz.build
+++ b/gfx/vr/moz.build
@@ -14,16 +14,17 @@ EXPORTS += [
     'ipc/VRLayerChild.h',
     'ipc/VRManagerChild.h',
     'ipc/VRManagerParent.h',
     'ipc/VRMessageUtils.h',
     'ipc/VRParent.h',
     'ipc/VRProcessChild.h',
     'ipc/VRProcessManager.h',
     'ipc/VRProcessParent.h',
+    'service/VRService.h',
     'VRDisplayClient.h',
     'VRDisplayHost.h',
     'VRDisplayPresentation.h',
     'VRManager.h',
     'VRThread.h',
 ]
 
 LOCAL_INCLUDES += [
--- a/gfx/vr/service/OpenVRSession.cpp
+++ b/gfx/vr/service/OpenVRSession.cpp
@@ -22,16 +22,18 @@
 #include "mozilla/dom/GamepadEventTypes.h"
 #include "mozilla/dom/GamepadBinding.h"
 #include "binding/OpenVRKnucklesBinding.h"
 #include "binding/OpenVRViveBinding.h"
 #if defined(XP_WIN)  // Windows Mixed Reality is only available in Windows.
 #include "binding/OpenVRWMRBinding.h"
 #endif
 
+#include "VRParent.h"
+#include "VRProcessChild.h"
 #include "VRThread.h"
 
 #if !defined(M_PI)
 #define M_PI 3.14159265358979323846264338327950288
 #endif
 
 #define BTN_MASK_FROM_ID(_id) ::vr::ButtonMaskFromId(vr::EVRButtonId::_id)
 
@@ -164,16 +166,23 @@ void UpdateButton(VRControllerState& aSt
     // not touched
     aState.buttonTouched &= ~mask;
   } else {
     // touched
     aState.buttonTouched |= mask;
   }
 }
 
+bool FileIsExisting(const nsCString& aPath) {
+  if (aPath.IsEmpty() || !std::ifstream(aPath.BeginReading())) {
+    return false;
+  }
+  return true;
+}
+
 };  // anonymous namespace
 
 OpenVRSession::OpenVRSession()
     : VRSession(),
       mVRSystem(nullptr),
       mVRChaperone(nullptr),
       mVRCompositor(nullptr),
       mControllerDeviceIndexObsolete{},
@@ -256,63 +265,141 @@ bool OpenVRSession::Initialize(mozilla::
 
   // Succeeded
   return true;
 }
 
 void OpenVRSession::SetupContollerActions() {
   // Check if this device binding file has been created.
   // If it didn't exist yet, create a new temp file.
-  if (!sViveBindingFile) {
-    sViveBindingFile = ControllerManifestFile::CreateManifest();
-    NS_DispatchToMainThread(
-        NS_NewRunnableFunction("ClearOnShutdown ControllerManifestFile",
-                               []() { ClearOnShutdown(&sViveBindingFile); }));
-  }
-  if (!sViveBindingFile->IsExisting()) {
-    sViveBindingFile->SetFileName(std::tmpnam(nullptr));
-    OpenVRViveBinding viveBinding;
-    std::ofstream viveBindingFile(sViveBindingFile->GetFileName());
-    if (viveBindingFile.is_open()) {
-      viveBindingFile << viveBinding.binding;
-      viveBindingFile.close();
+  nsCString controllerAction;
+  nsCString viveManifest;
+  nsCString WMRManifest;
+  nsCString knucklesManifest;
+
+  if (gfxPrefs::VRProcessEnabled()) {
+    VRParent* vrParent = VRProcessChild::GetVRParent();
+    nsCString output;
+
+    if (vrParent->GetOpenVRControllerActionPath(&output)) {
+      controllerAction = output;
+    } else {
+      controllerAction = std::tmpnam(nullptr);
+    }
+
+    if (vrParent->GetOpenVRControllerManifestPath(OpenVRControllerType::Vive,
+                                                  &output)) {
+      viveManifest = output;
+    } else {
+      viveManifest = std::tmpnam(nullptr);
+    }
+    if (!FileIsExisting(viveManifest)) {
+      OpenVRViveBinding viveBinding;
+      std::ofstream viveBindingFile(viveManifest.BeginReading());
+      if (viveBindingFile.is_open()) {
+        viveBindingFile << viveBinding.binding;
+        viveBindingFile.close();
+      }
+    }
+
+#if defined(XP_WIN)
+    if (vrParent->GetOpenVRControllerManifestPath(OpenVRControllerType::WMR,
+                                                  &output)) {
+      WMRManifest = output;
+    } else {
+      WMRManifest = std::tmpnam(nullptr);
+    }
+    if (!FileIsExisting(WMRManifest)) {
+      OpenVRWMRBinding WMRBinding;
+      std::ofstream WMRBindingFile(WMRManifest.BeginReading());
+      if (WMRBindingFile.is_open()) {
+        WMRBindingFile << WMRBinding.binding;
+        WMRBindingFile.close();
+      }
+    }
+#endif
+
+    if (vrParent->GetOpenVRControllerManifestPath(
+            OpenVRControllerType::Knuckles, &output)) {
+      knucklesManifest = output;
+    } else {
+      knucklesManifest = std::tmpnam(nullptr);
+    }
+    if (!FileIsExisting(knucklesManifest)) {
+      OpenVRKnucklesBinding knucklesBinding;
+      std::ofstream knucklesBindingFile(knucklesManifest.BeginReading());
+      if (knucklesBindingFile.is_open()) {
+        knucklesBindingFile << knucklesBinding.binding;
+        knucklesBindingFile.close();
+      }
     }
-  }
-  if (!sKnucklesBindingFile) {
-    sKnucklesBindingFile = ControllerManifestFile::CreateManifest();
-    NS_DispatchToMainThread(NS_NewRunnableFunction(
-        "ClearOnShutdown ControllerManifestFile",
-        []() { ClearOnShutdown(&sKnucklesBindingFile); }));
+  } else {
+    if (!sControllerActionFile) {
+      sControllerActionFile = ControllerManifestFile::CreateManifest();
+      NS_DispatchToMainThread(NS_NewRunnableFunction(
+          "ClearOnShutdown ControllerManifestFile",
+          []() { ClearOnShutdown(&sControllerActionFile); }));
+
+      sControllerActionFile->SetFileName(std::tmpnam(nullptr));
+    }
+    controllerAction = sControllerActionFile->GetFileName();
+
+    if (!sViveBindingFile) {
+      sViveBindingFile = ControllerManifestFile::CreateManifest();
+      NS_DispatchToMainThread(
+          NS_NewRunnableFunction("ClearOnShutdown ControllerManifestFile",
+                                 []() { ClearOnShutdown(&sViveBindingFile); }));
+    }
+    if (!sViveBindingFile->IsExisting()) {
+      sViveBindingFile->SetFileName(std::tmpnam(nullptr));
+      OpenVRViveBinding viveBinding;
+      std::ofstream viveBindingFile(sViveBindingFile->GetFileName());
+      if (viveBindingFile.is_open()) {
+        viveBindingFile << viveBinding.binding;
+        viveBindingFile.close();
+      }
+    }
+    viveManifest = sViveBindingFile->GetFileName();
+
+    if (!sKnucklesBindingFile) {
+      sKnucklesBindingFile = ControllerManifestFile::CreateManifest();
+      NS_DispatchToMainThread(NS_NewRunnableFunction(
+          "ClearOnShutdown ControllerManifestFile",
+          []() { ClearOnShutdown(&sKnucklesBindingFile); }));
+    }
+    if (!sKnucklesBindingFile->IsExisting()) {
+      sKnucklesBindingFile->SetFileName(std::tmpnam(nullptr));
+      OpenVRKnucklesBinding knucklesBinding;
+      std::ofstream knucklesBindingFile(sKnucklesBindingFile->GetFileName());
+      if (knucklesBindingFile.is_open()) {
+        knucklesBindingFile << knucklesBinding.binding;
+        knucklesBindingFile.close();
+      }
+    }
+    knucklesManifest = sKnucklesBindingFile->GetFileName();
+
+#if defined(XP_WIN)
+    if (!sWMRBindingFile) {
+      sWMRBindingFile = ControllerManifestFile::CreateManifest();
+      NS_DispatchToMainThread(
+          NS_NewRunnableFunction("ClearOnShutdown ControllerManifestFile",
+                                 []() { ClearOnShutdown(&sWMRBindingFile); }));
+    }
+    if (!sWMRBindingFile->IsExisting()) {
+      sWMRBindingFile->SetFileName(std::tmpnam(nullptr));
+      OpenVRWMRBinding WMRBinding;
+      std::ofstream WMRBindingFile(sWMRBindingFile->GetFileName());
+      if (WMRBindingFile.is_open()) {
+        WMRBindingFile << WMRBinding.binding;
+        WMRBindingFile.close();
+      }
+    }
+    WMRManifest = sWMRBindingFile->GetFileName();
+#endif
   }
-  if (!sKnucklesBindingFile->IsExisting()) {
-    sKnucklesBindingFile->SetFileName(std::tmpnam(nullptr));
-    OpenVRKnucklesBinding knucklesBinding;
-    std::ofstream knucklesBindingFile(sKnucklesBindingFile->GetFileName());
-    if (knucklesBindingFile.is_open()) {
-      knucklesBindingFile << knucklesBinding.binding;
-      knucklesBindingFile.close();
-    }
-  }
-#if defined(XP_WIN)
-  if (!sWMRBindingFile) {
-    sWMRBindingFile = ControllerManifestFile::CreateManifest();
-    NS_DispatchToMainThread(
-        NS_NewRunnableFunction("ClearOnShutdown ControllerManifestFile",
-                               []() { ClearOnShutdown(&sWMRBindingFile); }));
-  }
-  if (!sWMRBindingFile->IsExisting()) {
-    sWMRBindingFile->SetFileName(std::tmpnam(nullptr));
-    OpenVRWMRBinding WMRBinding;
-    std::ofstream WMRBindingFile(sWMRBindingFile->GetFileName());
-    if (WMRBindingFile.is_open()) {
-      WMRBindingFile << WMRBinding.binding;
-      WMRBindingFile.close();
-    }
-  }
-#endif
 
   ControllerInfo leftContollerInfo;
   leftContollerInfo.mActionPose =
       ControllerAction("/actions/firefox/in/LHand_pose", "pose");
   leftContollerInfo.mActionHaptic =
       ControllerAction("/actions/firefox/out/LHand_haptic", "vibration");
   leftContollerInfo.mActionTrackpad_Analog =
       ControllerAction("/actions/firefox/in/LHand_trackpad_analog", "vector2");
@@ -403,50 +490,40 @@ void OpenVRSession::SetupContollerAction
   rightContollerInfo.mActionFingerRing_Value = ControllerAction(
       "/actions/firefox/in/RHand_finger_ring_value", "vector1");
   rightContollerInfo.mActionFingerPinky_Value = ControllerAction(
       "/actions/firefox/in/RHand_finger_pinky_value", "vector1");
 
   mControllerHand[OpenVRHand::Left] = leftContollerInfo;
   mControllerHand[OpenVRHand::Right] = rightContollerInfo;
 
-  // Check if the action file has been created,
-  // if it doesn't exist, create a new temp file.
-  if (!sControllerActionFile) {
-    sControllerActionFile = ControllerManifestFile::CreateManifest();
-    NS_DispatchToMainThread(NS_NewRunnableFunction(
-        "ClearOnShutdown ControllerManifestFile",
-        []() { ClearOnShutdown(&sControllerActionFile); }));
-  }
-  if (sControllerActionFile->IsExisting()) {
+  if (FileIsExisting(controllerAction)) {
     return;
   }
 
-  sControllerActionFile->SetFileName(std::tmpnam(nullptr));
   nsAutoString actionData;
   JSONWriter actionWriter(MakeUnique<StringWriteFunc>(actionData));
   actionWriter.Start();
 
   actionWriter.StringProperty("version",
                               "0.1.0");  // TODO: adding a version check.
   // "default_bindings": []
   actionWriter.StartArrayProperty("default_bindings");
   actionWriter.StartObjectElement();
   actionWriter.StringProperty("controller_type", "vive_controller");
-  actionWriter.StringProperty("binding_url", sViveBindingFile->GetFileName());
+  actionWriter.StringProperty("binding_url", viveManifest.BeginReading());
   actionWriter.EndObject();
   actionWriter.StartObjectElement();
   actionWriter.StringProperty("controller_type", "knuckles");
-  actionWriter.StringProperty("binding_url",
-                              sKnucklesBindingFile->GetFileName());
+  actionWriter.StringProperty("binding_url", knucklesManifest.BeginReading());
   actionWriter.EndObject();
 #if defined(XP_WIN)
   actionWriter.StartObjectElement();
   actionWriter.StringProperty("controller_type", "holographic_controller");
-  actionWriter.StringProperty("binding_url", sWMRBindingFile->GetFileName());
+  actionWriter.StringProperty("binding_url", WMRManifest.BeginReading());
   actionWriter.EndObject();
 #endif
   actionWriter.EndArray();  // End "default_bindings": []
 
   // "actions": [] Action paths must take the form: "/actions/<action
   // set>/in|out/<action>"
   actionWriter.StartArrayProperty("actions");
 
@@ -610,24 +687,41 @@ void OpenVRSession::SetupContollerAction
                                 controller.mActionHaptic.name.BeginReading());
     actionWriter.StringProperty("type",
                                 controller.mActionHaptic.type.BeginReading());
     actionWriter.EndObject();
   }
   actionWriter.EndArray();  // End "actions": []
   actionWriter.End();
 
-  std::ofstream actionfile(sControllerActionFile->GetFileName());
+  std::ofstream actionfile(controllerAction.BeginReading());
   nsCString actionResult(NS_ConvertUTF16toUTF8(actionData.get()));
   if (actionfile.is_open()) {
     actionfile << actionResult.get();
     actionfile.close();
   }
 
-  vr::VRInput()->SetActionManifestPath(sControllerActionFile->GetFileName());
+  vr::VRInput()->SetActionManifestPath(controllerAction.BeginReading());
+
+  // Notify the parent process these manifest files are already been recorded.
+  if (gfxPrefs::VRProcessEnabled()) {
+    NS_DispatchToMainThread(NS_NewRunnableFunction(
+        "SendOpenVRControllerActionPathToParent",
+        [controllerAction, viveManifest, WMRManifest, knucklesManifest]() {
+          VRParent* vrParent = VRProcessChild::GetVRParent();
+          Unused << vrParent->SendOpenVRControllerActionPathToParent(
+              controllerAction);
+          Unused << vrParent->SendOpenVRControllerManifestPathToParent(
+              OpenVRControllerType::Vive, viveManifest);
+          Unused << vrParent->SendOpenVRControllerManifestPathToParent(
+              OpenVRControllerType::WMR, WMRManifest);
+          Unused << vrParent->SendOpenVRControllerManifestPathToParent(
+              OpenVRControllerType::Knuckles, knucklesManifest);
+        }));
+  }
 }
 
 #if defined(XP_WIN)
 bool OpenVRSession::CreateD3DObjects() {
   RefPtr<ID3D11Device> device = gfx::DeviceManagerDx::Get()->GetVRDevice();
   if (!device) {
     return false;
   }