зеркало из https://github.com/mozilla/gecko-dev.git
bug 1269998 - Prompt users with pending crash reports to submit them r=mconley ui-r=shorlander
This commit is contained in:
Родитель
5d418de2b6
Коммит
25f5af3107
|
@ -124,6 +124,11 @@ XPCOMUtils.defineLazyModuleGetter(this, "TabCrashHandler",
|
|||
if (AppConstants.MOZ_CRASHREPORTER) {
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PluginCrashReporter",
|
||||
"resource:///modules/ContentCrashHandlers.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "CrashSubmit",
|
||||
"resource://gre/modules/CrashSubmit.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PluralForm",
|
||||
"resource://gre/modules/PluralForm.jsm");
|
||||
|
||||
}
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "gBrandBundle", function() {
|
||||
|
@ -821,6 +826,57 @@ BrowserGlue.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
checkForPendingCrashReports: function() {
|
||||
// We don't process crash reports older than 28 days, so don't bother submitting them
|
||||
let numDays = 28;
|
||||
if (AppConstants.MOZ_CRASHREPORTER) {
|
||||
let dateLimit = new Date();
|
||||
dateLimit.setDate(dateLimit.getDate() - numDays);
|
||||
CrashSubmit.pendingIDsAsync(dateLimit).then(
|
||||
function onSuccess(ids) {
|
||||
let count = ids.length;
|
||||
if (count) {
|
||||
let win = RecentWindow.getMostRecentBrowserWindow();
|
||||
let nb = win.document.getElementById("global-notificationbox");
|
||||
let notification = nb.getNotificationWithValue("pending-crash-reports");
|
||||
if (notification) {
|
||||
return;
|
||||
}
|
||||
let buttons = [
|
||||
{
|
||||
label: win.gNavigatorBundle.getString("pendingCrashReports.submitAll"),
|
||||
callback: function() {
|
||||
ids.forEach(function(id) {
|
||||
CrashSubmit.submit(id, {extraExtraKeyVals: {"SubmittedFromInfobar": true}});
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
label: win.gNavigatorBundle.getString("pendingCrashReports.ignoreAll"),
|
||||
callback: function() {
|
||||
ids.forEach(function(id) {
|
||||
CrashSubmit.ignore(id);
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
label: win.gNavigatorBundle.getString("pendingCrashReports.viewAll"),
|
||||
callback: function() {
|
||||
win.openUILinkIn("about:crashes", "tab");
|
||||
}
|
||||
}
|
||||
];
|
||||
nb.appendNotification(PluralForm.get(count,
|
||||
win.gNavigatorBundle.getString("pendingCrashReports.label")).replace("#1", count),
|
||||
"pending-crash-reports",
|
||||
"chrome://browser/skin/tab-crashed.svg",
|
||||
nb.PRIORITY_INFO_HIGH, buttons);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
_onSafeModeRestart: function BG_onSafeModeRestart() {
|
||||
// prompt the user to confirm
|
||||
let strings = gBrowserBundle;
|
||||
|
@ -1071,6 +1127,10 @@ BrowserGlue.prototype = {
|
|||
|
||||
this._checkForOldBuildUpdates();
|
||||
|
||||
if ("release" != AppConstants.MOZ_UPDATE_CHANNEL) {
|
||||
this.checkForPendingCrashReports();
|
||||
}
|
||||
|
||||
this._firstWindowTelemetry(aWindow);
|
||||
this._firstWindowLoaded();
|
||||
},
|
||||
|
|
|
@ -760,6 +760,11 @@ certErrorDetailsCertChain.label = Certificate chain:
|
|||
tabgroups.migration.anonGroup = Group %S
|
||||
tabgroups.migration.tabGroupBookmarkFolderName = Bookmarked Tab Groups
|
||||
|
||||
pendingCrashReports.label = You have an unsubmitted crash report;You have #1 unsubmitted crash reports
|
||||
pendingCrashReports.viewAll = View
|
||||
pendingCrashReports.submitAll = Submit
|
||||
pendingCrashReports.ignoreAll = Ignore
|
||||
|
||||
decoder.noCodecs.button = Learn how
|
||||
decoder.noCodecs.accesskey = L
|
||||
decoder.noCodecs.message = To play video, you may need to install Microsoft’s Media Feature Pack.
|
||||
|
|
|
@ -11,6 +11,8 @@ Cu.importGlobalProperties(['File']);
|
|||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PromiseUtils",
|
||||
"resource://gre/modules/PromiseUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "OS",
|
||||
"resource://gre/modules/osfile.jsm");
|
||||
|
||||
this.EXPORTED_SYMBOLS = [
|
||||
"CrashSubmit"
|
||||
|
@ -23,6 +25,8 @@ const SUCCESS = "success";
|
|||
const FAILED = "failed";
|
||||
const SUBMITTING = "submitting";
|
||||
|
||||
const UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
||||
|
||||
var reportURL = null;
|
||||
var strings = null;
|
||||
var myListener = null;
|
||||
|
@ -475,6 +479,29 @@ this.CrashSubmit = {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Add a .dmg.ignore file along side the .dmp file to indicate that the user
|
||||
* shouldn't be prompted to submit this crash report again.
|
||||
*
|
||||
* @param id
|
||||
* Filename (minus .dmp extension) of the report to ignore
|
||||
*/
|
||||
|
||||
ignore: function CrashSubmit_ignore(id) {
|
||||
let [dump, extra, mem] = getPendingMinidump(id);
|
||||
return new Promise(
|
||||
function (resolve, reject) {
|
||||
let promise = OS.File.open(dump.path + ".ignore", {create: true}, {unixFlags:OS.Constants.libc.O_CREAT});
|
||||
promise.then(
|
||||
function createSuccess(file) {
|
||||
file.close();
|
||||
resolve();
|
||||
}
|
||||
);
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the list of pending crash IDs.
|
||||
*
|
||||
|
@ -485,6 +512,64 @@ this.CrashSubmit = {
|
|||
return getAllPendingMinidumpsIDs();
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the list of pending crash IDs, exluding those marked to be ignored
|
||||
* @param maxFileDate
|
||||
* A Date object. Any files last modified before that date will be ignored
|
||||
*
|
||||
* @return a Promise that is fulfilled with an array of string, each
|
||||
* being an ID as expected to be passed to submit() or ignore()
|
||||
*/
|
||||
pendingIDsAsync: function CrashSubmit_pendingIDsAsync(maxFileDate) {
|
||||
let promise = new Promise(function(resolve, reject) {
|
||||
OS.File.stat(getDir("pending").path).then(
|
||||
function onSuccess(info) {
|
||||
if (info.isDir) {
|
||||
let iterator = new OS.File.DirectoryIterator(getDir("pending").path);
|
||||
let ids = [];
|
||||
iterator.forEach(
|
||||
function onEntry(file) {
|
||||
if (file.name.endsWith(".dmp")) {
|
||||
return OS.File.exists(file.path + ".ignore").then(
|
||||
function onSuccess(ignoreExists) {
|
||||
if (!ignoreExists) {
|
||||
let id = file.name.slice(0, -4);
|
||||
if (UUID_REGEX.test(id)) {
|
||||
return OS.File.stat(file.path).then(
|
||||
function onSuccess(info) {
|
||||
if (info.lastAccessDate.valueOf() > maxFileDate.valueOf()) {
|
||||
ids.push(id);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
).then(
|
||||
function onSuccess() {
|
||||
iterator.close();
|
||||
resolve(ids);
|
||||
},
|
||||
function onError(err) {
|
||||
iterator.close();
|
||||
reject(err);
|
||||
}
|
||||
);
|
||||
} else {
|
||||
reject();
|
||||
}
|
||||
},
|
||||
function onError(err) {
|
||||
reject(err);
|
||||
}
|
||||
)
|
||||
});
|
||||
return promise;
|
||||
},
|
||||
|
||||
/**
|
||||
* Prune the saved dumps.
|
||||
*/
|
||||
|
|
Загрузка…
Ссылка в новой задаче