diff --git a/dom/plugins/PluginModuleParent.cpp b/dom/plugins/PluginModuleParent.cpp
--- a/dom/plugins/PluginModuleParent.cpp
+++ b/dom/plugins/PluginModuleParent.cpp
@@ -254,17 +254,17 @@ PluginModuleParent::ShouldContinueFromRe
     return waitMoar;
 }
 
 void
 PluginModuleParent::ActorDestroy(ActorDestroyReason why)
 {
     switch (why) {
     case AbnormalShutdown: {
-        nsCOMPtr<nsIFile> dump;
+        nsCOMPtr<nsILocalFile> dump;
         if (CrashReporter::TakeMinidumpForChild(ChildProcessHandle(),
                                                 getter_AddRefs(dump))) {
             WriteExtraDataForMinidump(dump);
             if (NS_SUCCEEDED(dump->GetLeafName(mDumpID))) {
                 mDumpID.Replace(mDumpID.Length() - 4, 4,
                                 NS_LITERAL_STRING(""));
             }
         }
diff --git a/toolkit/crashreporter/nsExceptionHandler.cpp b/toolkit/crashreporter/nsExceptionHandler.cpp
--- a/toolkit/crashreporter/nsExceptionHandler.cpp
+++ b/toolkit/crashreporter/nsExceptionHandler.cpp
@@ -85,17 +85,16 @@
 #include <prenv.h>
 #include <prio.h>
 #include <prmem.h>
 #include "mozilla/Mutex.h"
 #include "nsDebug.h"
 #include "nsCRT.h"
 #include "nsILocalFile.h"
 #include "nsIFileStreams.h"
-#include "nsDataHashtable.h"
 #include "nsInterfaceHashtable.h"
 #include "prprf.h"
 #include "nsIXULAppInfo.h"
 
 using google_breakpad::ExceptionHandler;
 
 #if defined(MOZ_IPC)
 using google_breakpad::CrashGenerationServer;
@@ -162,17 +161,17 @@ static XP_CHAR lastCrashTimeFilename[XP_
 static const char kCrashTimeParameter[] = "CrashTime=";
 static const int kCrashTimeParameterLen = sizeof(kCrashTimeParameter)-1;
 
 static const char kTimeSinceLastCrashParameter[] = "SecondsSinceLastCrash=";
 static const int kTimeSinceLastCrashParameterLen =
                                      sizeof(kTimeSinceLastCrashParameter)-1;
 
 // this holds additional data sent via the API
-static nsDataHashtable<nsCStringHashKey,nsCString>* crashReporterAPIData_Hash;
+static AnnotationTable* crashReporterAPIData_Hash;
 static nsCString* crashReporterAPIData = nsnull;
 static nsCString* notesField = nsnull;
 
 #if defined(MOZ_IPC)
 // OOP crash reporting
 static CrashGenerationServer* crashServer; // chrome process has this
 
 #  if defined(XP_WIN)
@@ -184,17 +183,17 @@ static char* childCrashNotifyPipe;
 #  elif defined(XP_LINUX)
 static int serverSocketFd = -1;
 static int clientSocketFd = -1;
 static const int kMagicChildCrashReportFd = 42;
 #  endif
 
 // |dumpMapLock| must protect all access to |pidToMinidump|.
 static Mutex* dumpMapLock;
-typedef nsInterfaceHashtable<nsUint32HashKey, nsIFile> ChildMinidumpMap;
+typedef nsInterfaceHashtable<nsUint32HashKey, nsILocalFile> ChildMinidumpMap;
 static ChildMinidumpMap* pidToMinidump;
 
 #endif  // MOZ_IPC
 
 #ifdef XP_WIN
 static void
 CreateFileFromPath(const xpstring& path, nsILocalFile** file)
 {
@@ -1173,20 +1172,83 @@ nsresult GetSubmitReports(PRBool* aSubmi
     return PrefSubmitReports(aSubmitReports, false);
 }
 
 nsresult SetSubmitReports(PRBool aSubmitReports)
 {
     return PrefSubmitReports(&aSubmitReports, true);
 }
 
+bool
+GetMinidumpForID(const nsAString& id, nsILocalFile** minidump)
+{
+  xpstring dumpFilename(gExceptionHandler->dump_path());
+  xpstring xID;
 
-#if defined(MOZ_IPC)
+  AStringToXPString(id, xID);
 
+  dumpFilename += XP_PATH_SEPARATOR;
+  dumpFilename += xID;
+  dumpFilename += dumpFileExtension;
+
+  CreateFileFromPath(dumpFilename, minidump);
+  return NULL != *minidump;
+}
+
+bool
+GetIDFromMinidump(nsILocalFile* minidump, nsAString& id)
+{
+  if (NS_SUCCEEDED(minidump->GetLeafName(id))) {
+    id.Replace(id.Length() - 4, 4, NS_LITERAL_STRING(""));
+    return true;
+  }
+  return false;
+}
+
+bool
+GetExtraFileForID(const nsAString& id, nsILocalFile** extraFile)
+{
+  xpstring extraFilename(gExceptionHandler->dump_path());
+  xpstring xID;
+
+  AStringToXPString(id, xID);
+
+  extraFilename += XP_PATH_SEPARATOR;
+  extraFilename += xID;
+  extraFilename += extraFileExtension;
+
+  CreateFileFromPath(extraFilename, extraFile);
+  return NULL != *extraFile;
+
+}
+
+bool
+GetExtraFileForMinidump(nsILocalFile* minidump, nsILocalFile** extraFile)
+{
+  nsAutoString id;
+  if (!GetIDFromMinidump(minidump, id))
+    return false;
+
+  return GetExtraFileForID(id, extraFile);
+}
+
+bool
+AppendExtraData(const nsAString& id, const AnnotationTable& data)
+{
+  nsCOMPtr<nsILocalFile> extraFile;
+  if (!GetExtraFileForID(id, getter_AddRefs(extraFile)))
+    return false;
+  return AppendExtraData(extraFile, data);
+}
+
+//-----------------------------------------------------------------------------
+// Helpers for AppendExtraData()
+//
 struct Blacklist {
+  Blacklist() : mItems(NULL), mLen(0) { }
   Blacklist(const char** items, int len) : mItems(items), mLen(len) { }
 
   bool Contains(const nsACString& key) const {
     for (int i = 0; i < mLen; ++i)
       if (key.EqualsASCII(mItems[i]))
         return true;
     return false;
   }
@@ -1195,81 +1257,96 @@ struct Blacklist {
   const int mLen;
 };
 
 struct EnumerateAnnotationsContext {
   const Blacklist* blacklist;
   PRFileDesc* fd;
 };
 
+static void
+WriteAnnotation(PRFileDesc* fd, const nsACString& key, const nsACString& value)
+{
+  PR_Write(fd, key.BeginReading(), key.Length());
+  PR_Write(fd, "=", 1);
+  PR_Write(fd, value.BeginReading(), value.Length());
+  PR_Write(fd, "\n", 1);
+}
+
 static PLDHashOperator
 EnumerateAnnotations(const nsACString& key,
                      nsCString entry,
                      void* userData)
 {
   EnumerateAnnotationsContext* ctx =
     static_cast<EnumerateAnnotationsContext*>(userData);
   const Blacklist& blacklist = *ctx->blacklist;
 
   // skip entries in the blacklist
   if (blacklist.Contains(key))
       return PL_DHASH_NEXT;
 
-  PRFileDesc* fd = ctx->fd;  
-  PR_Write(fd, key.BeginReading(), key.Length());
-  PR_Write(fd, "=", 1);
-  PR_Write(fd, entry.BeginReading(), entry.Length());
-  PR_Write(fd, "\n", 1);
+  WriteAnnotation(ctx->fd, key, entry);
 
   return PL_DHASH_NEXT;
 }
 
 static bool
+AppendExtraData(nsILocalFile* extraFile,
+                const AnnotationTable& data,
+                const Blacklist& blacklist,
+                const char* const crashTime=NULL,
+                bool truncate=false)
+{
+  PRFileDesc* fd;
+  PRIntn truncOrAppend = truncate ? PR_TRUNCATE : PR_APPEND;
+  nsresult rv = 
+    extraFile->OpenNSPRFileDesc(PR_WRONLY | PR_CREATE_FILE | truncOrAppend,
+                                0600, &fd);
+  if (NS_FAILED(rv))
+    return false;
+
+  EnumerateAnnotationsContext ctx = { &blacklist, fd };
+  data.EnumerateRead(EnumerateAnnotations, &ctx);
+
+  if (crashTime)
+    WriteAnnotation(fd,
+                    nsDependentCString(kCrashTimeParameter),
+                    nsDependentCString(crashTime));
+
+  PR_Close(fd);
+  return true;
+}
+
+bool
+AppendExtraData(nsILocalFile* extraFile, const AnnotationTable& data)
+{
+  return AppendExtraData(extraFile, data, Blacklist());
+}
+
+
+#if defined(MOZ_IPC)
+
+static bool
 WriteExtraForMinidump(nsILocalFile* minidump,
                       const Blacklist& blacklist,
                       nsILocalFile** extraFile)
 {
-  // Get an .extra file with the same base name as the .dmp file
-  nsCOMPtr<nsIFile> file;
-  nsresult rv = minidump->Clone(getter_AddRefs(file));
-  if (NS_FAILED(rv))
+  nsCOMPtr<nsILocalFile> extra;
+  if (!GetExtraFileForMinidump(minidump, getter_AddRefs(extra)))
     return false;
 
-  nsCOMPtr<nsILocalFile> extra = do_QueryInterface(file);
-
-  nsAutoString leafName;
-  rv = extra->GetLeafName(leafName);
-  if (NS_FAILED(rv))
-    return false;
-
-  leafName.Replace(leafName.Length() - 3, 3,
-                   NS_LITERAL_STRING("extra"));
-  rv = extra->SetLeafName(leafName);
-  if (NS_FAILED(rv))
-    return false;
-
-  // Now write out the annotations to it
-  PRFileDesc* fd;
-  rv = extra->OpenNSPRFileDesc(PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
-                                   0600, &fd);
-  if (NS_FAILED(rv))
-    return false;
-
-  EnumerateAnnotationsContext ctx = { &blacklist, fd };
-  crashReporterAPIData_Hash->EnumerateRead(EnumerateAnnotations, &ctx);
-
-  // Add CrashTime to extra data
   time_t crashTime = time(NULL);
   char crashTimeString[32];
   XP_TTOA(crashTime, crashTimeString, 10);
 
-  PR_Write(fd, kCrashTimeParameter, kCrashTimeParameterLen);
-  PR_Write(fd, crashTimeString, strlen(crashTimeString));
-  PR_Write(fd, "\n", 1);
-  PR_Close(fd);
+  if (!AppendExtraData(extra, *crashReporterAPIData_Hash,
+                       blacklist, crashTimeString,
+                       true /*truncate*/))
+    return false;
 
   *extraFile = NULL;
   extra.swap(*extraFile);
 
   return true;
 }
 
 static bool
@@ -1485,26 +1562,26 @@ SetRemoteExceptionHandler()
   // we either do remote or nothing, no fallback to regular crash reporting
   return gExceptionHandler->IsOutOfProcess();
 }
 
 #endif  // XP_WIN
 
 
 bool
-TakeMinidumpForChild(ProcessHandle childPid, nsIFile** dump)
+TakeMinidumpForChild(ProcessHandle childPid, nsILocalFile** dump)
 {
   if (!GetEnabled())
     return false;
 
   PRUint32 key = PRUint32(childPid);
 
   MutexAutoLock lock(*dumpMapLock);
 
-  nsCOMPtr<nsIFile> d;
+  nsCOMPtr<nsILocalFile> d;
   bool found = pidToMinidump->Get(key, getter_AddRefs(d));
   if (found)
     pidToMinidump->Remove(key);
 
   *dump = NULL;
   d.swap(*dump);
 
   return found;
@@ -1527,22 +1604,21 @@ PairedDumpCallback(const XP_CHAR* dump_p
                    MDRawAssertionInfo* /*unused*/,
 #endif
                    bool succeeded)
 {
   PairedDumpContext* ctx = static_cast<PairedDumpContext*>(context);
   nsCOMPtr<nsILocalFile>& minidump = *ctx->minidump;
   const Blacklist& blacklist = *ctx->blacklist;
 
-  xpstring dumpFilename(dump_path);
-  dumpFilename += XP_PATH_SEPARATOR;
-  dumpFilename += minidump_id;
-  dumpFilename += dumpFileExtension;
+  nsAutoString id;
+  XPStringToAString(minidump_id, id);
 
-  CreateFileFromPath(dumpFilename, getter_AddRefs(minidump));
+  if (!GetMinidumpForID(id, getter_AddRefs(minidump)))
+    return false;
 
   nsCOMPtr<nsILocalFile> dontcare;
   return WriteExtraForMinidump(minidump, blacklist, getter_AddRefs(dontcare));
 }
 
 bool
 CreatePairedMinidumps(ProcessHandle childPid,
                       nsAString* pairGUID,
diff --git a/toolkit/crashreporter/nsExceptionHandler.h b/toolkit/crashreporter/nsExceptionHandler.h
--- a/toolkit/crashreporter/nsExceptionHandler.h
+++ b/toolkit/crashreporter/nsExceptionHandler.h
@@ -34,16 +34,17 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef nsExceptionHandler_h__
 #define nsExceptionHandler_h__
 
 #include "nscore.h"
+#include "nsDataHashtable.h"
 #include "nsXPCOM.h"
 #include "nsStringGlue.h"
 
 #include "nsIFile.h"
 
 #if defined(XP_WIN32)
 #ifdef WIN32_LEAN_AND_MEAN
 #undef WIN32_LEAN_AND_MEAN
@@ -59,16 +60,27 @@ bool     GetServerURL(nsACString& aServe
 nsresult SetServerURL(const nsACString& aServerURL);
 bool     GetMinidumpPath(nsAString& aPath);
 nsresult SetMinidumpPath(const nsAString& aPath);
 nsresult AnnotateCrashReport(const nsACString& key, const nsACString& data);
 nsresult AppendAppNotesToCrashReport(const nsACString& data);
 nsresult SetRestartArgs(int argc, char** argv);
 nsresult SetupExtraData(nsILocalFile* aAppDataDirectory,
                         const nsACString& aBuildID);
+
+// Functions for working with minidumps and .extras
+typedef nsDataHashtable<nsCStringHashKey, nsCString> AnnotationTable;
+
+bool GetMinidumpForID(const nsAString& id, nsILocalFile** minidump);
+bool GetIDFromMinidump(nsILocalFile* minidump, nsAString& id);
+bool GetExtraFileForID(const nsAString& id, nsILocalFile** extraFile);
+bool GetExtraFileForMinidump(nsILocalFile* minidump, nsILocalFile** extraFile);
+bool AppendExtraData(const nsAString& id, const AnnotationTable& data);
+bool AppendExtraData(nsILocalFile* extraFile, const AnnotationTable& data);
+
 #ifdef XP_WIN32
   nsresult WriteMinidumpForException(EXCEPTION_POINTERS* aExceptionInfo);
 #endif
 #ifdef XP_MACOSX
   nsresult AppendObjCExceptionInfoToAppNotes(void *inException);
 #endif
 nsresult GetSubmitReports(PRBool* aSubmitReport);
 nsresult SetSubmitReports(PRBool aSubmitReport);
@@ -80,17 +92,18 @@ nsresult SetSubmitReports(PRBool aSubmit
 typedef HANDLE ProcessHandle;
 #else
 typedef int ProcessHandle;
 #endif
 
 // Return true iff a dump was found for |childPid|, and return the
 // path in |dump|.  The caller owns the last reference to |dump| if it
 // is non-NULL.
-bool TakeMinidumpForChild(ProcessHandle childPid, nsIFile** dump NS_OUTPARAM);
+bool TakeMinidumpForChild(ProcessHandle childPid,
+                          nsILocalFile** dump NS_OUTPARAM);
 
 // Create new minidumps that are snapshots of the state of this parent
 // process and |childPid|.  Return true on success along with the
 // minidumps and a new UUID that can be used to correlate the dumps.
 //
 // If this function fails, it's the caller's responsibility to clean
 // up |childDump| and |parentDump|.  Either or both can be created and
 // returned non-null on failure.
