Bug 1550422 - P9. Sync preferences in VR process when they change. r?daoshengmu! draft
authorJean-Yves Avenard <jyavenard@mozilla.com>
Tue, 14 May 2019 12:40:03 +1000
changeset 2008586 04c90f4ed76f625cc99d4a53f6ed6bb3fa7bb44a
parent 2008585 d8113a005c417457cd19af19cd45b1b09c21357b
child 2008587 7475652b856d0b9a584d454a2fda7e482556b497
push id363925
push userjyavenard@mozilla.com
push dateSat, 18 May 2019 07:53:18 +0000
treeherdertry@5082cd581229 [default view] [failures only]
reviewersdaoshengmu
bugs1550422
milestone68.0a1
Bug 1550422 - P9. Sync preferences in VR process when they change. r?daoshengmu! Differential Revision: https://phabricator.services.mozilla.com/D31017
gfx/vr/ipc/PVR.ipdl
gfx/vr/ipc/VRParent.cpp
gfx/vr/ipc/VRParent.h
gfx/vr/ipc/VRProcessManager.cpp
gfx/vr/ipc/VRProcessManager.h
--- a/gfx/vr/ipc/PVR.ipdl
+++ b/gfx/vr/ipc/PVR.ipdl
@@ -5,32 +5,34 @@
 
 using mozilla::TimeStamp from "mozilla/TimeStamp.h";
 using mozilla::gfx::OpenVRControllerType from "VRMessageUtils.h";
 using mozilla::dom::NativeThreadId from "mozilla/dom/TabMessageUtils.h";
 include "VRMessageUtils.h";
 
 include GraphicsMessages;
 include MemoryReportTypes;
+include PrefsTypes;
 include protocol PVRGPU;
 
 include "VRMessageUtils.h";
 
 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 PreferenceUpdate(Pref pref);
   async OpenVRControllerActionPathToVR(nsCString aPath);
   async OpenVRControllerManifestPathToVR(OpenVRControllerType aType, nsCString aPath);
   async RequestMemoryReport(uint32_t generation,
                             bool anonymize,
                             bool minimizeMemoryUsage,
                             FileDescriptor? DMDFile);
 child:
   // Sent when the GPU process has initialized devices. This occurs once, after
--- a/gfx/vr/ipc/VRParent.cpp
+++ b/gfx/vr/ipc/VRParent.cpp
@@ -80,16 +80,21 @@ IPCResult VRParent::RecvUpdatePref(const
   return IPC_OK();
 }
 
 IPCResult VRParent::RecvUpdateVar(const GfxVarUpdate& aUpdate) {
   gfxVars::ApplyUpdate(aUpdate);
   return IPC_OK();
 }
 
+mozilla::ipc::IPCResult VRParent::RecvPreferenceUpdate(const Pref& aPref) {
+  Preferences::SetPreference(aPref);
+  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) {
--- a/gfx/vr/ipc/VRParent.h
+++ b/gfx/vr/ipc/VRParent.h
@@ -37,16 +37,17 @@ class VRParent final : public PVRParent 
   mozilla::ipc::IPCResult RecvNewGPUVRManager(
       Endpoint<PVRGPUParent>&& aEndpoint);
   mozilla::ipc::IPCResult RecvInit(nsTArray<GfxPrefSetting>&& prefs,
                                    nsTArray<GfxVarUpdate>&& vars,
                                    const DevicePrefs& devicePrefs);
   mozilla::ipc::IPCResult RecvNotifyVsync(const TimeStamp& vsyncTimestamp);
   mozilla::ipc::IPCResult RecvUpdatePref(const GfxPrefSetting& setting);
   mozilla::ipc::IPCResult RecvUpdateVar(const GfxVarUpdate& pref);
+  mozilla::ipc::IPCResult RecvPreferenceUpdate(const Pref& pref);
   mozilla::ipc::IPCResult RecvOpenVRControllerActionPathToVR(
       const nsCString& aPath);
   mozilla::ipc::IPCResult RecvOpenVRControllerManifestPathToVR(
       const OpenVRControllerType& aType, const nsCString& aPath);
   mozilla::ipc::IPCResult RecvRequestMemoryReport(
       const uint32_t& generation, const bool& anonymize,
       const bool& minimizeMemoryUsage,
       const Maybe<ipc::FileDescriptor>& DMDFile);
--- a/gfx/vr/ipc/VRProcessManager.cpp
+++ b/gfx/vr/ipc/VRProcessManager.cpp
@@ -5,17 +5,19 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "VRProcessManager.h"
 
 #include "VRProcessParent.h"
 #include "VRChild.h"
 #include "VRGPUChild.h"
 #include "VRGPUParent.h"
+#include "mozilla/dom/ContentParent.h"
 #include "mozilla/MemoryReportingProcess.h"
+#include "mozilla/Preferences.h"
 
 namespace mozilla {
 namespace gfx {
 
 static StaticAutoPtr<VRProcessManager> sSingleton;
 
 /* static */
 VRProcessManager* VRProcessManager::Get() { return sSingleton; }
@@ -31,16 +33,17 @@ void VRProcessManager::Initialize() {
 /* static */
 void VRProcessManager::Shutdown() { sSingleton = nullptr; }
 
 VRProcessManager::VRProcessManager() : mProcess(nullptr), mVRChild(nullptr) {
   MOZ_COUNT_CTOR(VRProcessManager);
 
   mObserver = new Observer(this);
   nsContentUtils::RegisterShutdownObserver(mObserver);
+  Preferences::AddStrongObserver(mObserver, "");
 }
 
 VRProcessManager::~VRProcessManager() {
   MOZ_COUNT_DTOR(VRProcessManager);
 
   if (mObserver) {
     mObserver->Unregister();
     nsContentUtils::UnregisterShutdownObserver(mObserver);
@@ -117,16 +120,23 @@ void VRProcessManager::OnProcessLaunchCo
 
   mVRChild = mProcess->GetActor();
 
   if (!mProcess->IsConnected()) {
     DestroyProcess();
     return;
   }
 
+  // Flush any pref updates that happened during launch and weren't
+  // included in the blobs set up in LaunchGPUProcess.
+  for (const mozilla::dom::Pref& pref : mQueuedPrefs) {
+    Unused << NS_WARN_IF(!mVRChild->SendPreferenceUpdate(pref));
+  }
+  mQueuedPrefs.Clear();
+
   CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::VRProcessStatus,
                                      NS_LITERAL_CSTRING("Running"));
 }
 
 void VRProcessManager::OnProcessUnexpectedShutdown(VRProcessParent* aParent) {
   MOZ_ASSERT(mProcess && mProcess == aParent);
 
   DestroyProcess();
@@ -172,33 +182,55 @@ NS_IMPL_ISUPPORTS(VRProcessManager::Obse
 VRProcessManager::Observer::Observer(VRProcessManager* aManager)
     : mManager(aManager) {}
 
 NS_IMETHODIMP
 VRProcessManager::Observer::Observe(nsISupports* aSubject, const char* aTopic,
                                     const char16_t* aData) {
   if (!strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
     mManager->OnXPCOMShutdown();
+  } else if (!strcmp(aTopic, "nsPref:changed")) {
+    mManager->OnPreferenceChange(aData);
   }
   return NS_OK;
 }
 
 void VRProcessManager::Observer::Unregister() { mManager = nullptr; }
 
 void VRProcessManager::CleanShutdown() { DestroyProcess(); }
 
 void VRProcessManager::OnXPCOMShutdown() {
   if (mObserver) {
     nsContentUtils::UnregisterShutdownObserver(mObserver);
+    Preferences::RemoveObserver(mObserver, "");
     mObserver = nullptr;
   }
 
   CleanShutdown();
 }
 
+void VRProcessManager::OnPreferenceChange(const char16_t* aData) {
+  // A pref changed. If it's not on the blacklist, inform child processes.
+  if (!dom::ContentParent::ShouldSyncPreference(aData)) {
+    return;
+  }
+
+  // We know prefs are ASCII here.
+  NS_LossyConvertUTF16toASCII strData(aData);
+
+  mozilla::dom::Pref pref(strData, /* isLocked */ false, Nothing(), Nothing());
+  Preferences::GetPreference(&pref);
+  if (!!mVRChild) {
+    MOZ_ASSERT(mQueuedPrefs.IsEmpty());
+    mVRChild->SendPreferenceUpdate(pref);
+  } else {
+    mQueuedPrefs.AppendElement(pref);
+  }
+}
+
 VRChild* VRProcessManager::GetVRChild() { return mProcess->GetActor(); }
 
 class VRMemoryReporter : public MemoryReportingProcess {
  public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VRMemoryReporter, override)
 
   bool IsAlive() const override {
     if (VRProcessManager* vpm = VRProcessManager::Get()) {
--- a/gfx/vr/ipc/VRProcessManager.h
+++ b/gfx/vr/ipc/VRProcessManager.h
@@ -48,16 +48,17 @@ class VRProcessManager final : public VR
  private:
   VRProcessManager();
 
   DISALLOW_COPY_AND_ASSIGN(VRProcessManager);
 
   bool CreateGPUVRManager(base::ProcessId aOtherProcess,
                           mozilla::ipc::Endpoint<PVRGPUChild>* aOutEndpoint);
   void OnXPCOMShutdown();
+  void OnPreferenceChange(const char16_t* aData);
   void CleanShutdown();
   void DestroyProcess();
 
   // Permanently disable the VR process and record a message why.
   void DisableVRProcess(const char* aMessage);
 
   class Observer final : public nsIObserver {
    public:
@@ -71,14 +72,18 @@ class VRProcessManager final : public VR
 
     VRProcessManager* mManager;
   };
   friend class Observer;
 
   RefPtr<Observer> mObserver;
   VRProcessParent* mProcess;
   VRChild* mVRChild;
+  // Collects any pref changes that occur during process launch (after
+  // the initial map is passed in command-line arguments) to be sent
+  // when the process can receive IPC messages.
+  nsTArray<mozilla::dom::Pref> mQueuedPrefs;
 };
 
 }  // namespace gfx
 }  // namespace mozilla
 
 #endif  // GFX_VR_PROCESS_MANAGER_H