Back out bug 581341.
authorJosh Matthews <josh@joshmatthews.net>
Wed, 29 Jun 2011 15:13:17 -0400
changeset 72725 45352943ab6c040fa825c0c23b4cf8046190cb16
parent 72723 ebae45e5005c7f14abf1557771005c52735d41f9
child 72726 c7c6abdd64ab52d3bdea7efa59b8fd35130e8d4a
push id45
push userffxbld
push dateThu, 22 Sep 2011 17:29:26 +0000
treeherdermozilla-release@b3273da80b44 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs581341
milestone7.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
Back out bug 581341.
dom/ipc/ContentChild.cpp
dom/ipc/ContentChild.h
dom/ipc/ContentParent.cpp
dom/ipc/ContentParent.h
dom/ipc/CrashReporterChild.cpp
dom/ipc/CrashReporterChild.h
dom/ipc/CrashReporterParent.cpp
dom/ipc/CrashReporterParent.h
dom/ipc/Makefile.in
dom/ipc/PContent.ipdl
dom/ipc/PCrashReporter.ipdl
dom/ipc/TabMessageUtils.h
dom/plugins/ipc/PPluginModule.ipdl
dom/plugins/ipc/PluginMessageUtils.h
dom/plugins/ipc/PluginModuleChild.cpp
dom/plugins/ipc/PluginModuleChild.h
dom/plugins/ipc/PluginModuleParent.cpp
dom/plugins/ipc/PluginModuleParent.h
dom/plugins/ipc/PluginProcessChild.cpp
dom/plugins/ipc/PluginProcessChild.h
ipc/testshell/TestShellParent.cpp
ipc/testshell/TestShellParent.h
testing/xpcshell/xpcshell.ini
toolkit/crashreporter/Makefile.in
toolkit/crashreporter/nsExceptionHandler.cpp
toolkit/crashreporter/test/Makefile.in
toolkit/crashreporter/test/unit/crasher_subprocess_head.js
toolkit/crashreporter/test/unit/head_crashreporter.js
toolkit/crashreporter/test/unit_ipc/test_content_annotation.js
toolkit/crashreporter/test/unit_ipc/xpcshell.ini
toolkit/xre/nsEmbedFunctions.cpp
toolkit/xre/nsX11ErrorHandler.cpp
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -255,19 +255,18 @@ ContentChild::Init(MessageLoop* aIOLoop,
     XRE_InstallX11ErrorHandler();
 #endif
 
     NS_ASSERTION(!sSingleton, "only one ContentChild per child");
 
     Open(aChannel, aParentHandle, aIOLoop);
     sSingleton = this;
 
-    CrashReporterChild::CreateCrashReporter(this);
 #if defined(ANDROID) && defined(MOZ_CRASHREPORTER)
-    PCrashReporterChild* crashreporter = ManagedPCrashReporterChild()[0];
+    PCrashReporterChild* crashreporter = SendPCrashReporterConstructor();
     InfallibleTArray<Mapping> mappings;
     const struct mapping_info *info = getLibraryMapping();
     while (info && info->name) {
         mappings.AppendElement(Mapping(nsDependentCString(info->name),
                                        nsDependentCString(info->file_id),
                                        info->base,
                                        info->len,
                                        info->offset));
@@ -359,24 +358,19 @@ bool
 ContentChild::DeallocPBrowser(PBrowserChild* iframe)
 {
     TabChild* child = static_cast<TabChild*>(iframe);
     NS_RELEASE(child);
     return true;
 }
 
 PCrashReporterChild*
-ContentChild::AllocPCrashReporter(const NativeThreadId& tid,
-                                  const PRUint32& processType)
+ContentChild::AllocPCrashReporter()
 {
-#ifdef MOZ_CRASHREPORTER
     return new CrashReporterChild();
-#else
-    return nsnull;
-#endif
 }
 
 bool
 ContentChild::DeallocPCrashReporter(PCrashReporterChild* crashreporter)
 {
     delete crashreporter;
     return true;
 }
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -75,21 +75,18 @@ public:
     }
 
     /* if you remove this, please talk to cjones or dougt */
     virtual bool RecvDummy(Shmem& foo) { return true; }
 
     virtual PBrowserChild* AllocPBrowser(const PRUint32& aChromeFlags);
     virtual bool DeallocPBrowser(PBrowserChild*);
 
-    virtual PCrashReporterChild*
-    AllocPCrashReporter(const NativeThreadId& id,
-                        const PRUint32& processType);
-    virtual bool
-    DeallocPCrashReporter(PCrashReporterChild*);
+    virtual PCrashReporterChild* AllocPCrashReporter();
+    virtual bool DeallocPCrashReporter(PCrashReporterChild*);
 
     virtual PMemoryReportRequestChild*
     AllocPMemoryReportRequest();
 
     virtual bool
     DeallocPMemoryReportRequest(PMemoryReportRequestChild* actor);
 
     virtual bool
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -285,23 +285,37 @@ ContentParent::ActorDestroy(ActorDestroy
     if (obs) {
         nsRefPtr<nsHashPropertyBag> props = new nsHashPropertyBag();
         props->Init();
 
         if (AbnormalShutdown == why) {
             props->SetPropertyAsBool(NS_LITERAL_STRING("abnormal"), PR_TRUE);
 
 #ifdef MOZ_CRASHREPORTER
-            CrashReporterParent* crashReporter =
-                    static_cast<CrashReporterParent*>(ManagedPCrashReporterParent()[0]);
+            nsAutoString dumpID;
+
+            nsCOMPtr<nsILocalFile> crashDump;
+            TakeMinidump(getter_AddRefs(crashDump)) &&
+                CrashReporter::GetIDFromMinidump(crashDump, dumpID);
+
+            props->SetPropertyAsAString(NS_LITERAL_STRING("dumpID"), dumpID);
 
-            crashReporter->GenerateCrashReport(this, NULL);
+            if (!dumpID.IsEmpty()) {
+                CrashReporter::AnnotationTable notes;
+                notes.Init();
+                notes.Put(NS_LITERAL_CSTRING("ProcessType"), NS_LITERAL_CSTRING("content"));
 
-            nsAutoString dumpID(crashReporter->ChildDumpID());
-            props->SetPropertyAsAString(NS_LITERAL_STRING("dumpID"), dumpID);
+                char startTime[32];
+                sprintf(startTime, "%lld", static_cast<PRInt64>(mProcessStartTime));
+                notes.Put(NS_LITERAL_CSTRING("StartupTime"),
+                          nsDependentCString(startTime));
+
+                // TODO: Additional per-process annotations.
+                CrashReporter::AppendExtraData(dumpID, notes);
+            }
 #endif
 
             obs->NotifyObservers((nsIPropertyBag2*) props, "ipc:content-shutdown", nsnull);
         }
     }
 
     MessageLoop::current()->
         PostTask(FROM_HERE,
@@ -322,30 +336,22 @@ ContentParent::CreateTestShell()
 }
 
 bool
 ContentParent::DestroyTestShell(TestShellParent* aTestShell)
 {
     return PTestShellParent::Send__delete__(aTestShell);
 }
 
-TestShellParent*
-ContentParent::GetTestShellSingleton()
-{
-    if (ManagedPTestShellParent().IsEmpty()) {
-        return nsnull;
-    }
-    return static_cast<TestShellParent*>(ManagedPTestShellParent()[0]);
-}
-
 ContentParent::ContentParent()
     : mGeolocationWatchID(-1)
     , mRunToCompletionDepth(0)
     , mShouldCallUnblockChild(false)
     , mIsAlive(true)
+    , mProcessStartTime(time(NULL))
 {
     NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
     mSubprocess = new GeckoChildProcessHost(GeckoProcessType_Content);
     mSubprocess->AsyncLaunch();
     Open(mSubprocess->GetChannel(), mSubprocess->GetChildProcessHandle());
 
     nsCOMPtr<nsIChromeRegistry> registrySvc = nsChromeRegistry::GetService();
     nsChromeRegistryChrome* chromeRegistry =
@@ -668,24 +674,19 @@ bool
 ContentParent::DeallocPBrowser(PBrowserParent* frame)
 {
   TabParent* parent = static_cast<TabParent*>(frame);
   NS_RELEASE(parent);
   return true;
 }
 
 PCrashReporterParent*
-ContentParent::AllocPCrashReporter(const NativeThreadId& tid,
-                                   const PRUint32& processType)
+ContentParent::AllocPCrashReporter()
 {
-#ifdef MOZ_CRASHREPORTER
-  return new CrashReporterParent(tid, processType);
-#else
-  return nsnull;
-#endif
+  return new CrashReporterParent();
 }
 
 bool
 ContentParent::DeallocPCrashReporter(PCrashReporterParent* crashreporter)
 {
   delete crashreporter;
   return true;
 }
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -89,29 +89,24 @@ public:
     NS_DECL_NSITHREADOBSERVER
     NS_DECL_NSIDOMGEOPOSITIONCALLBACK
     NS_DECL_NSIDEVICEMOTIONLISTENER
 
     TabParent* CreateTab(PRUint32 aChromeFlags);
 
     TestShellParent* CreateTestShell();
     bool DestroyTestShell(TestShellParent* aTestShell);
-    TestShellParent* GetTestShellSingleton();
 
     void ReportChildAlreadyBlocked();
     bool RequestRunToCompletion();
 
     bool IsAlive();
 
     void SetChildMemoryReporters(const InfallibleTArray<MemoryReport>& report);
 
-    GeckoChildProcessHost* Process() {
-        return mSubprocess;
-    }
-
 protected:
     void OnChannelConnected(int32 pid);
     virtual void ActorDestroy(ActorDestroyReason why);
 
 private:
     static ContentParent* gSingleton;
 
     // Hide the raw constructor methods since we don't want client code
@@ -122,18 +117,17 @@ private:
     ContentParent();
     virtual ~ContentParent();
 
     void Init();
 
     virtual PBrowserParent* AllocPBrowser(const PRUint32& aChromeFlags);
     virtual bool DeallocPBrowser(PBrowserParent* frame);
 
-    virtual PCrashReporterParent* AllocPCrashReporter(const NativeThreadId& tid,
-                                                      const PRUint32& processType);
+    virtual PCrashReporterParent* AllocPCrashReporter();
     virtual bool DeallocPCrashReporter(PCrashReporterParent* crashreporter);
 
     virtual PMemoryReportRequestParent* AllocPMemoryReportRequest();
     virtual bool DeallocPMemoryReportRequest(PMemoryReportRequestParent* actor);
 
     virtual PTestShellParent* AllocPTestShell();
     virtual bool DeallocPTestShell(PTestShellParent* shell);
 
@@ -229,16 +223,15 @@ private:
     // This is a cache of all of the memory reporters
     // registered in the child process.  To update this, one
     // can broadcast the topic "child-memory-reporter-request" using
     // the nsIObserverService.
     nsCOMArray<nsIMemoryReporter> mMemoryReporters;
 
     bool mIsAlive;
     nsCOMPtr<nsIPrefServiceInternal> mPrefService;
-
-    friend class CrashReporterParent;
+    time_t mProcessStartTime;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif
deleted file mode 100644
--- a/dom/ipc/CrashReporterChild.cpp
+++ /dev/null
@@ -1,68 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- * vim: set sw=4 ts=8 et tw=80 : 
- * ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Mozilla Crash Reporter.
- *
- * The Initial Developer of the Original Code is
- *   The Mozilla Foundation
- * Portions created by the Initial Developer are Copyright (C) 2011
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Josh Matthews <josh@joshmatthews.net>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-#include "mozilla/plugins/PluginModuleChild.h"
-#include "ContentChild.h"
-#include "CrashReporterChild.h"
-#include "nsXULAppAPI.h"
-
-using mozilla::plugins::PluginModuleChild;
-
-namespace mozilla {
-namespace dom {
-
-/*static*/
-PCrashReporterChild*
-CrashReporterChild::GetCrashReporter()
-{
-  switch (XRE_GetProcessType()) {
-    case GeckoProcessType_Content: {
-      ContentChild* child = ContentChild::GetSingleton();
-      return child->ManagedPCrashReporterChild()[0];
-    }
-    case GeckoProcessType_Plugin: {
-      PluginModuleChild* child = PluginModuleChild::current();
-      return child->ManagedPCrashReporterChild()[0];
-    }
-    default:
-      return nsnull;
-  }
-}
-
-}
-}
--- a/dom/ipc/CrashReporterChild.h
+++ b/dom/ipc/CrashReporterChild.h
@@ -32,41 +32,24 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 #include "mozilla/dom/PCrashReporterChild.h"
-#include "mozilla/Util.h"
-#ifdef MOZ_CRASHREPORTER
-#include "nsExceptionHandler.h"
-#include "nsXULAppAPI.h"
-#endif
 
 namespace mozilla {
 namespace dom {
 class CrashReporterChild :
     public PCrashReporterChild
 {
  public:
     CrashReporterChild() {
-        MOZ_COUNT_CTOR(CrashReporterChild);
-    }
-    ~CrashReporterChild() {
-        MOZ_COUNT_DTOR(CrashReporterChild);
+      MOZ_COUNT_CTOR(CrashReporterChild);
     }
-
-    static PCrashReporterChild* GetCrashReporter();
-
-    template<class Toplevel>
-    static void CreateCrashReporter(Toplevel* actor) {
-#ifdef MOZ_CRASHREPORTER
-        MOZ_ASSERT(actor->ManagedPCrashReporterChild().Length() == 0);
-        actor->SendPCrashReporterConstructor(
-                CrashReporter::CurrentThreadId(),
-                XRE_GetProcessType());
-#endif
+    virtual ~CrashReporterChild() {
+      MOZ_COUNT_DTOR(CrashReporterChild);
     }
 };
 } // namespace dom
 } // namespace mozilla
--- a/dom/ipc/CrashReporterParent.cpp
+++ b/dom/ipc/CrashReporterParent.cpp
@@ -32,21 +32,22 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 #include "CrashReporterParent.h"
+#if defined(MOZ_CRASHREPORTER)
+#include "nsExceptionHandler.h"
+#endif
 
 #include "base/process_util.h"
 
-#include <time.h>
-
 using namespace base;
 
 namespace mozilla {
 namespace dom {
 
 void
 CrashReporterParent::ActorDestroy(ActorDestroyReason why)
 {
@@ -67,96 +68,20 @@ CrashReporterParent::RecvAddLibraryMappi
                                              m.start_address(),
                                              m.mapping_length(),
                                              m.file_offset());
   }
 #endif
   return true;
 }
 
-bool
-CrashReporterParent::RecvAnnotateCrashReport(const nsCString& key,
-                                             const nsCString& data)
-{
-#ifdef MOZ_CRASHREPORTER
-    mNotes.Put(key, data);
-#endif
-    return true;
-}
-
-bool
-CrashReporterParent::RecvAppendAppNotes(const nsCString& data)
-{
-    mAppNotes.Append(data);
-    return true;
-}
-
-CrashReporterParent::CrashReporterParent(const NativeThreadId& tid,
-                                         const PRUint32& processType)
-: mMainThread(tid)
-, mStartTime(time(NULL))
-, mProcessType(processType)
+CrashReporterParent::CrashReporterParent()
 {
     MOZ_COUNT_CTOR(CrashReporterParent);
-
-#ifdef MOZ_CRASHREPORTER
-    mNotes.Init(4);
-#endif
 }
 
 CrashReporterParent::~CrashReporterParent()
 {
     MOZ_COUNT_DTOR(CrashReporterParent);
 }
 
-#ifdef MOZ_CRASHREPORTER
-bool
-CrashReporterParent::GenerateHangCrashReport(const AnnotationTable* processNotes)
-{
-    if (mChildDumpID.IsEmpty())
-        return false;
-
-    GenerateChildData(processNotes);
-
-    CrashReporter::AnnotationTable notes;
-    if (!notes.Init(4))
-        return false;
-    notes.Put(nsDependentCString("HangID"), NS_ConvertUTF16toUTF8(mHangID));
-    if (!CrashReporter::AppendExtraData(mParentDumpID, notes))
-        NS_WARNING("problem appending parent data to .extra");
-    return true;
-}
-
-bool
-CrashReporterParent::GenerateChildData(const AnnotationTable* processNotes)
-{
-    nsCAutoString type;
-    switch (mProcessType) {
-        case GeckoProcessType_Content:
-            type = NS_LITERAL_CSTRING("content");
-            break;
-        case GeckoProcessType_Plugin:
-            type = NS_LITERAL_CSTRING("plugin");
-            break;
-        default:
-            NS_ERROR("unknown process type");
-            break;
-    }
-    mNotes.Put(NS_LITERAL_CSTRING("ProcessType"), type);
-
-    char startTime[32];
-    sprintf(startTime, "%lld", static_cast<PRInt64>(mStartTime));
-    mNotes.Put(NS_LITERAL_CSTRING("StartupTime"), nsDependentCString(startTime));
-
-    if (!mAppNotes.IsEmpty())
-        mNotes.Put(NS_LITERAL_CSTRING("Notes"), mAppNotes);
-
-    bool ret = CrashReporter::AppendExtraData(mChildDumpID, mNotes);
-    if (ret && processNotes)
-        ret = CrashReporter::AppendExtraData(mChildDumpID, *processNotes);
-    if (!ret)
-        NS_WARNING("problem appending child data to .extra");
-    return ret;
-}
-#endif
-
 } // namespace dom
 } // namespace mozilla
--- a/dom/ipc/CrashReporterParent.h
+++ b/dom/ipc/CrashReporterParent.h
@@ -1,9 +1,9 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * vim: set sw=4 ts=8 et tw=80 : 
  * ***** BEGIN LICENSE BLOCK *****
  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  *
  * The contents of this file are subject to the Mozilla Public License Version
  * 1.1 (the "License"); you may not use this file except in compliance with
  * the License. You may obtain a copy of the License at
  * http://www.mozilla.org/MPL/
@@ -32,139 +32,26 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 #include "mozilla/dom/PCrashReporterParent.h"
-#include "mozilla/dom/TabMessageUtils.h"
-#include "nsXULAppAPI.h"
-#include "nsILocalFile.h"
-#ifdef MOZ_CRASHREPORTER
-#include "nsExceptionHandler.h"
-#endif
 
 namespace mozilla {
 namespace dom {
-class ProcessReporter;
-
 class CrashReporterParent :
     public PCrashReporterParent
 {
-#ifdef MOZ_CRASHREPORTER
-  typedef CrashReporter::AnnotationTable AnnotationTable;
-#endif
 public:
-  CrashReporterParent(const NativeThreadId& tid, const PRUint32& processType);
-  virtual ~CrashReporterParent();
-
-#ifdef MOZ_CRASHREPORTER
-  /* Attempt to generate a parent/child pair of minidumps from the given
-     toplevel actor in the event of a hang. Returns true if successful,
-     false otherwise.
-  */
-  template<class Toplevel>
-  bool
-  GeneratePairedMinidump(Toplevel* t);
-
-  /* Attempt to create a bare-bones crash report for a hang, along with extra
-     process-specific annotations present in the given AnnotationTable. Returns
-     true if successful, false otherwise.
-  */
-  bool
-  GenerateHangCrashReport(const AnnotationTable* processNotes);
-
-  /* Attempt to create a bare-bones crash report, along with extra process-
-     specific annotations present in the given AnnotationTable. Returns true if
-     successful, false otherwise.
-  */
-  template<class Toplevel>
-  bool
-  GenerateCrashReport(Toplevel* t, const AnnotationTable* processNotes);
-#endif
-
-  /* Returns the shared hang ID of a parent/child paired minidump.
-     GeneratePairedMinidump must be called first.
-  */
-  const nsString& HangID() {
-    return mHangID;
-  }
-  /* Returns the ID of the parent minidump.
-     GeneratePairedMinidump must be called first.
-  */
-  const nsString& ParentDumpID() {
-    return mParentDumpID;
-  }
-  /* Returns the ID of the child minidump.
-     GeneratePairedMinidump or GenerateCrashReport must be called first.
-  */
-  const nsString& ChildDumpID() {
-    return mChildDumpID;
-  }
+    CrashReporterParent();
+    virtual ~CrashReporterParent();
 
  protected:
   virtual void ActorDestroy(ActorDestroyReason why);
 
   virtual bool
     RecvAddLibraryMappings(const InfallibleTArray<Mapping>& m);
-  virtual bool
-    RecvAnnotateCrashReport(const nsCString& key, const nsCString& data);
-  virtual bool
-    RecvAppendAppNotes(const nsCString& data);
-
-#ifdef MOZ_CRASHREPORTER
-  bool
-  GenerateChildData(const AnnotationTable* processNotes);
-
-  CrashReporter::AnnotationTable mNotes;
-#endif
-  nsCString mAppNotes;
-  nsString mHangID;
-  nsString mChildDumpID;
-  nsString mParentDumpID;
-  NativeThreadId mMainThread;
-  time_t mStartTime;
-  PRUint32 mProcessType;
 };
-
-#ifdef MOZ_CRASHREPORTER
-template<class Toplevel>
-inline bool
-CrashReporterParent::GeneratePairedMinidump(Toplevel* t)
-{
-  CrashReporter::ProcessHandle child;
-#ifdef XP_MACOSX
-  child = t->Process()->GetChildTask();
-#else
-  child = t->OtherProcess();
-#endif
-  nsCOMPtr<nsILocalFile> childDump;
-  nsCOMPtr<nsILocalFile> parentDump;
-  if (CrashReporter::CreatePairedMinidumps(child,
-                                           mMainThread,
-                                           &mHangID,
-                                           getter_AddRefs(childDump),
-                                           getter_AddRefs(parentDump)) &&
-      CrashReporter::GetIDFromMinidump(childDump, mChildDumpID) &&
-      CrashReporter::GetIDFromMinidump(parentDump, mParentDumpID)) {
-    return true;
-  }
-  return false;
-}
-
-template<class Toplevel>
-inline bool
-CrashReporterParent::GenerateCrashReport(Toplevel* t,
-                                         const AnnotationTable* processNotes)
-{
-  nsCOMPtr<nsILocalFile> crashDump;
-  if (t->TakeMinidump(getter_AddRefs(crashDump)) &&
-      CrashReporter::GetIDFromMinidump(crashDump, mChildDumpID)) {
-    return GenerateChildData(processNotes);
-  }
-  return false;
-}
-#endif
-
 } // namespace dom
 } // namespace mozilla
--- a/dom/ipc/Makefile.in
+++ b/dom/ipc/Makefile.in
@@ -58,41 +58,40 @@ EXPORTS_NAMESPACES = mozilla/dom
 EXPORTS_mozilla/dom = \
   ContentChild.h \
   ContentParent.h \
   ContentProcess.h \
   CrashReporterChild.h \
   CrashReporterParent.h \
   TabParent.h \
   TabChild.h \
-  TabMessageUtils.h \
   $(NULL)
 
 CPPSRCS = \
   ContentProcess.cpp \
   ContentParent.cpp \
   ContentChild.cpp \
   CrashReporterParent.cpp \
-  CrashReporterChild.cpp \
   TabParent.cpp \
   TabChild.cpp \
   TabMessageUtils.cpp \
   $(NULL)
 
 ifdef MOZ_SYDNEYAUDIO
 EXPORTS_mozilla/dom += \
   AudioChild.h \
   AudioParent.h \
   $(NULL)
 CPPSRCS += \
   AudioChild.cpp \
   AudioParent.cpp \
   $(NULL)
 endif
 
+
 include $(topsrcdir)/config/config.mk
 include $(topsrcdir)/ipc/chromium/chromium-config.mk
 include $(topsrcdir)/config/rules.mk
 
 LOCAL_INCLUDES += \
 	-I$(srcdir)/../../content/base/src \
 	-I$(srcdir)/../../content/events/src \
 	-I$(srcdir)/../../toolkit/components/places \
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -42,31 +42,29 @@ include protocol PCrashReporter;
 include protocol PTestShell;
 include protocol PNecko;
 include protocol PExternalHelperApp;
 include protocol PStorage;
 include protocol PMemoryReportRequest;
 
 include "mozilla/chrome/RegistryMessageUtils.h";
 include "mozilla/net/NeckoMessageUtils.h";
-include "mozilla/dom/TabMessageUtils.h";
 
 include "nsGeoPositionIPCSerialiser.h";
 include "PPrefTuple.h";
 
 using GeoPosition;
 using PrefTuple;
 
 using ChromePackage;
 using ResourceMapping;
 using OverrideMapping;
 using IPC::URI;
 using IPC::Permission;
 using mozilla::null_t;
-using mozilla::dom::NativeThreadId;
 using gfxIntSize;
 
 namespace mozilla {
 namespace dom {
 
 // Data required to clone an existing DOMStorageImpl in the parent
 struct StorageClone
 {
@@ -128,17 +126,17 @@ child:
     DeviceMotionChanged(long type, double x, double y, double z);
 
     ScreenSizeChanged(gfxIntSize size);
 
     FlushMemory(nsString reason);
 
 parent:
     PNecko();
-    PCrashReporter(NativeThreadId tid, PRUint32 processType);
+    PCrashReporter();
     
     PStorage(StorageConstructData data);
 
     PAudio(PRInt32 aNumChannels, PRInt32 aRate, PRInt32 aFormat);
 
     // Services remoting
 
     async StartVisitedQuery(URI uri);
--- a/dom/ipc/PCrashReporter.ipdl
+++ b/dom/ipc/PCrashReporter.ipdl
@@ -33,32 +33,29 @@
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 include protocol PContent;
-include protocol PPluginModule;
 
 namespace mozilla {
 namespace dom {
 
 struct Mapping {
   nsCString library_name;
   nsCString file_id;
   uintptr_t start_address;
   size_t mapping_length;
   size_t file_offset;
 };
 
 protocol PCrashReporter {
-  manager PContent or PPluginModule;
+  manager PContent;
 parent:
   AddLibraryMappings(Mapping[] m);
-  AnnotateCrashReport(nsCString key, nsCString data);
-  AppendAppNotes(nsCString data);
   __delete__();
 };
 
 }
-}
+}
\ No newline at end of file
--- a/dom/ipc/TabMessageUtils.h
+++ b/dom/ipc/TabMessageUtils.h
@@ -38,37 +38,26 @@
 
 #ifndef TABMESSAGE_UTILS_H
 #define TABMESSAGE_UTILS_H
 
 #include "IPC/IPCMessageUtils.h"
 #include "nsIPrivateDOMEvent.h"
 #include "nsCOMPtr.h"
 
-#ifdef MOZ_CRASHREPORTER
-#include "nsExceptionHandler.h"
-#endif
-
 namespace mozilla {
 namespace dom {
 struct RemoteDOMEvent
 {
   nsCOMPtr<nsIPrivateDOMEvent> mEvent;
 };
 
 bool ReadRemoteEvent(const IPC::Message* aMsg, void** aIter,
                      mozilla::dom::RemoteDOMEvent* aResult);
 
-#ifdef MOZ_CRASHREPORTER
-typedef CrashReporter::ThreadId NativeThreadId;
-#else
-// unused in this case
-typedef int32 NativeThreadId;
-#endif
-
 }
 }
 
 namespace IPC {
 
 template<>
 struct ParamTraits<mozilla::dom::RemoteDOMEvent>
 {
@@ -84,12 +73,13 @@ struct ParamTraits<mozilla::dom::RemoteD
     return mozilla::dom::ReadRemoteEvent(aMsg, aIter, aResult);
   }
 
   static void Log(const paramType& aParam, std::wstring* aLog)
   {
   }
 };
 
+
 }
 
 
 #endif
--- a/dom/plugins/ipc/PPluginModule.ipdl
+++ b/dom/plugins/ipc/PPluginModule.ipdl
@@ -34,37 +34,34 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 include protocol PPluginIdentifier;
 include protocol PPluginInstance;
-include protocol PCrashReporter;
 
 include "npapi.h";
 include "mozilla/plugins/PluginMessageUtils.h";
-include "mozilla/dom/TabMessageUtils.h";
 
 using NPError;
 using NPNVariable;
 using base::FileDescriptor;
-using mozilla::dom::NativeThreadId;
+using mozilla::plugins::NativeThreadId;
 using mac_plugin_interposing::NSCursorInfo;
 using nsID;
 
 namespace mozilla {
 namespace plugins {
 
 rpc protocol PPluginModule
 {
   manages PPluginInstance;
   manages PPluginIdentifier;
-  manages PCrashReporter;
 
 both:
   /**
    * Sending a void string to this constructor creates an int identifier whereas
    * sending a non-void string will create a string identifier. This constructor
    * may be called by either child or parent. If a race occurs by calling the
    * constructor with the same string or int argument then we create two actors
    * and detect the second instance in the child. We prevent the parent's actor
@@ -83,17 +80,17 @@ both:
 
 child:
   // Forces the child process to update its plugin function table.
   rpc NP_GetEntryPoints()
     returns (NPError rv);
 
   // Return the plugin's thread ID, if it can be found.
   rpc NP_Initialize()
-    returns (NPError rv);
+    returns (NativeThreadId tid, NPError rv);
 
   rpc PPluginInstance(nsCString aMimeType,
                       uint16_t aMode,
                       nsCString[] aNames,
                       nsCString[] aValues)
     returns (NPError rv);
 
   rpc NP_Shutdown()
@@ -136,25 +133,25 @@ parent:
              bool aBoolVal);
 
   // Wake up and process a few native events.  Periodically called by
   // Gtk-specific code upon detecting that the plugin process has
   // entered a nested event loop.  If the browser doesn't process
   // native events, then "livelock" and some other glitches can occur.
   rpc ProcessSomeEvents();
 
+  sync AppendNotesToCrashReport(nsCString aNotes);
+
   // OS X Specific calls to manage the plugin's window
   // when interposing system calls.
   async PluginShowWindow(uint32_t aWindowId, bool aModal,
                          int32_t aX, int32_t aY,
                          size_t aWidth, size_t aHeight);
   async PluginHideWindow(uint32_t aWindowId);
 
-  async PCrashReporter(NativeThreadId tid, PRUint32 processType);
-
   // OS X Specific calls to allow the plugin to manage the cursor.
   async SetCursor(NSCursorInfo cursorInfo);
   async ShowCursor(bool show);
   async PushCursor(NSCursorInfo cursorInfo);
   async PopCursor();
   sync GetNativeCursorsSupported() returns (bool supported);
 };
 
--- a/dom/plugins/ipc/PluginMessageUtils.h
+++ b/dom/plugins/ipc/PluginMessageUtils.h
@@ -137,16 +137,23 @@ typedef intptr_t NativeWindowHandle; // 
 #endif
 
 #ifdef XP_WIN
 typedef base::SharedMemoryHandle WindowsSharedMemoryHandle;
 #else
 typedef mozilla::null_t WindowsSharedMemoryHandle;
 #endif
 
+#ifdef MOZ_CRASHREPORTER
+typedef CrashReporter::ThreadId NativeThreadId;
+#else
+// unused in this case
+typedef int32 NativeThreadId;
+#endif
+
 // XXX maybe not the best place for these. better one?
 
 #define VARSTR(v_)  case v_: return #v_
 inline const char* const
 NPPVariableToString(NPPVariable aVar)
 {
     switch (aVar) {
         VARSTR(NPPVpluginNameString);
--- a/dom/plugins/ipc/PluginModuleChild.cpp
+++ b/dom/plugins/ipc/PluginModuleChild.cpp
@@ -60,34 +60,31 @@
 #ifdef MOZ_X11
 # include "mozilla/X11Util.h"
 #endif
 #include "mozilla/plugins/PluginInstanceChild.h"
 #include "mozilla/plugins/StreamNotifyChild.h"
 #include "mozilla/plugins/BrowserStreamChild.h"
 #include "mozilla/plugins/PluginStreamChild.h"
 #include "PluginIdentifierChild.h"
-#include "mozilla/dom/CrashReporterChild.h"
 
 #include "nsNPAPIPlugin.h"
 
 #ifdef XP_WIN
 #include "COMMessageFilter.h"
 #include "nsWindowsDllInterceptor.h"
 #include "mozilla/widget/AudioSession.h"
 #endif
 
 #ifdef MOZ_WIDGET_COCOA
 #include "PluginInterposeOSX.h"
 #include "PluginUtilsOSX.h"
 #endif
 
 using namespace mozilla::plugins;
-using mozilla::dom::CrashReporterChild;
-using mozilla::dom::PCrashReporterChild;
 
 #if defined(XP_WIN)
 const PRUnichar * kFlashFullscreenClass = L"ShockwaveFlashFullScreen";
 const PRUnichar * kMozillaWindowClass = L"MozillaWindowClass";
 #endif
 
 namespace {
 PluginModuleChild* gInstance = nsnull;
@@ -261,17 +258,16 @@ PluginModuleChild::Init(const std::strin
 #ifdef XP_MACOSX
     nsPluginInfo info = nsPluginInfo();
     rv = pluginFile.GetPluginInfo(info, &mLibrary);
     if (rv == NS_OK) {
         mozilla::plugins::PluginUtilsOSX::SetProcessName(info.fName);
     }
 #endif
 
-    CrashReporterChild::CreateCrashReporter(this);
     return true;
 }
 
 #if defined(MOZ_WIDGET_GTK2)
 typedef void (*GObjectDisposeFn)(GObject*);
 typedef gboolean (*GtkWidgetScrollEventFn)(GtkWidget*, GdkEventScroll*);
 typedef void (*GtkPlugEmbeddedFn)(GtkPlug*);
 
@@ -574,16 +570,17 @@ PluginModuleChild::InitGraphics()
     }
 #else
     // may not be necessary on all platforms
 #endif
 #ifdef MOZ_X11
     // Do this after initializing GDK, or GDK will install its own handler.
     XRE_InstallX11ErrorHandler();
 #endif
+
     return true;
 }
 
 void
 PluginModuleChild::DeinitGraphics()
 {
 #ifdef MOZ_WIDGET_QT
     nsQAppInstance::Release();
@@ -687,30 +684,16 @@ PluginModuleChild::RecvSetAudioSessionDa
 
 void
 PluginModuleChild::QuickExit()
 {
     NS_WARNING("plugin process _exit()ing");
     _exit(0);
 }
 
-PCrashReporterChild*
-PluginModuleChild::AllocPCrashReporter(const mozilla::dom::NativeThreadId& id,
-                                       const PRUint32& processType)
-{
-    return new CrashReporterChild;
-}
-
-bool
-PluginModuleChild::DeallocPCrashReporter(PCrashReporterChild* actor)
-{
-    delete actor;
-    return true;
-}
-
 void
 PluginModuleChild::ActorDestroy(ActorDestroyReason why)
 {
     if (AbnormalShutdown == why) {
         NS_WARNING("shutting down early because of crash!");
         QuickExit();
     }
 
@@ -1785,21 +1768,27 @@ PluginModuleChild::AnswerNP_GetEntryPoin
     *_retval = mGetEntryPointsFunc(&mFunctions);
     return true;
 #else
 #  error Please implement me for your platform
 #endif
 }
 
 bool
-PluginModuleChild::AnswerNP_Initialize(NPError* _retval)
+PluginModuleChild::AnswerNP_Initialize(NativeThreadId* tid, NPError* _retval)
 {
     PLUGIN_LOG_DEBUG_METHOD;
     AssertPluginThread();
 
+#ifdef MOZ_CRASHREPORTER
+    *tid = CrashReporter::CurrentThreadId();
+#else
+    *tid = 0;
+#endif
+
 #ifdef OS_WIN
     SetEventHooks();
 #endif
 
 #ifdef MOZ_X11
     // Send the parent a dup of our X socket, to act as a proxy
     // reference for our X resources
     int xSocketFd = ConnectionNumber(DefaultXDisplay());
--- a/dom/plugins/ipc/PluginModuleChild.h
+++ b/dom/plugins/ipc/PluginModuleChild.h
@@ -86,44 +86,39 @@
 #endif
 
 typedef NS_NPAPIPLUGIN_CALLBACK(NPError, NP_GETENTRYPOINTS) (NPPluginFuncs* pCallbacks);
 typedef NS_NPAPIPLUGIN_CALLBACK(NPError, NP_PLUGININIT) (const NPNetscapeFuncs* pCallbacks);
 typedef NS_NPAPIPLUGIN_CALLBACK(NPError, NP_PLUGINUNIXINIT) (const NPNetscapeFuncs* pCallbacks, NPPluginFuncs* fCallbacks);
 typedef NS_NPAPIPLUGIN_CALLBACK(NPError, NP_PLUGINSHUTDOWN) (void);
 
 namespace mozilla {
-namespace dom {
-class PCrashReporterChild;
-}
-
 namespace plugins {
 
 #ifdef MOZ_WIDGET_QT
 class NestedLoopTimer;
 static const int kNestedLoopDetectorIntervalMs = 90;
 #endif
 
 class PluginScriptableObjectChild;
 class PluginInstanceChild;
 
 class PluginModuleChild : public PPluginModuleChild
 {
-    typedef mozilla::dom::PCrashReporterChild PCrashReporterChild;
 protected:
     NS_OVERRIDE
     virtual mozilla::ipc::RPCChannel::RacyRPCPolicy
     MediateRPCRace(const Message& parent, const Message& child)
     {
         return MediateRace(parent, child);
     }
 
     // Implement the PPluginModuleChild interface
     virtual bool AnswerNP_GetEntryPoints(NPError* rv);
-    virtual bool AnswerNP_Initialize(NPError* rv);
+    virtual bool AnswerNP_Initialize(NativeThreadId* tid, NPError* rv);
 
     virtual PPluginIdentifierChild*
     AllocPPluginIdentifier(const nsCString& aString,
                            const int32_t& aInt,
                            const bool& aTemporary);
 
     virtual bool
     RecvPPluginIdentifierConstructor(PPluginIdentifierChild* actor,
@@ -168,22 +163,16 @@ protected:
     virtual bool
     AnswerNPP_GetSitesWithData(InfallibleTArray<nsCString>* aResult);
 
     virtual bool
     RecvSetAudioSessionData(const nsID& aId,
                             const nsString& aDisplayName,
                             const nsString& aIconPath);
 
-    virtual PCrashReporterChild*
-    AllocPCrashReporter(const mozilla::dom::NativeThreadId& id,
-                        const PRUint32& processType);
-    virtual bool
-    DeallocPCrashReporter(PCrashReporterChild* actor);
-
     virtual void
     ActorDestroy(ActorDestroyReason why);
 
     NS_NORETURN void QuickExit();
 
     NS_OVERRIDE virtual bool
     RecvProcessNativeEventsInRPCCall();
 
--- a/dom/plugins/ipc/PluginModuleParent.cpp
+++ b/dom/plugins/ipc/PluginModuleParent.cpp
@@ -51,37 +51,34 @@
 
 #include "base/process_util.h"
 
 #include "mozilla/Preferences.h"
 #include "mozilla/unused.h"
 #include "mozilla/ipc/SyncChannel.h"
 #include "mozilla/plugins/PluginModuleParent.h"
 #include "mozilla/plugins/BrowserStreamParent.h"
-#include "mozilla/dom/PCrashReporterParent.h"
 #include "PluginIdentifierParent.h"
 
 #include "nsAutoPtr.h"
 #include "nsCRT.h"
 #ifdef MOZ_CRASHREPORTER
-#include "mozilla/dom/CrashReporterParent.h"
+#include "nsExceptionHandler.h"
 #endif
 #include "nsNPAPIPlugin.h"
 #include "nsILocalFile.h"
 
 #ifdef XP_WIN
 #include "mozilla/widget/AudioSession.h"
 #endif
 
 using base::KillProcess;
 
 using mozilla::PluginLibrary;
 using mozilla::ipc::SyncChannel;
-using mozilla::dom::PCrashReporterParent;
-using mozilla::dom::CrashReporterParent;
 
 using namespace mozilla;
 using namespace mozilla::plugins;
 using namespace mozilla::plugins::parent;
 
 static const char kTimeoutPref[] = "dom.ipc.plugins.timeoutSecs";
 static const char kLaunchTimeoutPref[] = "dom.ipc.plugins.processLaunchTimeoutSecs";
 
@@ -114,21 +111,23 @@ PluginModuleParent::LoadModule(const cha
 
     TimeoutChanged(kTimeoutPref, parent);
     return parent.forget();
 }
 
 
 PluginModuleParent::PluginModuleParent(const char* aFilePath)
     : mSubprocess(new PluginProcessParent(aFilePath))
+    , mPluginThread(0)
     , mShutdown(false)
     , mClearSiteDataSupported(false)
     , mGetSitesWithDataSupported(false)
     , mNPNIface(NULL)
     , mPlugin(NULL)
+    , mProcessStartTime(time(NULL))
     , mTaskFactory(this)
 {
     NS_ASSERTION(mSubprocess, "Out of memory!");
 
     if (!mIdentifiers.Init()) {
         NS_ERROR("Out of memory");
     }
 
@@ -157,40 +156,77 @@ PluginModuleParent::~PluginModuleParent(
         mSubprocess = nsnull;
     }
 
     Preferences::UnregisterCallback(TimeoutChanged, kTimeoutPref, this);
 }
 
 #ifdef MOZ_CRASHREPORTER
 void
-PluginModuleParent::WriteExtraDataForMinidump(CrashReporter::AnnotationTable& notes)
+PluginModuleParent::WritePluginExtraDataForMinidump(const nsAString& id)
 {
     typedef nsDependentCString CS;
 
+    CrashReporter::AnnotationTable notes;
+    if (!notes.Init(32))
+        return;
+
+    notes.Put(CS("ProcessType"), CS("plugin"));
+
+    char startTime[32];
+    sprintf(startTime, "%lld", static_cast<PRInt64>(mProcessStartTime));
+    notes.Put(CS("StartupTime"), CS(startTime));
+
     // Get the plugin filename, try to get just the file leafname
     const std::string& pluginFile = mSubprocess->GetPluginFilePath();
     size_t filePos = pluginFile.rfind(FILE_PATH_SEPARATOR);
     if (filePos == std::string::npos)
         filePos = 0;
     else
         filePos++;
     notes.Put(CS("PluginFilename"), CS(pluginFile.substr(filePos).c_str()));
 
     //TODO: add plugin name and version: bug 539841
     // (as PluginName, PluginVersion)
     notes.Put(CS("PluginName"), CS(""));
     notes.Put(CS("PluginVersion"), CS(""));
 
-    const nsString& hangID = CrashReporter()->HangID();
-    if (!hangID.IsEmpty())
-        notes.Put(CS("HangID"), NS_ConvertUTF16toUTF8(hangID));
+    if (!mCrashNotes.IsEmpty())
+        notes.Put(CS("Notes"), CS(mCrashNotes.get()));
+
+    if (!mHangID.IsEmpty())
+        notes.Put(CS("HangID"), NS_ConvertUTF16toUTF8(mHangID));
+
+    if (!CrashReporter::AppendExtraData(id, notes))
+        NS_WARNING("problem appending plugin data to .extra");
+}
+
+void
+PluginModuleParent::WriteExtraDataForHang()
+{
+    // this writes HangID
+    WritePluginExtraDataForMinidump(mPluginDumpID);
+
+    CrashReporter::AnnotationTable notes;
+    if (!notes.Init(4))
+        return;
+
+    notes.Put(nsDependentCString("HangID"), NS_ConvertUTF16toUTF8(mHangID));
+    if (!CrashReporter::AppendExtraData(mBrowserDumpID, notes))
+        NS_WARNING("problem appending browser data to .extra");
 }
 #endif  // MOZ_CRASHREPORTER
 
+bool
+PluginModuleParent::RecvAppendNotesToCrashReport(const nsCString& aNotes)
+{
+    mCrashNotes.Append(aNotes);
+    return true;
+}
+
 int
 PluginModuleParent::TimeoutChanged(const char* aPref, void* aModule)
 {
     NS_ASSERTION(NS_IsMainThread(), "Wrong thead!");
     NS_ABORT_IF_FALSE(!strcmp(aPref, kTimeoutPref),
                       "unexpected pref callback");
 
     PRInt32 timeoutSecs = Preferences::GetInt(kTimeoutPref, 0);
@@ -207,26 +243,39 @@ PluginModuleParent::CleanupFromTimeout()
     if (!mShutdown)
         Close();
 }
 
 bool
 PluginModuleParent::ShouldContinueFromReplyTimeout()
 {
 #ifdef MOZ_CRASHREPORTER
-    CrashReporterParent* crashReporter = CrashReporter();
-    if (crashReporter->GeneratePairedMinidump(this)) {
-        mBrowserDumpID = crashReporter->ParentDumpID();
-        mPluginDumpID = crashReporter->ChildDumpID();
+    nsCOMPtr<nsILocalFile> pluginDump;
+    nsCOMPtr<nsILocalFile> browserDump;
+    CrashReporter::ProcessHandle child;
+#ifdef XP_MACOSX
+    child = mSubprocess->GetChildTask();
+#else
+    child = OtherProcess();
+#endif
+    if (CrashReporter::CreatePairedMinidumps(child,
+                                             mPluginThread,
+                                             &mHangID,
+                                             getter_AddRefs(pluginDump),
+                                             getter_AddRefs(browserDump)) &&
+        CrashReporter::GetIDFromMinidump(pluginDump, mPluginDumpID) &&
+        CrashReporter::GetIDFromMinidump(browserDump, mBrowserDumpID)) {
+
         PLUGIN_LOG_DEBUG(
-                ("generated paired browser/plugin minidumps: %s/%s (ID=%s)",
-                 NS_ConvertUTF16toUTF8(mBrowserDumpID).get(),
-                 NS_ConvertUTF16toUTF8(mPluginDumpID).get(),
-                 NS_ConvertUTF16toUTF8(crashReporter->HangID()).get()));
-    } else {
+            ("generated paired browser/plugin minidumps: %s/%s (ID=%s)",
+             NS_ConvertUTF16toUTF8(mBrowserDumpID).get(),
+             NS_ConvertUTF16toUTF8(mPluginDumpID).get(),
+             NS_ConvertUTF16toUTF8(mHangID).get()));
+    }
+    else {
         NS_WARNING("failed to capture paired minidumps from hang");
     }
 #endif
 
     // this must run before the error notification from the channel,
     // or not at all
     MessageLoop::current()->PostTask(
         FROM_HERE,
@@ -234,43 +283,31 @@ PluginModuleParent::ShouldContinueFromRe
             &PluginModuleParent::CleanupFromTimeout));
 
     if (!KillProcess(OtherProcess(), 1, false))
         NS_WARNING("failed to kill subprocess!");
 
     return false;
 }
 
-#ifdef MOZ_CRASHREPORTER
-CrashReporterParent*
-PluginModuleParent::CrashReporter()
-{
-    return static_cast<CrashReporterParent*>(ManagedPCrashReporterParent()[0]);
-}
-#endif
-
 void
 PluginModuleParent::ActorDestroy(ActorDestroyReason why)
 {
     switch (why) {
     case AbnormalShutdown: {
 #ifdef MOZ_CRASHREPORTER
-        CrashReporterParent* crashReporter = CrashReporter();
-
-        CrashReporter::AnnotationTable notes;
-        notes.Init(4);
-        WriteExtraDataForMinidump(notes);
-        
-        if (crashReporter->GenerateCrashReport(this, &notes)) {
-            mPluginDumpID = crashReporter->ChildDumpID();
+        nsCOMPtr<nsILocalFile> pluginDump;
+        if (TakeMinidump(getter_AddRefs(pluginDump)) &&
+            CrashReporter::GetIDFromMinidump(pluginDump, mPluginDumpID)) {
             PLUGIN_LOG_DEBUG(("got child minidump: %s",
                               NS_ConvertUTF16toUTF8(mPluginDumpID).get()));
+            WritePluginExtraDataForMinidump(mPluginDumpID);
         }
         else if (!mPluginDumpID.IsEmpty() && !mBrowserDumpID.IsEmpty()) {
-            crashReporter->GenerateHangCrashReport(&notes);
+            WriteExtraDataForHang();
         }
         else {
             NS_WARNING("[PluginModuleParent::ActorDestroy] abnormal shutdown without minidump!");
         }
 #endif
 
         mShutdown = true;
         // Defer the PluginCrashed method so that we don't re-enter
@@ -721,17 +758,17 @@ PluginModuleParent::NP_Initialize(NPNets
 
     mNPNIface = bFuncs;
 
     if (mShutdown) {
         *error = NPERR_GENERIC_ERROR;
         return NS_ERROR_FAILURE;
     }
 
-    if (!CallNP_Initialize(error)) {
+    if (!CallNP_Initialize(&mPluginThread, error)) {
         return NS_ERROR_FAILURE;
     }
     else if (*error != NPERR_NO_ERROR) {
         return NS_OK;
     }
 
     SetPluginFuncs(pFuncs);
 
@@ -745,17 +782,17 @@ PluginModuleParent::NP_Initialize(NPNets
 
     mNPNIface = bFuncs;
 
     if (mShutdown) {
         *error = NPERR_GENERIC_ERROR;
         return NS_ERROR_FAILURE;
     }
 
-    if (!CallNP_Initialize(error))
+    if (!CallNP_Initialize(&mPluginThread, error))
         return NS_ERROR_FAILURE;
 
 #if defined XP_WIN && MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
     // Send the info needed to join the chrome process's audio session to the
     // plugin process
     nsID id;
     nsString sessionName;
     nsString iconPath;
@@ -1032,34 +1069,16 @@ PluginModuleParent::RecvPluginHideWindow
     return true;
 #else
     NS_NOTREACHED(
         "PluginInstanceParent::RecvPluginHideWindow not implemented!");
     return false;
 #endif
 }
 
-PCrashReporterParent*
-PluginModuleParent::AllocPCrashReporter(const NativeThreadId& tid,
-                                        const PRUint32& processType)
-{
-#ifdef MOZ_CRASHREPORTER
-    return new CrashReporterParent(tid, processType);
-#else
-    return nsnull;
-#endif
-}
-
-bool
-PluginModuleParent::DeallocPCrashReporter(PCrashReporterParent* actor)
-{
-    delete actor;
-    return true;
-}
-
 bool
 PluginModuleParent::RecvSetCursor(const NSCursorInfo& aCursorInfo)
 {
     PLUGIN_LOG_DEBUG(("%s", FULLFUNCTION));
 #if defined(XP_MACOSX)
     mac_plugin_interposing::parent::OnSetCursor(aCursorInfo);
     return true;
 #else
--- a/dom/plugins/ipc/PluginModuleParent.h
+++ b/dom/plugins/ipc/PluginModuleParent.h
@@ -60,21 +60,16 @@
 #include "nsAutoPtr.h"
 #include "nsDataHashtable.h"
 #include "nsHashKeys.h"
 #include "nsIFileStreams.h"
 #include "nsTObserverArray.h"
 #include "nsITimer.h"
 
 namespace mozilla {
-namespace dom {
-class PCrashReporterParent;
-class CrashReporterParent;
-}
-
 namespace plugins {
 //-----------------------------------------------------------------------------
 
 class BrowserStreamParent;
 
 /**
  * PluginModuleParent
  *
@@ -85,18 +80,16 @@ class BrowserStreamParent;
  * This class /also/ implements a version of the NPN API, because the
  * child process needs to make these calls back into Gecko proper.
  * This class is responsible for "actually" making those function calls.
  */
 class PluginModuleParent : public PPluginModuleParent, PluginLibrary
 {
 private:
     typedef mozilla::PluginLibrary PluginLibrary;
-    typedef mozilla::dom::PCrashReporterParent PCrashReporterParent;
-    typedef mozilla::dom::CrashReporterParent CrashReporterParent;
 
 protected:
 
     virtual PPluginIdentifierParent*
     AllocPPluginIdentifier(const nsCString& aString,
                            const int32_t& aInt,
                            const bool& aTemporary);
 
@@ -186,30 +179,27 @@ protected:
                                       bool* aBoolVal);
 
     NS_OVERRIDE
     virtual bool AnswerProcessSomeEvents();
 
     NS_OVERRIDE virtual bool
     RecvProcessNativeEventsInRPCCall();
 
+    virtual bool
+    RecvAppendNotesToCrashReport(const nsCString& aNotes);
+
     NS_OVERRIDE virtual bool
     RecvPluginShowWindow(const uint32_t& aWindowId, const bool& aModal,
                          const int32_t& aX, const int32_t& aY,
                          const size_t& aWidth, const size_t& aHeight);
 
     NS_OVERRIDE virtual bool
     RecvPluginHideWindow(const uint32_t& aWindowId);
 
-    NS_OVERRIDE virtual PCrashReporterParent*
-    AllocPCrashReporter(const NativeThreadId& tid,
-                        const PRUint32& processType);
-    NS_OVERRIDE virtual bool
-    DeallocPCrashReporter(PCrashReporterParent* actor);
-
     NS_OVERRIDE virtual bool
     RecvSetCursor(const NSCursorInfo& aCursorInfo);
 
     NS_OVERRIDE virtual bool
     RecvShowCursor(const bool& aShow);
 
     NS_OVERRIDE virtual bool
     RecvPushCursor(const NSCursorInfo& aCursorInfo);
@@ -295,49 +285,46 @@ private:
                              uint16_t mode, int16_t argc, char* argn[],
                              char* argv[], NPSavedData* saved,
                              NPError* error);
     virtual nsresult NPP_ClearSiteData(const char* site, uint64_t flags,
                                        uint64_t maxAge);
     virtual nsresult NPP_GetSitesWithData(InfallibleTArray<nsCString>& result);
 
 private:
-    CrashReporterParent* CrashReporter();
-
-#ifdef MOZ_CRASHREPORTER
-    void WriteExtraDataForMinidump(CrashReporter::AnnotationTable& notes);
-#endif
+    void WritePluginExtraDataForMinidump(const nsAString& id);
+    void WriteExtraDataForHang();
     void CleanupFromTimeout();
     static int TimeoutChanged(const char* aPref, void* aModule);
     void NotifyPluginCrashed();
 
+    nsCString mCrashNotes;
     PluginProcessParent* mSubprocess;
     // the plugin thread in mSubprocess
     NativeThreadId mPluginThread;
     bool mShutdown;
     bool mClearSiteDataSupported;
     bool mGetSitesWithDataSupported;
     const NPNetscapeFuncs* mNPNIface;
     nsDataHashtable<nsVoidPtrHashKey, PluginIdentifierParent*> mIdentifiers;
     nsNPAPIPlugin* mPlugin;
+    time_t mProcessStartTime;
     ScopedRunnableMethodFactory<PluginModuleParent> mTaskFactory;
     nsString mPluginDumpID;
     nsString mBrowserDumpID;
     nsString mHangID;
 
 #ifdef OS_MACOSX
     nsCOMPtr<nsITimer> mCATimer;
     nsTObserverArray<PluginInstanceParent*> mCATimerTargets;
 #endif
 
 #ifdef MOZ_X11
     // Dup of plugin's X socket, used to scope its resources to this
     // object instead of the plugin process's lifetime
     ScopedClose mPluginXSocketFdDup;
 #endif
-
-    friend class mozilla::dom::CrashReporterParent;
 };
 
 } // namespace plugins
 } // namespace mozilla
 
 #endif  // ifndef dom_plugins_PluginModuleParent_h
--- a/dom/plugins/ipc/PluginProcessChild.cpp
+++ b/dom/plugins/ipc/PluginProcessChild.cpp
@@ -170,10 +170,22 @@ void
 PluginProcessChild::CleanUp()
 {
 #ifdef XP_WIN
     ::OleUninitialize();
 #endif
     nsRegion::ShutdownStatic();
 }
 
+/* static */
+void
+PluginProcessChild::AppendNotesToCrashReport(const nsCString& aNotes)
+{
+    AssertPluginThread();
+
+    PluginProcessChild* p = PluginProcessChild::current();
+    if (p) {
+        p->mPlugin.SendAppendNotesToCrashReport(aNotes);
+    }
+}
+
 } // namespace plugins
 } // namespace mozilla
--- a/dom/plugins/ipc/PluginProcessChild.h
+++ b/dom/plugins/ipc/PluginProcessChild.h
@@ -56,16 +56,19 @@ public:
     { }
 
     virtual ~PluginProcessChild()
     { }
 
     NS_OVERRIDE virtual bool Init();
     NS_OVERRIDE virtual void CleanUp();
 
+    // For use on the plugin thread.
+    static void AppendNotesToCrashReport(const nsCString& aNotes);
+
 protected:
     static PluginProcessChild* current() {
         return static_cast<PluginProcessChild*>(ProcessChild::current());
     }
 
 private:
     PluginModuleChild mPlugin;
 
--- a/ipc/testshell/TestShellParent.cpp
+++ b/ipc/testshell/TestShellParent.cpp
@@ -141,23 +141,8 @@ TestShellCommandParent::RunCallback(cons
   return JS_TRUE;
 }
 
 void
 TestShellCommandParent::ReleaseCallback()
 {
   mCallback.Release();
 }
-
-bool
-TestShellCommandParent::ExecuteCallback(const nsString& aResponse)
-{
-  return static_cast<TestShellParent*>(Manager())->CommandDone(
-      this, aResponse);
-}
-
-void
-TestShellCommandParent::ActorDestroy(ActorDestroyReason why)
-{
-  if (why == AbnormalShutdown) {
-    ExecuteCallback(EmptyString());
-  }
-}
--- a/ipc/testshell/TestShellParent.h
+++ b/ipc/testshell/TestShellParent.h
@@ -87,22 +87,19 @@ public:
   JSBool SetCallback(JSContext* aCx,
                      jsval aCallback);
 
   JSBool RunCallback(const nsString& aResponse);
 
   void ReleaseCallback();
 
 protected:
-  bool ExecuteCallback(const nsString& aResponse);
-
-  void ActorDestroy(ActorDestroyReason why);
-  
   bool Recv__delete__(const nsString& aResponse) {
-    return ExecuteCallback(aResponse);
+    return static_cast<TestShellParent*>(Manager())->CommandDone(
+      this, aResponse);
   }
 
 private:
   JSContext* mCx;
   nsAutoJSValHolder mCallback;
 };
 
 
--- a/testing/xpcshell/xpcshell.ini
+++ b/testing/xpcshell/xpcshell.ini
@@ -72,19 +72,16 @@
 skip-if = !debug
 
 [include:intl/locale/tests_multilocale/unit/xpcshell.ini]
 run-if = toolkit == "windows" || toolkit == "cocoa"
 
 [include:toolkit/crashreporter/test/unit/xpcshell.ini]
 skip-if = os == "linux" || !crashreporter
 
-[include:toolkit/crashreporter/test/unit_ipc/xpcshell.ini]
-skip-if.os = linux || !crashreporter
-
 #XXX: we don't actually set os = maemo
 [include:toolkit/crashreporter/client/maemo-unit/xpcshell.ini]
 run-if = os == "maemo"
 
 [include:intl/locale/src/unix/tests/unit/xpcshell.ini]
 skip-if = toolkit == "windows" || toolkit == "cocoa" || toolkit == "os2"
 
 [include:toolkit/components/commandlines/test/unit_win/xpcshell.ini]
--- a/toolkit/crashreporter/Makefile.in
+++ b/toolkit/crashreporter/Makefile.in
@@ -122,11 +122,9 @@ FORCE_STATIC_LIB = 1
 EXTRA_JS_MODULES = \
   CrashSubmit.jsm \
   $(NULL)
 
 ifdef ENABLE_TESTS
 TOOL_DIRS = test
 endif
 
-include $(topsrcdir)/config/config.mk
-include $(topsrcdir)/ipc/chromium/chromium-config.mk
 include $(topsrcdir)/config/rules.mk
--- a/toolkit/crashreporter/nsExceptionHandler.cpp
+++ b/toolkit/crashreporter/nsExceptionHandler.cpp
@@ -32,19 +32,16 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
-#include "mozilla/dom/CrashReporterChild.h"
-#include "nsXULAppAPI.h"
-
 #include "nsExceptionHandler.h"
 
 #if defined(XP_WIN32)
 #ifdef WIN32_LEAN_AND_MEAN
 #undef WIN32_LEAN_AND_MEAN
 #endif
 
 #include "nsIWindowsRegKey.h"
@@ -110,18 +107,16 @@ CFStringRef reporterClientAppID = CFSTR(
 #endif
 
 #include "nsIUUIDGenerator.h"
 
 using google_breakpad::CrashGenerationServer;
 using google_breakpad::ClientInfo;
 using mozilla::Mutex;
 using mozilla::MutexAutoLock;
-using mozilla::dom::CrashReporterChild;
-using mozilla::dom::PCrashReporterChild;
 
 namespace CrashReporter {
 
 #ifdef XP_WIN32
 typedef wchar_t XP_CHAR;
 typedef std::wstring xpstring;
 #define CONVERT_UTF16_TO_XP_CHAR(x) x
 #define CONVERT_XP_CHAR_TO_UTF16(x) x
@@ -801,17 +796,17 @@ nsresult SetExceptionHandler(nsILocalFil
   }
 #endif
 
   return NS_OK;
 }
 
 bool GetEnabled()
 {
-  return gExceptionHandler != nsnull;
+  return gExceptionHandler != nsnull && !gExceptionHandler->IsOutOfProcess();
 }
 
 bool GetMinidumpPath(nsAString& aPath)
 {
   if (!gExceptionHandler)
     return false;
 
   aPath = CONVERT_XP_CHAR_TO_UTF16(gExceptionHandler->dump_path().c_str());
@@ -1095,55 +1090,38 @@ static PLDHashOperator EnumerateEntries(
                                         nsCString entry,
                                         void* userData)
 {
   crashReporterAPIData->Append(key + NS_LITERAL_CSTRING("=") + entry +
                                NS_LITERAL_CSTRING("\n"));
   return PL_DHASH_NEXT;
 }
 
-static nsresult
-EscapeAnnotation(const nsACString& key, nsCString& data)
+nsresult AnnotateCrashReport(const nsACString& key, const nsACString& data)
 {
+  if (!GetEnabled())
+    return NS_ERROR_NOT_INITIALIZED;
+
   if (DoFindInReadable(key, NS_LITERAL_CSTRING("=")) ||
       DoFindInReadable(key, NS_LITERAL_CSTRING("\n")))
     return NS_ERROR_INVALID_ARG;
 
   if (DoFindInReadable(data, NS_LITERAL_CSTRING("\0")))
     return NS_ERROR_INVALID_ARG;
 
+  nsCString escapedData(data);
+
   // escape backslashes
-  ReplaceChar(data, NS_LITERAL_CSTRING("\\"),
+  ReplaceChar(escapedData, NS_LITERAL_CSTRING("\\"),
               NS_LITERAL_CSTRING("\\\\"));
   // escape newlines
-  ReplaceChar(data, NS_LITERAL_CSTRING("\n"),
+  ReplaceChar(escapedData, NS_LITERAL_CSTRING("\n"),
               NS_LITERAL_CSTRING("\\n"));
-  return NS_OK;
-}
-
-nsresult AnnotateCrashReport(const nsACString& key, const nsACString& data)
-{
-  if (!GetEnabled())
-    return NS_ERROR_NOT_INITIALIZED;
 
-  nsCString escapedData(data);
-  nsresult rv = EscapeAnnotation(key, escapedData);
-  if (NS_FAILED(rv))
-    return rv;
-
-  if (XRE_GetProcessType() != GeckoProcessType_Default) {
-    PCrashReporterChild* reporter = CrashReporterChild::GetCrashReporter();
-    if (!reporter)
-      return NS_ERROR_NOT_INITIALIZED;
-    if (!reporter->SendAnnotateCrashReport(nsCString(key), escapedData))
-      return NS_ERROR_FAILURE;
-    return NS_OK;
-  }
-
-  crashReporterAPIData_Hash->Put(key, escapedData);
+  nsresult rv = crashReporterAPIData_Hash->Put(key, escapedData);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // now rebuild the file contents
   crashReporterAPIData->Truncate(0);
   crashReporterAPIData_Hash->EnumerateRead(EnumerateEntries,
                                            crashReporterAPIData);
 
   return NS_OK;
@@ -1152,34 +1130,16 @@ nsresult AnnotateCrashReport(const nsACS
 nsresult AppendAppNotesToCrashReport(const nsACString& data)
 {
   if (!GetEnabled())
     return NS_ERROR_NOT_INITIALIZED;
 
   if (DoFindInReadable(data, NS_LITERAL_CSTRING("\0")))
     return NS_ERROR_INVALID_ARG;
 
-  if (XRE_GetProcessType() != GeckoProcessType_Default) {
-    PCrashReporterChild* reporter = CrashReporterChild::GetCrashReporter();
-    if (!reporter)
-      return NS_ERROR_NOT_INITIALIZED;
-
-    // Since we don't go through AnnotateCrashReport in the parent process,
-    // we must ensure that the data is escaped and valid before the parent
-    // sees it.
-    nsCString escapedData(data);
-    nsresult rv = EscapeAnnotation(NS_LITERAL_CSTRING("Notes"), escapedData);
-    if (NS_FAILED(rv))
-      return rv;
-
-    if (!reporter->SendAppendAppNotes(escapedData))
-      return NS_ERROR_FAILURE;
-    return NS_OK;
-  }
-
   notesField->Append(data);
   return AnnotateCrashReport(NS_LITERAL_CSTRING("Notes"), *notesField);
 }
 
 // Returns true if found, false if not found.
 bool GetAnnotation(const nsACString& key, nsACString& data)
 {
   if (!gExceptionHandler)
@@ -1881,17 +1841,17 @@ SetRemoteExceptionHandler(const nsACStri
   // crash reporting is disabled
   if (crashPipe.Equals(kNullNotifyPipe))
     return true;
 
   NS_ABORT_IF_FALSE(!gExceptionHandler, "crash client already init'd");
 
   gExceptionHandler = new google_breakpad::
     ExceptionHandler(L"",
-                     FPEFilter,
+                     NULL,    // no filter callback
                      NULL,    // no minidump callback
                      NULL,    // no callback context
                      google_breakpad::ExceptionHandler::HANDLER_ALL,
                      MiniDumpNormal,
                      NS_ConvertASCIItoUTF16(crashPipe).BeginReading(),
                      NULL);
 #ifdef XP_WIN
   gExceptionHandler->set_handle_debug_exceptions(true);
--- a/toolkit/crashreporter/test/Makefile.in
+++ b/toolkit/crashreporter/test/Makefile.in
@@ -39,17 +39,17 @@ DEPTH		= ../../..
 topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 relativesrcdir  = toolkit/crashreporter/test
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE = crashreporter_test
-XPCSHELL_TESTS = unit unit_ipc
+XPCSHELL_TESTS = unit
 
 LIBRARY_NAME = testcrasher
 NO_DIST_INSTALL = 1
 
 FORCE_SHARED_LIB = 1
 
 VPATH += \
   $(srcdir)/../google-breakpad/src/processor/ \
@@ -90,10 +90,9 @@ ifneq (mobile,$(MOZ_BUILD_APP))
   $(NULL)
 
 libs::  $(_BROWSER_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)/browser
 endif
 
 libs:: $(SHARED_LIBRARY) $(EXTRA_JS_MODULES)
 	$(INSTALL) $^ $(DEPTH)/_tests/xpcshell/$(relativesrcdir)/unit/
-	$(INSTALL) $^ $(DEPTH)/_tests/xpcshell/$(relativesrcdir)/unit_ipc/
 
--- a/toolkit/crashreporter/test/unit/crasher_subprocess_head.js
+++ b/toolkit/crashreporter/test/unit/crasher_subprocess_head.js
@@ -1,25 +1,17 @@
 // enable crash reporting first
 let cwd = Components.classes["@mozilla.org/file/directory_service;1"]
       .getService(Components.interfaces.nsIProperties)
       .get("CurWorkD", Components.interfaces.nsILocalFile);
-
 let crashReporter =
   Components.classes["@mozilla.org/toolkit/crash-reporter;1"]
     .getService(Components.interfaces.nsICrashReporter);
-
-// the crash reporter is already enabled in content processes,
-// and setting the minidump path is not allowed
-let processType = Components.classes["@mozilla.org/xre/runtime;1"].
-      getService(Components.interfaces.nsIXULRuntime).processType;
-if (processType == Components.interfaces.nsIXULRuntime.PROCESS_TYPE_DEFAULT) {
-  crashReporter.enabled = true;
-  crashReporter.minidumpPath = cwd;
-}
+crashReporter.enabled = true;
+crashReporter.minidumpPath = cwd;
 
 let ios = Components.classes["@mozilla.org/network/io-service;1"]
             .getService(Components.interfaces.nsIIOService);
 let protocolHandler = ios.getProtocolHandler("resource")
                         .QueryInterface(Components.interfaces.nsIResProtocolHandler);
 let curDirURI = ios.newFileURI(cwd);
 protocolHandler.setSubstitution("test", curDirURI);
 Components.utils.import("resource://test/CrashTestUtils.jsm");
--- a/toolkit/crashreporter/test/unit/head_crashreporter.js
+++ b/toolkit/crashreporter/test/unit/head_crashreporter.js
@@ -60,21 +60,16 @@ function do_crash(setup, callback, canRe
   }
   catch(ex) {} // on Windows we exit with a -1 status when crashing.
 
   if (!canReturnZero) {
     // should exit with an error (should have crashed)
     do_check_neq(process.exitValue, 0);
   }
 
-  handleMinidump(callback);
-}
-
-function handleMinidump(callback)
-{
   // find minidump
   let minidump = null;
   let en = do_get_cwd().directoryEntries;
   while (en.hasMoreElements()) {
     let f = en.getNext().QueryInterface(Components.interfaces.nsILocalFile);
     if (f.leafName.substr(-4) == ".dmp") {
       minidump = f;
       break;
@@ -101,54 +96,16 @@ function handleMinidump(callback)
     callback(minidump, extra);
 
   if (minidump.exists())
     minidump.remove(false);
   if (extrafile.exists())
     extrafile.remove(false);
 }
 
-function do_content_crash(setup, callback)
-{
-  do_load_child_test_harness();
-  do_test_pending();
-
-  // Setting the minidump path won't work in the child, so we need to do
-  // that here.
-  let crashReporter =
-      Components.classes["@mozilla.org/toolkit/crash-reporter;1"]
-      .getService(Components.interfaces.nsICrashReporter);
-  crashReporter.minidumpPath = do_get_cwd();
-
-  let headfile = do_get_file("../unit/crasher_subprocess_head.js");
-  let tailfile = do_get_file("../unit/crasher_subprocess_tail.js");
-  if (setup) {
-    if (typeof(setup) == "function")
-      // funky, but convenient
-      setup = "("+setup.toSource()+")();";
-  }
-
-  let handleCrash = function() {
-    try {            
-      handleMinidump(callback);
-    } catch (x) {
-      do_report_unexpected_exception(x);
-    }
-    do_test_finished();
-  };
-  
-  sendCommand("load(\"" + headfile.path.replace(/\\/g, "/") + "\");", function()
-    sendCommand(setup, function()
-      sendCommand("load(\"" + tailfile.path.replace(/\\/g, "/") + "\");",
-        function() do_execute_soon(handleCrash)
-      )
-    )
-  );
-}
-
 // Utility functions for parsing .extra files
 function parseKeyValuePairs(text) {
   var lines = text.split('\n');
   var data = {};
   for (let i = 0; i < lines.length; i++) {
     if (lines[i] == '')
       continue;
 
deleted file mode 100644
--- a/toolkit/crashreporter/test/unit_ipc/test_content_annotation.js
+++ /dev/null
@@ -1,22 +0,0 @@
-load("../unit/head_crashreporter.js");
-
-function run_test()
-{
-  if (!("@mozilla.org/toolkit/crash-reporter;1" in Components.classes)) {
-    dump("INFO | test_content_annotation.js | Can't test crashreporter in a non-libxul build.\n");
-    return;
-  }
-
-  // Try crashing with a pure virtual call
-  do_content_crash(function() {
-                     crashType = CrashTestUtils.CRASH_RUNTIMEABORT;
-                     crashReporter.annotateCrashReport("TestKey", "TestValue");
-                     crashReporter.appendAppNotesToCrashReport("!!!foo!!!");
-		   },
-                   function(mdump, extra) {
-                     do_check_eq(extra.TestKey, "TestValue");
-                     do_check_true('StartupTime' in extra);
-                     do_check_true('ProcessType' in extra);
-                     do_check_neq(extra.Notes.indexOf("!!!foo!!!"), -1);
-                   });
-}
\ No newline at end of file
deleted file mode 100644
--- a/toolkit/crashreporter/test/unit_ipc/xpcshell.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[DEFAULT]
-head = head_crashreporter.js
-tail = 
-
-[test_content_annotation.js]
--- a/toolkit/xre/nsEmbedFunctions.cpp
+++ b/toolkit/xre/nsEmbedFunctions.cpp
@@ -354,19 +354,17 @@ XRE_InitChildProcess(int aArgc,
   }
   err = task_set_bootstrap_port(mach_task_self(),
                                 parent_message.GetTranslatedPort(0));
   if (err != KERN_SUCCESS) {
     NS_WARNING("child task_set_bootstrap_port() failed");
     return 1;
   }
 #endif
-
-  SetupErrorHandling(aArgv[0]);  
-
+  
 #if defined(MOZ_CRASHREPORTER)
   if (aArgc < 1)
     return 1;
   const char* const crashReporterArg = aArgv[--aArgc];
   
 #  if defined(XP_WIN) || defined(XP_MACOSX)
   // on windows and mac, |crashReporterArg| is the named pipe on which the
   // server is listening for requests, or "-" if crash reporting is
@@ -383,16 +381,18 @@ XRE_InitChildProcess(int aArgc,
 #  else
 #    error "OOP crash reporting unsupported on this platform"
 #  endif   
 #endif // if defined(MOZ_CRASHREPORTER)
 
   gArgv = aArgv;
   gArgc = aArgc;
 
+  SetupErrorHandling(aArgv[0]);
+  
 #if defined(MOZ_WIDGET_GTK2)
   g_thread_init(NULL);
 #endif
 
 #if defined(MOZ_WIDGET_QT)
   nsQAppInstance::AddRef();
 #endif
 
@@ -701,28 +701,26 @@ XRE_ShutdownChildProcess()
       // that case, we fire off an Exit() here.  If we were indeed
       // above MessagePump::Run(), this Exit() is just superfluous.
       appShell->Exit();
   }
 #endif // XP_MACOSX
 }
 
 namespace {
+TestShellParent* gTestShellParent = nsnull;
 TestShellParent* GetOrCreateTestShellParent()
 {
-    ContentParent* parent = ContentParent::GetSingleton();
-    if (!parent) {
-      return nsnull;
+    if (!gTestShellParent) {
+        ContentParent* parent = ContentParent::GetSingleton();
+        NS_ENSURE_TRUE(parent, nsnull);
+        gTestShellParent = parent->CreateTestShell();
+        NS_ENSURE_TRUE(gTestShellParent, nsnull);
     }
-
-    TestShellParent* testShell = parent->GetTestShellSingleton();
-    if (!testShell) {
-      testShell = parent->CreateTestShell();
-    }
-    return testShell;
+    return gTestShellParent;
 }
 }
 
 bool
 XRE_SendTestShellCommand(JSContext* aCx,
                          JSString* aCommand,
                          void* aCallback)
 {
@@ -751,19 +749,19 @@ XRE_GetChildGlobalObject(JSContext* aCx,
 {
     TestShellParent* tsp = GetOrCreateTestShellParent();
     return tsp && tsp->GetGlobalJSObject(aCx, aGlobalP);
 }
 
 bool
 XRE_ShutdownTestShell()
 {
-  ContentParent* cp = ContentParent::GetSingleton(PR_FALSE);
-  TestShellParent* tsp = cp ? cp->GetTestShellSingleton() : nsnull;
-  return tsp ? cp->DestroyTestShell(tsp) : true;
+  if (!gTestShellParent)
+    return true;
+  return ContentParent::GetSingleton()->DestroyTestShell(gTestShellParent);
 }
 
 #ifdef MOZ_X11
 void
 XRE_InstallX11ErrorHandler()
 {
   InstallX11ErrorHandler();
 }
--- a/toolkit/xre/nsX11ErrorHandler.cpp
+++ b/toolkit/xre/nsX11ErrorHandler.cpp
@@ -33,16 +33,19 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsX11ErrorHandler.h"
 
+#include "mozilla/plugins/PluginProcessChild.h"
+using mozilla::plugins::PluginProcessChild;
+
 #include "prenv.h"
 #include "nsXULAppAPI.h"
 #include "nsExceptionHandler.h"
 #include "nsDebug.h"
 
 #include "mozilla/X11Util.h"
 #include <X11/Xlib.h>
 
@@ -148,19 +151,25 @@ X11Error(Display *display, XErrorEvent *
       notes.AppendInt(PRUint32(age));
       notes.Append(" requests ago");
     }
   }
 
 #ifdef MOZ_CRASHREPORTER
   switch (XRE_GetProcessType()) {
   case GeckoProcessType_Default:
+    CrashReporter::AppendAppNotesToCrashReport(notes);
+    break;
   case GeckoProcessType_Plugin:
-  case GeckoProcessType_Content:
-    CrashReporter::AppendAppNotesToCrashReport(notes);
+    if (CrashReporter::GetEnabled()) {
+      // This is assuming that X operations are performed on the plugin
+      // thread.  If plugins are using X on another thread, then we'll need to
+      // handle that differently.
+      PluginProcessChild::AppendNotesToCrashReport(notes);
+    }
     break;
   default: 
     ; // crash report notes not supported.
   }
 #endif
 
 #ifdef DEBUG
   // The resource id is unlikely to be useful in a crash report without