Bug 1514874 - start RDD process on-demand r=jya,jld
authorMichael Froman <mfroman@mozilla.com>
Sat, 12 Jan 2019 04:51:20 +0000
changeset 510699 c28b226ee6c1d383487fb7dd75a14f419221a143
parent 510698 199b64bd4ead7f270101d53e2e781edfb22a63a5
child 510700 37838b3650fd5b4c66cb1b63b366a40931076fcb
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)
reviewersjya, jld
bugs1514874
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 1514874 - start RDD process on-demand r=jya,jld 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
@@ -68,16 +68,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"
@@ -1111,16 +1112,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));
 }
 
@@ -1435,22 +1452,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
@@ -1115,16 +1115,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;
@@ -2590,32 +2615,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
@@ -406,18 +406,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,
@@ -776,16 +774,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
@@ -926,25 +926,16 @@ void gfxPlatform::Init() {
   }
   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();
-    }
-  }
-
   gLastUsedFrameRate = ForceSoftwareVsync() ? GetSoftwareVsyncRate() : -1;
   auto updateFrameRateCallback = [](const GfxPrefValue& aValue) -> void {
     int32_t newRate = ForceSoftwareVsync() ? GetSoftwareVsyncRate() : -1;
     if (newRate != gLastUsedFrameRate) {
       gLastUsedFrameRate = newRate;
       ReInitFrameRate();
     }
   };
--- a/ipc/ipdl/sync-messages.ini
+++ b/ipc/ipdl/sync-messages.ini
@@ -909,16 +909,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