mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-02 10:00:54 +00:00
bug 366970, crash reporter needs to send Product, Build ID, Platform. r=mento
This commit is contained in:
parent
766a715fb4
commit
c9ff2ca6e0
@ -48,6 +48,7 @@ LIBRARY_NAME = airbagexception_s
|
||||
REQUIRES = \
|
||||
xpcom \
|
||||
string \
|
||||
xulapp \
|
||||
$(NULL)
|
||||
|
||||
DIRS = \
|
||||
|
@ -61,6 +61,7 @@ LOCAL_INCLUDES += -I$(srcdir)
|
||||
RCINCLUDE = crashreporter.rc
|
||||
DEFINES += -DUNICODE -D_UNICODE
|
||||
OS_LIBS += $(call EXPAND_LIBNAME,comctl32 shell32 wininet)
|
||||
MOZ_WINCONSOLE = 0
|
||||
endif
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
@ -45,27 +45,34 @@
|
||||
#include <shellapi.h>
|
||||
#include "resource.h"
|
||||
#include "client/windows/sender/crash_report_sender.h"
|
||||
#include <fstream>
|
||||
|
||||
#define CRASH_REPORTER_KEY L"Software\\Mozilla\\Crash Reporter"
|
||||
#define CRASH_REPORTER_VALUE L"Enabled"
|
||||
|
||||
#define WM_UPLOADCOMPLETE WM_APP
|
||||
|
||||
using std::string;
|
||||
using std::wstring;
|
||||
using std::map;
|
||||
using std::ifstream;
|
||||
|
||||
bool ReadConfig();
|
||||
BOOL CALLBACK EnableDialogProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam);
|
||||
BOOL CALLBACK SendDialogProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam);
|
||||
BOOL CALLBACK EnableDialogProc(HWND hwndDlg, UINT message, WPARAM wParam,
|
||||
LPARAM lParam);
|
||||
BOOL CALLBACK SendDialogProc(HWND hwndDlg, UINT message, WPARAM wParam,
|
||||
LPARAM lParam);
|
||||
HANDLE CreateSendThread(HWND hDlg, LPCTSTR dumpFile);
|
||||
bool CheckCrashReporterEnabled(bool* enabled);
|
||||
void SetCrashReporterEnabled(bool enabled);
|
||||
bool SendCrashReport(HINSTANCE hInstance, LPCTSTR dumpFile);
|
||||
bool SendCrashReport(wstring dumpFile,
|
||||
const map<wstring,wstring> *query_parameters);
|
||||
DWORD WINAPI SendThreadProc(LPVOID param);
|
||||
|
||||
typedef struct {
|
||||
HWND hDlg;
|
||||
LPCTSTR dumpFile;
|
||||
wstring dumpFile;
|
||||
const map<wstring,wstring> *query_parameters;
|
||||
} SENDTHREADDATA;
|
||||
|
||||
TCHAR sendURL[2048] = L"\0";
|
||||
@ -99,6 +106,8 @@ LPCTSTR stringNames[] = {
|
||||
|
||||
LPTSTR strings[NUM_STRINGS];
|
||||
|
||||
const wchar_t* kExtraDataExtension = L".extra";
|
||||
|
||||
void DoInitCommonControls()
|
||||
{
|
||||
INITCOMMONCONTROLSEX ic;
|
||||
@ -143,52 +152,6 @@ bool ReadConfig()
|
||||
return false;
|
||||
}
|
||||
|
||||
int WINAPI WinMain(HINSTANCE hInstance,
|
||||
HINSTANCE hPrevInstance,
|
||||
LPSTR lpCmdLine,
|
||||
int nCmdShow)
|
||||
|
||||
{
|
||||
bool enabled;
|
||||
LPTSTR* argv = NULL;
|
||||
int argc = 0;
|
||||
|
||||
DoInitCommonControls();
|
||||
if (!ReadConfig()) {
|
||||
MessageBox(NULL, L"Missing crashreporter.ini file", L"Crash Reporter Error", MB_OK | MB_ICONSTOP);
|
||||
return 0;
|
||||
}
|
||||
|
||||
argv = CommandLineToArgvW(GetCommandLine(), &argc);
|
||||
|
||||
if (argc == 1) {
|
||||
// nothing specified, just ask about enabling
|
||||
if (!CheckCrashReporterEnabled(&enabled))
|
||||
enabled = true;
|
||||
|
||||
enabled = (1 == DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_ENABLEDIALOG), NULL, (DLGPROC)EnableDialogProc, (LPARAM)enabled));
|
||||
SetCrashReporterEnabled(enabled);
|
||||
}
|
||||
else {
|
||||
if (!CheckCrashReporterEnabled(&enabled)) {
|
||||
//ask user if crash reporter should be enabled
|
||||
enabled = (1 == DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_ENABLEDIALOG), NULL, (DLGPROC)EnableDialogProc, (LPARAM)true));
|
||||
SetCrashReporterEnabled(enabled);
|
||||
}
|
||||
// if enabled, send crash report
|
||||
if (enabled) {
|
||||
if (SendCrashReport(hInstance, argv[1]) && deleteDump)
|
||||
DeleteFile(argv[1]);
|
||||
//TODO: show details?
|
||||
}
|
||||
}
|
||||
|
||||
if (argv)
|
||||
LocalFree(argv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL CALLBACK EnableDialogProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch (message) {
|
||||
@ -286,8 +249,9 @@ BOOL CALLBACK SendDialogProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM l
|
||||
SendDlgItemMessage(hwndDlg, IDC_PROGRESS, PBM_SETRANGE, 0, MAKELPARAM(0, 100));
|
||||
SendDlgItemMessage(hwndDlg, IDC_PROGRESS, PBM_SETPOS, 0, 0);
|
||||
// now create a thread to actually do the sending
|
||||
LPCTSTR dumpFile = (LPCTSTR)lParam;
|
||||
hThread = CreateSendThread(hwndDlg, dumpFile);
|
||||
SENDTHREADDATA* td = (SENDTHREADDATA*)lParam;
|
||||
td->hDlg = hwndDlg;
|
||||
CreateThread(NULL, 0, SendThreadProc, td, 0, NULL);
|
||||
}
|
||||
return TRUE;
|
||||
|
||||
@ -315,9 +279,17 @@ BOOL CALLBACK SendDialogProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM l
|
||||
}
|
||||
}
|
||||
|
||||
bool SendCrashReport(HINSTANCE hInstance, LPCTSTR dumpFile)
|
||||
bool SendCrashReport(wstring dumpFile,
|
||||
const map<wstring,wstring> *query_parameters)
|
||||
{
|
||||
int res = (int)DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_SENDDIALOG), NULL, (DLGPROC)SendDialogProc, (LPARAM)dumpFile);
|
||||
SENDTHREADDATA td;
|
||||
td.hDlg = NULL;
|
||||
td.dumpFile = dumpFile;
|
||||
td.query_parameters = query_parameters;
|
||||
|
||||
int res = (int)DialogBoxParam(NULL, MAKEINTRESOURCE(IDD_SENDDIALOG), NULL,
|
||||
(DLGPROC)SendDialogProc, (LPARAM)&td);
|
||||
|
||||
return (res >= 0);
|
||||
}
|
||||
|
||||
@ -325,8 +297,7 @@ DWORD WINAPI SendThreadProc(LPVOID param)
|
||||
{
|
||||
bool finishedOk;
|
||||
SENDTHREADDATA* td = (SENDTHREADDATA*)param;
|
||||
//XXX: send some extra params?
|
||||
map<wstring, wstring> params;
|
||||
|
||||
wstring url(sendURL);
|
||||
if (url.empty()) {
|
||||
finishedOk = false;
|
||||
@ -334,18 +305,129 @@ DWORD WINAPI SendThreadProc(LPVOID param)
|
||||
else {
|
||||
finishedOk = google_airbag::CrashReportSender
|
||||
::SendCrashReport(url,
|
||||
params,
|
||||
wstring(td->dumpFile));
|
||||
*(td->query_parameters),
|
||||
td->dumpFile);
|
||||
}
|
||||
PostMessage(td->hDlg, WM_UPLOADCOMPLETE, finishedOk ? 1 : 0, 0);
|
||||
delete td;
|
||||
return 0;
|
||||
}
|
||||
|
||||
HANDLE CreateSendThread(HWND hDlg, LPCTSTR dumpFile)
|
||||
//XXX: change this to use Breakpad's string conversion functions
|
||||
// when we update to latest SVN
|
||||
bool ConvertString(const char* utf8_string, wstring& ucs2_string)
|
||||
{
|
||||
SENDTHREADDATA* td = new SENDTHREADDATA;
|
||||
td->hDlg = hDlg;
|
||||
td->dumpFile = dumpFile;
|
||||
return CreateThread(NULL, 0, SendThreadProc, td, 0, NULL);
|
||||
wchar_t *buffer = NULL;
|
||||
int buffer_size = MultiByteToWideChar(CP_ACP, 0, utf8_string,
|
||||
-1, NULL, 0);
|
||||
if(buffer_size == 0)
|
||||
return false;
|
||||
|
||||
buffer = new wchar_t[buffer_size];
|
||||
if(buffer == NULL)
|
||||
return false;
|
||||
|
||||
MultiByteToWideChar(CP_ACP, 0, utf8_string,
|
||||
-1, buffer, buffer_size);
|
||||
ucs2_string = buffer;
|
||||
delete [] buffer;
|
||||
return true;
|
||||
}
|
||||
|
||||
void ReadExtraData(const wstring& filename,
|
||||
map<wstring, wstring>& query_parameters)
|
||||
{
|
||||
#if _MSC_VER >= 1400 // MSVC 2005/8
|
||||
ifstream file;
|
||||
file.open(filename.c_str(), std::ios::in);
|
||||
#else // _MSC_VER >= 1400
|
||||
ifstream file(_wfopen(filename.c_str(), L"rb"));
|
||||
#endif // _MSC_VER >= 1400
|
||||
if (file.is_open()) {
|
||||
do {
|
||||
string in_line;
|
||||
std::getline(file, in_line);
|
||||
if (!in_line.empty()) {
|
||||
int pos = in_line.find('=');
|
||||
if (pos >= 0) {
|
||||
wstring key, value;
|
||||
ConvertString(in_line.substr(0, pos).c_str(), key);
|
||||
ConvertString(in_line.substr(pos + 1,
|
||||
in_line.length() - pos - 1).c_str(),
|
||||
value);
|
||||
query_parameters[key] = value;
|
||||
}
|
||||
}
|
||||
} while(!file.eof());
|
||||
file.close();
|
||||
}
|
||||
}
|
||||
|
||||
wstring GetExtraDataFilename(const wstring& dumpfile)
|
||||
{
|
||||
wstring filename(dumpfile);
|
||||
int dot = filename.rfind('.');
|
||||
if (dot < 0)
|
||||
return L"";
|
||||
|
||||
filename.replace(dot, filename.length() - dot, kExtraDataExtension);
|
||||
return filename;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
map<wstring,wstring> query_parameters;
|
||||
|
||||
DoInitCommonControls();
|
||||
if (!ReadConfig()) {
|
||||
MessageBox(NULL, L"Missing crashreporter.ini file", L"Crash Reporter Error", MB_OK | MB_ICONSTOP);
|
||||
return 0;
|
||||
}
|
||||
|
||||
wstring dumpfile;
|
||||
bool enabled = false;
|
||||
|
||||
if (argc > 1) {
|
||||
if (!ConvertString(argv[1], dumpfile))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (dumpfile.empty()) {
|
||||
// no dump file specified, just ask about enabling
|
||||
if (!CheckCrashReporterEnabled(&enabled))
|
||||
enabled = true;
|
||||
|
||||
enabled = (1 == DialogBoxParam(NULL, MAKEINTRESOURCE(IDD_ENABLEDIALOG), NULL, (DLGPROC)EnableDialogProc, (LPARAM)enabled));
|
||||
SetCrashReporterEnabled(enabled);
|
||||
}
|
||||
else {
|
||||
wstring extrafile = GetExtraDataFilename(dumpfile);
|
||||
if (!extrafile.empty())
|
||||
ReadExtraData(extrafile, query_parameters);
|
||||
|
||||
if (!CheckCrashReporterEnabled(&enabled)) {
|
||||
//ask user if crash reporter should be enabled
|
||||
enabled = (1 == DialogBoxParam(NULL, MAKEINTRESOURCE(IDD_ENABLEDIALOG), NULL, (DLGPROC)EnableDialogProc, (LPARAM)true));
|
||||
SetCrashReporterEnabled(enabled);
|
||||
}
|
||||
// if enabled, send crash report
|
||||
if (enabled) {
|
||||
if (SendCrashReport(dumpfile, &query_parameters) && deleteDump) {
|
||||
DeleteFile(dumpfile.c_str());
|
||||
if (!extrafile.empty())
|
||||
DeleteFile(extrafile.c_str());
|
||||
}
|
||||
//TODO: show details?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(XP_WIN) && !defined(DEBUG) && !defined(__GNUC__)
|
||||
// We need WinMain in order to not be a console app. This function is unused
|
||||
// if we are a console application.
|
||||
int WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR args, int )
|
||||
{
|
||||
// Do the real work.
|
||||
return main(__argc, __argv);
|
||||
}
|
||||
#endif
|
||||
|
@ -44,26 +44,91 @@
|
||||
|
||||
#include "client/windows/handler/exception_handler.h"
|
||||
#include <string.h>
|
||||
#else
|
||||
#error "Not yet implemented for this platform"
|
||||
#endif // XP_WIN32
|
||||
|
||||
#ifndef HAVE_CPP_2BYTE_WCHAR_T
|
||||
#error "This code expects a 2 byte wchar_t. You should --disable-airbag."
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <prenv.h>
|
||||
#include "nsDebug.h"
|
||||
#include "nsCRT.h"
|
||||
#include "nsILocalFile.h"
|
||||
|
||||
static google_airbag::ExceptionHandler* gAirbagExceptionHandler = nsnull;
|
||||
namespace CrashReporter {
|
||||
|
||||
using std::wstring;
|
||||
|
||||
static const PRUnichar dumpFileExtension[] = {'.', 'd', 'm', 'p',
|
||||
'\"', '\0'}; // .dmp"
|
||||
static const PRUnichar extraFileExtension[] = {'.', 'e', 'x', 't',
|
||||
'r', 'a', '\0'}; // .extra
|
||||
|
||||
// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
||||
static const PRInt32 kGUIDLength = 36;
|
||||
// length of a GUID + .dmp" (yes, trailing double quote)
|
||||
static const PRInt32 kMinidumpFilenameLength =
|
||||
kGUIDLength + sizeof(dumpFileExtension) / sizeof(dumpFileExtension[0]);
|
||||
|
||||
#ifdef XP_WIN32
|
||||
static TCHAR crashReporterExe[MAX_PATH] = L"\0";
|
||||
static TCHAR minidumpPath[MAX_PATH] = L"\0";
|
||||
NS_NAMED_LITERAL_STRING(crashReporterFilename, "crashreporter.exe");
|
||||
#else
|
||||
NS_NAMED_LITERAL_STRING(crashReporterFilename, "crashreporter");
|
||||
#endif
|
||||
|
||||
void AirbagMinidumpCallback(const std::wstring &minidump_id,
|
||||
void *context, bool succeeded)
|
||||
static google_airbag::ExceptionHandler* gExceptionHandler = nsnull;
|
||||
|
||||
// for ease of replacing the dump path when someone
|
||||
// calls SetMinidumpPath
|
||||
static nsString crashReporterCmdLine_withoutDumpPath;
|
||||
// this is set up so we don't have to do heap allocation in the handler
|
||||
static PRUnichar* crashReporterCmdLine = nsnull;
|
||||
// points at the end of the previous string
|
||||
// so we can append the minidump filename
|
||||
static PRUnichar* crashReporterCmdLineEnd = nsnull;
|
||||
// space to hold a filename for the API data
|
||||
static PRUnichar* crashReporterAPIDataFilename = nsnull;
|
||||
static PRUnichar* crashReporterAPIDataFilenameEnd = nsnull;
|
||||
|
||||
// this holds additional data sent via the API
|
||||
static nsCString crashReporterAPIData;
|
||||
|
||||
static void MinidumpCallback(const wstring &minidump_id,
|
||||
void *context, bool succeeded)
|
||||
{
|
||||
// append minidump filename to command line
|
||||
memcpy(crashReporterCmdLineEnd, minidump_id.c_str(),
|
||||
kGUIDLength * sizeof(PRUnichar));
|
||||
// this will copy the null terminator as well
|
||||
memcpy(crashReporterCmdLineEnd + kGUIDLength,
|
||||
dumpFileExtension, sizeof(dumpFileExtension));
|
||||
|
||||
// append minidump filename to API data filename
|
||||
memcpy(crashReporterAPIDataFilenameEnd, minidump_id.c_str(),
|
||||
kGUIDLength * sizeof(PRUnichar));
|
||||
// this will copy the null terminator as well
|
||||
memcpy(crashReporterAPIDataFilenameEnd + kGUIDLength,
|
||||
extraFileExtension, sizeof(extraFileExtension));
|
||||
|
||||
#ifdef XP_WIN32
|
||||
if (!crashReporterAPIData.IsEmpty()) {
|
||||
// write out API data
|
||||
HANDLE hFile = CreateFile(crashReporterAPIDataFilename, GENERIC_WRITE, 0,
|
||||
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
|
||||
NULL);
|
||||
if(hFile != INVALID_HANDLE_VALUE) {
|
||||
DWORD nBytes;
|
||||
WriteFile(hFile, crashReporterAPIData.get(),
|
||||
crashReporterAPIData.Length(), &nBytes, NULL);
|
||||
CloseHandle(hFile);
|
||||
}
|
||||
}
|
||||
|
||||
STARTUPINFO si;
|
||||
PROCESS_INFORMATION pi;
|
||||
TCHAR cmdLine[2*MAX_PATH];
|
||||
|
||||
ZeroMemory(&si, sizeof(si));
|
||||
si.cb = sizeof(si);
|
||||
@ -71,11 +136,8 @@ void AirbagMinidumpCallback(const std::wstring &minidump_id,
|
||||
si.wShowWindow = SW_SHOWNORMAL;
|
||||
ZeroMemory(&pi, sizeof(pi));
|
||||
|
||||
wcscat(minidumpPath, minidump_id.c_str());
|
||||
wcscat(minidumpPath, L".dmp");
|
||||
wsprintf(cmdLine, L"\"%s\" \"%s\"", crashReporterExe, minidumpPath);
|
||||
|
||||
if (CreateProcess(NULL, cmdLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) {
|
||||
if (CreateProcess(NULL, (LPWSTR)crashReporterCmdLine, NULL, NULL, FALSE, 0,
|
||||
NULL, NULL, &si, &pi)) {
|
||||
CloseHandle( pi.hProcess );
|
||||
CloseHandle( pi.hThread );
|
||||
}
|
||||
@ -84,9 +146,65 @@ void AirbagMinidumpCallback(const std::wstring &minidump_id,
|
||||
#endif
|
||||
}
|
||||
|
||||
nsresult SetAirbagExceptionHandler()
|
||||
static nsresult BuildCommandLine(const nsAString &tempPath)
|
||||
{
|
||||
if (gAirbagExceptionHandler)
|
||||
nsString crashReporterCmdLine_temp =
|
||||
crashReporterCmdLine_withoutDumpPath + NS_LITERAL_STRING(" \"") + tempPath;
|
||||
PRInt32 cmdLineLength = crashReporterCmdLine_temp.Length();
|
||||
|
||||
// allocate extra space for minidump file name
|
||||
crashReporterCmdLine_temp.SetLength(cmdLineLength + kMinidumpFilenameLength
|
||||
+ 1);
|
||||
crashReporterCmdLine = ToNewUnicode(crashReporterCmdLine_temp);
|
||||
crashReporterCmdLineEnd = crashReporterCmdLine + cmdLineLength;
|
||||
|
||||
// build API data filename
|
||||
if(crashReporterAPIDataFilename != nsnull) {
|
||||
NS_Free(crashReporterAPIDataFilename);
|
||||
crashReporterAPIDataFilename = nsnull;
|
||||
}
|
||||
|
||||
nsString apiDataFilename_temp(tempPath);
|
||||
PRInt32 filenameLength = apiDataFilename_temp.Length();
|
||||
apiDataFilename_temp.SetLength(filenameLength + kMinidumpFilenameLength + 1);
|
||||
crashReporterAPIDataFilename = ToNewUnicode(apiDataFilename_temp);
|
||||
crashReporterAPIDataFilenameEnd =
|
||||
crashReporterAPIDataFilename + filenameLength;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static nsresult GetExecutablePath(nsString& exePath)
|
||||
{
|
||||
#ifdef XP_WIN32
|
||||
// sort of arbitrary, but MAX_PATH is kinda small
|
||||
exePath.SetLength(4096);
|
||||
if (!GetModuleFileName(NULL, (LPWSTR)exePath.BeginWriting(), 4096))
|
||||
return NS_ERROR_FAILURE;
|
||||
#else
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
#endif
|
||||
|
||||
#ifdef XP_WIN32
|
||||
NS_NAMED_LITERAL_STRING(pathSep, "\\");
|
||||
#else
|
||||
NS_NAMED_LITERAL_STRING(pathSep, "/");
|
||||
#endif
|
||||
|
||||
PRInt32 lastSlash = exePath.RFind(pathSep);
|
||||
if (lastSlash < 0)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
exePath.Truncate(lastSlash + 1);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult SetExceptionHandler(nsILocalFile* aXREDirectory)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
if (gExceptionHandler)
|
||||
return NS_ERROR_ALREADY_INITIALIZED;
|
||||
|
||||
// check environment var to see if we're enabled.
|
||||
@ -95,64 +213,153 @@ nsresult SetAirbagExceptionHandler()
|
||||
// so it must exist and be set to a non-zero value.
|
||||
const char *airbagEnv = PR_GetEnv("MOZ_AIRBAG");
|
||||
if (airbagEnv == NULL || atoi(airbagEnv) == 0)
|
||||
return NS_OK;
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
// locate crashreporter executable
|
||||
nsString exePath;
|
||||
|
||||
if (aXREDirectory) {
|
||||
aXREDirectory->GetPath(exePath);
|
||||
}
|
||||
else {
|
||||
rv = GetExecutablePath(exePath);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// note that we enclose the exe filename in double quotes
|
||||
crashReporterCmdLine_withoutDumpPath = NS_LITERAL_STRING("\"") +
|
||||
exePath + crashReporterFilename + NS_LITERAL_STRING("\"");
|
||||
|
||||
// get temp path to use for minidump path
|
||||
nsString tempPath;
|
||||
#ifdef XP_WIN32
|
||||
//TODO: check registry to see if crash reporting is enabled
|
||||
if (!GetTempPath(MAX_PATH, minidumpPath))
|
||||
// first figure out buffer size
|
||||
int pathLen = GetTempPath(0, NULL);
|
||||
if (pathLen == 0)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
std::wstring tempStr(minidumpPath);
|
||||
gAirbagExceptionHandler = new google_airbag::ExceptionHandler(tempStr,
|
||||
AirbagMinidumpCallback,
|
||||
nsnull,
|
||||
true);
|
||||
if (GetModuleFileName(NULL, crashReporterExe, MAX_PATH)) {
|
||||
// get crashreporter exe
|
||||
LPTSTR s = wcsrchr(crashReporterExe, '\\');
|
||||
if (s) {
|
||||
s++;
|
||||
wcscpy(s, L"crashreporter.exe");
|
||||
}
|
||||
}
|
||||
#else
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
tempPath.SetLength(pathLen);
|
||||
GetTempPath(pathLen, (LPWSTR)tempPath.BeginWriting());
|
||||
#endif
|
||||
|
||||
if (!gAirbagExceptionHandler)
|
||||
rv = BuildCommandLine(tempPath);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// finally, set the exception handler
|
||||
gExceptionHandler = new google_airbag::ExceptionHandler(
|
||||
PromiseFlatString(tempPath).get(),
|
||||
MinidumpCallback,
|
||||
nsnull,
|
||||
true);
|
||||
|
||||
if (!gExceptionHandler)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult SetAirbagMinidumpPath(const nsAString* aPath)
|
||||
nsresult SetMinidumpPath(const nsAString& aPath)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aPath);
|
||||
|
||||
if (!gAirbagExceptionHandler)
|
||||
if (!gExceptionHandler)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
std::wstring path;
|
||||
#ifdef XP_WIN32
|
||||
wcsncpy(minidumpPath, PromiseFlatString(*aPath).get(), MAX_PATH);
|
||||
path = std::wstring(minidumpPath);
|
||||
int l = wcslen(minidumpPath);
|
||||
if (minidumpPath[l-1] != '\\' && l < MAX_PATH - 1) {
|
||||
minidumpPath[l] = '\\';
|
||||
minidumpPath[l+1] = '\0';
|
||||
if(crashReporterCmdLine != nsnull) {
|
||||
NS_Free(crashReporterCmdLine);
|
||||
crashReporterCmdLine = nsnull;
|
||||
}
|
||||
|
||||
#ifdef XP_WIN32
|
||||
NS_NAMED_LITERAL_STRING(pathSep, "\\");
|
||||
#else
|
||||
NS_NAMED_LITERAL_STRING(pathSep, "/");
|
||||
#endif
|
||||
gAirbagExceptionHandler->set_dump_path(path);
|
||||
|
||||
nsresult rv;
|
||||
|
||||
if(!StringEndsWith(aPath, pathSep)) {
|
||||
rv = BuildCommandLine(aPath + pathSep);
|
||||
}
|
||||
else {
|
||||
rv = BuildCommandLine(aPath);
|
||||
}
|
||||
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
gExceptionHandler->set_dump_path(PromiseFlatString(aPath).get());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult UnsetAirbagExceptionHandler()
|
||||
nsresult UnsetExceptionHandler()
|
||||
{
|
||||
if (!gAirbagExceptionHandler)
|
||||
if (!gExceptionHandler)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
delete gAirbagExceptionHandler;
|
||||
gAirbagExceptionHandler = nsnull;
|
||||
delete gExceptionHandler;
|
||||
gExceptionHandler = nsnull;
|
||||
|
||||
if(crashReporterCmdLine != nsnull) {
|
||||
NS_Free(crashReporterCmdLine);
|
||||
crashReporterCmdLine = nsnull;
|
||||
}
|
||||
|
||||
if(crashReporterAPIDataFilename != nsnull) {
|
||||
NS_Free(crashReporterAPIDataFilename);
|
||||
crashReporterAPIDataFilename = nsnull;
|
||||
}
|
||||
|
||||
crashReporterCmdLineEnd = nsnull;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static void ReplaceChar(nsCString& str, const nsACString& character,
|
||||
const nsACString& replacement)
|
||||
{
|
||||
nsCString::const_iterator start, end;
|
||||
|
||||
str.BeginReading(start);
|
||||
str.EndReading(end);
|
||||
|
||||
while (FindInReadable(character, start, end)) {
|
||||
PRInt32 pos = end.size_backward();
|
||||
str.Replace(pos - 1, 1, replacement);
|
||||
|
||||
str.BeginReading(start);
|
||||
start.advance(pos + replacement.Length() - 1);
|
||||
str.EndReading(end);
|
||||
}
|
||||
}
|
||||
|
||||
static PRBool DoFindInReadable(const nsACString& str, const nsACString& value)
|
||||
{
|
||||
nsACString::const_iterator start, end;
|
||||
str.BeginReading(start);
|
||||
str.EndReading(end);
|
||||
|
||||
return FindInReadable(value, start, end);
|
||||
}
|
||||
|
||||
nsresult AnnotateCrashReport(const nsACString &key, const nsACString &data)
|
||||
{
|
||||
if (!gExceptionHandler)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
if (DoFindInReadable(key, NS_LITERAL_CSTRING("=")) ||
|
||||
DoFindInReadable(key, NS_LITERAL_CSTRING("\n")))
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
nsCString escapedData(data);
|
||||
|
||||
// escape backslashes
|
||||
ReplaceChar(escapedData, NS_LITERAL_CSTRING("\\"),
|
||||
NS_LITERAL_CSTRING("\\\\"));
|
||||
// escape newlines
|
||||
ReplaceChar(escapedData, NS_LITERAL_CSTRING("\n"),
|
||||
NS_LITERAL_CSTRING("\\n"));
|
||||
|
||||
crashReporterAPIData.Append(key + NS_LITERAL_CSTRING("=") + escapedData +
|
||||
NS_LITERAL_CSTRING("\n"));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace CrashReporter
|
||||
|
@ -42,8 +42,11 @@
|
||||
#include "nsXPCOM.h"
|
||||
#include "nsStringGlue.h"
|
||||
|
||||
nsresult SetAirbagExceptionHandler();
|
||||
nsresult SetAirbagMinidumpPath(const nsAString* aPath);
|
||||
nsresult UnsetAirbagExceptionHandler();
|
||||
namespace CrashReporter {
|
||||
nsresult SetExceptionHandler(nsILocalFile* aXREDirectory);
|
||||
nsresult SetMinidumpPath(const nsAString& aPath);
|
||||
nsresult UnsetExceptionHandler();
|
||||
nsresult AnnotateCrashReport(const nsACString &key, const nsACString &data);
|
||||
}
|
||||
|
||||
#endif /* nsAirbagExceptionHandler_h__ */
|
||||
|
Loading…
Reference in New Issue
Block a user