summaryrefslogtreecommitdiffstats
path: root/toolkit/crashreporter/nsExceptionHandler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/crashreporter/nsExceptionHandler.cpp')
-rw-r--r--toolkit/crashreporter/nsExceptionHandler.cpp207
1 files changed, 42 insertions, 165 deletions
diff --git a/toolkit/crashreporter/nsExceptionHandler.cpp b/toolkit/crashreporter/nsExceptionHandler.cpp
index aca266749a..868005a5c7 100644
--- a/toolkit/crashreporter/nsExceptionHandler.cpp
+++ b/toolkit/crashreporter/nsExceptionHandler.cpp
@@ -7,6 +7,7 @@
#include "nsExceptionHandler.h"
#include "nsExceptionHandlerUtils.h"
+#include "json/json.h"
#include "nsAppDirectoryServiceDefs.h"
#include "nsComponentManagerUtils.h"
#include "nsDirectoryServiceDefs.h"
@@ -95,6 +96,9 @@
using mozilla::InjectCrashRunnable;
#endif
+#include <fstream>
+#include <optional>
+
#include <stdlib.h>
#include <time.h>
#include <prenv.h>
@@ -195,7 +199,7 @@ static const XP_CHAR dumpFileExtension[] = XP_TEXT(".dmp");
static const XP_CHAR extraFileExtension[] = XP_TEXT(".extra");
static const XP_CHAR memoryReportExtension[] = XP_TEXT(".memory.json.gz");
-static xpstring* defaultMemoryReportPath = nullptr;
+static std::optional<xpstring> defaultMemoryReportPath = {};
static const char kCrashMainID[] = "crash.main.3\n";
@@ -433,26 +437,26 @@ static void CreateFileFromPath(const xpstring& path, nsIFile** file) {
NS_NewLocalFile(nsDependentString(path.c_str()), false, file);
}
-static xpstring* CreatePathFromFile(nsIFile* file) {
+static std::optional<xpstring> CreatePathFromFile(nsIFile* file) {
nsAutoString path;
nsresult rv = file->GetPath(path);
if (NS_FAILED(rv)) {
- return nullptr;
+ return {};
}
- return new xpstring(static_cast<wchar_t*>(path.get()), path.Length());
+ return xpstring(static_cast<wchar_t*>(path.get()), path.Length());
}
#else
static void CreateFileFromPath(const xpstring& path, nsIFile** file) {
NS_NewNativeLocalFile(nsDependentCString(path.c_str()), false, file);
}
-MAYBE_UNUSED static xpstring* CreatePathFromFile(nsIFile* file) {
+MAYBE_UNUSED static std::optional<xpstring> CreatePathFromFile(nsIFile* file) {
nsAutoCString path;
nsresult rv = file->GetNativePath(path);
if (NS_FAILED(rv)) {
- return nullptr;
+ return {};
}
- return new xpstring(path.get(), path.Length());
+ return xpstring(path.get(), path.Length());
}
#endif
@@ -2252,7 +2256,7 @@ static nsresult SetupCrashReporterDirectory(nsIFile* aAppDataDirectory,
NS_ENSURE_SUCCESS(rv, rv);
EnsureDirectoryExists(directory);
- xpstring* directoryPath = CreatePathFromFile(directory);
+ std::optional<xpstring> directoryPath = CreatePathFromFile(directory);
if (!directoryPath) {
return NS_ERROR_FAILURE;
@@ -2264,8 +2268,6 @@ static nsresult SetupCrashReporterDirectory(nsIFile* aAppDataDirectory,
setenv(aEnvVarName, directoryPath->c_str(), /* overwrite */ 1);
#endif
- delete directoryPath;
-
if (aDirectory) {
directory.forget(aDirectory);
}
@@ -2760,177 +2762,54 @@ nsresult AppendObjCExceptionInfoToAppNotes(void* inException) {
*/
static nsresult PrefSubmitReports(bool* aSubmitReports, bool writePref) {
nsresult rv;
-#if defined(XP_WIN)
+#if defined(XP_WIN) || defined(XP_MACOSX) || defined(XP_UNIX)
/*
- * NOTE! This needs to stay in sync with the preference checking code
- * in toolkit/crashreporter/client/crashreporter_win.cpp
+ * NOTE! This needs to stay in sync with the code in
+ * toolkit/crashreporter/client/app/src/{logic,settings}.rs
*/
- nsCOMPtr<nsIXULAppInfo> appinfo =
- do_GetService("@mozilla.org/xre/app-info;1", &rv);
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsAutoCString appVendor, appName;
- rv = appinfo->GetVendor(appVendor);
- NS_ENSURE_SUCCESS(rv, rv);
- rv = appinfo->GetName(appName);
+ nsCOMPtr<nsIFile> reporterSettings;
+ rv = NS_GetSpecialDirectory("UAppData", getter_AddRefs(reporterSettings));
NS_ENSURE_SUCCESS(rv, rv);
+ reporterSettings->AppendNative("Crash Reports"_ns);
+ reporterSettings->AppendNative("crashreporter_settings.json"_ns);
- nsCOMPtr<nsIWindowsRegKey> regKey(
- do_CreateInstance("@mozilla.org/windows-registry-key;1", &rv));
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsAutoCString regPath;
-
- regPath.AppendLiteral("Software\\");
-
- // We need to ensure the registry keys are created so we can properly
- // write values to it
-
- // Create appVendor key
- if (!appVendor.IsEmpty()) {
- regPath.Append(appVendor);
- regKey->Create(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER,
- NS_ConvertUTF8toUTF16(regPath),
- nsIWindowsRegKey::ACCESS_SET_VALUE);
- regPath.Append('\\');
- }
-
- // Create appName key
- regPath.Append(appName);
- regKey->Create(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER,
- NS_ConvertUTF8toUTF16(regPath),
- nsIWindowsRegKey::ACCESS_SET_VALUE);
- regPath.Append('\\');
-
- // Create Crash Reporter key
- regPath.AppendLiteral("Crash Reporter");
- regKey->Create(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER,
- NS_ConvertUTF8toUTF16(regPath),
- nsIWindowsRegKey::ACCESS_SET_VALUE);
-
- // If we're saving the pref value, just write it to ROOT_KEY_CURRENT_USER
- // and we're done.
- if (writePref) {
- rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER,
- NS_ConvertUTF8toUTF16(regPath),
- nsIWindowsRegKey::ACCESS_SET_VALUE);
- NS_ENSURE_SUCCESS(rv, rv);
-
- uint32_t value = *aSubmitReports ? 1 : 0;
- rv = regKey->WriteIntValue(u"SubmitCrashReport"_ns, value);
- regKey->Close();
- return rv;
- }
-
- // We're reading the pref value, so we need to first look under
- // ROOT_KEY_LOCAL_MACHINE to see if it's set there, and then fall back to
- // ROOT_KEY_CURRENT_USER. If it's not set in either place, the pref defaults
- // to "true".
- uint32_t value;
- rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_LOCAL_MACHINE,
- NS_ConvertUTF8toUTF16(regPath),
- nsIWindowsRegKey::ACCESS_QUERY_VALUE);
- if (NS_SUCCEEDED(rv)) {
- rv = regKey->ReadIntValue(u"SubmitCrashReport"_ns, &value);
- regKey->Close();
- if (NS_SUCCEEDED(rv)) {
- *aSubmitReports = !!value;
- return NS_OK;
- }
- }
-
- rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER,
- NS_ConvertUTF8toUTF16(regPath),
- nsIWindowsRegKey::ACCESS_QUERY_VALUE);
- if (NS_FAILED(rv)) {
- *aSubmitReports = true;
- return NS_OK;
- }
+ std::optional<xpstring> file_path = CreatePathFromFile(reporterSettings);
- rv = regKey->ReadIntValue(u"SubmitCrashReport"_ns, &value);
- // default to true on failure
- if (NS_FAILED(rv)) {
- value = 1;
- rv = NS_OK;
+ if (!file_path) {
+ return NS_ERROR_FAILURE;
}
- regKey->Close();
- *aSubmitReports = !!value;
- return NS_OK;
-#elif defined(XP_MACOSX)
- rv = NS_OK;
- if (writePref) {
- CFPropertyListRef cfValue =
- (CFPropertyListRef)(*aSubmitReports ? kCFBooleanTrue : kCFBooleanFalse);
- ::CFPreferencesSetAppValue(CFSTR("submitReport"), cfValue,
- reporterClientAppID);
- if (!::CFPreferencesAppSynchronize(reporterClientAppID))
- rv = NS_ERROR_FAILURE;
- } else {
- *aSubmitReports = true;
- Boolean keyExistsAndHasValidFormat = false;
- Boolean prefValue = ::CFPreferencesGetAppBooleanValue(
- CFSTR("submitReport"), reporterClientAppID,
- &keyExistsAndHasValidFormat);
- if (keyExistsAndHasValidFormat) *aSubmitReports = !!prefValue;
- }
- return rv;
-#elif defined(XP_UNIX)
- /*
- * NOTE! This needs to stay in sync with the preference checking code
- * in toolkit/crashreporter/client/crashreporter_linux.cpp
- */
- nsCOMPtr<nsIFile> reporterINI;
- rv = NS_GetSpecialDirectory("UAppData", getter_AddRefs(reporterINI));
- NS_ENSURE_SUCCESS(rv, rv);
- reporterINI->AppendNative("Crash Reports"_ns);
- reporterINI->AppendNative("crashreporter.ini"_ns);
+ Json::Value root;
bool exists;
- rv = reporterINI->Exists(&exists);
+ rv = reporterSettings->Exists(&exists);
NS_ENSURE_SUCCESS(rv, rv);
if (!exists) {
if (!writePref) {
- // If reading the pref, default to true if .ini doesn't exist.
+ // If reading the pref, default to true if the settings file doesn't
+ // exist.
*aSubmitReports = true;
return NS_OK;
}
- // Create the file so the INI processor can write to it.
- rv = reporterINI->Create(nsIFile::NORMAL_FILE_TYPE, 0600);
+ // Create the file so the JSON processor can write to it.
+ rv = reporterSettings->Create(nsIFile::NORMAL_FILE_TYPE, 0600);
NS_ENSURE_SUCCESS(rv, rv);
+ } else {
+ // Read the root value
+ std::ifstream file(*file_path);
+ file >> root;
}
- nsCOMPtr<nsIINIParserFactory> iniFactory =
- do_GetService("@mozilla.org/xpcom/ini-parser-factory;1", &rv);
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsCOMPtr<nsIINIParser> iniParser;
- rv = iniFactory->CreateINIParser(reporterINI, getter_AddRefs(iniParser));
- NS_ENSURE_SUCCESS(rv, rv);
-
- // If we're writing the pref, just set and we're done.
if (writePref) {
- nsCOMPtr<nsIINIParserWriter> iniWriter = do_QueryInterface(iniParser);
- NS_ENSURE_TRUE(iniWriter, NS_ERROR_FAILURE);
-
- rv = iniWriter->SetString("Crash Reporter"_ns, "SubmitReport"_ns,
- *aSubmitReports ? "1"_ns : "0"_ns);
- NS_ENSURE_SUCCESS(rv, rv);
- rv = iniWriter->WriteFile(reporterINI);
- return rv;
- }
-
- nsAutoCString submitReportValue;
- rv = iniParser->GetString("Crash Reporter"_ns, "SubmitReport"_ns,
- submitReportValue);
-
- // Default to "true" if the pref can't be found.
- if (NS_FAILED(rv))
- *aSubmitReports = true;
- else if (submitReportValue.EqualsASCII("0"))
- *aSubmitReports = false;
- else
+ root["submit_report"] = *aSubmitReports;
+ std::ofstream file(*file_path);
+ file << root;
+ } else if (root["submit_report"].isBool()) {
+ *aSubmitReports = root["submit_report"].asBool();
+ } else {
+ // Default to "true" if the pref can't be found.
*aSubmitReports = true;
+ }
return NS_OK;
#else
@@ -2973,19 +2852,17 @@ static void SetCrashEventsDir(nsIFile* aDir) {
EnsureDirectoryExists(eventsDir);
}
- xpstring* path = CreatePathFromFile(eventsDir);
+ std::optional<xpstring> path = CreatePathFromFile(eventsDir);
if (!path) {
return; // There's no clean failure from this
}
- eventsDirectory = xpstring(*path);
+ eventsDirectory = *path;
#ifdef XP_WIN
SetEnvironmentVariableW(eventsDirectoryEnv, path->c_str());
#else
setenv(eventsDirectoryEnv, path->c_str(), /* overwrite */ 1);
#endif
-
- delete path;
}
void SetProfileDirectory(nsIFile* aDir) {