Bug 1514874 - Start RDD process on-demand. r=jya,jld, a=RyanVM
authorMichael Froman <mfroman@mozilla.com>
Sat, 12 Jan 2019 04:51:20 +0000
changeset 509490 c10cd6aadb9656703e01212906b77d3232694f3b
parent 509489 44fe44a6a340b557bda4467ec632db5f4ac47c02
child 509491 92b23e3b94efeb8093e22cab16828efd5b1cc693
push id1905
push userffxbld-merge
push dateMon, 21 Jan 2019 12:33:13 +0000
treeherdermozilla-release@c2fca1944d8c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjya, jld, RyanVM
bugs1514874
milestone65.0
Bug 1514874 - Start RDD process on-demand. r=jya,jld, a=RyanVM Differential Revision: https://phabricator.services.mozilla.com/D15775
dom/ipc/ContentChild.cpp
dom/ipc/ContentChild.h
dom/ipc/ContentParent.cpp
dom/ipc/ContentParent.h
dom/ipc/PContent.ipdl
dom/media/ipc/RemoteDecoderModule.cpp
dom/media/ipc/RemoteDecoderModule.h
gfx/thebes/gfxPlatform.cpp
ipc/ipdl/sync-messages.ini
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -66,16 +66,17 @@
 #include "mozilla/intl/LocaleService.h"
 #include "mozilla/ipc/TestShellChild.h"
 #include "mozilla/jsipc/CrossProcessObjectWrappers.h"
 #include "mozilla/jsipc/PJavaScript.h"
 #include "mozilla/layers/APZChild.h"
 #include "mozilla/layers/CompositorManagerChild.h"
 #include "mozilla/layers/ContentProcessController.h"
 #include "mozilla/layers/ImageBridgeChild.h"
+#include "mozilla/layers/SynchronousTask.h"  // for LaunchRDDProcess
 #include "mozilla/loader/ScriptCacheActors.h"
 #include "mozilla/net/NeckoChild.h"
 #include "mozilla/net/CookieServiceChild.h"
 #include "mozilla/net/CaptivePortalService.h"
 #include "mozilla/PerformanceMetricsCollector.h"
 #include "mozilla/PerformanceUtils.h"
 #include "mozilla/plugins/PluginInstanceParent.h"
 #include "mozilla/plugins/PluginModuleParent.h"
@@ -1108,16 +1109,32 @@ nsresult ContentChild::ProvideWindowComm
   MOZ_ASSERT_IF(NS_SUCCEEDED(rv), *aReturn);
   return rv;
 }
 
 void ContentChild::GetProcessName(nsAString& aName) const {
   aName.Assign(mProcessName);
 }
 
+void ContentChild::LaunchRDDProcess() {
+  SynchronousTask task("LaunchRDDProcess");
+  SystemGroup::Dispatch(
+      TaskCategory::Other,
+      NS_NewRunnableFunction("LaunchRDDProcess", [&task, this] {
+        AutoCompleteTask complete(&task);
+        nsresult rv;
+        Endpoint<PRemoteDecoderManagerChild> endpoint;
+        Unused << SendLaunchRDDProcess(&rv, &endpoint);
+        if (rv == NS_OK) {
+          RemoteDecoderManagerChild::InitForContent(std::move(endpoint));
+        }
+      }));
+  task.Wait();
+}
+
 bool ContentChild::IsAlive() const { return mIsAlive; }
 
 bool ContentChild::IsShuttingDown() const { return mShuttingDown; }
 
 void ContentChild::GetProcessName(nsACString& aName) const {
   aName.Assign(NS_ConvertUTF16toUTF8(mProcessName));
 }
 
@@ -1426,22 +1443,16 @@ mozilla::ipc::IPCResult ContentChild::Re
   for (const auto& tabChild : tabs) {
     if (tabChild->GetLayersId().IsValid()) {
       tabChild->ReinitRenderingForDeviceReset();
     }
   }
   return IPC_OK();
 }
 
-mozilla::ipc::IPCResult ContentChild::RecvInitRemoteDecoder(
-    Endpoint<PRemoteDecoderManagerChild>&& aRemoteManager) {
-  RemoteDecoderManagerChild::InitForContent(std::move(aRemoteManager));
-  return IPC_OK();
-}
-
 #if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX)
 extern "C" {
 CGError CGSSetDenyWindowServerConnections(bool);
 void CGSShutdownServerConnections();
 };
 
 static bool StartMacOSContentSandbox() {
   int sandboxLevel = GetEffectiveContentSandboxLevel();
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -128,16 +128,18 @@ class ContentChild final : public PConte
   const AppInfo& GetAppInfo() { return mAppInfo; }
 
   void SetProcessName(const nsAString& aName);
 
   void GetProcessName(nsAString& aName) const;
 
   void GetProcessName(nsACString& aName) const;
 
+  void LaunchRDDProcess();
+
 #if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX)
   void GetProfileDir(nsIFile** aProfileDir) const {
     *aProfileDir = mProfileDir;
     NS_IF_ADDREF(*aProfileDir);
   }
 
   void SetProfileDir(nsIFile* aProfileDir) { mProfileDir = aProfileDir; }
 #endif
@@ -183,19 +185,16 @@ class ContentChild final : public PConte
       Endpoint<PVRManagerChild>&& aVRBridge,
       Endpoint<PVideoDecoderManagerChild>&& aVideoManager,
       nsTArray<uint32_t>&& namespaces) override;
 
   virtual mozilla::ipc::IPCResult RecvAudioDefaultDeviceChange() override;
 
   mozilla::ipc::IPCResult RecvReinitRenderingForDeviceReset() override;
 
-  virtual mozilla::ipc::IPCResult RecvInitRemoteDecoder(
-      Endpoint<PRemoteDecoderManagerChild>&& aRemoteManager) override;
-
   virtual mozilla::ipc::IPCResult RecvSetProcessSandbox(
       const MaybeFileDesc& aBroker) override;
 
   virtual PBrowserChild* AllocPBrowserChild(const TabId& aTabId,
                                             const TabId& aSameTabGroupAs,
                                             const IPCTabContext& aContext,
                                             const uint32_t& aChromeFlags,
                                             const ContentParentId& aCpID,
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -1113,16 +1113,41 @@ mozilla::ipc::IPCResult ContentParent::R
   // pointer and just throw it away.
   uint32_t dummy = 0;
   if (!mozilla::plugins::SetupBridge(aPluginId, this, aRv, &dummy, aEndpoint)) {
     return IPC_FAIL(this, "SetupBridge failed");
   }
   return IPC_OK();
 }
 
+mozilla::ipc::IPCResult ContentParent::RecvLaunchRDDProcess(
+    nsresult* aRv, Endpoint<PRemoteDecoderManagerChild>* aEndpoint) {
+  *aRv = NS_OK;
+
+  if (XRE_IsParentProcess() &&
+      BrowserTabsRemoteAutostart() &&  // only do rdd process if e10s on
+      Preferences::GetBool("media.rdd-process.enabled", false)) {
+    RDDProcessManager* rdd = RDDProcessManager::Get();
+    if (rdd) {
+      rdd->LaunchRDDProcess();
+
+      bool rddOpened = rdd->CreateContentBridge(OtherPid(), aEndpoint);
+      MOZ_ASSERT(rddOpened);
+
+      if (!rddOpened) {
+        *aRv = NS_ERROR_NOT_AVAILABLE;
+      }
+    } else {
+      *aRv = NS_ERROR_NOT_AVAILABLE;
+    }
+  }
+
+  return IPC_OK();
+}
+
 /*static*/ TabParent* ContentParent::CreateBrowser(
     const TabContext& aContext, Element* aFrameElement,
     ContentParent* aOpenerContentParent, TabParent* aSameTabGroupAs,
     uint64_t aNextTabParentId) {
   AUTO_PROFILER_LABEL("ContentParent::CreateBrowser", OTHER);
 
   if (!sCanLaunchSubprocesses) {
     return nullptr;
@@ -2606,32 +2631,16 @@ void ContentParent::InitInternal(Process
   MOZ_ASSERT(opened);
 
   Unused << SendInitRendering(std::move(compositor), std::move(imageBridge),
                               std::move(vrBridge), std::move(videoManager),
                               namespaces);
 
   gpm->AddListener(this);
 
-  if (StaticPrefs::MediaRddProcessEnabled() && BrowserTabsRemoteAutostart()) {
-    RDDProcessManager* rdd = RDDProcessManager::Get();
-
-    Endpoint<PRemoteDecoderManagerChild> remoteManager;
-    bool rddOpened = rdd->CreateContentBridge(OtherPid(), &remoteManager);
-    MOZ_ASSERT(rddOpened);
-
-    if (rddOpened) {
-      // not using std::move here (like in SendInitRendering above) because
-      // clang-tidy says:
-      // Warning: Passing result of std::move() as a const reference
-      // argument; no move will actually happen
-      Unused << SendInitRemoteDecoder(remoteManager);
-    }
-  }
-
   nsStyleSheetService* sheetService = nsStyleSheetService::GetInstance();
   if (sheetService) {
     // This looks like a lot of work, but in a normal browser session we just
     // send two loads.
     //
     // The URIs of the Gecko and Servo sheets should be the same, so it
     // shouldn't matter which we look at.
 
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -297,16 +297,19 @@ class ContentParent final : public PCont
       Endpoint<PPluginModuleParent>* aEndpoint) override;
 
   virtual mozilla::ipc::IPCResult RecvMaybeReloadPlugins() override;
 
   virtual mozilla::ipc::IPCResult RecvConnectPluginBridge(
       const uint32_t& aPluginId, nsresult* aRv,
       Endpoint<PPluginModuleParent>* aEndpoint) override;
 
+  virtual mozilla::ipc::IPCResult RecvLaunchRDDProcess(
+      nsresult* aRv, Endpoint<PRemoteDecoderManagerChild>* aEndpoint) override;
+
   virtual mozilla::ipc::IPCResult RecvUngrabPointer(
       const uint32_t& aTime) override;
 
   virtual mozilla::ipc::IPCResult RecvRemovePermission(
       const IPC::Principal& aPrincipal, const nsCString& aPermissionType,
       nsresult* aRv) override;
 
   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(ContentParent, nsIObserver)
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -393,18 +393,16 @@ child:
       Endpoint<PVideoDecoderManagerChild> video,
       uint32_t[] namespaces);
 
     async AudioDefaultDeviceChange();
 
     // Re-create the rendering stack for a device reset.
     async ReinitRenderingForDeviceReset();
 
-    async InitRemoteDecoder(Endpoint<PRemoteDecoderManagerChild> decoder);
-
     /**
      * Enable system-level sandboxing features, if available.  Can
      * usually only be performed zero or one times.  The child may
      * abnormally exit if this fails; the details are OS-specific.
      */
     async SetProcessSandbox(MaybeFileDesc aBroker);
 
     async RequestMemoryReport(uint32_t generation,
@@ -761,16 +759,20 @@ parent:
      * This call is used by asynchronous plugin instantiation to notify the
      * content parent that it is now safe to initiate the plugin bridge for
      * the specified plugin id. The endpoint for the content process part of the
      * bridge is returned.
      */
     sync ConnectPluginBridge(uint32_t aPluginId)
         returns (nsresult rv, Endpoint<PPluginModuleParent> aEndpoint);
 
+    // See Bug 1518344 - Investigate using async for PContent::LaunchRDDProcess
+    sync LaunchRDDProcess()
+        returns (nsresult rv, Endpoint<PRemoteDecoderManagerChild> aEndpoint);
+
     async PJavaScript();
 
     async PRemoteSpellcheckEngine();
 
     async InitCrashReporter(Shmem shmem, NativeThreadId tid);
 
     sync IsSecureURI(uint32_t aType, URIParams aURI, uint32_t aFlags,
                      OriginAttributes aOriginAttributes)
--- a/dom/media/ipc/RemoteDecoderModule.cpp
+++ b/dom/media/ipc/RemoteDecoderModule.cpp
@@ -1,39 +1,34 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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/. */
 #include "RemoteDecoderModule.h"
 
 #include "base/thread.h"
+#include "mozilla/dom/ContentChild.h"  // for launching RDD w/ ContentChild
 #include "mozilla/layers/SynchronousTask.h"
 #include "mozilla/StaticPrefs.h"
 
 #ifdef MOZ_AV1
 #include "AOMDecoder.h"
 #endif
 #include "RemoteDecoderManagerChild.h"
 #include "RemoteMediaDataDecoder.h"
 #include "RemoteVideoDecoderChild.h"
 
 namespace mozilla {
 
 using base::Thread;
+using dom::ContentChild;
 using namespace ipc;
 using namespace layers;
 
-nsresult RemoteDecoderModule::Startup() {
-  if (!RemoteDecoderManagerChild::GetManagerThread()) {
-    return NS_ERROR_FAILURE;
-  }
-  return NS_OK;
-}
-
 bool RemoteDecoderModule::SupportsMimeType(
     const nsACString& aMimeType, DecoderDoctorDiagnostics* aDiagnostics) const {
   bool supports = false;
 
 #ifdef MOZ_AV1
   if (StaticPrefs::MediaAv1Enabled()) {
     supports |= AOMDecoder::IsAV1(aMimeType);
   }
@@ -41,16 +36,25 @@ bool RemoteDecoderModule::SupportsMimeTy
   MOZ_LOG(
       sPDMLog, LogLevel::Debug,
       ("Sandbox decoder %s requested type", supports ? "supports" : "rejects"));
   return supports;
 }
 
 already_AddRefed<MediaDataDecoder> RemoteDecoderModule::CreateVideoDecoder(
     const CreateDecoderParams& aParams) {
+  if (XRE_IsContentProcess()) {
+    ContentChild* contentChild = ContentChild::GetSingleton();
+    contentChild->LaunchRDDProcess();
+  }
+
+  if (!RemoteDecoderManagerChild::GetManagerThread()) {
+    return nullptr;
+  }
+
   RemoteVideoDecoderChild* child = new RemoteVideoDecoderChild();
   RefPtr<RemoteMediaDataDecoder> object = new RemoteMediaDataDecoder(
       child, RemoteDecoderManagerChild::GetManagerThread(),
       RemoteDecoderManagerChild::GetManagerAbstractThread());
 
   // (per Matt Woodrow) We can't use NS_DISPATCH_SYNC here since that
   // can spin the event loop while it waits.
   SynchronousTask task("InitIPDL");
--- a/dom/media/ipc/RemoteDecoderModule.h
+++ b/dom/media/ipc/RemoteDecoderModule.h
@@ -12,18 +12,16 @@ namespace mozilla {
 // A PDM implementation that creates a RemoteMediaDataDecoder (a
 // MediaDataDecoder) that proxies to a RemoteVideoDecoderChild.
 // A decoder child will talk to its respective decoder parent
 // (RemoteVideoDecoderParent) on the RDD process.
 class RemoteDecoderModule : public PlatformDecoderModule {
  public:
   RemoteDecoderModule() = default;
 
-  nsresult Startup() override;
-
   bool SupportsMimeType(const nsACString& aMimeType,
                         DecoderDoctorDiagnostics* aDiagnostics) const override;
 
   already_AddRefed<MediaDataDecoder> CreateVideoDecoder(
       const CreateDecoderParams& aParams) override;
 
   already_AddRefed<MediaDataDecoder> CreateAudioDecoder(
       const CreateDecoderParams& aParams) override {
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -913,25 +913,16 @@ void gfxPlatform::Init() {
   gPlatform->InitWebRenderConfig();
   gPlatform->InitOMTPConfig();
 
   if (gfxConfig::IsEnabled(Feature::GPU_PROCESS)) {
     GPUProcessManager* gpu = GPUProcessManager::Get();
     gpu->LaunchGPUProcess();
   }
 
-  if (XRE_IsParentProcess() &&
-      BrowserTabsRemoteAutostart() &&  // only do rdd process if e10s on
-      Preferences::GetBool("media.rdd-process.enabled", false)) {
-    RDDProcessManager* rdd = RDDProcessManager::Get();
-    if (rdd) {
-      rdd->LaunchRDDProcess();
-    }
-  }
-
   if (XRE_IsParentProcess() || recordreplay::IsRecordingOrReplaying()) {
     if (gfxPlatform::ForceSoftwareVsync()) {
       gPlatform->mVsyncSource =
           (gPlatform)->gfxPlatform::CreateHardwareVsyncSource();
     } else {
       gPlatform->mVsyncSource = gPlatform->CreateHardwareVsyncSource();
     }
   }
--- a/ipc/ipdl/sync-messages.ini
+++ b/ipc/ipdl/sync-messages.ini
@@ -911,16 +911,18 @@ description =
 [PGMPService::GetGMPNodeId]
 description =
 [PGMPVideoDecoder::NeedShmem]
 description =
 [PGMPVideoEncoder::NeedShmem]
 description =
 [PRemoteDecoderManager::PRemoteVideoDecoder]
 description = See Bug 1505976 - investigate changing to async instead of matching GPU pattern
+[PContent::LaunchRDDProcess]
+description = See Bug 1518344 - investigate using async for PContent::LaunchRDDProcess
 [PVideoDecoderManager::PVideoDecoder]
 description =
 [PVideoDecoderManager::Readback]
 description =
 [PBackgroundStorage::Preload]
 description =
 [PBackgroundLSDatabase::PBackgroundLSSnapshot]
 description = See corresponding comment in PBackgroundLSDatabase.ipdl