Bug 1571711 - Factorize crash handling out of the various process IPC classes r=froydnj
☠☠ backed out by 7710c9d9b6b0 ☠ ☠
authorGabriele Svelto <gsvelto@mozilla.com>
Tue, 13 Aug 2019 21:43:00 +0000
changeset 488038 c60ee628dd0e2c7ff6d829c5536dc15332735286
parent 488037 f48c581ece1bfd0f54d206d9f7d3bdf17789eded
child 488039 77b5eec7b9e5b3f1fdf55bab886cc9391cd8a536
push id36434
push usercbrindusan@mozilla.com
push dateThu, 15 Aug 2019 09:44:30 +0000
treeherdermozilla-central@144fbfb409b7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj
bugs1571711
milestone70.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 1571711 - Factorize crash handling out of the various process IPC classes r=froydnj Differential Revision: https://phabricator.services.mozilla.com/D41657
dom/media/gmp/GMPParent.cpp
dom/media/gmp/GMPParent.h
dom/media/ipc/RDDChild.cpp
dom/media/ipc/RDDChild.h
gfx/ipc/GPUChild.cpp
gfx/ipc/GPUChild.h
gfx/vr/ipc/VRChild.cpp
gfx/vr/ipc/VRChild.h
ipc/glue/CrashReporterClient.h
ipc/glue/CrashReporterHelper.h
ipc/glue/CrashReporterHost.h
ipc/glue/moz.build
netwerk/ipc/SocketProcessParent.cpp
netwerk/ipc/SocketProcessParent.h
security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerParent.cpp
security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerParent.h
--- a/dom/media/gmp/GMPParent.cpp
+++ b/dom/media/gmp/GMPParent.cpp
@@ -419,39 +419,31 @@ bool GMPParent::EnsureProcessLoaded() {
   }
 
   nsresult rv = LoadProcess();
 
   return NS_SUCCEEDED(rv);
 }
 
 void GMPParent::AddCrashAnnotations() {
-  mCrashReporter->AddAnnotation(CrashReporter::Annotation::GMPPlugin, true);
-  mCrashReporter->AddAnnotation(CrashReporter::Annotation::PluginFilename,
-                                NS_ConvertUTF16toUTF8(mName));
-  mCrashReporter->AddAnnotation(CrashReporter::Annotation::PluginName,
-                                mDisplayName);
-  mCrashReporter->AddAnnotation(CrashReporter::Annotation::PluginVersion,
-                                mVersion);
+  if (mCrashReporter) {
+    mCrashReporter->AddAnnotation(CrashReporter::Annotation::GMPPlugin, true);
+    mCrashReporter->AddAnnotation(CrashReporter::Annotation::PluginFilename,
+                                  NS_ConvertUTF16toUTF8(mName));
+    mCrashReporter->AddAnnotation(CrashReporter::Annotation::PluginName,
+                                  mDisplayName);
+    mCrashReporter->AddAnnotation(CrashReporter::Annotation::PluginVersion,
+                                  mVersion);
+  }
 }
 
 bool GMPParent::GetCrashID(nsString& aResult) {
-  if (!mCrashReporter) {
-    CrashReporter::FinalizeOrphanedMinidump(OtherPid(),
-                                            GeckoProcessType_GMPlugin);
-    return false;
-  }
+  AddCrashAnnotations();
 
-  AddCrashAnnotations();
-  if (!mCrashReporter->GenerateCrashReport(OtherPid())) {
-    return false;
-  }
-
-  aResult = mCrashReporter->MinidumpID();
-  return true;
+  return GenerateCrashReport(OtherPid(), &aResult);
 }
 
 static void GMPNotifyObservers(const uint32_t aPluginID,
                                const nsACString& aPluginName,
                                const nsAString& aPluginDumpID) {
   nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
   nsCOMPtr<nsIWritablePropertyBag2> propbag =
       do_CreateInstance("@mozilla.org/hash-property-bag;1");
@@ -503,24 +495,16 @@ void GMPParent::ActorDestroy(ActorDestro
     // infinitely if we do.
     MOZ_ASSERT(mState == GMPStateClosing);
     DeleteProcess();
     // Note: final destruction will be Dispatched to ourself
     mService->ReAddOnGMPThread(self);
   }
 }
 
-mozilla::ipc::IPCResult GMPParent::RecvInitCrashReporter(
-    Shmem&& aShmem, const NativeThreadId& aThreadId) {
-  mCrashReporter = MakeUnique<ipc::CrashReporterHost>(GeckoProcessType_GMPlugin,
-                                                      aShmem, aThreadId);
-
-  return IPC_OK();
-}
-
 PGMPStorageParent* GMPParent::AllocPGMPStorageParent() {
   GMPStorageParent* p = new GMPStorageParent(mNodeId, this);
   mStorage.AppendElement(p);  // Addrefs, released in DeallocPGMPStorageParent.
   return p;
 }
 
 bool GMPParent::DeallocPGMPStorageParent(PGMPStorageParent* aActor) {
   GMPStorageParent* p = static_cast<GMPStorageParent*>(aActor);
--- a/dom/media/gmp/GMPParent.h
+++ b/dom/media/gmp/GMPParent.h
@@ -8,28 +8,26 @@
 
 #include "GMPProcessParent.h"
 #include "GMPServiceParent.h"
 #include "GMPVideoDecoderParent.h"
 #include "GMPVideoEncoderParent.h"
 #include "GMPTimerParent.h"
 #include "GMPStorageParent.h"
 #include "mozilla/gmp/PGMPParent.h"
+#include "mozilla/ipc/CrashReporterHelper.h"
 #include "nsCOMPtr.h"
 #include "nscore.h"
 #include "nsISupports.h"
 #include "nsString.h"
 #include "nsTArray.h"
 #include "nsIFile.h"
 #include "mozilla/MozPromise.h"
 
 namespace mozilla {
-namespace ipc {
-class CrashReporterHost;
-}  // namespace ipc
 namespace gmp {
 
 class GMPCapability {
  public:
   explicit GMPCapability() {}
   GMPCapability(GMPCapability&& aOther)
       : mAPIName(std::move(aOther.mAPIName)),
         mAPITags(std::move(aOther.mAPITags)) {}
@@ -49,17 +47,19 @@ enum GMPState {
   GMPStateNotLoaded,
   GMPStateLoaded,
   GMPStateUnloading,
   GMPStateClosing
 };
 
 class GMPContentParent;
 
-class GMPParent final : public PGMPParent {
+class GMPParent final
+    : public PGMPParent,
+      public ipc::CrashReporterHelper<GeckoProcessType_GMPlugin> {
   friend class PGMPParent;
 
  public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GMPParent)
 
   explicit GMPParent(AbstractThread* aMainThread);
 
   RefPtr<GenericPromise> Init(GeckoMediaPluginServiceParent* aService,
@@ -152,19 +152,16 @@ class GMPParent final : public PGMPParen
   RefPtr<GenericPromise> ParseChromiumManifest(
       const nsAString& aJSON);  // Main thread.
   RefPtr<GenericPromise> ReadChromiumManifestFile(
       nsIFile* aFile);  // GMP thread.
   void AddCrashAnnotations();
   bool GetCrashID(nsString& aResult);
   void ActorDestroy(ActorDestroyReason aWhy) override;
 
-  mozilla::ipc::IPCResult RecvInitCrashReporter(
-      Shmem&& shmem, const NativeThreadId& aThreadId);
-
   mozilla::ipc::IPCResult RecvPGMPStorageConstructor(
       PGMPStorageParent* actor) override;
   PGMPStorageParent* AllocPGMPStorageParent();
   bool DeallocPGMPStorageParent(PGMPStorageParent* aActor);
 
   mozilla::ipc::IPCResult RecvPGMPTimerConstructor(
       PGMPTimerParent* actor) override;
   PGMPTimerParent* AllocPGMPTimerParent();
@@ -212,17 +209,15 @@ class GMPParent final : public PGMPParen
   int mChildPid;
 
   // We hold a self reference to ourself while the child process is alive.
   // This ensures that if the GMPService tries to shut us down and drops
   // its reference to us, we stay alive long enough for the child process
   // to terminate gracefully.
   bool mHoldingSelfRef;
 
-  UniquePtr<ipc::CrashReporterHost> mCrashReporter;
-
   const RefPtr<AbstractThread> mMainThread;
 };
 
 }  // namespace gmp
 }  // namespace mozilla
 
 #endif  // GMPParent_h_
--- a/dom/media/ipc/RDDChild.cpp
+++ b/dom/media/ipc/RDDChild.cpp
@@ -75,24 +75,16 @@ mozilla::ipc::IPCResult RDDChild::RecvIn
   if (mRDDReady) {
     return IPC_OK();
   }
 
   mRDDReady = true;
   return IPC_OK();
 }
 
-mozilla::ipc::IPCResult RDDChild::RecvInitCrashReporter(
-    Shmem&& aShmem, const NativeThreadId& aThreadId) {
-  mCrashReporter = MakeUnique<ipc::CrashReporterHost>(GeckoProcessType_RDD,
-                                                      aShmem, aThreadId);
-
-  return IPC_OK();
-}
-
 bool RDDChild::SendRequestMemoryReport(const uint32_t& aGeneration,
                                        const bool& aAnonymize,
                                        const bool& aMinimizeMemoryUsage,
                                        const Maybe<FileDescriptor>& aDMDFile) {
   mMemoryReportRequest = MakeUnique<MemoryReportRequestHost>(aGeneration);
   Unused << PRDDChild::SendRequestMemoryReport(aGeneration, aAnonymize,
                                                aMinimizeMemoryUsage, aDMDFile);
   return true;
@@ -114,22 +106,17 @@ mozilla::ipc::IPCResult RDDChild::RecvFi
     mMemoryReportRequest->Finish(aGeneration);
     mMemoryReportRequest = nullptr;
   }
   return IPC_OK();
 }
 
 void RDDChild::ActorDestroy(ActorDestroyReason aWhy) {
   if (aWhy == AbnormalShutdown) {
-    if (mCrashReporter) {
-      mCrashReporter->GenerateCrashReport(OtherPid());
-      mCrashReporter = nullptr;
-    } else {
-      CrashReporter::FinalizeOrphanedMinidump(OtherPid(), GeckoProcessType_RDD);
-    }
+    GenerateCrashReport(OtherPid());
   }
 
   gfxVars::RemoveReceiver(this);
   mHost->OnChannelClosed();
 }
 
 class DeferredDeleteRDDChild : public Runnable {
  public:
--- a/dom/media/ipc/RDDChild.h
+++ b/dom/media/ipc/RDDChild.h
@@ -2,68 +2,64 @@
 /* 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/. */
 #ifndef _include_dom_media_ipc_RDDChild_h_
 #define _include_dom_media_ipc_RDDChild_h_
 #include "mozilla/PRDDChild.h"
 
-#include "mozilla/RefPtr.h"
+#include "mozilla/ipc/CrashReporterHelper.h"
 #include "mozilla/UniquePtr.h"
 #include "mozilla/gfx/gfxVarReceiver.h"
 
 namespace mozilla {
 
 #if defined(XP_LINUX) && defined(MOZ_SANDBOX)
 class SandboxBroker;
 #endif
 
-namespace ipc {
-class CrashReporterHost;
-}  // namespace ipc
 namespace dom {
 class MemoryReportRequestHost;
 }  // namespace dom
 
 class RDDProcessHost;
 
-class RDDChild final : public PRDDChild, public gfx::gfxVarReceiver {
+class RDDChild final : public PRDDChild,
+                       public ipc::CrashReporterHelper<GeckoProcessType_RDD>,
+                       public gfx::gfxVarReceiver {
   typedef mozilla::dom::MemoryReportRequestHost MemoryReportRequestHost;
 
  public:
   explicit RDDChild(RDDProcessHost* aHost);
   ~RDDChild();
 
   bool Init(bool aStartMacSandbox);
 
   bool EnsureRDDReady();
 
   void OnVarChanged(const GfxVarUpdate& aVar) override;
 
   // PRDDChild overrides.
   mozilla::ipc::IPCResult RecvInitComplete();
-  mozilla::ipc::IPCResult RecvInitCrashReporter(
-      Shmem&& shmem, const NativeThreadId& aThreadId);
 
   void ActorDestroy(ActorDestroyReason aWhy) override;
 
   mozilla::ipc::IPCResult RecvAddMemoryReport(const MemoryReport& aReport);
   mozilla::ipc::IPCResult RecvFinishMemoryReport(const uint32_t& aGeneration);
 
   bool SendRequestMemoryReport(const uint32_t& aGeneration,
                                const bool& aAnonymize,
                                const bool& aMinimizeMemoryUsage,
                                const Maybe<ipc::FileDescriptor>& aDMDFile);
 
   static void Destroy(UniquePtr<RDDChild>&& aChild);
 
  private:
   RDDProcessHost* mHost;
-  UniquePtr<ipc::CrashReporterHost> mCrashReporter;
   UniquePtr<MemoryReportRequestHost> mMemoryReportRequest;
 #if defined(XP_LINUX) && defined(MOZ_SANDBOX)
   UniquePtr<SandboxBroker> mSandboxBroker;
 #endif
   bool mRDDReady;
 };
 
 }  // namespace mozilla
--- a/gfx/ipc/GPUChild.cpp
+++ b/gfx/ipc/GPUChild.cpp
@@ -12,17 +12,16 @@
 #include "mozilla/Telemetry.h"
 #include "mozilla/TelemetryIPC.h"
 #include "mozilla/dom/CheckerboardReportService.h"
 #include "mozilla/dom/MemoryReportRequest.h"
 #include "mozilla/gfx/gfxVars.h"
 #if defined(XP_WIN)
 #  include "mozilla/gfx/DeviceManagerDx.h"
 #endif
-#include "mozilla/ipc/CrashReporterHost.h"
 #include "mozilla/layers/APZInputBridgeChild.h"
 #include "mozilla/layers/LayerTreeOwnerTracker.h"
 #include "mozilla/Unused.h"
 #include "mozilla/HangDetails.h"
 #include "nsIObserverService.h"
 
 #ifdef MOZ_GECKO_PROFILER
 #  include "ProfilerParent.h"
@@ -113,24 +112,16 @@ mozilla::ipc::IPCResult GPUChild::RecvGr
   if (lf) {
     std::stringstream message;
     message << "GP+" << aError.get();
     lf->UpdateStringsVector(message.str());
   }
   return IPC_OK();
 }
 
-mozilla::ipc::IPCResult GPUChild::RecvInitCrashReporter(
-    Shmem&& aShmem, const NativeThreadId& aThreadId) {
-  mCrashReporter = MakeUnique<ipc::CrashReporterHost>(GeckoProcessType_GPU,
-                                                      aShmem, aThreadId);
-
-  return IPC_OK();
-}
-
 mozilla::ipc::IPCResult GPUChild::RecvCreateVRProcess() {
   // Make sure create VR process at the main process
   MOZ_ASSERT(XRE_IsParentProcess());
   if (StaticPrefs::dom_vr_process_enabled_AtStartup()) {
     VRProcessManager::Initialize();
     VRProcessManager* vr = VRProcessManager::Get();
     MOZ_ASSERT(vr, "VRProcessManager must be initialized first.");
 
@@ -232,22 +223,17 @@ mozilla::ipc::IPCResult GPUChild::RecvFi
     mMemoryReportRequest->Finish(aGeneration);
     mMemoryReportRequest = nullptr;
   }
   return IPC_OK();
 }
 
 void GPUChild::ActorDestroy(ActorDestroyReason aWhy) {
   if (aWhy == AbnormalShutdown) {
-    if (mCrashReporter) {
-      mCrashReporter->GenerateCrashReport(OtherPid());
-      mCrashReporter = nullptr;
-    } else {
-      CrashReporter::FinalizeOrphanedMinidump(OtherPid(), GeckoProcessType_GPU);
-    }
+    GenerateCrashReport(OtherPid());
 
     Telemetry::Accumulate(
         Telemetry::SUBPROCESS_ABNORMAL_ABORT,
         nsDependentCString(XRE_ChildProcessTypeToString(GeckoProcessType_GPU)),
         1);
 
     // Notify the Telemetry environment so that we can refresh and do a
     // subsession split
--- a/gfx/ipc/GPUChild.h
+++ b/gfx/ipc/GPUChild.h
@@ -3,32 +3,32 @@
 /* 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 _include_mozilla_gfx_ipc_GPUChild_h_
 #define _include_mozilla_gfx_ipc_GPUChild_h_
 
 #include "mozilla/RefPtr.h"
 #include "mozilla/UniquePtr.h"
+#include "mozilla/ipc/CrashReporterHelper.h"
 #include "mozilla/gfx/PGPUChild.h"
 #include "mozilla/gfx/gfxVarReceiver.h"
 
 namespace mozilla {
 
-namespace ipc {
-class CrashReporterHost;
-}  // namespace ipc
 namespace dom {
 class MemoryReportRequestHost;
 }  // namespace dom
 namespace gfx {
 
 class GPUProcessHost;
 
-class GPUChild final : public PGPUChild, public gfxVarReceiver {
+class GPUChild final : public ipc::CrashReporterHelper<GeckoProcessType_GPU>,
+                       public PGPUChild,
+                       public gfxVarReceiver {
   typedef mozilla::dom::MemoryReportRequestHost MemoryReportRequestHost;
 
  public:
   explicit GPUChild(GPUProcessHost* aHost);
   virtual ~GPUChild();
 
   void Init();
 
@@ -37,18 +37,16 @@ class GPUChild final : public PGPUChild,
 
   // gfxVarReceiver overrides.
   void OnVarChanged(const GfxVarUpdate& aVar) override;
 
   // PGPUChild overrides.
   mozilla::ipc::IPCResult RecvInitComplete(const GPUDeviceData& aData);
   mozilla::ipc::IPCResult RecvReportCheckerboard(const uint32_t& aSeverity,
                                                  const nsCString& aLog);
-  mozilla::ipc::IPCResult RecvInitCrashReporter(
-      Shmem&& shmem, const NativeThreadId& aThreadId);
   mozilla::ipc::IPCResult RecvCreateVRProcess();
   mozilla::ipc::IPCResult RecvShutdownVRProcess();
 
   mozilla::ipc::IPCResult RecvAccumulateChildHistograms(
       nsTArray<HistogramAccumulation>&& aAccumulations);
   mozilla::ipc::IPCResult RecvAccumulateChildKeyedHistograms(
       nsTArray<KeyedHistogramAccumulation>&& aAccumulations);
   mozilla::ipc::IPCResult RecvUpdateChildScalars(
@@ -76,17 +74,16 @@ class GPUChild final : public PGPUChild,
                                const bool& aAnonymize,
                                const bool& aMinimizeMemoryUsage,
                                const Maybe<ipc::FileDescriptor>& aDMDFile);
 
   static void Destroy(UniquePtr<GPUChild>&& aChild);
 
  private:
   GPUProcessHost* mHost;
-  UniquePtr<ipc::CrashReporterHost> mCrashReporter;
   UniquePtr<MemoryReportRequestHost> mMemoryReportRequest;
   bool mGPUReady;
 };
 
 }  // namespace gfx
 }  // namespace mozilla
 
 #endif  // _include_mozilla_gfx_ipc_GPUChild_h_
--- a/gfx/vr/ipc/VRChild.cpp
+++ b/gfx/vr/ipc/VRChild.cpp
@@ -9,17 +9,17 @@
 #include "gfxConfig.h"
 
 #include "mozilla/gfx/gfxVars.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/SystemGroup.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/VsyncDispatcher.h"
 #include "mozilla/dom/MemoryReportRequest.h"
-#include "mozilla/ipc/CrashReporterHost.h"
+#include "mozilla/ipc/CrashReporterHelper.h"
 
 namespace mozilla {
 namespace gfx {
 
 class OpenVRControllerManifestManager {
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(OpenVRControllerManifestManager)
  public:
   explicit OpenVRControllerManifestManager() = default;
@@ -86,22 +86,17 @@ mozilla::ipc::IPCResult VRChild::RecvFin
     mMemoryReportRequest->Finish(aGeneration);
     mMemoryReportRequest = nullptr;
   }
   return IPC_OK();
 }
 
 void VRChild::ActorDestroy(ActorDestroyReason aWhy) {
   if (aWhy == AbnormalShutdown) {
-    if (mCrashReporter) {
-      mCrashReporter->GenerateCrashReport(OtherPid());
-      mCrashReporter = nullptr;
-    } else {
-      CrashReporter::FinalizeOrphanedMinidump(OtherPid(), GeckoProcessType_VR);
-    }
+    GenerateCrashReport(OtherPid());
 
     Telemetry::Accumulate(
         Telemetry::SUBPROCESS_ABNORMAL_ABORT,
         nsDependentCString(XRE_ChildProcessTypeToString(GeckoProcessType_VR)),
         1);
   }
   gfxVars::RemoveReceiver(this);
   mHost->OnChannelClosed();
@@ -170,24 +165,16 @@ mozilla::ipc::IPCResult VRChild::RecvOpe
 }
 
 mozilla::ipc::IPCResult VRChild::RecvInitComplete() {
   // We synchronously requested VR parameters before this arrived.
   mVRReady = true;
   return IPC_OK();
 }
 
-mozilla::ipc::IPCResult VRChild::RecvInitCrashReporter(
-    Shmem&& aShmem, const NativeThreadId& aThreadId) {
-  mCrashReporter = MakeUnique<ipc::CrashReporterHost>(GeckoProcessType_VR,
-                                                      aShmem, aThreadId);
-
-  return IPC_OK();
-}
-
 bool VRChild::SendRequestMemoryReport(const uint32_t& aGeneration,
                                       const bool& aAnonymize,
                                       const bool& aMinimizeMemoryUsage,
                                       const Maybe<FileDescriptor>& aDMDFile) {
   mMemoryReportRequest = MakeUnique<MemoryReportRequestHost>(aGeneration);
   Unused << PVRChild::SendRequestMemoryReport(aGeneration, aAnonymize,
                                               aMinimizeMemoryUsage, aDMDFile);
   return true;
--- a/gfx/vr/ipc/VRChild.h
+++ b/gfx/vr/ipc/VRChild.h
@@ -4,32 +4,32 @@
  * 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_CHILD_H
 #define GFX_VR_CHILD_H
 
 #include "mozilla/gfx/PVRChild.h"
 #include "mozilla/gfx/gfxVarReceiver.h"
+#include "mozilla/ipc/CrashReporterHelper.h"
 #include "mozilla/VsyncDispatcher.h"
 #include "gfxVR.h"
 
 namespace mozilla {
-namespace ipc {
-class CrashReporterHost;
-}  // namespace ipc
 namespace dom {
 class MemoryReportRequestHost;
 }  // namespace dom
 namespace gfx {
 
 class VRProcessParent;
 class VRChild;
 
-class VRChild final : public PVRChild, public gfxVarReceiver {
+class VRChild final : public PVRChild,
+                      public ipc::CrashReporterHelper<GeckoProcessType_VR>,
+                      public gfxVarReceiver {
   typedef mozilla::dom::MemoryReportRequestHost MemoryReportRequestHost;
   friend class PVRChild;
 
  public:
   explicit VRChild(VRProcessParent* aHost);
   ~VRChild() = default;
 
   static void Destroy(UniquePtr<VRChild>&& aChild);
@@ -43,25 +43,22 @@ class VRChild final : public PVRChild, p
 
  protected:
   virtual void ActorDestroy(ActorDestroyReason aWhy) override;
   mozilla::ipc::IPCResult RecvOpenVRControllerActionPathToParent(
       const nsCString& aPath);
   mozilla::ipc::IPCResult RecvOpenVRControllerManifestPathToParent(
       const OpenVRControllerType& aType, const nsCString& aPath);
   mozilla::ipc::IPCResult RecvInitComplete();
-  mozilla::ipc::IPCResult RecvInitCrashReporter(
-      Shmem&& shmem, const NativeThreadId& aThreadId);
 
   mozilla::ipc::IPCResult RecvAddMemoryReport(const MemoryReport& aReport);
   mozilla::ipc::IPCResult RecvFinishMemoryReport(const uint32_t& aGeneration);
 
  private:
   VRProcessParent* mHost;
-  UniquePtr<ipc::CrashReporterHost> mCrashReporter;
   UniquePtr<MemoryReportRequestHost> mMemoryReportRequest;
   bool mVRReady;
 };
 
 }  // namespace gfx
 }  // namespace mozilla
 
 #endif  // GFX_VR_CHILD_H
--- a/ipc/glue/CrashReporterClient.h
+++ b/ipc/glue/CrashReporterClient.h
@@ -19,17 +19,17 @@ class CrashReporterMetadataShmem;
 
 class CrashReporterClient {
  public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CrashReporterClient);
 
   // |aTopLevelProtocol| must be a top-level protocol instance, as sub-actors
   // do not have AllocUnsafeShmem. It must also have a child-to-parent message:
   //
-  //   async SetCrashReporterClient(Shmem shmem);
+  //   async InitCrashReporter(Shmem shmem, NativeThreadId threadId);
   //
   // The parent-side receive function of this message should save the shmem
   // somewhere, and when the top-level actor's ActorDestroy runs (or when the
   // crash reporter needs metadata), the shmem should be parsed.
   template <typename T>
   static bool InitSingleton(T* aToplevelProtocol) {
     // The crash reporter is not enabled in recording/replaying processes.
     if (recordreplay::IsRecordingOrReplaying()) {
new file mode 100644
--- /dev/null
+++ b/ipc/glue/CrashReporterHelper.h
@@ -0,0 +1,64 @@
+/* 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 mozilla_ipc_CrashReporterHelper_h
+#define mozilla_ipc_CrashReporterHelper_h
+
+#include "CrashReporterHost.h"
+#include "mozilla/ipc/Shmem.h"
+#include "mozilla/UniquePtr.h"
+#include "nsExceptionHandler.h"
+
+namespace mozilla {
+namespace ipc {
+
+/**
+ * This class encapsulates the common elements of crash report handling for
+ * toplevel protocols representing processes. To use this class, you should:
+ *
+ * 1. Declare a method to initialize the crash reporter in your IPDL:
+ *    `async InitCrashReporter(Shmem shmem, NativeThreadId threadId)`
+ *
+ * 2. Inherit from this class, providing the appropriate `GeckoProcessType`
+ *    enum value for the template parameter PT.
+ *
+ * 3. When your protocol actor is destroyed with a reason of `AbnormalShutdown`,
+ *    you should call `GenerateCrashReport(OtherPid())`. If you need the crash
+ *    report ID it will be copied in the second optional parameter upon
+ *    successful crash report generation.
+ */
+template <GeckoProcessType PT>
+class CrashReporterHelper {
+ public:
+  CrashReporterHelper() : mCrashReporter(nullptr) {}
+  IPCResult RecvInitCrashReporter(Shmem&& aShmem,
+                                  const CrashReporter::ThreadId& aThreadId) {
+    mCrashReporter = MakeUnique<ipc::CrashReporterHost>(PT, aShmem, aThreadId);
+    return IPC_OK();
+  }
+
+ protected:
+  bool GenerateCrashReport(base::ProcessId aPid,
+                           nsString* aMinidumpId = nullptr) {
+    if (!mCrashReporter) {
+      CrashReporter::FinalizeOrphanedMinidump(aPid, PT);
+      return false;
+    }
+
+    bool generated = mCrashReporter->GenerateCrashReport(aPid);
+    if (generated && aMinidumpId) {
+      *aMinidumpId = mCrashReporter->MinidumpID();
+    }
+
+    mCrashReporter = nullptr;
+    return generated;
+  }
+
+  UniquePtr<ipc::CrashReporterHost> mCrashReporter;
+};
+
+}  // namespace ipc
+}  // namespace mozilla
+
+#endif  // mozilla_ipc_CrashReporterHelper_h
--- a/ipc/glue/CrashReporterHost.h
+++ b/ipc/glue/CrashReporterHost.h
@@ -9,16 +9,17 @@
 
 #include <functional>
 
 #include "mozilla/UniquePtr.h"
 #include "mozilla/ipc/Shmem.h"
 #include "base/process.h"
 #include "nsExceptionHandler.h"
 #include "nsThreadUtils.h"
+#include "ProtocolUtils.h"
 
 namespace mozilla {
 namespace ipc {
 
 // This is the newer replacement for CrashReporterParent. It is created in
 // response to a InitCrashReporter message on a top-level actor, and simply
 // holds the metadata shmem alive until the process ends. When the process
 // terminates abnormally, the top-level should call GenerateCrashReport to
--- a/ipc/glue/moz.build
+++ b/ipc/glue/moz.build
@@ -11,16 +11,17 @@ EXPORTS += [
 
 EXPORTS.mozilla.ipc += [
     'BackgroundChild.h',
     'BackgroundParent.h',
     'BackgroundUtils.h',
     'BrowserProcessSubThread.h',
     'ByteBuf.h',
     'CrashReporterClient.h',
+    'CrashReporterHelper.h',
     'CrashReporterHost.h',
     'CrashReporterMetadataShmem.h',
     'CrossProcessMutex.h',
     'CrossProcessSemaphore.h',
     'EnvironmentMap.h',
     'FileDescriptor.h',
     'FileDescriptorSetChild.h',
     'FileDescriptorSetParent.h',
--- a/netwerk/ipc/SocketProcessParent.cpp
+++ b/netwerk/ipc/SocketProcessParent.cpp
@@ -1,17 +1,16 @@
 /* -*- Mode: C++; tab-width: 2; 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/. */
 
 #include "SocketProcessParent.h"
 
 #include "SocketProcessHost.h"
-#include "mozilla/ipc/CrashReporterHost.h"
 #include "mozilla/net/DNSRequestParent.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/TelemetryIPC.h"
 #ifdef MOZ_WEBRTC
 #  include "mozilla/dom/ContentProcessManager.h"
 #  include "mozilla/dom/BrowserParent.h"
 #  include "mozilla/net/WebrtcProxyChannelParent.h"
 #endif
@@ -39,33 +38,19 @@ SocketProcessParent::~SocketProcessParen
 
 /* static */
 SocketProcessParent* SocketProcessParent::GetSingleton() {
   MOZ_ASSERT(NS_IsMainThread());
 
   return sSocketProcessParent;
 }
 
-mozilla::ipc::IPCResult SocketProcessParent::RecvInitCrashReporter(
-    Shmem&& aShmem, const NativeThreadId& aThreadId) {
-  mCrashReporter = MakeUnique<CrashReporterHost>(GeckoProcessType_Content,
-                                                 aShmem, aThreadId);
-
-  return IPC_OK();
-}
-
 void SocketProcessParent::ActorDestroy(ActorDestroyReason aWhy) {
   if (aWhy == AbnormalShutdown) {
-    if (mCrashReporter) {
-      mCrashReporter->GenerateCrashReport(OtherPid());
-      mCrashReporter = nullptr;
-    } else {
-      CrashReporter::FinalizeOrphanedMinidump(OtherPid(),
-                                              GeckoProcessType_Content);
-    }
+    GenerateCrashReport(OtherPid());
   }
 
   if (mHost) {
     mHost->OnChannelClosed();
   }
 }
 
 bool SocketProcessParent::SendRequestMemoryReport(
--- a/netwerk/ipc/SocketProcessParent.h
+++ b/netwerk/ipc/SocketProcessParent.h
@@ -2,16 +2,17 @@
 /* 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 mozilla_net_SocketProcessParent_h
 #define mozilla_net_SocketProcessParent_h
 
 #include "mozilla/UniquePtr.h"
+#include "mozilla/ipc/CrashReporterHelper.h"
 #include "mozilla/net/PSocketProcessParent.h"
 
 namespace mozilla {
 
 namespace dom {
 class MemoryReport;
 class MemoryReportRequestHost;
 }  // namespace dom
@@ -21,27 +22,27 @@ class CrashReporterHost;
 }  // namespace ipc
 
 namespace net {
 
 class SocketProcessHost;
 
 // IPC actor of socket process in parent process. This is allocated and managed
 // by SocketProcessHost.
-class SocketProcessParent final : public PSocketProcessParent {
+class SocketProcessParent final
+    : public PSocketProcessParent,
+      public ipc::CrashReporterHelper<GeckoProcessType_Content> {
  public:
   friend class SocketProcessHost;
 
   explicit SocketProcessParent(SocketProcessHost* aHost);
   ~SocketProcessParent();
 
   static SocketProcessParent* GetSingleton();
 
-  mozilla::ipc::IPCResult RecvInitCrashReporter(
-      Shmem&& aShmem, const NativeThreadId& aThreadId);
   mozilla::ipc::IPCResult RecvAddMemoryReport(const MemoryReport& aReport);
   mozilla::ipc::IPCResult RecvFinishMemoryReport(const uint32_t& aGeneration);
   mozilla::ipc::IPCResult RecvAccumulateChildHistograms(
       nsTArray<HistogramAccumulation>&& aAccumulations);
   mozilla::ipc::IPCResult RecvAccumulateChildKeyedHistograms(
       nsTArray<KeyedHistogramAccumulation>&& aAccumulations);
   mozilla::ipc::IPCResult RecvUpdateChildScalars(
       nsTArray<ScalarAction>&& aScalarActions);
@@ -67,17 +68,16 @@ class SocketProcessParent final : public
   void ActorDestroy(ActorDestroyReason aWhy) override;
   bool SendRequestMemoryReport(const uint32_t& aGeneration,
                                const bool& aAnonymize,
                                const bool& aMinimizeMemoryUsage,
                                const Maybe<ipc::FileDescriptor>& aDMDFile);
 
  private:
   SocketProcessHost* mHost;
-  UniquePtr<ipc::CrashReporterHost> mCrashReporter;
   UniquePtr<dom::MemoryReportRequestHost> mMemoryReportRequest;
 
   static void Destroy(UniquePtr<SocketProcessParent>&& aParent);
 };
 
 }  // namespace net
 }  // namespace mozilla
 
--- a/security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerParent.cpp
+++ b/security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerParent.cpp
@@ -58,39 +58,25 @@ bool RemoteSandboxBrokerParent::Duplicat
 }
 
 void RemoteSandboxBrokerParent::ActorDestroy(ActorDestroyReason aWhy) {
   if (AbnormalShutdown == aWhy) {
     Telemetry::Accumulate(Telemetry::SUBPROCESS_ABNORMAL_ABORT,
                           nsDependentCString(XRE_ChildProcessTypeToString(
                               GeckoProcessType_RemoteSandboxBroker)),
                           1);
-    if (mCrashReporter) {
-      mCrashReporter->GenerateCrashReport(OtherPid());
-      mCrashReporter = nullptr;
-    } else {
-      CrashReporter::FinalizeOrphanedMinidump(
-          OtherPid(), GeckoProcessType_RemoteSandboxBroker);
-    }
+    GenerateCrashReport(OtherPid());
   }
   Shutdown();
 }
 
 void RemoteSandboxBrokerParent::Shutdown() {
   if (mOpened) {
     mOpened = false;
     Close();
   }
   if (mProcess) {
     mProcess->Destroy();
     mProcess = nullptr;
   }
 }
 
-mozilla::ipc::IPCResult RemoteSandboxBrokerParent::RecvInitCrashReporter(
-    Shmem&& aShmem, const NativeThreadId& aThreadId) {
-  mCrashReporter = MakeUnique<ipc::CrashReporterHost>(
-      GeckoProcessType_RemoteSandboxBroker, aShmem, aThreadId);
-
-  return IPC_OK();
-}
-
 }  // namespace mozilla
--- a/security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerParent.h
+++ b/security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerParent.h
@@ -4,40 +4,38 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
 
 #ifndef RemoteSandboxBrokerParent_h_
 #define RemoteSandboxBrokerParent_h_
 
 #include "mozilla/PRemoteSandboxBrokerParent.h"
 #include "RemoteSandboxBrokerProcessParent.h"
-#include "mozilla/ipc/CrashReporterHost.h"
+#include "mozilla/ipc/CrashReporterHelper.h"
 
 namespace mozilla {
 
-class RemoteSandboxBrokerParent : public PRemoteSandboxBrokerParent {
+class RemoteSandboxBrokerParent
+    : public PRemoteSandboxBrokerParent,
+      public CrashReporterHelper<GeckoProcessType_RemoteSandboxBroker> {
   friend class PRemoteSandboxBrokerParent;
 
  public:
   bool DuplicateFromLauncher(HANDLE aLauncherHandle, LPHANDLE aOurHandle);
 
   void Shutdown();
 
   // Asynchronously launches the launcher process.
   // Note: we rely on the caller to keep this instance alive
   // until this promise resolves.
   RefPtr<GenericPromise> Launch(const nsTArray<uint64_t>& aHandlesToShare);
 
  private:
-  mozilla::ipc::IPCResult RecvInitCrashReporter(
-      Shmem&& aShmem, const NativeThreadId& aThreadId);
-
   void ActorDestroy(ActorDestroyReason aWhy) override;
 
   RemoteSandboxBrokerProcessParent* mProcess = nullptr;
 
   bool mOpened = false;
-  UniquePtr<ipc::CrashReporterHost> mCrashReporter;
 };
 
 }  // namespace mozilla
 
 #endif  // RemoteSandboxBrokerParent_h_