bug 444103 - add ability to add string-formatted notes to crash report

This commit is contained in:
Ted Mielczarek 2008-07-25 16:54:41 -04:00
Родитель b612e8907b
Коммит 38dc60766a
5 изменённых файлов: 141 добавлений и 31 удалений

Просмотреть файл

@ -136,6 +136,7 @@ static const int kTimeSinceLastCrashParameterLen =
// this holds additional data sent via the API
static nsDataHashtable<nsCStringHashKey,nsCString>* crashReporterAPIData_Hash;
static nsCString* crashReporterAPIData = nsnull;
static nsCString* notesField = nsnull;
static XP_CHAR*
Concat(XP_CHAR* str, const XP_CHAR* toAppend, int* size)
@ -340,6 +341,9 @@ nsresult SetExceptionHandler(nsILocalFile* aXREDirectory,
rv = crashReporterAPIData_Hash->Init();
NS_ENSURE_SUCCESS(rv, rv);
notesField = new nsCString();
NS_ENSURE_TRUE(notesField, NS_ERROR_OUT_OF_MEMORY);
// locate crashreporter executable
nsCOMPtr<nsIFile> exePath;
rv = aXREDirectory->Clone(getter_AddRefs(exePath));
@ -696,6 +700,11 @@ nsresult UnsetExceptionHandler()
crashReporterAPIData = nsnull;
}
if (notesField) {
delete notesField;
notesField = nsnull;
}
if (crashReporterPath) {
NS_Free(crashReporterPath);
crashReporterPath = nsnull;
@ -778,6 +787,32 @@ nsresult AnnotateCrashReport(const nsACString &key, const nsACString &data)
return NS_OK;
}
nsresult AppendAppNotesToCrashReport(const nsACString& data)
{
if (!gExceptionHandler)
return NS_ERROR_NOT_INITIALIZED;
if (DoFindInReadable(data, NS_LITERAL_CSTRING("\0")))
return NS_ERROR_INVALID_ARG;
notesField->Append(data);
return AnnotateCrashReport(NS_LITERAL_CSTRING("Notes"), *notesField);
}
// Returns true if found, false if not found.
bool GetAnnotation(const nsACString& key, nsACString& data)
{
if (!gExceptionHandler)
return NS_ERROR_NOT_INITIALIZED;
nsCAutoString entry;
if (!crashReporterAPIData_Hash->Get(key, &entry))
return false;
data = entry;
return true;
}
nsresult
SetRestartArgs(int argc, char** argv)
{

Просмотреть файл

@ -55,6 +55,7 @@ nsresult SetExceptionHandler(nsILocalFile* aXREDirectory,
nsresult SetMinidumpPath(const nsAString& aPath);
nsresult UnsetExceptionHandler();
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);

Просмотреть файл

@ -49,27 +49,36 @@
#include "nsILocalFile.h"
#include "nsExceptionHandler.h"
#include "nsICrashReporter.h"
#define mu_assert(message, test) do { if (NS_FAILED(test)) \
return message; } while (0)
#define mu_assert_failure(message, test) do { if (NS_SUCCEEDED(test)) \
return message; } while (0)
#define mu_run_test(test) do { char *message = test(); tests_run++; \
// Defined in nsExceptionHandler.cpp, but not normally exposed
namespace CrashReporter {
bool GetAnnotation(const nsACString& key, nsACString& data);
};
#define ok(message, test) do { \
if (!(test)) \
return message; \
} while (0)
#define equals(message, a, b) ok(message, a == b)
#define ok_nsresult(message, rv) ok(message, NS_SUCCEEDED(rv))
#define fail_nsresult(message, rv) ok(message, NS_FAILED(rv))
#define run_test(test) do { char *message = test(); tests_run++; \
if (message) return message; } while (0)
int tests_run;
char *
test_init_exception_handler()
{
nsCOMPtr<nsILocalFile> lf;
// we don't plan on launching the crash reporter in this app anyway,
// so it's ok to pass a bogus nsILocalFile
mu_assert("NS_NewNativeLocalFile", NS_NewNativeLocalFile(EmptyCString(),
ok_nsresult("NS_NewNativeLocalFile", NS_NewNativeLocalFile(EmptyCString(),
PR_TRUE,
getter_AddRefs(lf)));
mu_assert("CrashReporter::SetExceptionHandler",
ok_nsresult("CrashReporter::SetExceptionHandler",
CrashReporter::SetExceptionHandler(lf, nsnull));
return 0;
}
@ -81,19 +90,19 @@ test_set_minidump_path()
nsCOMPtr<nsIProperties> directoryService =
do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
mu_assert("do_GetService", rv);
ok_nsresult("do_GetService", rv);
nsCOMPtr<nsILocalFile> currentDirectory;
rv = directoryService->Get(NS_XPCOM_CURRENT_PROCESS_DIR,
NS_GET_IID(nsILocalFile),
getter_AddRefs(currentDirectory));
mu_assert("directoryService->Get", rv);
ok_nsresult("directoryService->Get", rv);
nsAutoString currentDirectoryPath;
rv = currentDirectory->GetPath(currentDirectoryPath);
mu_assert("currentDirectory->GetPath", rv);
ok_nsresult("currentDirectory->GetPath", rv);
mu_assert("CrashReporter::SetMinidumpPath",
ok_nsresult("CrashReporter::SetMinidumpPath",
CrashReporter::SetMinidumpPath(currentDirectoryPath));
return 0;
@ -102,17 +111,62 @@ test_set_minidump_path()
char *
test_annotate_crash_report_basic()
{
mu_assert("CrashReporter::AnnotateCrashReport: basic",
ok_nsresult("CrashReporter::AnnotateCrashReport: basic 1",
CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("test"),
NS_LITERAL_CSTRING("some data")));
nsCAutoString result;
ok("CrashReporter::GetAnnotation", CrashReporter::GetAnnotation(NS_LITERAL_CSTRING("test"),
result));
nsCString msg = result + NS_LITERAL_CSTRING(" == ") +
NS_LITERAL_CSTRING("some data");
equals((char*)PromiseFlatCString(msg).get(), result,
NS_LITERAL_CSTRING("some data"));
// now replace it with something else
ok_nsresult("CrashReporter::AnnotateCrashReport: basic 2",
CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("test"),
NS_LITERAL_CSTRING("some other data")));
ok("CrashReporter::GetAnnotation", CrashReporter::GetAnnotation(NS_LITERAL_CSTRING("test"),
result));
msg = result + NS_LITERAL_CSTRING(" == ") +
NS_LITERAL_CSTRING("some other data");
equals((char*)PromiseFlatCString(msg).get(), result,
NS_LITERAL_CSTRING("some other data"));
return 0;
}
char *
test_appendnotes_crash_report()
{
// Append two notes
ok_nsresult("CrashReporter::AppendAppNotesToCrashReport: 1",
CrashReporter::AppendAppNotesToCrashReport(NS_LITERAL_CSTRING("some data")));
ok_nsresult("CrashReporter::AppendAppNotesToCrashReport: 2",
CrashReporter::AppendAppNotesToCrashReport(NS_LITERAL_CSTRING("some other data")));
// ensure that the result is correct
nsCAutoString result;
ok("CrashReporter::GetAnnotation",
CrashReporter::GetAnnotation(NS_LITERAL_CSTRING("Notes"),
result));
nsCString msg = result + NS_LITERAL_CSTRING(" == ") +
NS_LITERAL_CSTRING("some datasome other data");
equals((char*)PromiseFlatCString(msg).get(), result,
NS_LITERAL_CSTRING("some datasome other data"));
return 0;
}
char *
test_annotate_crash_report_invalid_equals()
{
mu_assert_failure("CrashReporter::AnnotateCrashReport: invalid = in key",
fail_nsresult("CrashReporter::AnnotateCrashReport: invalid = in key",
CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("test=something"),
NS_LITERAL_CSTRING("some data")));
return 0;
@ -121,7 +175,7 @@ test_annotate_crash_report_invalid_equals()
char *
test_annotate_crash_report_invalid_cr()
{
mu_assert_failure("CrashReporter::AnnotateCrashReport: invalid \n in key",
fail_nsresult("CrashReporter::AnnotateCrashReport: invalid \n in key",
CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("test\nsomething"),
NS_LITERAL_CSTRING("some data")));
return 0;
@ -130,19 +184,20 @@ test_annotate_crash_report_invalid_cr()
char *
test_unset_exception_handler()
{
mu_assert("CrashReporter::UnsetExceptionHandler",
ok_nsresult("CrashReporter::UnsetExceptionHandler",
CrashReporter::UnsetExceptionHandler());
return 0;
}
static char* all_tests()
{
mu_run_test(test_init_exception_handler);
mu_run_test(test_set_minidump_path);
mu_run_test(test_annotate_crash_report_basic);
mu_run_test(test_annotate_crash_report_invalid_equals);
mu_run_test(test_annotate_crash_report_invalid_cr);
mu_run_test(test_unset_exception_handler);
run_test(test_init_exception_handler);
run_test(test_set_minidump_path);
run_test(test_annotate_crash_report_basic);
run_test(test_annotate_crash_report_invalid_equals);
run_test(test_annotate_crash_report_invalid_cr);
run_test(test_appendnotes_crash_report);
run_test(test_unset_exception_handler);
return 0;
}
@ -155,10 +210,10 @@ main (int argc, char **argv)
char* result = all_tests();
if (result != 0) {
printf("FAIL: %s\n", result);
printf("TEST-UNEXPECTED-FAIL | %s | %s\n", __FILE__, result);
}
else {
printf("ALL TESTS PASSED\n");
printf("TEST-PASS | %s | all tests passed\n", __FILE__);
}
printf("Tests run: %d\n", tests_run);

Просмотреть файл

@ -836,6 +836,12 @@ nsXULAppInfo::AnnotateCrashReport(const nsACString& key,
return CrashReporter::AnnotateCrashReport(key, data);
}
NS_IMETHODIMP
nsXULAppInfo::AppendAppNotesToCrashReport(const nsACString& data)
{
return CrashReporter::AppendAppNotesToCrashReport(data);
}
NS_IMETHODIMP
nsXULAppInfo::WriteMinidumpForException(void* aExceptionInfo)
{

Просмотреть файл

@ -60,6 +60,19 @@ interface nsICrashReporter : nsISupports
*/
void annotateCrashReport(in ACString key, in ACString data);
/**
* Append some data to the "Notes" field, to be submitted with a crash report.
* Unlike annotateCrashReport, this method will append to existing data.
*
* @param data
* Data to be added.
*
* @throw NS_ERROR_NOT_INITIALIZED if crash reporting not initialized
* @throw NS_ERROR_INVALID_ARG if or data contains invalid characters.
* The only invalid character is '\0'.
*/
void appendAppNotesToCrashReport(in ACString data);
/**
* Write a minidump immediately, with the user-supplied exception
* information. This is implemented on Windows only, because