Back out bug 581341.
authorJosh Matthews <josh@joshmatthews.net>
Wed, 29 Jun 2011 15:13:17 -0400
changeset 72289 45352943ab6c040fa825c0c23b4cf8046190cb16
parent 72287 ebae45e5005c7f14abf1557771005c52735d41f9
child 72290 c7c6abdd64ab52d3bdea7efa59b8fd35130e8d4a
push idunknown
push userunknown
push dateunknown
bugs581341
milestone7.0a1
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