Bug 1402519 - When the crash reporter code is disabled at configure time replace it with a dummy implementation; r=ted.mielczarek
☠☠ backed out by ffc12802d558 ☠ ☠
authorGabriele Svelto <gsvelto@mozilla.com>
Tue, 14 Nov 2017 14:49:33 +0100
changeset 393159 f8fdf450613ff65c9574a172dfee97995349998a
parent 393158 467b1f003297392089d262eee88fde53cb8aff94
child 393160 24e0dcd018987af240baa09fd8d3112fae9913e3
push id97608
push usergsvelto@mozilla.com
push dateWed, 22 Nov 2017 21:15:43 +0000
treeherdermozilla-inbound@07fcf163241a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersted
bugs1402519
milestone59.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1402519 - When the crash reporter code is disabled at configure time replace it with a dummy implementation; r=ted.mielczarek MozReview-Commit-ID: F5QbaI1LlmZ
browser/base/content/test/general/browser_restore_isAppTab.js
js/xpconnect/src/XPCShellImpl.cpp
memory/gtest/TestJemalloc.cpp
mobile/android/chrome/content/browser.js
mobile/android/components/SessionStore.js
testing/mochitest/BrowserTestUtils/BrowserTestUtils.jsm
toolkit/components/crashes/moz.build
toolkit/components/moz.build
toolkit/crashreporter/jar.mn
toolkit/crashreporter/moz.build
toolkit/crashreporter/nsDummyExceptionHandler.cpp
toolkit/crashreporter/nsExceptionHandler.cpp
toolkit/crashreporter/nsExceptionHandler.h
toolkit/crashreporter/nsExceptionHandlerUtils.cpp
toolkit/crashreporter/nsExceptionHandlerUtils.h
toolkit/moz.build
--- a/browser/base/content/test/general/browser_restore_isAppTab.js
+++ b/browser/base/content/test/general/browser_restore_isAppTab.js
@@ -81,18 +81,19 @@ add_task(async function navigate() {
   loadFrameScript(browser);
   isAppTab = await isBrowserAppTab(browser);
   ok(isAppTab, "Docshell should think it is an app tab");
 
   gBrowser.removeCurrentTab();
 });
 
 add_task(async function crash() {
-  if (!gMultiProcessBrowser || !("nsICrashReporter" in Ci))
+  if (!gMultiProcessBrowser || !AppConstants.MOZ_CRASHREPORTER) {
     return;
+  }
 
   let tab = BrowserTestUtils.addTab(gBrowser, DUMMY);
   let browser = tab.linkedBrowser;
   gBrowser.selectedTab = tab;
   await BrowserTestUtils.browserStopped(gBrowser);
   loadFrameScript(browser);
   let isAppTab = await isBrowserAppTab(browser);
   ok(!isAppTab, "Docshell shouldn't think it is an app tab");
--- a/js/xpconnect/src/XPCShellImpl.cpp
+++ b/js/xpconnect/src/XPCShellImpl.cpp
@@ -1190,17 +1190,17 @@ XRE_XPCShellMain(int argc, char** argv, 
             XRE_AddManifestLocation(NS_APP_LOCATION, lf);
 
             argc -= 2;
             argv += 2;
         }
 
 #ifdef MOZ_CRASHREPORTER
         const char* val = getenv("MOZ_CRASHREPORTER");
-        if (val && *val) {
+        if (val && *val && !CrashReporter::IsDummy()) {
             rv = CrashReporter::SetExceptionHandler(greDir, true);
             if (NS_FAILED(rv)) {
                 printf("CrashReporter::SetExceptionHandler failed!\n");
                 return 1;
             }
             MOZ_ASSERT(CrashReporter::GetEnabled());
         }
 #endif
--- a/memory/gtest/TestJemalloc.cpp
+++ b/memory/gtest/TestJemalloc.cpp
@@ -3,43 +3,39 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/mozalloc.h"
 #include "mozilla/UniquePtr.h"
 #include "mozilla/Vector.h"
 #include "mozmemory.h"
+#include "nsCOMPtr.h"
+#include "nsICrashReporter.h"
+#include "nsServiceManagerUtils.h"
 #include "Utils.h"
 
 #include "gtest/gtest.h"
 
-#ifdef MOZ_CRASHREPORTER
-#include "nsCOMPtr.h"
-#include "nsICrashReporter.h"
-#include "nsServiceManagerUtils.h"
-#endif
 
 #ifdef NIGHTLY_BUILD
 #if defined(DEBUG) && !defined(XP_WIN) && !defined(ANDROID)
 #define HAS_GDB_SLEEP_DURATION 1
 extern unsigned int _gdb_sleep_duration;
 #endif
 
 // Death tests are too slow on OSX because of the system crash reporter.
 #ifndef XP_DARWIN
 static void DisableCrashReporter()
 {
-#ifdef MOZ_CRASHREPORTER
   nsCOMPtr<nsICrashReporter> crashreporter =
     do_GetService("@mozilla.org/toolkit/crash-reporter;1");
   if (crashreporter) {
     crashreporter->SetEnabled(false);
   }
-#endif
 }
 
 // Wrap ASSERT_DEATH_IF_SUPPORTED to disable the crash reporter
 // when entering the subprocess, so that the expected crashes don't
 // create a minidump that the gtest harness will interpret as an error.
 #define ASSERT_DEATH_WRAP(a, b) \
   ASSERT_DEATH_IF_SUPPORTED({ DisableCrashReporter(); a; }, b)
 #else
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -1986,19 +1986,17 @@ var BrowserApp = {
           case "privacy.trackingprotection.state": {
             aSubject.setAsAString(this.getTrackingProtectionState());
             break;
           }
 
           // Crash reporter submit pref must be fetched from nsICrashReporter
           // service.
           case "datareporting.crashreporter.submitEnabled":
-            let crashReporterBuilt = "nsICrashReporter" in Ci &&
-                Services.appinfo instanceof Ci.nsICrashReporter;
-            if (crashReporterBuilt) {
+            if (AppConstants.MOZ_CRASHREPORTER) {
               aSubject.setAsBool(Services.appinfo.submitReports);
             }
             break;
         }
         break;
       }
 
       case "android-set-pref": {
@@ -2041,19 +2039,17 @@ var BrowserApp = {
                 break;
             }
             aSubject.setAsEmpty();
             break;
           }
 
           // Crash reporter preference is in a service; set and return.
           case "datareporting.crashreporter.submitEnabled":
-            let crashReporterBuilt = "nsICrashReporter" in Ci &&
-                Services.appinfo instanceof Ci.nsICrashReporter;
-            if (crashReporterBuilt) {
+            if (AppConstants.MOZ_CRASHREPORTER) {
               Services.appinfo.submitReports = value;
               aSubject.setAsEmpty();
             }
             break;
         }
         break;
       }
 
--- a/mobile/android/components/SessionStore.js
+++ b/mobile/android/components/SessionStore.js
@@ -1234,18 +1234,17 @@ SessionStore.prototype = {
     aFileTemp.renameTo(null, aFile.leafName);
     log("_write() writing synchronously");
 
     // Return a resolved promise to make the caller happy
     return Promise.resolve();
   },
 
   _updateCrashReportURL: function ss_updateCrashReportURL(aWindow) {
-    let crashReporterBuilt = "nsICrashReporter" in Ci && Services.appinfo instanceof Ci.nsICrashReporter;
-    if (!crashReporterBuilt) {
+    if (!AppConstants.MOZ_CRASHREPORTER) {
       return;
     }
 
     if (!aWindow.BrowserApp.selectedBrowser) {
       return;
     }
 
     try {
--- a/testing/mochitest/BrowserTestUtils/BrowserTestUtils.jsm
+++ b/testing/mochitest/BrowserTestUtils/BrowserTestUtils.jsm
@@ -1083,17 +1083,17 @@ this.BrowserTestUtils = {
         // we might see this called as the process terminates due to previous tests.
         // We are only looking for "abnormal" exits...
         if (!subject.hasKey("abnormal")) {
           dump("\nThis is a normal termination and isn't the one we are looking for...\n");
           return;
         }
 
         let dumpID;
-        if ('nsICrashReporter' in Ci) {
+        if (AppConstants.MOZ_CRASHREPORTER) {
           dumpID = subject.getPropertyAsAString('dumpID');
           if (!dumpID) {
             return reject("dumpID was not present despite crash reporting " +
                           "being enabled");
           }
         }
 
         let removalPromise = Promise.resolve();
--- a/toolkit/components/crashes/moz.build
+++ b/toolkit/components/crashes/moz.build
@@ -1,31 +1,33 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 SPHINX_TREES['crash-manager'] = 'docs'
 
-EXTRA_COMPONENTS += [
-    'CrashService.js',
-    'CrashService.manifest',
-]
-
-EXTRA_JS_MODULES += [
-    'CrashManager.jsm',
-]
-
-TESTING_JS_MODULES += [
-    'CrashManagerTest.jsm',
-]
-
-XPCSHELL_TESTS_MANIFESTS += ['tests/xpcshell/xpcshell.ini']
-
 XPIDL_MODULE = 'toolkit_crashservice'
 
 XPIDL_SOURCES += [
     'nsICrashService.idl',
 ]
 
+if CONFIG['MOZ_CRASHREPORTER']:
+    EXTRA_COMPONENTS += [
+        'CrashService.js',
+        'CrashService.manifest',
+    ]
+
+    EXTRA_JS_MODULES += [
+        'CrashManager.jsm',
+    ]
+
+    TESTING_JS_MODULES += [
+        'CrashManagerTest.jsm',
+    ]
+
+    XPCSHELL_TESTS_MANIFESTS += ['tests/xpcshell/xpcshell.ini']
+
 with Files('**'):
     BUG_COMPONENT = ('Toolkit', 'Crash Reporting')
+
--- a/toolkit/components/moz.build
+++ b/toolkit/components/moz.build
@@ -21,16 +21,17 @@ DIRS += [
     'apppicker',
     'asyncshutdown',
     'backgroundhangmonitor',
     'browser',
     'cloudstorage',
     'commandlines',
     'contentprefs',
     'contextualidentity',
+    'crashes',
     'crashmonitor',
     'diskspacewatcher',
     'downloads',
     'extensions',
     'filewatcher',
     'finalizationwitness',
     'find',
     'jsdownloads',
@@ -75,19 +76,16 @@ DIRS += [
 ]
 
 if CONFIG['MOZ_BUILD_APP'] != 'mobile/android':
     DIRS += ['narrate', 'viewsource'];
 
     if CONFIG['NS_PRINTING']:
         DIRS += ['printing']
 
-if CONFIG['MOZ_CRASHREPORTER']:
-    DIRS += ['crashes']
-
 if CONFIG['BUILD_CTYPES']:
     DIRS += ['ctypes']
 
 if CONFIG['MOZ_FEEDS']:
     DIRS += ['feeds']
 
 if CONFIG['MOZ_XUL']:
     DIRS += ['autocomplete', 'printingui', 'satchel']
--- a/toolkit/crashreporter/jar.mn
+++ b/toolkit/crashreporter/jar.mn
@@ -1,7 +1,9 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 toolkit.jar:
+#ifdef MOZ_CRASHREPORTER
   content/global/crashes.xhtml            (content/crashes.xhtml)
   content/global/crashes.js               (content/crashes.js)
+#endif
--- a/toolkit/crashreporter/moz.build
+++ b/toolkit/crashreporter/moz.build
@@ -1,115 +1,125 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 SPHINX_TREES['crashreporter'] = 'docs'
 
-if CONFIG['OS_ARCH'] == 'WINNT':
-    DIRS += [
-        'google-breakpad/src/common',
-        'google-breakpad/src/processor',
-        'breakpad-windows-libxul',
-    ]
-
-    if CONFIG['MSVC_HAS_DIA_SDK']:
-        DIRS += ['google-breakpad/src/tools/windows/dump_syms']
-
-    if CONFIG['MOZ_CRASHREPORTER_INJECTOR']:
-        DIRS += ['breakpad-windows-standalone']
-
-elif CONFIG['OS_ARCH'] == 'Darwin':
-    DIRS += [
-        'breakpad-client',
-        'breakpad-client/mac/crash_generation',
-        'breakpad-client/mac/handler',
-        'google-breakpad/src/common',
-        'google-breakpad/src/common/mac',
-        'google-breakpad/src/processor',
-        'google-breakpad/src/tools/mac/dump_syms',
-    ]
-
-elif CONFIG['OS_ARCH'] == 'Linux':
-    DIRS += [
-        'breakpad-client',
-        'breakpad-client/linux/',
-        'google-breakpad/src/common',
-        'google-breakpad/src/common/linux',
-        'google-breakpad/src/processor',
-        'google-breakpad/src/tools/linux/dump_syms',
-    ]
-
-
-DIRS += [
-    'client',
-    'minidump-analyzer',
-]
-
-if CONFIG['MOZ_CRASHREPORTER_INJECTOR']:
-    DIRS += ['injector']
-    UNIFIED_SOURCES += [
-        'InjectCrashReporter.cpp',
-        'LoadLibraryRemote.cpp',
-    ]
-
-if CONFIG['ENABLE_TESTS']:
-    DIRS += ['test/gtest']
-
-TEST_DIRS += ['test']
-
 EXPORTS += [
     'nsExceptionHandler.h',
 ]
 
-UNIFIED_SOURCES += [
-    'nsExceptionHandler.cpp',
-    'ThreadAnnotation.cpp',
-]
+JAR_MANIFESTS += ['jar.mn']
 
-if CONFIG['OS_ARCH'] == 'Darwin':
-    UNIFIED_SOURCES += [
-        'mac_utils.mm',
-    ]
-
-EXTRA_JS_MODULES += [
-    'CrashReports.jsm',
-    'CrashSubmit.jsm',
-    'KeyValueParser.jsm',
+UNIFIED_SOURCES = [
+    'nsExceptionHandlerUtils.cpp',
 ]
 
-include('/ipc/chromium/chromium-config.mozbuild')
-
 FINAL_LIBRARY = 'xul'
 
-if CONFIG['OS_TARGET'] == 'Android':
-    DEFINES['ANDROID_NDK_MAJOR_VERSION'] = CONFIG['ANDROID_NDK_MAJOR_VERSION']
-    DEFINES['ANDROID_NDK_MINOR_VERSION'] = CONFIG['ANDROID_NDK_MINOR_VERSION']
-    DEFINES['ANDROID_PACKAGE_NAME'] = '"%s"' % CONFIG['ANDROID_PACKAGE_NAME']
-    # NDK5 workarounds
-    DEFINES['_STLP_CONST_CONSTRUCTOR_BUG'] = True
-    DEFINES['_STLP_NO_MEMBER_TEMPLATES'] = True
-    LOCAL_INCLUDES += [
-        '/toolkit/crashreporter/google-breakpad/src/common/android/include',
+if CONFIG['MOZ_CRASHREPORTER']:
+    if CONFIG['OS_ARCH'] == 'WINNT':
+        DIRS += [
+            'google-breakpad/src/common',
+            'google-breakpad/src/processor',
+            'breakpad-windows-libxul',
+        ]
+
+        if CONFIG['MSVC_HAS_DIA_SDK']:
+            DIRS += ['google-breakpad/src/tools/windows/dump_syms']
+
+        if CONFIG['MOZ_CRASHREPORTER_INJECTOR']:
+            DIRS += ['breakpad-windows-standalone']
+
+    elif CONFIG['OS_ARCH'] == 'Darwin':
+        DIRS += [
+            'breakpad-client',
+            'breakpad-client/mac/crash_generation',
+            'breakpad-client/mac/handler',
+            'google-breakpad/src/common',
+            'google-breakpad/src/common/mac',
+            'google-breakpad/src/processor',
+            'google-breakpad/src/tools/mac/dump_syms',
+        ]
+
+    elif CONFIG['OS_ARCH'] == 'Linux':
+        DIRS += [
+            'breakpad-client',
+            'breakpad-client/linux/',
+            'google-breakpad/src/common',
+            'google-breakpad/src/common/linux',
+            'google-breakpad/src/processor',
+            'google-breakpad/src/tools/linux/dump_syms',
+        ]
+
+
+    DIRS += [
+        'client',
+        'minidump-analyzer',
     ]
 
-DEFINES['UNICODE'] = True
-DEFINES['_UNICODE'] = True
+    if CONFIG['MOZ_CRASHREPORTER_INJECTOR']:
+        DIRS += ['injector']
+        UNIFIED_SOURCES += [
+            'InjectCrashReporter.cpp',
+            'LoadLibraryRemote.cpp',
+        ]
+
+    if CONFIG['ENABLE_TESTS']:
+        DIRS += ['test/gtest']
+
+    TEST_DIRS += ['test']
 
-JAR_MANIFESTS += ['jar.mn']
+    UNIFIED_SOURCES += [
+        'nsExceptionHandler.cpp',
+        'ThreadAnnotation.cpp',
+    ]
+
+    if CONFIG['OS_ARCH'] == 'Darwin':
+        UNIFIED_SOURCES += [
+            'mac_utils.mm',
+        ]
+
+    EXTRA_JS_MODULES += [
+        'CrashReports.jsm',
+        'CrashSubmit.jsm',
+        'KeyValueParser.jsm',
+    ]
+
+    include('/ipc/chromium/chromium-config.mozbuild')
 
-LOCAL_INCLUDES += [
-    'google-breakpad/src',
-]
+    if CONFIG['OS_TARGET'] == 'Android':
+        DEFINES['ANDROID_NDK_MAJOR_VERSION'] = CONFIG['ANDROID_NDK_MAJOR_VERSION']
+        DEFINES['ANDROID_NDK_MINOR_VERSION'] = CONFIG['ANDROID_NDK_MINOR_VERSION']
+        DEFINES['ANDROID_PACKAGE_NAME'] = '"%s"' % CONFIG['ANDROID_PACKAGE_NAME']
+        # NDK5 workarounds
+        DEFINES['_STLP_CONST_CONSTRUCTOR_BUG'] = True
+        DEFINES['_STLP_NO_MEMBER_TEMPLATES'] = True
+        LOCAL_INCLUDES += [
+            '/toolkit/crashreporter/google-breakpad/src/common/android/include',
+        ]
+
+    DEFINES['UNICODE'] = True
+    DEFINES['_UNICODE'] = True
 
-PYTHON_UNITTEST_MANIFESTS += [
-    'tools/python.ini',
-]
+    LOCAL_INCLUDES += [
+        'google-breakpad/src',
+    ]
+
+    PYTHON_UNITTEST_MANIFESTS += [
+        'tools/python.ini',
+    ]
 
-include('/toolkit/crashreporter/crashreporter.mozbuild')
+    include('/toolkit/crashreporter/crashreporter.mozbuild')
+
+    if CONFIG['GNU_CXX']:
+        CXXFLAGS += ['-Wno-shadow']
+else:
+    UNIFIED_SOURCES += [
+        'nsDummyExceptionHandler.cpp',
+    ]
+
 
 with Files('**'):
     BUG_COMPONENT = ('Toolkit', 'Crash Reporting')
-
-if CONFIG['GNU_CXX']:
-    CXXFLAGS += ['-Wno-shadow']
new file mode 100644
--- /dev/null
+++ b/toolkit/crashreporter/nsDummyExceptionHandler.cpp
@@ -0,0 +1,425 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsExceptionHandler.h"
+#include "nsExceptionHandlerUtils.h"
+
+namespace CrashReporter {
+
+void
+AnnotateOOMAllocationSize(size_t size)
+{
+}
+
+void
+AnnotateTexturesSize(size_t size)
+{
+}
+
+void
+AnnotatePendingIPC(size_t aNumOfPendingIPC,
+                   uint32_t aTopPendingIPCCount,
+                   const char* aTopPendingIPCName,
+                   uint32_t aTopPendingIPCType)
+{
+}
+
+nsresult
+SetExceptionHandler(nsIFile* aXREDirectory,
+                    bool force/*=false*/)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+bool
+GetEnabled()
+{
+  return false;
+}
+
+bool
+GetMinidumpPath(nsAString& aPath)
+{
+  return false;
+}
+
+nsresult
+SetMinidumpPath(const nsAString& aPath)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+nsresult
+SetupExtraData(nsIFile* aAppDataDirectory,
+               const nsACString& aBuildID)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+nsresult
+UnsetExceptionHandler()
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+nsresult
+AnnotateCrashReport(const nsACString& key,
+                    const nsACString& data)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+nsresult
+RemoveCrashReportAnnotation(const nsACString& key)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+nsresult
+SetGarbageCollecting(bool collecting)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+void
+SetEventloopNestingLevel(uint32_t level)
+{
+}
+
+void
+SetMinidumpAnalysisAllThreads()
+{
+}
+
+nsresult
+AppendAppNotesToCrashReport(const nsACString& data)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+bool
+GetAnnotation(const nsACString& key, nsACString& data)
+{
+  return false;
+}
+
+nsresult
+RegisterAppMemory(void* ptr, size_t length)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+nsresult
+UnregisterAppMemory(void* ptr)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+void
+SetIncludeContextHeap(bool aValue)
+{
+}
+
+bool
+GetServerURL(nsACString& aServerURL)
+{
+  return false;
+}
+
+nsresult
+SetServerURL(const nsACString& aServerURL)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+nsresult
+SetRestartArgs(int argc, char** argv)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+#ifdef XP_WIN32
+nsresult
+WriteMinidumpForException(EXCEPTION_POINTERS* aExceptionInfo)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+#endif
+
+#ifdef XP_LINUX
+bool
+WriteMinidumpForSigInfo(int signo,
+                        siginfo_t* info,
+                        void* uc)
+{
+  return false;
+}
+#endif
+
+#ifdef XP_MACOSX
+nsresult
+AppendObjCExceptionInfoToAppNotes(void *inException)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+#endif
+
+nsresult
+GetSubmitReports(bool* aSubmitReports)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+nsresult
+SetSubmitReports(bool aSubmitReports)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+void
+SetProfileDirectory(nsIFile* aDir)
+{
+}
+
+void
+SetUserAppDataDirectory(nsIFile* aDir)
+{
+}
+
+void
+UpdateCrashEventsDir()
+{
+}
+
+bool
+GetCrashEventsDir(nsAString& aPath)
+{
+  return false;
+}
+
+void
+SetMemoryReportFile(nsIFile* aFile)
+{
+}
+
+nsresult
+GetDefaultMemoryReportFile(nsIFile** aFile)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+void
+SetTelemetrySessionId(const nsACString& id)
+{
+}
+
+void
+DeleteMinidumpFilesForID(const nsAString& id)
+{
+}
+
+bool
+GetMinidumpForID(const nsAString& id, nsIFile** minidump)
+{
+  return false;
+}
+
+bool
+GetIDFromMinidump(nsIFile* minidump, nsAString& id)
+{
+  return false;
+}
+
+bool
+GetExtraFileForID(const nsAString& id,
+                  nsIFile** extraFile)
+{
+  return false;
+}
+
+bool
+GetExtraFileForMinidump(nsIFile* minidump,
+                        nsIFile** extraFile)
+{
+  return false;
+}
+
+bool
+AppendExtraData(const nsAString& id,
+                const AnnotationTable& data)
+{
+  return false;
+}
+
+bool
+AppendExtraData(nsIFile* extraFile,
+                const AnnotationTable& data)
+{
+  return false;
+}
+
+void
+OOPInit()
+{
+}
+
+void
+GetChildProcessTmpDir(nsIFile** aOutTmpDir)
+{
+}
+
+#if defined(XP_WIN) || defined(XP_MACOSX)
+const char*
+GetChildNotificationPipe()
+{
+  return nullptr;
+}
+#endif
+
+#ifdef MOZ_CRASHREPORTER_INJECTOR
+void
+InjectCrashReporterIntoProcess(DWORD processID, InjectorCrashCallback* cb)
+{
+}
+
+void
+UnregisterInjectorCallback(DWORD processID)
+{
+}
+
+#endif // MOZ_CRASHREPORTER_INJECTOR
+
+bool
+GetLastRunCrashID(nsAString& id)
+{
+  return false;
+}
+
+#if defined(XP_WIN) || defined(XP_MACOSX)
+void
+InitChildProcessTmpDir(nsIFile* aDirOverride)
+{
+}
+#endif // defined(XP_WIN) || defined(XP_MACOSX)
+
+#if defined(XP_WIN)
+bool
+SetRemoteExceptionHandler(const nsACString& crashPipe)
+{
+  return false;
+}
+
+#elif defined(XP_LINUX)
+
+bool
+CreateNotificationPipeForChild(int* childCrashFd, int* childCrashRemapFd)
+{
+  return false;
+}
+
+bool
+SetRemoteExceptionHandler()
+{
+  return false;
+}
+
+#elif defined(XP_MACOSX)
+
+bool
+SetRemoteExceptionHandler(const nsACString& crashPipe)
+{
+  return false;
+}
+#endif  // XP_WIN
+
+bool
+TakeMinidumpForChild(uint32_t childPid, nsIFile** dump, uint32_t* aSequence)
+{
+  return false;
+}
+
+void
+RenameAdditionalHangMinidump(nsIFile* minidump, nsIFile* childMinidump,
+                             const nsACString& name)
+{
+}
+
+ThreadId
+CurrentThreadId()
+{
+  return -1;
+}
+
+bool
+TakeMinidump(nsIFile** aResult, bool aMoveToPending)
+{
+  return false;
+}
+
+void
+CreateMinidumpsAndPair(ProcessHandle aTargetPid,
+                       ThreadId aTargetBlamedThread,
+                       const nsACString& aIncomingPairName,
+                       nsIFile* aIncomingDumpToPair,
+                       nsIFile** aMainDumpOut,
+                       std::function<void(bool)>&& aCallback,
+                       bool aAsync)
+{
+}
+
+bool
+CreateAdditionalChildMinidump(ProcessHandle childPid,
+                              ThreadId childBlamedThread,
+                              nsIFile* parentMinidump,
+                              const nsACString& name)
+{
+  return false;
+}
+
+bool
+UnsetRemoteExceptionHandler()
+{
+  return false;
+}
+
+#if defined(MOZ_WIDGET_ANDROID)
+void
+SetNotificationPipeForChild(int childCrashFd)
+{
+}
+
+void
+AddLibraryMapping(const char* library_name,
+                  uintptr_t   start_address,
+                  size_t      mapping_length,
+                  size_t      file_offset)
+{
+}
+#endif
+
+// From ThreadAnnotation.cpp
+
+void
+InitThreadAnnotation()
+{
+}
+
+void
+SetCurrentThreadName(const char* aName)
+{
+}
+
+void
+GetFlatThreadAnnotation(const std::function<void(const char*)>& aCallback)
+{
+}
+
+void
+ShutdownThreadAnnotation()
+{
+}
+
+} // namespace CrashReporter
--- a/toolkit/crashreporter/nsExceptionHandler.cpp
+++ b/toolkit/crashreporter/nsExceptionHandler.cpp
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsExceptionHandler.h"
+#include "nsExceptionHandlerUtils.h"
 
 #include "nsAppDirectoryServiceDefs.h"
 #include "nsDirectoryServiceDefs.h"
 #include "nsDirectoryService.h"
 #include "nsDataHashtable.h"
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/Services.h"
 #include "nsIObserverService.h"
@@ -82,17 +83,16 @@ using mozilla::InjectCrashRunnable;
 #include <prio.h>
 #include "mozilla/Mutex.h"
 #include "nsDebug.h"
 #include "nsCRT.h"
 #include "nsIFile.h"
 #include <map>
 #include <vector>
 
-#include "mozilla/double-conversion.h"
 #include "mozilla/IOInterposer.h"
 #include "mozilla/mozalloc_oom.h"
 #include "mozilla/WindowsDllBlocklist.h"
 
 #if defined(XP_MACOSX)
 CFStringRef reporterClientAppID = CFSTR("org.mozilla.crashreporter");
 #endif
 #if defined(MOZ_WIDGET_ANDROID)
@@ -408,64 +408,16 @@ typedef struct {
   size_t      length;
   size_t      file_offset;
 } mapping_info;
 static std::vector<mapping_info> library_mappings;
 typedef std::map<uint32_t,google_breakpad::MappingList> MappingMap;
 #endif
 }
 
-// Format a non-negative double to a string, without using C-library functions,
-// which need to be avoided (.e.g. bug 1240160, comment 10).  Leave the utility
-// non-file static so that we can gtest it.  Return false if we failed to
-// get the formatting done correctly.
-bool SimpleNoCLibDtoA(double aValue, char* aBuffer, int aBufferLength)
-{
-  // aBufferLength is the size of the buffer.  Be paranoid.
-  aBuffer[aBufferLength-1] = '\0';
-
-  if (aValue < 0) {
-    return false;
-  }
-
-  int length, point, i;
-  bool sign;
-  bool ok = true;
-  double_conversion::DoubleToStringConverter::DoubleToAscii(
-                                     aValue,
-                                     double_conversion::DoubleToStringConverter::SHORTEST,
-                                     8,
-                                     aBuffer,
-                                     aBufferLength,
-                                     &sign,
-                                     &length,
-                                     &point);
-
-  // length does not account for the 0 terminator.
-  if (length > point && (length+1) < (aBufferLength-1)) {
-    // We have to insert a decimal point.  Not worried about adding a leading zero
-    // in the < 1 (point == 0) case.
-    aBuffer[length+1] = '\0';
-    for (i=length; i>point; i-=1) {
-      aBuffer[i] = aBuffer[i-1];
-    }
-    aBuffer[i] = '.'; // Not worried about locales
-  } else if (length < point) {
-    // Trailing zeros scenario
-    for (i=length; i<point; i+=1) {
-      if (i >= aBufferLength-2) {
-        ok = false;
-      }
-      aBuffer[i] = '0';
-    }
-    aBuffer[i] = '\0';
-  }
-  return ok;
-}
-
 namespace CrashReporter {
 
 #ifdef XP_LINUX
 static inline void
 my_inttostring(intmax_t t, char* buffer, size_t buffer_length)
 {
   my_memset(buffer, 0, buffer_length);
   my_uitos(buffer, t, my_uint_len(t));
--- a/toolkit/crashreporter/nsExceptionHandler.h
+++ b/toolkit/crashreporter/nsExceptionHandler.h
@@ -1,13 +1,19 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+// This header has two implementations, the real one in nsExceptionHandler.cpp
+// and a dummy in nsDummyExceptionHandler.cpp. The latter is used in builds
+// configured with --disable-crashreporter. If you add or remove a function
+// from this header you must update both implementations otherwise you'll break
+// builds that disable the crash reporter.
+
 #ifndef nsExceptionHandler_h__
 #define nsExceptionHandler_h__
 
 #include "mozilla/Assertions.h"
 
 #include <functional>
 #include <stddef.h>
 #include <stdint.h>
@@ -29,16 +35,29 @@
 #include <signal.h>
 #endif
 
 class nsIFile;
 template<class KeyClass, class DataType> class nsDataHashtable;
 class nsCStringHashKey;
 
 namespace CrashReporter {
+
+/**
+ * Returns true if the crash reporter is using the dummy implementation.
+ */
+static inline bool
+IsDummy() {
+#ifdef MOZ_CRASHREPORTER
+  return false;
+#else
+  return true;
+#endif
+}
+
 nsresult SetExceptionHandler(nsIFile* aXREDirectory, bool force=false);
 nsresult UnsetExceptionHandler();
 
 /**
  * Tell the crash reporter to recalculate where crash events files should go.
  * SetCrashEventsDir is used before XPCOM is initialized from the startup
  * code.
  *
new file mode 100644
--- /dev/null
+++ b/toolkit/crashreporter/nsExceptionHandlerUtils.cpp
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsExceptionHandlerUtils.h"
+
+#include "mozilla/double-conversion.h"
+
+// Format a non-negative double to a string, without using C-library functions,
+// which need to be avoided (.e.g. bug 1240160, comment 10).  Return false if
+// we failed to get the formatting done correctly.
+bool SimpleNoCLibDtoA(double aValue, char* aBuffer, int aBufferLength)
+{
+  // aBufferLength is the size of the buffer.  Be paranoid.
+  aBuffer[aBufferLength-1] = '\0';
+
+  if (aValue < 0) {
+    return false;
+  }
+
+  int length, point, i;
+  bool sign;
+  bool ok = true;
+  double_conversion::DoubleToStringConverter::DoubleToAscii(
+                                     aValue,
+                                     double_conversion::DoubleToStringConverter::SHORTEST,
+                                     8,
+                                     aBuffer,
+                                     aBufferLength,
+                                     &sign,
+                                     &length,
+                                     &point);
+
+  // length does not account for the 0 terminator.
+  if (length > point && (length+1) < (aBufferLength-1)) {
+    // We have to insert a decimal point.  Not worried about adding a leading zero
+    // in the < 1 (point == 0) case.
+    aBuffer[length+1] = '\0';
+    for (i=length; i>point; i-=1) {
+      aBuffer[i] = aBuffer[i-1];
+    }
+    aBuffer[i] = '.'; // Not worried about locales
+  } else if (length < point) {
+    // Trailing zeros scenario
+    for (i=length; i<point; i+=1) {
+      if (i >= aBufferLength-2) {
+        ok = false;
+      }
+      aBuffer[i] = '0';
+    }
+    aBuffer[i] = '\0';
+  }
+  return ok;
+}
new file mode 100644
--- /dev/null
+++ b/toolkit/crashreporter/nsExceptionHandlerUtils.h
@@ -0,0 +1,12 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nsExceptionHandlerUtils_h__
+#define nsExceptionHandlerUtils_h__
+
+bool SimpleNoCLibDtoA(double aValue, char* aBuffer, int aBufferLength);
+
+#endif // nsExceptionHandlerUtils_h__
--- a/toolkit/moz.build
+++ b/toolkit/moz.build
@@ -2,16 +2,17 @@
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 DIRS += [
     'components',
     'content',
+    'crashreporter',
     'forgetaboutsite',
     'locales',
     'modules',
     'mozapps/downloads',
     'mozapps/extensions',
     'mozapps/handling',
     'mozapps/preferences',
     'pluginproblem',
@@ -41,19 +42,16 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('gtk
     DIRS += ['system/unixproxy']
 elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
     DIRS += ['system/osxproxy']
 elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
     DIRS += ['system/windowsproxy']
 elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
     DIRS += ['system/androidproxy']
 
-if CONFIG['MOZ_CRASHREPORTER']:
-    DIRS += ['crashreporter']
-
 TEST_HARNESS_FILES.testing.mochitest.browser.toolkit.crashreporter.test.browser += [
     'crashreporter/test/browser/crashreport.sjs',
 ]
 
 with Files('moz.*'):
     BUG_COMPONENT = ('Core', 'Build Config')
 
 with Files('toolkit.mozbuild'):