зеркало из https://github.com/mozilla/gecko-dev.git
Improve crash reporter errors. b=385359, r=luser
This commit is contained in:
Родитель
7792764eb4
Коммит
6cb5c63b15
|
@ -68,6 +68,22 @@ static string gExtraFile;
|
||||||
|
|
||||||
static string kExtraDataExtension = ".extra";
|
static string kExtraDataExtension = ".extra";
|
||||||
|
|
||||||
|
void UIError(const string& message)
|
||||||
|
{
|
||||||
|
string errorMessage;
|
||||||
|
if (!gStrings[ST_CRASHREPORTERERROR].empty()) {
|
||||||
|
char buf[2048];
|
||||||
|
UI_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)
|
static string Unescape(const string& str)
|
||||||
{
|
{
|
||||||
string ret;
|
string ret;
|
||||||
|
@ -210,14 +226,20 @@ static bool MoveCrashData(const string& toDir,
|
||||||
string& extrafile)
|
string& extrafile)
|
||||||
{
|
{
|
||||||
if (!UIEnsurePathExists(toDir)) {
|
if (!UIEnsurePathExists(toDir)) {
|
||||||
|
UIError(gStrings[ST_ERROR_CREATEDUMPDIR]);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
string newDump = toDir + UI_DIR_SEPARATOR + Basename(dumpfile);
|
string newDump = toDir + UI_DIR_SEPARATOR + Basename(dumpfile);
|
||||||
string newExtra = toDir + UI_DIR_SEPARATOR + Basename(extrafile);
|
string newExtra = toDir + UI_DIR_SEPARATOR + Basename(extrafile);
|
||||||
|
|
||||||
if (!UIMoveFile(dumpfile, newDump) ||
|
if (!UIMoveFile(dumpfile, newDump)) {
|
||||||
!UIMoveFile(extrafile, newExtra)) {
|
UIError(gStrings[ST_ERROR_DUMPFILEMOVE]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!UIMoveFile(extrafile, newExtra)) {
|
||||||
|
UIError(gStrings[ST_ERROR_EXTRAFILEMOVE]);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -288,13 +310,52 @@ bool SendCompleted(bool success, const string& serverResponse)
|
||||||
|
|
||||||
using namespace CrashReporter;
|
using namespace CrashReporter;
|
||||||
|
|
||||||
|
void RewriteStrings(StringTable& queryParameters)
|
||||||
|
{
|
||||||
|
// rewrite some UI strings with the values from the query parameters
|
||||||
|
string product = queryParameters["ProductName"];
|
||||||
|
string vendor = queryParameters["Vendor"];
|
||||||
|
if (vendor.empty()) {
|
||||||
|
// Assume Mozilla if no vendor is specified
|
||||||
|
vendor = "Mozilla";
|
||||||
|
}
|
||||||
|
|
||||||
|
char buf[4096];
|
||||||
|
UI_SNPRINTF(buf, sizeof(buf),
|
||||||
|
gStrings[ST_CRASHREPORTERVENDORTITLE].c_str(),
|
||||||
|
vendor.c_str());
|
||||||
|
gStrings[ST_CRASHREPORTERTITLE] = buf;
|
||||||
|
|
||||||
|
// Leave a format specifier for UIError to fill in
|
||||||
|
UI_SNPRINTF(buf, sizeof(buf),
|
||||||
|
gStrings[ST_CRASHREPORTERPRODUCTERROR].c_str(),
|
||||||
|
product.c_str(),
|
||||||
|
"%s");
|
||||||
|
gStrings[ST_CRASHREPORTERERROR] = buf;
|
||||||
|
|
||||||
|
UI_SNPRINTF(buf, sizeof(buf),
|
||||||
|
gStrings[ST_CRASHREPORTERDESCRIPTION].c_str(),
|
||||||
|
product.c_str());
|
||||||
|
gStrings[ST_CRASHREPORTERDESCRIPTION] = buf;
|
||||||
|
|
||||||
|
UI_SNPRINTF(buf, sizeof(buf),
|
||||||
|
gStrings[ST_CHECKSUBMIT].c_str(),
|
||||||
|
vendor.c_str());
|
||||||
|
gStrings[ST_CHECKSUBMIT] = buf;
|
||||||
|
|
||||||
|
UI_SNPRINTF(buf, sizeof(buf),
|
||||||
|
gStrings[ST_RESTART].c_str(),
|
||||||
|
product.c_str());
|
||||||
|
gStrings[ST_RESTART] = buf;
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
gArgc = argc;
|
gArgc = argc;
|
||||||
gArgv = argv;
|
gArgv = argv;
|
||||||
|
|
||||||
if (!ReadConfig()) {
|
if (!ReadConfig()) {
|
||||||
UIError("Couldn't read configuration");
|
UIError("Couldn't read configuration.");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -311,36 +372,49 @@ int main(int argc, char** argv)
|
||||||
} else {
|
} else {
|
||||||
gExtraFile = GetExtraDataFilename(gDumpFile);
|
gExtraFile = GetExtraDataFilename(gDumpFile);
|
||||||
if (gExtraFile.empty()) {
|
if (gExtraFile.empty()) {
|
||||||
UIError("Couldn't get extra data filename");
|
UIError(gStrings[ST_ERROR_BADARGUMENTS]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!UIFileExists(gExtraFile)) {
|
||||||
|
UIError(gStrings[ST_ERROR_EXTRAFILEEXISTS]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
StringTable queryParameters;
|
StringTable queryParameters;
|
||||||
if (!ReadStringsFromFile(gExtraFile, queryParameters, true)) {
|
if (!ReadStringsFromFile(gExtraFile, queryParameters, true)) {
|
||||||
UIError("Couldn't read extra data");
|
UIError(gStrings[ST_ERROR_EXTRAFILEREAD]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (queryParameters.find("ProductName") == queryParameters.end()) {
|
if (queryParameters.find("ProductName") == queryParameters.end()) {
|
||||||
UIError("No product name specified");
|
UIError(gStrings[ST_ERROR_NOPRODUCTNAME]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// There is enough information in the extra file to rewrite strings
|
||||||
|
// to be product specific
|
||||||
|
RewriteStrings(queryParameters);
|
||||||
|
|
||||||
if (queryParameters.find("ServerURL") == queryParameters.end()) {
|
if (queryParameters.find("ServerURL") == queryParameters.end()) {
|
||||||
UIError("No server URL specified");
|
UIError(gStrings[ST_ERROR_NOSERVERURL]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
string product = queryParameters["ProductName"];
|
string product = queryParameters["ProductName"];
|
||||||
string vendor = queryParameters["Vendor"];
|
string vendor = queryParameters["Vendor"];
|
||||||
if (!UIGetSettingsPath(vendor, product, gSettingsPath)) {
|
if (!UIGetSettingsPath(vendor, product, gSettingsPath)) {
|
||||||
UIError("Couldn't get settings path");
|
UIError(gStrings[ST_ERROR_NOSETTINGSPATH]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!UIFileExists(gDumpFile)) {
|
||||||
|
UIError(gStrings[ST_ERROR_DUMPFILEEXISTS]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
string pendingDir = gSettingsPath + UI_DIR_SEPARATOR + "pending";
|
string pendingDir = gSettingsPath + UI_DIR_SEPARATOR + "pending";
|
||||||
if (!MoveCrashData(pendingDir, gDumpFile, gExtraFile)) {
|
if (!MoveCrashData(pendingDir, gDumpFile, gExtraFile)) {
|
||||||
UIError("Couldn't move crash data");
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -370,28 +444,6 @@ int main(int argc, char** argv)
|
||||||
sendURL = urlEnv;
|
sendURL = urlEnv;
|
||||||
}
|
}
|
||||||
|
|
||||||
// rewrite some UI strings with the values from the query parameters
|
|
||||||
char buf[4096];
|
|
||||||
UI_SNPRINTF(buf, sizeof(buf),
|
|
||||||
gStrings[ST_RESTART].c_str(),
|
|
||||||
product.c_str());
|
|
||||||
gStrings[ST_RESTART] = buf;
|
|
||||||
|
|
||||||
UI_SNPRINTF(buf, sizeof(buf),
|
|
||||||
gStrings[ST_CRASHREPORTERDESCRIPTION].c_str(),
|
|
||||||
product.c_str());
|
|
||||||
gStrings[ST_CRASHREPORTERDESCRIPTION] = buf;
|
|
||||||
|
|
||||||
UI_SNPRINTF(buf, sizeof(buf),
|
|
||||||
gStrings[ST_CHECKSUBMIT].c_str(),
|
|
||||||
vendor.empty() ? "Mozilla" : vendor.c_str());
|
|
||||||
gStrings[ST_CHECKSUBMIT] = buf;
|
|
||||||
|
|
||||||
UI_SNPRINTF(buf, sizeof(buf),
|
|
||||||
gStrings[ST_CRASHREPORTERTITLE].c_str(),
|
|
||||||
vendor.empty() ? "Mozilla" : vendor.c_str());
|
|
||||||
gStrings[ST_CRASHREPORTERTITLE] = buf;
|
|
||||||
|
|
||||||
UIShowCrashUI(gDumpFile, queryParameters, sendURL, restartArgs);
|
UIShowCrashUI(gDumpFile, queryParameters, sendURL, restartArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,17 +29,31 @@
|
||||||
|
|
||||||
typedef std::map<std::string, std::string> StringTable;
|
typedef std::map<std::string, std::string> StringTable;
|
||||||
|
|
||||||
#define ST_CRASHREPORTERTITLE "CrashReporterTitle"
|
#define ST_CRASHREPORTERTITLE "CrashReporterTitle"
|
||||||
#define ST_CRASHREPORTERHEADER "CrashReporterHeader"
|
#define ST_CRASHREPORTERVENDORTITLE "CrashReporterVendorTitle"
|
||||||
#define ST_CRASHREPORTERDESCRIPTION "CrashReporterDescription"
|
#define ST_CRASHREPORTERERROR "CrashReporterError"
|
||||||
#define ST_CRASHREPORTERDEFAULT "CrashReporterDefault"
|
#define ST_CRASHREPORTERPRODUCTERROR "CrashReporterProductError"
|
||||||
#define ST_VIEWREPORT "ViewReport"
|
#define ST_CRASHREPORTERHEADER "CrashReporterHeader"
|
||||||
#define ST_EXTRAREPORTINFO "ExtraReportInfo"
|
#define ST_CRASHREPORTERDESCRIPTION "CrashReporterDescription"
|
||||||
#define ST_CHECKSUBMIT "CheckSubmit"
|
#define ST_CRASHREPORTERDEFAULT "CrashReporterDefault"
|
||||||
#define ST_CHECKEMAIL "CheckEmail"
|
#define ST_VIEWREPORT "ViewReport"
|
||||||
#define ST_CLOSE "Close"
|
#define ST_EXTRAREPORTINFO "ExtraReportInfo"
|
||||||
#define ST_RESTART "Restart"
|
#define ST_CHECKSUBMIT "CheckSubmit"
|
||||||
#define ST_SUBMITFAILED "SubmitFailed"
|
#define ST_CHECKEMAIL "CheckEmail"
|
||||||
|
#define ST_CLOSE "Close"
|
||||||
|
#define ST_RESTART "Restart"
|
||||||
|
#define ST_SUBMITFAILED "SubmitFailed"
|
||||||
|
|
||||||
|
#define ST_ERROR_BADARGUMENTS "ErrorBadArguments"
|
||||||
|
#define ST_ERROR_EXTRAFILEEXISTS "ErrorExtraFileExists"
|
||||||
|
#define ST_ERROR_EXTRAFILEREAD "ErrorExtraFileRead"
|
||||||
|
#define ST_ERROR_EXTRAFILEMOVE "ErrorExtraFileMove"
|
||||||
|
#define ST_ERROR_DUMPFILEEXISTS "ErrorDumpFileExists"
|
||||||
|
#define ST_ERROR_DUMPFILEMOVE "ErrorDumpFileMove"
|
||||||
|
#define ST_ERROR_NOPRODUCTNAME "ErrorNoProductName"
|
||||||
|
#define ST_ERROR_NOSERVERURL "ErrorNoServerURL"
|
||||||
|
#define ST_ERROR_NOSETTINGSPATH "ErrorNoSettingsPath"
|
||||||
|
#define ST_ERROR_CREATEDUMPDIR "ErrorCreateDumpDir"
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
// implemented in crashreporter.cpp
|
// implemented in crashreporter.cpp
|
||||||
|
@ -51,6 +65,8 @@ namespace CrashReporter {
|
||||||
extern int gArgc;
|
extern int gArgc;
|
||||||
extern char** gArgv;
|
extern char** gArgv;
|
||||||
|
|
||||||
|
void UIError(const std::string& message);
|
||||||
|
|
||||||
// The UI finished sending the report
|
// The UI finished sending the report
|
||||||
bool SendCompleted(bool success, const std::string& serverResponse);
|
bool SendCompleted(bool success, const std::string& serverResponse);
|
||||||
|
|
||||||
|
@ -87,13 +103,14 @@ void UIShowCrashUI(const std::string& dumpfile,
|
||||||
const std::string& sendURL,
|
const std::string& sendURL,
|
||||||
const std::vector<std::string>& restartArgs);
|
const std::vector<std::string>& restartArgs);
|
||||||
|
|
||||||
void UIError(const std::string& message);
|
void UIError_impl(const std::string& message);
|
||||||
|
|
||||||
bool UIGetIniPath(std::string& path);
|
bool UIGetIniPath(std::string& path);
|
||||||
bool UIGetSettingsPath(const std::string& vendor,
|
bool UIGetSettingsPath(const std::string& vendor,
|
||||||
const std::string& product,
|
const std::string& product,
|
||||||
std::string& settingsPath);
|
std::string& settingsPath);
|
||||||
bool UIEnsurePathExists(const std::string& path);
|
bool UIEnsurePathExists(const std::string& path);
|
||||||
|
bool UIFileExists(const std::string& path);
|
||||||
bool UIMoveFile(const std::string& oldfile, const std::string& newfile);
|
bool UIMoveFile(const std::string& oldfile, const std::string& newfile);
|
||||||
bool UIDeleteFile(const std::string& oldfile);
|
bool UIDeleteFile(const std::string& oldfile);
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
; This file is in the UTF-8 encoding
|
; This file is in the UTF-8 encoding
|
||||||
[Strings]
|
[Strings]
|
||||||
CrashReporterTitle=%s Crash Reporter
|
CrashReporterTitle=Crash Reporter
|
||||||
|
CrashReporterVendorTitle=%s Crash Reporter
|
||||||
|
CrashReporterError=We're sorry, but the application hit an unexpected problem and crashed.\n\nUnfortunately the crash reporter is unable to submit a report for this crash.\n\nDetails: %s
|
||||||
|
CrashReporterProductError=We're sorry, but %s hit an unexpected problem and crashed. We'll try to restore your tabs and windows when it restarts.\n\nUnfortunately the crash reporter is unable to submit a crash report.\n\nDetails: %s
|
||||||
CrashReporterHeader=Crash! Bang! Boom!
|
CrashReporterHeader=Crash! Bang! Boom!
|
||||||
CrashReporterDescription=We're sorry, but %s hit an unexpected problem and crashed. We'll try to restore your tabs and windows when it restarts.\n\nTo help us diagnose and repair this problem, you can send us a crash report.
|
CrashReporterDescription=We're sorry, but %s hit an unexpected problem and crashed. We'll try to restore your tabs and windows when it restarts.\n\nTo help us diagnose and repair this problem, you can send us a crash report.
|
||||||
CrashReporterDefault=This application is run after a crash to report the problem to the application vendor. It should not be run directly.
|
CrashReporterDefault=This application is run after a crash to report the problem to the application vendor. It should not be run directly.
|
||||||
|
@ -13,3 +16,15 @@ Restart=Restart %s
|
||||||
SubmitFailed=Failed to submit crash report
|
SubmitFailed=Failed to submit crash report
|
||||||
CrashID=Crash ID: %s
|
CrashID=Crash ID: %s
|
||||||
CrashDetailsURL=You can view details of this crash at %s
|
CrashDetailsURL=You can view details of this crash at %s
|
||||||
|
|
||||||
|
ErrorBadArguments=The application passed an invalid argument.
|
||||||
|
ErrorExtraFileExists=The application didn't leave an application data file.
|
||||||
|
ErrorExtraFileRead=Couldn't read the application data file.
|
||||||
|
ErrorExtraFileMove=Couldn't move application data file.
|
||||||
|
ErrorDumpFileExists=The application did not leave a crash dump file.
|
||||||
|
ErrorDumpFileMove=Couldn't move crash dump.
|
||||||
|
ErrorNoProductName=The application did not identify itself.
|
||||||
|
ErrorNoServerURL=The application did not specify a crash reporting server.
|
||||||
|
ErrorNoSettingsPath=Couldn't find the crash reporter's settings.
|
||||||
|
ErrorCreateDumpDir=Couldn't create pending dump directory.
|
||||||
|
|
||||||
|
|
|
@ -412,7 +412,7 @@ void UIShowCrashUI(const string& dumpfile,
|
||||||
gtk_main();
|
gtk_main();
|
||||||
}
|
}
|
||||||
|
|
||||||
void UIError(const string& message)
|
void UIError_impl(const string& message)
|
||||||
{
|
{
|
||||||
if (!gInitialized) {
|
if (!gInitialized) {
|
||||||
// Didn't initialize, this is the best we can do
|
// Didn't initialize, this is the best we can do
|
||||||
|
@ -477,6 +477,16 @@ bool UIEnsurePathExists(const string& path)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool UIFileExists(const string& path)
|
||||||
|
{
|
||||||
|
struct stat sb;
|
||||||
|
int ret = stat(path.c_str(), &sb);
|
||||||
|
if (ret == -1 || !(sb.st_mode & S_IFREG))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool UIMoveFile(const string& file, const string& newfile)
|
bool UIMoveFile(const string& file, const string& newfile)
|
||||||
{
|
{
|
||||||
return (rename(file.c_str(), newfile.c_str()) != -1);
|
return (rename(file.c_str(), newfile.c_str()) != -1);
|
||||||
|
|
|
@ -428,7 +428,8 @@ void UIShutdown()
|
||||||
|
|
||||||
void UIShowDefaultUI()
|
void UIShowDefaultUI()
|
||||||
{
|
{
|
||||||
UIError(gStrings[ST_CRASHREPORTERDEFAULT]);
|
[gUI showErrorUI: gStrings[ST_CRASHREPORTERDEFAULT]];
|
||||||
|
[NSApp run];
|
||||||
}
|
}
|
||||||
|
|
||||||
void UIShowCrashUI(const string& dumpfile,
|
void UIShowCrashUI(const string& dumpfile,
|
||||||
|
@ -444,7 +445,7 @@ void UIShowCrashUI(const string& dumpfile,
|
||||||
[NSApp run];
|
[NSApp run];
|
||||||
}
|
}
|
||||||
|
|
||||||
void UIError(const string& message)
|
void UIError_impl(const string& message)
|
||||||
{
|
{
|
||||||
if (!gUI) {
|
if (!gUI) {
|
||||||
// UI failed to initialize, printing is the best we can do
|
// UI failed to initialize, printing is the best we can do
|
||||||
|
@ -502,6 +503,16 @@ bool UIEnsurePathExists(const string& path)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool UIFileExists(const string& path)
|
||||||
|
{
|
||||||
|
struct stat sb;
|
||||||
|
int ret = stat(path.c_str(), &sb);
|
||||||
|
if (ret == -1 || !(sb.st_mode & S_IFREG))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool UIMoveFile(const string& file, const string& newfile)
|
bool UIMoveFile(const string& file, const string& newfile)
|
||||||
{
|
{
|
||||||
return (rename(file.c_str(), newfile.c_str()) != -1);
|
return (rename(file.c_str(), newfile.c_str()) != -1);
|
||||||
|
|
|
@ -706,7 +706,7 @@ void UIShowCrashUI(const string& dumpFile,
|
||||||
(DLGPROC)CrashReporterDialogProc, 0);
|
(DLGPROC)CrashReporterDialogProc, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UIError(const string& message)
|
void UIError_impl(const string& message)
|
||||||
{
|
{
|
||||||
wstring title = Str(ST_CRASHREPORTERTITLE);
|
wstring title = Str(ST_CRASHREPORTERTITLE);
|
||||||
if (title.empty())
|
if (title.empty())
|
||||||
|
@ -765,6 +765,12 @@ bool UIEnsurePathExists(const string& path)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool UIFileExists(const string& path)
|
||||||
|
{
|
||||||
|
DWORD attrs = GetFileAttributes(UTF8ToWide(path).c_str());
|
||||||
|
return (attrs != INVALID_FILE_ATTRIBUTES);
|
||||||
|
}
|
||||||
|
|
||||||
bool UIMoveFile(const string& oldfile, const string& newfile)
|
bool UIMoveFile(const string& oldfile, const string& newfile)
|
||||||
{
|
{
|
||||||
if (oldfile == newfile)
|
if (oldfile == newfile)
|
||||||
|
|
Загрузка…
Ссылка в новой задаче