summaryrefslogtreecommitdiffstats
path: root/toolkit/crashreporter/client/crashreporter.cpp
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-15 03:34:42 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-15 03:34:42 +0000
commitda4c7e7ed675c3bf405668739c3012d140856109 (patch)
treecdd868dba063fecba609a1d819de271f0d51b23e /toolkit/crashreporter/client/crashreporter.cpp
parentAdding upstream version 125.0.3. (diff)
downloadfirefox-da4c7e7ed675c3bf405668739c3012d140856109.tar.xz
firefox-da4c7e7ed675c3bf405668739c3012d140856109.zip
Adding upstream version 126.0.upstream/126.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'toolkit/crashreporter/client/crashreporter.cpp')
-rw-r--r--toolkit/crashreporter/client/crashreporter.cpp852
1 files changed, 0 insertions, 852 deletions
diff --git a/toolkit/crashreporter/client/crashreporter.cpp b/toolkit/crashreporter/client/crashreporter.cpp
deleted file mode 100644
index 2887b16170..0000000000
--- a/toolkit/crashreporter/client/crashreporter.cpp
+++ /dev/null
@@ -1,852 +0,0 @@
-/* -*- 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/. */
-
-#include "crashreporter.h"
-
-#ifdef _MSC_VER
-// Disable exception handler warnings.
-# pragma warning(disable : 4530)
-#endif
-
-#include <fstream>
-#include <iomanip>
-#include <sstream>
-#include <memory>
-#include <ctime>
-#include <cstdlib>
-#include <cstring>
-#include <string>
-#include <utility>
-
-#ifdef XP_LINUX
-# include <dlfcn.h>
-#endif
-
-#include "json/json.h"
-#include "nss.h"
-#include "sechash.h"
-
-using std::ifstream;
-using std::ios;
-using std::istream;
-using std::istringstream;
-using std::ofstream;
-using std::ostream;
-using std::ostringstream;
-using std::string;
-using std::unique_ptr;
-using std::vector;
-
-namespace CrashReporter {
-
-StringTable gStrings;
-Json::Value gData;
-string gSettingsPath;
-string gEventsPath;
-string gPingPath;
-int gArgc;
-char** gArgv;
-bool gAutoSubmit;
-
-enum SubmissionResult { Succeeded, Failed };
-
-static unique_ptr<ofstream> gLogStream(nullptr);
-static string gReporterDumpFile;
-static string gExtraFile;
-static string gMemoryFile;
-
-static const char kExtraDataExtension[] = ".extra";
-static const char kMemoryReportExtension[] = ".memory.json.gz";
-
-void UIError(const string& message) {
- if (gAutoSubmit) {
- return;
- }
-
- string errorMessage;
- if (!gStrings[ST_CRASHREPORTERERROR].empty()) {
- char buf[2048];
- snprintf(buf, 2048, gStrings[ST_CRASHREPORTERERROR].c_str(),
- message.c_str());
- errorMessage = buf;
- } else {
- errorMessage = message;
- }
-
- UIError_impl(errorMessage);
-}
-
-static string Unescape(const string& str) {
- string ret;
- for (string::const_iterator iter = str.begin(); iter != str.end(); iter++) {
- if (*iter == '\\') {
- iter++;
- if (*iter == '\\') {
- ret.push_back('\\');
- } else if (*iter == 'n') {
- ret.push_back('\n');
- } else if (*iter == 't') {
- ret.push_back('\t');
- }
- } else {
- ret.push_back(*iter);
- }
- }
-
- return ret;
-}
-
-bool ReadStrings(istream& in, StringTable& strings, bool unescape) {
- while (!in.eof()) {
- string line;
- std::getline(in, line);
- int sep = line.find('=');
- if (sep >= 0) {
- string key, value;
- key = line.substr(0, sep);
- value = line.substr(sep + 1);
- if (unescape) value = Unescape(value);
- strings[key] = value;
- }
- }
-
- return true;
-}
-
-bool ReadStringsFromFile(const string& path, StringTable& strings,
- bool unescape) {
- ifstream* f = UIOpenRead(path, ios::in);
- bool success = false;
- if (f->is_open()) {
- success = ReadStrings(*f, strings, unescape);
- f->close();
- }
-
- delete f;
- return success;
-}
-
-static bool ReadExtraFile(const string& aExtraDataPath, Json::Value& aExtra) {
- bool success = false;
- ifstream* f = UIOpenRead(aExtraDataPath, ios::in);
- if (f->is_open()) {
- Json::CharReaderBuilder builder;
- success = parseFromStream(builder, *f, &aExtra, nullptr);
- }
-
- delete f;
- return success;
-}
-
-static string Basename(const string& file) {
- string::size_type slashIndex = file.rfind(UI_DIR_SEPARATOR);
- if (slashIndex != string::npos) {
- return file.substr(slashIndex + 1);
- }
- return file;
-}
-
-static bool ReadEventFile(const string& aPath, string& aEventVersion,
- string& aTime, string& aUuid, Json::Value& aData) {
- bool res = false;
- ifstream* f = UIOpenRead(aPath, ios::binary);
-
- if (f->is_open()) {
- std::getline(*f, aEventVersion, '\n');
- res = f->good();
- std::getline(*f, aTime, '\n');
- res &= f->good();
- std::getline(*f, aUuid, '\n');
- res &= f->good();
-
- if (res) {
- Json::CharReaderBuilder builder;
- res = parseFromStream(builder, *f, &aData, nullptr);
- }
- }
-
- delete f;
- return res;
-}
-
-static void OverwriteEventFile(const string& aPath, const string& aEventVersion,
- const string& aTime, const string& aUuid,
- const Json::Value& aData) {
- ofstream* f = UIOpenWrite(aPath, ios::binary | ios::trunc);
- if (f->is_open()) {
- f->write(aEventVersion.c_str(), aEventVersion.length()) << '\n';
- f->write(aTime.c_str(), aTime.length()) << '\n';
- f->write(aUuid.c_str(), aUuid.length()) << '\n';
-
- Json::StreamWriterBuilder builder;
- builder["indentation"] = "";
- std::unique_ptr<Json::StreamWriter> writer(builder.newStreamWriter());
- writer->write(aData, f);
- *f << "\n";
- }
-
- delete f;
-}
-
-static void UpdateEventFile(const Json::Value& aExtraData, const string& aHash,
- const string& aPingUuid) {
- if (gEventsPath.empty()) {
- // If there is no path for finding the crash event, skip this step.
- return;
- }
-
- string localId = CrashReporter::GetDumpLocalID();
- string path = gEventsPath + UI_DIR_SEPARATOR + localId;
- string eventVersion;
- string crashTime;
- string crashUuid;
- Json::Value eventData;
-
- if (!ReadEventFile(path, eventVersion, crashTime, crashUuid, eventData)) {
- return;
- }
-
- if (!aHash.empty()) {
- eventData["MinidumpSha256Hash"] = aHash;
- }
-
- if (!aPingUuid.empty()) {
- eventData["CrashPingUUID"] = aPingUuid;
- }
-
- if (aExtraData.isMember("StackTraces")) {
- eventData["StackTraces"] = aExtraData["StackTraces"];
- }
-
- OverwriteEventFile(path, eventVersion, crashTime, crashUuid, eventData);
-}
-
-static void WriteSubmissionEvent(SubmissionResult result,
- const string& remoteId) {
- if (gEventsPath.empty()) {
- // If there is no path for writing the submission event, skip it.
- return;
- }
-
- string localId = CrashReporter::GetDumpLocalID();
- string fpath = gEventsPath + UI_DIR_SEPARATOR + localId + "-submission";
- ofstream* f = UIOpenWrite(fpath, ios::binary);
- time_t tm;
- time(&tm);
-
- if (f->is_open()) {
- *f << "crash.submission.1\n";
- *f << tm << "\n";
- *f << localId << "\n";
- *f << (result == Succeeded ? "true" : "false") << "\n";
- *f << remoteId;
-
- f->close();
- }
-
- delete f;
-}
-
-void LogMessage(const std::string& message) {
- if (gLogStream.get()) {
- char date[64];
- time_t tm;
- time(&tm);
- if (strftime(date, sizeof(date) - 1, "%c", localtime(&tm)) == 0)
- date[0] = '\0';
- (*gLogStream) << "[" << date << "] " << message << '\n';
- }
-}
-
-static void OpenLogFile() {
- string logPath = gSettingsPath + UI_DIR_SEPARATOR + "submit.log";
- gLogStream.reset(UIOpenWrite(logPath, ios::app));
-}
-
-static bool ReadConfig() {
- string iniPath;
- if (!UIGetIniPath(iniPath)) {
- return false;
- }
-
- if (!ReadStringsFromFile(iniPath, gStrings, true)) return false;
-
- // See if we have a string override file, if so process it
- char* overrideEnv = getenv("MOZ_CRASHREPORTER_STRINGS_OVERRIDE");
- if (overrideEnv && *overrideEnv && UIFileExists(overrideEnv))
- ReadStringsFromFile(overrideEnv, gStrings, true);
-
- return true;
-}
-
-static string GetAdditionalFilename(const string& dumpfile,
- const char* extension) {
- string filename(dumpfile);
- int dot = filename.rfind('.');
- if (dot < 0) return "";
-
- filename.replace(dot, filename.length() - dot, extension);
- return filename;
-}
-
-static bool MoveCrashData(const string& toDir, string& dumpfile,
- string& extrafile, string& memoryfile) {
- if (!UIEnsurePathExists(toDir)) {
- UIError(gStrings[ST_ERROR_CREATEDUMPDIR]);
- return false;
- }
-
- string newDump = toDir + UI_DIR_SEPARATOR + Basename(dumpfile);
- string newExtra = toDir + UI_DIR_SEPARATOR + Basename(extrafile);
- string newMemory = toDir + UI_DIR_SEPARATOR + Basename(memoryfile);
-
- if (!UIMoveFile(dumpfile, newDump)) {
- UIError(gStrings[ST_ERROR_DUMPFILEMOVE]);
- return false;
- }
-
- if (!UIMoveFile(extrafile, newExtra)) {
- UIError(gStrings[ST_ERROR_EXTRAFILEMOVE]);
- return false;
- }
-
- if (!memoryfile.empty()) {
- // Ignore errors from moving the memory file
- if (!UIMoveFile(memoryfile, newMemory)) {
- UIDeleteFile(memoryfile);
- newMemory.erase();
- }
- memoryfile = newMemory;
- }
-
- dumpfile = newDump;
- extrafile = newExtra;
-
- return true;
-}
-
-static bool AddSubmittedReport(const string& serverResponse) {
- StringTable responseItems;
- istringstream in(serverResponse);
- ReadStrings(in, responseItems, false);
-
- if (responseItems.find("StopSendingReportsFor") != responseItems.end()) {
- // server wants to tell us to stop sending reports for a certain version
- string reportPath = gSettingsPath + UI_DIR_SEPARATOR + "EndOfLife" +
- responseItems["StopSendingReportsFor"];
-
- ofstream* reportFile = UIOpenWrite(reportPath, ios::trunc);
- if (reportFile->is_open()) {
- // don't really care about the contents
- *reportFile << 1 << "\n";
- reportFile->close();
- }
- delete reportFile;
- }
-
- if (responseItems.find("Discarded") != responseItems.end()) {
- // server discarded this report... save it so the user can resubmit it
- // manually
- return false;
- }
-
- if (responseItems.find("CrashID") == responseItems.end()) return false;
-
- string submittedDir = gSettingsPath + UI_DIR_SEPARATOR + "submitted";
- if (!UIEnsurePathExists(submittedDir)) {
- return false;
- }
-
- string path =
- submittedDir + UI_DIR_SEPARATOR + responseItems["CrashID"] + ".txt";
-
- ofstream* file = UIOpenWrite(path, ios::trunc);
- if (!file->is_open()) {
- delete file;
- return false;
- }
-
- char buf[1024];
- snprintf(buf, 1024, gStrings["CrashID"].c_str(),
- responseItems["CrashID"].c_str());
- *file << buf << "\n";
-
- if (responseItems.find("ViewURL") != responseItems.end()) {
- snprintf(buf, 1024, gStrings["CrashDetailsURL"].c_str(),
- responseItems["ViewURL"].c_str());
- *file << buf << "\n";
- }
-
- file->close();
- delete file;
-
- WriteSubmissionEvent(Succeeded, responseItems["CrashID"]);
- return true;
-}
-
-void DeleteDump() {
- const char* noDelete = getenv("MOZ_CRASHREPORTER_NO_DELETE_DUMP");
- if (!noDelete || *noDelete == '\0') {
- if (!gReporterDumpFile.empty()) UIDeleteFile(gReporterDumpFile);
- if (!gExtraFile.empty()) UIDeleteFile(gExtraFile);
- if (!gMemoryFile.empty()) UIDeleteFile(gMemoryFile);
- }
-}
-
-void SendCompleted(bool success, const string& serverResponse) {
- if (success) {
- if (AddSubmittedReport(serverResponse)) {
- DeleteDump();
- } else {
- string directory = gReporterDumpFile;
- int slashpos = directory.find_last_of("/\\");
- if (slashpos < 2) return;
- directory.resize(slashpos);
- UIPruneSavedDumps(directory);
- WriteSubmissionEvent(Failed, "");
- }
- } else {
- WriteSubmissionEvent(Failed, "");
- }
-}
-
-static string ComputeDumpHash() {
-#ifdef XP_LINUX
- // On Linux we rely on the system-provided libcurl which uses nss so we have
- // to also use the system-provided nss instead of the ones we have bundled.
- const char* libnssNames[] = {
- "libnss3.so",
-# ifndef HAVE_64BIT_BUILD
- // 32-bit versions on 64-bit hosts
- "/usr/lib32/libnss3.so",
-# endif
- };
- void* lib = nullptr;
-
- for (const char* libname : libnssNames) {
- lib = dlopen(libname, RTLD_NOW);
-
- if (lib) {
- break;
- }
- }
-
- if (!lib) {
- return "";
- }
-
- SECStatus (*NSS_Initialize)(const char*, const char*, const char*,
- const char*, PRUint32);
- HASHContext* (*HASH_Create)(HASH_HashType);
- void (*HASH_Destroy)(HASHContext*);
- void (*HASH_Begin)(HASHContext*);
- void (*HASH_Update)(HASHContext*, const unsigned char*, unsigned int);
- void (*HASH_End)(HASHContext*, unsigned char*, unsigned int*, unsigned int);
-
- *(void**)(&NSS_Initialize) = dlsym(lib, "NSS_Initialize");
- *(void**)(&HASH_Create) = dlsym(lib, "HASH_Create");
- *(void**)(&HASH_Destroy) = dlsym(lib, "HASH_Destroy");
- *(void**)(&HASH_Begin) = dlsym(lib, "HASH_Begin");
- *(void**)(&HASH_Update) = dlsym(lib, "HASH_Update");
- *(void**)(&HASH_End) = dlsym(lib, "HASH_End");
-
- if (!HASH_Create || !HASH_Destroy || !HASH_Begin || !HASH_Update ||
- !HASH_End) {
- return "";
- }
-#endif
- // Minimal NSS initialization so we can use the hash functions
- const PRUint32 kNssFlags = NSS_INIT_READONLY | NSS_INIT_NOROOTINIT |
- NSS_INIT_NOMODDB | NSS_INIT_NOCERTDB;
- if (NSS_Initialize(nullptr, "", "", "", kNssFlags) != SECSuccess) {
- return "";
- }
-
- HASHContext* hashContext = HASH_Create(HASH_AlgSHA256);
-
- if (!hashContext) {
- return "";
- }
-
- HASH_Begin(hashContext);
-
- ifstream* f = UIOpenRead(gReporterDumpFile, ios::binary);
- bool error = false;
-
- // Read the minidump contents
- if (f->is_open()) {
- uint8_t buff[4096];
-
- do {
- f->read((char*)buff, sizeof(buff));
-
- if (f->bad()) {
- error = true;
- break;
- }
-
- HASH_Update(hashContext, buff, f->gcount());
- } while (!f->eof());
-
- f->close();
- } else {
- error = true;
- }
-
- delete f;
-
- // Finalize the hash computation
- uint8_t result[SHA256_LENGTH];
- uint32_t resultLen = 0;
-
- HASH_End(hashContext, result, &resultLen, SHA256_LENGTH);
-
- if (resultLen != SHA256_LENGTH) {
- error = true;
- }
-
- HASH_Destroy(hashContext);
-
- if (!error) {
- ostringstream hash;
-
- for (size_t i = 0; i < SHA256_LENGTH; i++) {
- hash << std::setw(2) << std::setfill('0') << std::hex
- << static_cast<unsigned int>(result[i]);
- }
-
- return hash.str();
- }
- return ""; // If we encountered an error, return an empty hash
-}
-
-string GetDumpLocalID() {
- string localId = Basename(gReporterDumpFile);
- string::size_type dot = localId.rfind('.');
-
- if (dot == string::npos) return "";
-
- return localId.substr(0, dot);
-}
-
-string GetProgramPath(const string& exename) {
- string path = gArgv[0];
- size_t pos = path.rfind(UI_CRASH_REPORTER_FILENAME BIN_SUFFIX);
- path.erase(pos);
-#ifdef XP_MACOSX
- // On macOS the crash reporter client is shipped as an application bundle
- // contained within Firefox' main application bundle. So when it's invoked
- // its current working directory looks like:
- // Firefox.app/Contents/MacOS/crashreporter.app/Contents/MacOS/
- // The other applications we ship with Firefox are stored in the main bundle
- // (Firefox.app/Contents/MacOS/) so we we need to go back three directories
- // to reach them.
- path.erase(pos - 1);
- for (size_t i = 0; i < 3; i++) {
- pos = path.rfind(UI_DIR_SEPARATOR, pos - 1);
- }
-
- path.erase(pos + 1);
-#endif // XP_MACOSX
- path.append(exename + BIN_SUFFIX);
-
- return path;
-}
-
-} // namespace CrashReporter
-
-using namespace CrashReporter;
-
-Json::Value kEmptyJsonString("");
-
-void RewriteStrings(Json::Value& aExtraData) {
- // rewrite some UI strings with the values from the query parameters
- string product = aExtraData.get("ProductName", kEmptyJsonString).asString();
- Json::Value mozilla("Mozilla");
- string vendor = aExtraData.get("Vendor", mozilla).asString();
-
- char buf[4096];
- snprintf(buf, sizeof(buf), gStrings[ST_CRASHREPORTERVENDORTITLE].c_str(),
- vendor.c_str());
- gStrings[ST_CRASHREPORTERTITLE] = buf;
-
- string str = gStrings[ST_CRASHREPORTERPRODUCTERROR];
- // Only do the replacement here if the string has two
- // format specifiers to start. Otherwise
- // we assume it has the product name hardcoded.
- string::size_type pos = str.find("%s");
- if (pos != string::npos) pos = str.find("%s", pos + 2);
- if (pos != string::npos) {
- // Leave a format specifier for UIError to fill in
- snprintf(buf, sizeof(buf), gStrings[ST_CRASHREPORTERPRODUCTERROR].c_str(),
- product.c_str(), "%s");
- gStrings[ST_CRASHREPORTERERROR] = buf;
- } else {
- // product name is hardcoded
- gStrings[ST_CRASHREPORTERERROR] = str;
- }
-
- snprintf(buf, sizeof(buf), gStrings[ST_CRASHREPORTERDESCRIPTION].c_str(),
- product.c_str());
- gStrings[ST_CRASHREPORTERDESCRIPTION] = buf;
-
- snprintf(buf, sizeof(buf), gStrings[ST_CHECKSUBMIT].c_str(), vendor.c_str());
- gStrings[ST_CHECKSUBMIT] = buf;
-
- snprintf(buf, sizeof(buf), gStrings[ST_RESTART].c_str(), product.c_str());
- gStrings[ST_RESTART] = buf;
-
- snprintf(buf, sizeof(buf), gStrings[ST_QUIT].c_str(), product.c_str());
- gStrings[ST_QUIT] = buf;
-
- snprintf(buf, sizeof(buf), gStrings[ST_ERROR_ENDOFLIFE].c_str(),
- product.c_str());
- gStrings[ST_ERROR_ENDOFLIFE] = buf;
-}
-
-bool CheckEndOfLifed(const Json::Value& aVersion) {
- if (!aVersion.isString()) {
- return false;
- }
-
- string reportPath =
- gSettingsPath + UI_DIR_SEPARATOR + "EndOfLife" + aVersion.asString();
- return UIFileExists(reportPath);
-}
-
-int main(int argc, char** argv) {
- gArgc = argc;
- gArgv = argv;
-
- string autoSubmitEnv = UIGetEnv("MOZ_CRASHREPORTER_AUTO_SUBMIT");
- gAutoSubmit = !autoSubmitEnv.empty();
-
- if (!ReadConfig()) {
- UIError("Couldn't read configuration.");
- return 0;
- }
-
- if (!UIInit()) {
- return 0;
- }
-
- if (argc > 1) {
- gReporterDumpFile = argv[1];
- }
-
- if (gReporterDumpFile.empty()) {
- // no dump file specified, run the default UI
- if (!gAutoSubmit) {
- UIShowDefaultUI();
- }
- } else {
- // Start by running minidump analyzer to gather stack traces.
- string reporterDumpFile = gReporterDumpFile;
- vector<string> args = {reporterDumpFile};
- string dumpAllThreadsEnv = UIGetEnv("MOZ_CRASHREPORTER_DUMP_ALL_THREADS");
- if (!dumpAllThreadsEnv.empty()) {
- args.insert(args.begin(), "--full");
- }
- UIRunProgram(CrashReporter::GetProgramPath(UI_MINIDUMP_ANALYZER_FILENAME),
- args,
- /* wait */ true);
-
- // go ahead with the crash reporter
- gExtraFile = GetAdditionalFilename(gReporterDumpFile, kExtraDataExtension);
- if (gExtraFile.empty()) {
- UIError(gStrings[ST_ERROR_BADARGUMENTS]);
- return 0;
- }
-
- if (!UIFileExists(gExtraFile)) {
- UIError(gStrings[ST_ERROR_EXTRAFILEEXISTS]);
- return 0;
- }
-
- gMemoryFile =
- GetAdditionalFilename(gReporterDumpFile, kMemoryReportExtension);
- if (!UIFileExists(gMemoryFile)) {
- gMemoryFile.erase();
- }
-
- Json::Value extraData;
- if (!ReadExtraFile(gExtraFile, extraData)) {
- UIError(gStrings[ST_ERROR_EXTRAFILEREAD]);
- return 0;
- }
-
- if (!extraData.isMember("ProductName")) {
- UIError(gStrings[ST_ERROR_NOPRODUCTNAME]);
- return 0;
- }
-
- // There is enough information in the extra file to rewrite strings
- // to be product specific
- RewriteStrings(extraData);
-
- if (!extraData.isMember("ServerURL")) {
- UIError(gStrings[ST_ERROR_NOSERVERURL]);
- return 0;
- }
-
- // Hopefully the settings path exists in the environment. Try that before
- // asking the platform-specific code to guess.
- gSettingsPath = UIGetEnv("MOZ_CRASHREPORTER_DATA_DIRECTORY");
- if (gSettingsPath.empty()) {
- string product =
- extraData.get("ProductName", kEmptyJsonString).asString();
- string vendor = extraData.get("Vendor", kEmptyJsonString).asString();
-
- if (!UIGetSettingsPath(vendor, product, gSettingsPath)) {
- gSettingsPath.clear();
- }
- }
-
- if (gSettingsPath.empty() || !UIEnsurePathExists(gSettingsPath)) {
- UIError(gStrings[ST_ERROR_NOSETTINGSPATH]);
- return 0;
- }
-
- OpenLogFile();
-
- gEventsPath = UIGetEnv("MOZ_CRASHREPORTER_EVENTS_DIRECTORY");
- gPingPath = UIGetEnv("MOZ_CRASHREPORTER_PING_DIRECTORY");
-
- // Assemble and send the crash ping
- string hash = ComputeDumpHash();
-
- string pingUuid;
- SendCrashPing(extraData, hash, pingUuid, gPingPath);
- UpdateEventFile(extraData, hash, pingUuid);
-
- if (!UIFileExists(gReporterDumpFile)) {
- UIError(gStrings[ST_ERROR_DUMPFILEEXISTS]);
- return 0;
- }
-
- string pendingDir = gSettingsPath + UI_DIR_SEPARATOR + "pending";
- if (!MoveCrashData(pendingDir, gReporterDumpFile, gExtraFile,
- gMemoryFile)) {
- return 0;
- }
-
- string sendURL = extraData.get("ServerURL", kEmptyJsonString).asString();
- // we don't need to actually send these
- extraData.removeMember("ServerURL");
- extraData.removeMember("StackTraces");
-
- extraData["SubmittedFrom"] = "Client";
- extraData["Throttleable"] = "1";
-
- // re-set XUL_APP_FILE for xulrunner wrapped apps
- const char* appfile = getenv("MOZ_CRASHREPORTER_RESTART_XUL_APP_FILE");
- if (appfile && *appfile) {
- const char prefix[] = "XUL_APP_FILE=";
- char* env = (char*)malloc(strlen(appfile) + strlen(prefix) + 1);
- if (!env) {
- UIError("Out of memory");
- return 0;
- }
- strcpy(env, prefix);
- strcat(env, appfile);
- putenv(env);
- free(env);
- }
-
- vector<string> restartArgs;
-
- if (!extraData.isMember("WindowsErrorReporting")) {
- // We relaunch the application associated with the client, but only when
- // we encountered a crash caught by the exception handler. Crashes handled
- // by WER are prevented from directly restarting the application.
- string programPath = GetProgramPath(MOZ_APP_NAME);
-#ifndef XP_WIN
- const char* moz_app_launcher = getenv("MOZ_APP_LAUNCHER");
- if (moz_app_launcher) {
- programPath = moz_app_launcher;
- }
-#endif // XP_WIN
-
- restartArgs.push_back(programPath);
-
- ostringstream paramName;
- int i = 1;
- paramName << "MOZ_CRASHREPORTER_RESTART_ARG_" << i++;
- const char* param = getenv(paramName.str().c_str());
- while (param && *param) {
- restartArgs.push_back(param);
-
- paramName.str("");
- paramName << "MOZ_CRASHREPORTER_RESTART_ARG_" << i++;
- param = getenv(paramName.str().c_str());
- }
- }
-
- // allow override of the server url via environment variable
- // XXX: remove this in the far future when our robot
- // masters force everyone to use XULRunner
- char* urlEnv = getenv("MOZ_CRASHREPORTER_URL");
- if (urlEnv && *urlEnv) {
- sendURL = urlEnv;
- }
-
- // see if this version has been end-of-lifed
-
- if (extraData.isMember("Version") &&
- CheckEndOfLifed(extraData["Version"])) {
- UIError(gStrings[ST_ERROR_ENDOFLIFE]);
- DeleteDump();
- return 0;
- }
-
- StringTable files;
- files["upload_file_minidump"] = gReporterDumpFile;
- if (!gMemoryFile.empty()) {
- files["memory_report"] = gMemoryFile;
- }
-
- if (!UIShowCrashUI(files, extraData, sendURL, restartArgs)) {
- DeleteDump();
- }
- }
-
- UIShutdown();
-
- return 0;
-}
-
-#if defined(XP_WIN) && !defined(__GNUC__)
-# include <windows.h>
-
-// We need WinMain in order to not be a console app. This function is unused
-// if we are a console application.
-int WINAPI wWinMain(HINSTANCE, HINSTANCE, LPWSTR args, int) {
- // Remove everything except close window from the context menu
- {
- HKEY hkApp;
- RegCreateKeyExW(HKEY_CURRENT_USER, L"Software\\Classes\\Applications", 0,
- nullptr, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, nullptr,
- &hkApp, nullptr);
- RegCloseKey(hkApp);
- if (RegCreateKeyExW(HKEY_CURRENT_USER,
- L"Software\\Classes\\Applications\\crashreporter.exe",
- 0, nullptr, REG_OPTION_VOLATILE, KEY_SET_VALUE, nullptr,
- &hkApp, nullptr) == ERROR_SUCCESS) {
- RegSetValueExW(hkApp, L"IsHostApp", 0, REG_NONE, 0, 0);
- RegSetValueExW(hkApp, L"NoOpenWith", 0, REG_NONE, 0, 0);
- RegSetValueExW(hkApp, L"NoStartPage", 0, REG_NONE, 0, 0);
- RegCloseKey(hkApp);
- }
- }
-
- char** argv = static_cast<char**>(malloc(__argc * sizeof(char*)));
- for (int i = 0; i < __argc; i++) {
- argv[i] = strdup(WideToUTF8(__wargv[i]).c_str());
- }
-
- // Do the real work.
- return main(__argc, argv);
-}
-#endif