diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp
index af715e8028441784d36df542556b1b32bd3c1f35..d623b72a0e20fc3e4eebd18ef4b9ef296cba0a5c 100755
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -1569,6 +1569,11 @@ ContentParent::Init()
         rv = profiler->GetStartParams(getter_AddRefs(currentProfilerParams));
         MOZ_ASSERT(NS_SUCCEEDED(rv));
 
+        nsCOMPtr<nsISupports> gatherer;
+        rv = profiler->GetProfileGatherer(getter_AddRefs(gatherer));
+        MOZ_ASSERT(NS_SUCCEEDED(rv));
+        mGatherer = static_cast<ProfileGatherer*>(gatherer.get());
+
         StartProfiler(currentProfilerParams);
     }
 #endif
@@ -3293,6 +3298,7 @@ ContentParent::Observe(nsISupports* aSubject,
         StartProfiler(params);
     }
     else if (!strcmp(aTopic, "profiler-stopped")) {
+        mGatherer = nullptr;
         Unused << SendStopProfiler();
     }
     else if (!strcmp(aTopic, "profiler-paused")) {
@@ -3302,9 +3308,10 @@ ContentParent::Observe(nsISupports* aSubject,
         Unused << SendPauseProfiler(false);
     }
     else if (!strcmp(aTopic, "profiler-subprocess-gather")) {
-        mGatherer = static_cast<ProfileGatherer*>(aSubject);
-        mGatherer->WillGatherOOPProfile();
-        Unused << SendGatherProfile();
+        if (mGatherer) {
+            mGatherer->WillGatherOOPProfile();
+            Unused << SendGatherProfile();
+        }
     }
     else if (!strcmp(aTopic, "profiler-subprocess")) {
         nsCOMPtr<nsIProfileSaveEvent> pse = do_QueryInterface(aSubject);
@@ -5656,7 +5663,6 @@ ContentParent::RecvProfile(const nsCString& aProfile)
     }
     mProfile = aProfile;
     mGatherer->GatheredOOPProfile();
-    mGatherer = nullptr;
 #endif
     return true;
 }
@@ -5747,6 +5753,14 @@ ContentParent::StartProfiler(nsIProfilerStartParams* aParams)
     ipcParams.threadFilters() = aParams->GetThreadFilterNames();
 
     Unused << SendStartProfiler(ipcParams);
+
+    nsCOMPtr<nsIProfiler> profiler(do_GetService("@mozilla.org/tools/profiler;1"));
+    if (NS_WARN_IF(!profiler)) {
+        return;
+    }
+    nsCOMPtr<nsISupports> gatherer;
+    profiler->GetProfileGatherer(getter_AddRefs(gatherer));
+    mGatherer = static_cast<ProfileGatherer*>(gatherer.get());
 #endif
 }
 
diff --git a/dom/plugins/ipc/PluginModuleParent.cpp b/dom/plugins/ipc/PluginModuleParent.cpp
index c4374febbb6799c4b876922742051070b586be40..813f2522a9aa233b7469a4815ebfbe16e7312b17 100755
--- a/dom/plugins/ipc/PluginModuleParent.cpp
+++ b/dom/plugins/ipc/PluginModuleParent.cpp
@@ -627,6 +627,25 @@ PluginModuleChromeParent::OnProcessLaunched(const bool aSucceeded)
         }
 #endif
     }
+
+#ifdef MOZ_ENABLE_PROFILER_SPS
+    nsCOMPtr<nsIProfiler> profiler(do_GetService("@mozilla.org/tools/profiler;1"));
+    bool profilerActive = false;
+    DebugOnly<nsresult> rv = profiler->IsActive(&profilerActive);
+    MOZ_ASSERT(NS_SUCCEEDED(rv));
+    if (profilerActive) {
+        nsCOMPtr<nsIProfilerStartParams> currentProfilerParams;
+        rv = profiler->GetStartParams(getter_AddRefs(currentProfilerParams));
+        MOZ_ASSERT(NS_SUCCEEDED(rv));
+
+        nsCOMPtr<nsISupports> gatherer;
+        rv = profiler->GetProfileGatherer(getter_AddRefs(gatherer));
+        MOZ_ASSERT(NS_SUCCEEDED(rv));
+        mGatherer = static_cast<ProfileGatherer*>(gatherer.get());
+
+        StartProfiler(currentProfilerParams);
+    }
+#endif
 }
 
 bool
@@ -3162,23 +3181,9 @@ PluginProfilerObserver::Observe(nsISupports *aSubject,
 {
     if (!strcmp(aTopic, "profiler-started")) {
         nsCOMPtr<nsIProfilerStartParams> params(do_QueryInterface(aSubject));
-        uint32_t entries;
-        double interval;
-        params->GetEntries(&entries);
-        params->GetInterval(&interval);
-        const nsTArray<nsCString>& features = params->GetFeatures();
-        const nsTArray<nsCString>& threadFilterNames = params->GetThreadFilterNames();
-
-        ProfilerInitParams ipcParams;
-        ipcParams.enabled() = true;
-        ipcParams.entries() = entries;
-        ipcParams.interval() = interval;
-        ipcParams.features() = features;
-        ipcParams.threadFilters() = threadFilterNames;
-
-        Unused << mPmp->SendStartProfiler(ipcParams);
+        mPmp->StartProfiler(params);
     } else if (!strcmp(aTopic, "profiler-stopped")) {
-        Unused << mPmp->SendStopProfiler();
+        mPmp->StopProfiler();
     } else if (!strcmp(aTopic, "profiler-subprocess-gather")) {
         RefPtr<ProfileGatherer> gatherer = static_cast<ProfileGatherer*>(aSubject);
         mPmp->GatherAsyncProfile(gatherer);
@@ -3215,9 +3220,44 @@ PluginModuleChromeParent::ShutdownPluginProfiling()
 }
 
 void
-PluginModuleChromeParent::GatherAsyncProfile(ProfileGatherer* aGatherer)
+PluginModuleChromeParent::StartProfiler(nsIProfilerStartParams* aParams)
 {
-    mGatherer = aGatherer;
+    if (NS_WARN_IF(!aParams)) {
+        return;
+    }
+
+    ProfilerInitParams ipcParams;
+
+    ipcParams.enabled() = true;
+    aParams->GetEntries(&ipcParams.entries());
+    aParams->GetInterval(&ipcParams.interval());
+    ipcParams.features() = aParams->GetFeatures();
+    ipcParams.threadFilters() = aParams->GetThreadFilterNames();
+
+    Unused << SendStartProfiler(ipcParams);
+
+    nsCOMPtr<nsIProfiler> profiler(do_GetService("@mozilla.org/tools/profiler;1"));
+    if (NS_WARN_IF(!profiler)) {
+        return;
+    }
+    nsCOMPtr<nsISupports> gatherer;
+    profiler->GetProfileGatherer(getter_AddRefs(gatherer));
+    mGatherer = static_cast<ProfileGatherer*>(gatherer.get());
+}
+
+void
+PluginModuleChromeParent::StopProfiler()
+{
+    mGatherer = nullptr;
+    Unused << SendStopProfiler();
+}
+
+void
+PluginModuleChromeParent::GatherAsyncProfile()
+{
+    if (NS_WARN_IF(!mGatherer)) {
+        return;
+    }
     mGatherer->WillGatherOOPProfile();
     Unused << SendGatherProfile();
 }
@@ -3242,7 +3282,6 @@ PluginModuleChromeParent::RecvProfile(const nsCString& aProfile)
 
     mProfile = aProfile;
     mGatherer->GatheredOOPProfile();
-    mGatherer = nullptr;
 #endif
     return true;
 }
diff --git a/dom/plugins/ipc/PluginModuleParent.h b/dom/plugins/ipc/PluginModuleParent.h
index c3c0f9ed057f261729c4c8ea4d0f911ae22ddbcc..74c3a0bc491c128f4baf558f52de9dc087ae5a86 100644
--- a/dom/plugins/ipc/PluginModuleParent.h
+++ b/dom/plugins/ipc/PluginModuleParent.h
@@ -456,8 +456,10 @@ class PluginModuleChromeParent
     void OnExitedSyncSend() override;
 
 #ifdef  MOZ_ENABLE_PROFILER_SPS
-    void GatherAsyncProfile(mozilla::ProfileGatherer* aGatherer);
+    void GatherAsyncProfile();
     void GatheredAsyncProfile(nsIProfileSaveEvent* aSaveEvent);
+    void StartProfiler(nsIProfilerStartParams* aParams);
+    void StopProfiler();
 #endif
 
     virtual bool
diff --git a/tools/profiler/core/GeckoSampler.cpp b/tools/profiler/core/GeckoSampler.cpp
index 119154c5a9e30d592b1484605b6d671950675345..82e8ed9036b30e633a869e4cc9c3fa3f35e3e57c 100644
--- a/tools/profiler/core/GeckoSampler.cpp
+++ b/tools/profiler/core/GeckoSampler.cpp
@@ -410,6 +410,14 @@ JSObject* GeckoSampler::ToJSObject(JSContext *aCx, double aSinceTime)
   }
   return &val.toObject();
 }
+
+void GeckoSampler::GetGatherer(nsISupports** aRetVal)
+{
+  if (!aRetVal || NS_WARN_IF(!mGatherer)) {
+    return;
+  }
+  NS_ADDREF(*aRetVal = mGatherer);
+}
 #endif
 
 UniquePtr<char[]> GeckoSampler::ToJSON(double aSinceTime)
diff --git a/tools/profiler/core/GeckoSampler.h b/tools/profiler/core/GeckoSampler.h
index a5bc73a6b4fe556916bbc06dd1cf0e3b26803ac2..aaba3961c06fd1d04d397d33794529f02f625434 100644
--- a/tools/profiler/core/GeckoSampler.h
+++ b/tools/profiler/core/GeckoSampler.h
@@ -104,6 +104,7 @@ class GeckoSampler: public Sampler {
   void ToStreamAsJSON(std::ostream& stream, double aSinceTime = 0);
 #ifndef SPS_STANDALONE
   virtual JSObject *ToJSObject(JSContext *aCx, double aSinceTime = 0);
+  void GetGatherer(nsISupports** aRetVal);
 #endif
   mozilla::UniquePtr<char[]> ToJSON(double aSinceTime = 0);
   virtual void ToJSObjectAsync(double aSinceTime = 0, mozilla::dom::Promise* aPromise = 0);
diff --git a/tools/profiler/core/platform.cpp b/tools/profiler/core/platform.cpp
index aa8b65e9d366ee4f476b56ffeb05e76f34a8ecc8..af915a1711727275161acfbeaea8ba5bde8f6825 100644
--- a/tools/profiler/core/platform.cpp
+++ b/tools/profiler/core/platform.cpp
@@ -642,6 +642,26 @@ void mozilla_sampler_get_profiler_start_params(int* aEntrySize,
   }
 }
 
+void mozilla_sampler_get_gatherer(nsISupports** aRetVal)
+{
+  if (!aRetVal) {
+    return;
+  }
+
+  if (NS_WARN_IF(!profiler_is_active())) {
+    *aRetVal = nullptr;
+    return;
+  }
+
+  GeckoSampler *t = tlsTicker.get();
+  if (NS_WARN_IF(!t)) {
+    *aRetVal = nullptr;
+    return;
+  }
+
+  t->GetGatherer(aRetVal);
+}
+
 #endif
 
 void mozilla_sampler_save_profile_to_file(const char* aFilename)
diff --git a/tools/profiler/gecko/nsIProfiler.idl b/tools/profiler/gecko/nsIProfiler.idl
index 5a628de4b0051165b3f43e381d425dc21518f837..98260a1e6f7761ab0e31ad2faf15eb987f358187 100644
--- a/tools/profiler/gecko/nsIProfiler.idl
+++ b/tools/profiler/gecko/nsIProfiler.idl
@@ -27,7 +27,7 @@ interface nsIProfilerStartParams : nsISupports
   [noscript, notxpcom, nostdcall] StringArrayRef getThreadFilterNames();
 };
 
-[scriptable, uuid(b373b360-c997-448a-b60d-4985b70dc810)]
+[scriptable, uuid(ead3f75c-0e0e-4fbb-901c-1e5392ef5b2a)]
 interface nsIProfiler : nsISupports
 {
   boolean CanProfile();
@@ -66,6 +66,12 @@ interface nsIProfiler : nsISupports
    */
   readonly attribute nsIProfilerStartParams startParams;
 
+  /**
+   * The profileGatherer will be null if the profiler is not currently
+   * active.
+   */
+  readonly attribute nsISupports profileGatherer;
+
   void GetBufferInfo(out uint32_t aCurrentPosition, out uint32_t aTotalSize,
                      out uint32_t aGeneration);
 
diff --git a/tools/profiler/gecko/nsProfiler.cpp b/tools/profiler/gecko/nsProfiler.cpp
index b4b0068f01ee149984c3adfa9aed91b374e0778b..c38447381bc79d6077bde85100acf1c427339ee1 100644
--- a/tools/profiler/gecko/nsProfiler.cpp
+++ b/tools/profiler/gecko/nsProfiler.cpp
@@ -288,3 +288,21 @@ nsProfiler::GetBufferInfo(uint32_t *aCurrentPosition, uint32_t *aTotalSize, uint
   profiler_get_buffer_info(aCurrentPosition, aTotalSize, aGeneration);
   return NS_OK;
 }
+
+NS_IMETHODIMP
+nsProfiler::GetProfileGatherer(nsISupports** aRetVal)
+{
+  if (!aRetVal) {
+    return NS_ERROR_INVALID_POINTER;
+  }
+
+  // If we're not profiling, there will be no gatherer.
+  if (!profiler_is_active()) {
+    *aRetVal = nullptr;
+  } else {
+    nsCOMPtr<nsISupports> gatherer;
+    profiler_get_gatherer(getter_AddRefs(gatherer));
+    gatherer.forget(aRetVal);
+  }
+  return NS_OK;
+}
\ No newline at end of file
diff --git a/tools/profiler/public/GeckoProfilerFunc.h b/tools/profiler/public/GeckoProfilerFunc.h
index 9ee14f3c34f98bcaef63273a2be485529641489a..bc9562a365121ebd53bb166d2350a2539797ad12 100644
--- a/tools/profiler/public/GeckoProfilerFunc.h
+++ b/tools/profiler/public/GeckoProfilerFunc.h
@@ -14,6 +14,8 @@
 #include "mozilla/Vector.h"
 #include <stdint.h>
 
+class nsISupports;
+
 namespace mozilla {
 class TimeStamp;
 
@@ -73,6 +75,7 @@ void mozilla_sampler_get_profiler_start_params(int* aEntrySize,
                                                double* aInterval,
                                                mozilla::Vector<const char*>* aFilters,
                                                mozilla::Vector<const char*>* aFeatures);
+void mozilla_sampler_get_gatherer(nsISupports** aRetVal);
 #endif
 
 // Make this function easily callable from a debugger in a build without
diff --git a/tools/profiler/public/GeckoProfilerImpl.h b/tools/profiler/public/GeckoProfilerImpl.h
index 943752fde2693517f913958fcdc2809370bb5c7f..3792bb17fcc3dd8c99ebb8c1f4bc16ec6a530e73 100644
--- a/tools/profiler/public/GeckoProfilerImpl.h
+++ b/tools/profiler/public/GeckoProfilerImpl.h
@@ -179,6 +179,13 @@ void profiler_get_start_params(int* aEntrySize,
 {
   mozilla_sampler_get_profiler_start_params(aEntrySize, aInterval, aFilters, aFeatures);
 }
+
+static inline
+void profiler_get_gatherer(nsISupports** aRetVal)
+{
+  mozilla_sampler_get_gatherer(aRetVal);
+}
+
 #endif
 
 static inline