mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 765285 - Include last 3 days of crash IDs in about:support. r=Mossop,dolske
This commit is contained in:
parent
e8e8b45530
commit
20f5e19299
@ -6,6 +6,7 @@ const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
||||
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
Components.utils.import("resource://gre/modules/Troubleshoot.jsm");
|
||||
Components.utils.import("resource://gre/modules/PluralForm.jsm");
|
||||
Components.utils.import("resource://gre/modules/ResetProfile.jsm");
|
||||
|
||||
window.addEventListener("load", function onload(event) {
|
||||
@ -32,6 +33,73 @@ let snapshotFormatters = {
|
||||
$("version-box").textContent = version;
|
||||
},
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
crashes: function crashes(data) {
|
||||
let strings = stringBundle();
|
||||
let daysRange = Troubleshoot.kMaxCrashAge / (24 * 60 * 60 * 1000);
|
||||
$("crashes-title").textContent =
|
||||
PluralForm.get(daysRange, strings.GetStringFromName("crashesTitle"))
|
||||
.replace("#1", daysRange);
|
||||
let reportURL;
|
||||
try {
|
||||
reportURL = Services.prefs.getCharPref("breakpad.reportURL");
|
||||
// Ignore any non http/https urls
|
||||
if (!/^https?:/i.test(reportURL))
|
||||
reportURL = null;
|
||||
}
|
||||
catch (e) { }
|
||||
if (!reportURL) {
|
||||
$("crashes-noConfig").style.display = "block";
|
||||
$("crashes-noConfig").classList.remove("no-copy");
|
||||
return;
|
||||
}
|
||||
else {
|
||||
$("crashes-allReports").style.display = "block";
|
||||
$("crashes-allReports").classList.remove("no-copy");
|
||||
}
|
||||
|
||||
if (data.pending > 0) {
|
||||
$("crashes-allReportsWithPending").textContent =
|
||||
PluralForm.get(data.pending, strings.GetStringFromName("pendingReports"))
|
||||
.replace("#1", data.pending);
|
||||
}
|
||||
|
||||
let dateNow = new Date();
|
||||
$.append($("crashes-tbody"), data.submitted.map(function (crash) {
|
||||
let date = new Date(crash.date);
|
||||
let timePassed = dateNow - date;
|
||||
let formattedDate;
|
||||
if (timePassed >= 24 * 60 * 60 * 1000)
|
||||
{
|
||||
let daysPassed = Math.round(timePassed / (24 * 60 * 60 * 1000));
|
||||
let daysPassedString = strings.GetStringFromName("crashesTimeDays");
|
||||
formattedDate = PluralForm.get(daysPassed, daysPassedString)
|
||||
.replace("#1", daysPassed);
|
||||
}
|
||||
else if (timePassed >= 60 * 60 * 1000)
|
||||
{
|
||||
let hoursPassed = Math.round(timePassed / (60 * 60 * 1000));
|
||||
let hoursPassedString = strings.GetStringFromName("crashesTimeHours");
|
||||
formattedDate = PluralForm.get(hoursPassed, hoursPassedString)
|
||||
.replace("#1", hoursPassed);
|
||||
}
|
||||
else
|
||||
{
|
||||
let minutesPassed = Math.max(Math.round(timePassed / (60 * 1000)), 1);
|
||||
let minutesPassedString = strings.GetStringFromName("crashesTimeMinutes");
|
||||
formattedDate = PluralForm.get(minutesPassed, minutesPassedString)
|
||||
.replace("#1", minutesPassed);
|
||||
}
|
||||
return $.new("tr", [
|
||||
$.new("td", [
|
||||
$.new("a", crash.id, null, {href : reportURL + crash.id})
|
||||
]),
|
||||
$.new("td", formattedDate)
|
||||
]);
|
||||
}));
|
||||
},
|
||||
#endif
|
||||
|
||||
extensions: function extensions(data) {
|
||||
$.append($("extensions-tbody"), data.map(function (extension) {
|
||||
return $.new("tr", [
|
||||
@ -212,10 +280,14 @@ let snapshotFormatters = {
|
||||
|
||||
let $ = document.getElementById.bind(document);
|
||||
|
||||
$.new = function $_new(tag, textContentOrChildren, className) {
|
||||
$.new = function $_new(tag, textContentOrChildren, className, attributes) {
|
||||
let elt = document.createElement(tag);
|
||||
if (className)
|
||||
elt.className = className;
|
||||
if (attributes) {
|
||||
for (let attrName in attributes)
|
||||
elt.setAttribute(attrName, attributes[attrName]);
|
||||
}
|
||||
if (Array.isArray(textContentOrChildren))
|
||||
this.append(elt, textContentOrChildren);
|
||||
else
|
||||
|
@ -152,18 +152,6 @@
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
<tr class="no-copy">
|
||||
<th class="column">
|
||||
&aboutSupport.appBasicsCrashIDs;
|
||||
</th>
|
||||
|
||||
<td>
|
||||
<a href="about:crashes">about:crashes</a>
|
||||
</td>
|
||||
</tr>
|
||||
#endif
|
||||
|
||||
<tr class="no-copy">
|
||||
<th class="column">
|
||||
&aboutSupport.appBasicsMemoryUse;
|
||||
@ -178,6 +166,33 @@
|
||||
</table>
|
||||
|
||||
<!-- - - - - - - - - - - - - - - - - - - - - -->
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
|
||||
<h2 class="major-section" id="crashes-title">
|
||||
&aboutSupport.crashes.title;
|
||||
</h2>
|
||||
|
||||
<table id="crashes-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
&aboutSupport.crashes.id;
|
||||
</th>
|
||||
<th>
|
||||
&aboutSupport.crashes.sendDate;
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="crashes-tbody">
|
||||
</tbody>
|
||||
</table>
|
||||
<p id="crashes-allReports" class="no-copy" style="display: none">
|
||||
<a href="about:crashes" id="crashes-allReportsWithPending" style="display: block">&aboutSupport.crashes.allReports;</a>
|
||||
</p>
|
||||
<p id="crashes-noConfig" class="no-copy" style="display: none">&aboutSupport.crashes.noConfig;</p>
|
||||
|
||||
#endif
|
||||
<!-- - - - - - - - - - - - - - - - - - - - - -->
|
||||
|
||||
<h2 class="major-section">
|
||||
&aboutSupport.extensionsTitle;
|
||||
|
91
toolkit/crashreporter/CrashReports.jsm
Normal file
91
toolkit/crashreporter/CrashReports.jsm
Normal file
@ -0,0 +1,91 @@
|
||||
/* 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/. */
|
||||
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
this.EXPORTED_SYMBOLS = [
|
||||
"CrashReports"
|
||||
];
|
||||
|
||||
this.CrashReports = {
|
||||
pendingDir: null,
|
||||
reportsDir: null,
|
||||
submittedDir: null,
|
||||
getReports: function CrashReports_getReports()
|
||||
{
|
||||
let reports = [];
|
||||
|
||||
try {
|
||||
// Ignore any non http/https urls
|
||||
if (!/^https?:/i.test(Services.prefs.getCharPref("breakpad.reportURL")))
|
||||
return reports;
|
||||
}
|
||||
catch (e) { }
|
||||
|
||||
if (this.submittedDir.exists() && this.submittedDir.isDirectory()) {
|
||||
let entries = this.submittedDir.directoryEntries;
|
||||
while (entries.hasMoreElements()) {
|
||||
let file = entries.getNext().QueryInterface(Components.interfaces.nsIFile);
|
||||
let leaf = file.leafName;
|
||||
if (leaf.startsWith("bp-") &&
|
||||
leaf.endsWith(".txt")) {
|
||||
let entry = {
|
||||
id: leaf.slice(0, -4),
|
||||
date: file.lastModifiedTime,
|
||||
pending: false
|
||||
};
|
||||
reports.push(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.pendingDir.exists() && this.pendingDir.isDirectory()) {
|
||||
let uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
||||
let entries = this.pendingDir.directoryEntries;
|
||||
while (entries.hasMoreElements()) {
|
||||
let file = entries.getNext().QueryInterface(Components.interfaces.nsIFile);
|
||||
let leaf = file.leafName;
|
||||
let id = leaf.slice(0, -4);
|
||||
if (leaf.endsWith(".dmp") && uuidRegex.test(id)) {
|
||||
let entry = {
|
||||
id: id,
|
||||
date: file.lastModifiedTime,
|
||||
pending: true
|
||||
};
|
||||
reports.push(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sort reports descending by date
|
||||
return reports.sort( (a, b) => b.date - a.date);
|
||||
}
|
||||
}
|
||||
|
||||
function CrashReports_pendingDir()
|
||||
{
|
||||
let pendingDir = Services.dirsvc.get("UAppData", Components.interfaces.nsIFile);
|
||||
pendingDir.append("Crash Reports");
|
||||
pendingDir.append("pending");
|
||||
return pendingDir;
|
||||
}
|
||||
|
||||
function CrashReports_reportsDir()
|
||||
{
|
||||
let reportsDir = Services.dirsvc.get("UAppData", Components.interfaces.nsIFile);
|
||||
reportsDir.append("Crash Reports");
|
||||
return reportsDir;
|
||||
}
|
||||
|
||||
function CrashReports_submittedDir()
|
||||
{
|
||||
let submittedDir = Services.dirsvc.get("UAppData", Components.interfaces.nsIFile);
|
||||
submittedDir.append("Crash Reports");
|
||||
submittedDir.append("submitted");
|
||||
return submittedDir;
|
||||
}
|
||||
|
||||
this.CrashReports.pendingDir = CrashReports_pendingDir();
|
||||
this.CrashReports.reportsDir = CrashReports_reportsDir();
|
||||
this.CrashReports.submittedDir = CrashReports_submittedDir();
|
@ -5,9 +5,9 @@
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
var reportsDir, submittedDir, pendingDir;
|
||||
var reportURL;
|
||||
|
||||
Components.utils.import("resource://gre/modules/CrashReports.jsm");
|
||||
Components.utils.import("resource://gre/modules/CrashSubmit.jsm");
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
@ -55,26 +55,6 @@ function submitPendingReport(event) {
|
||||
return false;
|
||||
}
|
||||
|
||||
function findInsertionPoint(reports, date) {
|
||||
if (reports.length == 0)
|
||||
return 0;
|
||||
|
||||
var min = 0;
|
||||
var max = reports.length - 1;
|
||||
while (min < max) {
|
||||
var mid = parseInt((min + max) / 2);
|
||||
if (reports[mid].date < date)
|
||||
max = mid - 1;
|
||||
else if (reports[mid].date > date)
|
||||
min = mid + 1;
|
||||
else
|
||||
return mid;
|
||||
}
|
||||
if (reports[min].date <= date)
|
||||
return min;
|
||||
return min+1;
|
||||
}
|
||||
|
||||
function populateReportList() {
|
||||
var prefService = Cc["@mozilla.org/preferences-service;1"].
|
||||
getService(Ci.nsIPrefBranch);
|
||||
@ -92,57 +72,7 @@ function populateReportList() {
|
||||
document.getElementById("noConfig").style.display = "block";
|
||||
return;
|
||||
}
|
||||
var directoryService = Cc["@mozilla.org/file/directory_service;1"].
|
||||
getService(Ci.nsIProperties);
|
||||
|
||||
reportsDir = directoryService.get("UAppData", Ci.nsIFile);
|
||||
reportsDir.append("Crash Reports");
|
||||
|
||||
submittedDir = directoryService.get("UAppData", Ci.nsIFile);
|
||||
submittedDir.append("Crash Reports");
|
||||
submittedDir.append("submitted");
|
||||
|
||||
var reports = [];
|
||||
if (submittedDir.exists() && submittedDir.isDirectory()) {
|
||||
var entries = submittedDir.directoryEntries;
|
||||
while (entries.hasMoreElements()) {
|
||||
var file = entries.getNext().QueryInterface(Ci.nsIFile);
|
||||
var leaf = file.leafName;
|
||||
if (leaf.substr(0, 3) == "bp-" &&
|
||||
leaf.substr(-4) == ".txt") {
|
||||
var entry = {
|
||||
id: leaf.slice(0, -4),
|
||||
date: file.lastModifiedTime,
|
||||
pending: false
|
||||
};
|
||||
var pos = findInsertionPoint(reports, entry.date);
|
||||
reports.splice(pos, 0, entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pendingDir = directoryService.get("UAppData", Ci.nsIFile);
|
||||
pendingDir.append("Crash Reports");
|
||||
pendingDir.append("pending");
|
||||
|
||||
if (pendingDir.exists() && pendingDir.isDirectory()) {
|
||||
var uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
||||
var entries = pendingDir.directoryEntries;
|
||||
while (entries.hasMoreElements()) {
|
||||
var file = entries.getNext().QueryInterface(Ci.nsIFile);
|
||||
var leaf = file.leafName;
|
||||
var id = leaf.slice(0, -4);
|
||||
if (leaf.substr(-4) == ".dmp" && uuidRegex.test(id)) {
|
||||
var entry = {
|
||||
id: id,
|
||||
date: file.lastModifiedTime,
|
||||
pending: true
|
||||
};
|
||||
var pos = findInsertionPoint(reports, entry.date);
|
||||
reports.splice(pos, 0, entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
let reports = CrashReports.getReports();
|
||||
|
||||
if (reports.length == 0) {
|
||||
document.getElementById("clear-reports").style.display = "none";
|
||||
@ -208,7 +138,7 @@ function clearReports() {
|
||||
bundle.GetStringFromName("deleteconfirm.description")))
|
||||
return;
|
||||
|
||||
var entries = submittedDir.directoryEntries;
|
||||
var entries = CrashReports.submittedDir.directoryEntries;
|
||||
while (entries.hasMoreElements()) {
|
||||
var file = entries.getNext().QueryInterface(Ci.nsIFile);
|
||||
var leaf = file.leafName;
|
||||
@ -217,7 +147,7 @@ function clearReports() {
|
||||
file.remove(false);
|
||||
}
|
||||
}
|
||||
entries = reportsDir.directoryEntries;
|
||||
entries = CrashReports.reportsDir.directoryEntries;
|
||||
var oneYearAgo = Date.now() - 31586000000;
|
||||
while (entries.hasMoreElements()) {
|
||||
var file = entries.getNext().QueryInterface(Ci.nsIFile);
|
||||
@ -228,7 +158,7 @@ function clearReports() {
|
||||
file.remove(false);
|
||||
}
|
||||
}
|
||||
entries = pendingDir.directoryEntries;
|
||||
entries = CrashReports.pendingDir.directoryEntries;
|
||||
while (entries.hasMoreElements()) {
|
||||
entries.getNext().QueryInterface(Ci.nsIFile).remove(false);
|
||||
}
|
||||
|
@ -73,6 +73,7 @@ if CONFIG['OS_ARCH'] == 'Darwin':
|
||||
]
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
'CrashReports.jsm',
|
||||
'CrashSubmit.jsm',
|
||||
'KeyValueParser.jsm',
|
||||
]
|
||||
|
@ -11,6 +11,16 @@
|
||||
about &brandShortName;, check out our <a id='supportLink'>support website</a>.
|
||||
">
|
||||
|
||||
<!ENTITY aboutSupport.crashes.title "Crash Reports">
|
||||
<!-- LOCALIZATION NOTE (aboutSupport.crashes.id):
|
||||
This is likely the same like id.heading in crashes.dtd. -->
|
||||
<!ENTITY aboutSupport.crashes.id "Report ID">
|
||||
<!-- LOCALIZATION NOTE (aboutSupport.crashes.id):
|
||||
This is likely the same like date.heading in crashes.dtd. -->
|
||||
<!ENTITY aboutSupport.crashes.sendDate "Submitted">
|
||||
<!ENTITY aboutSupport.crashes.allReports "All Crash Reports">
|
||||
<!ENTITY aboutSupport.crashes.noConfig "This application has not been configured to display crash reports.">
|
||||
|
||||
<!ENTITY aboutSupport.extensionsTitle "Extensions">
|
||||
<!ENTITY aboutSupport.extensionName "Name">
|
||||
<!ENTITY aboutSupport.extensionEnabled "Enabled">
|
||||
@ -35,7 +45,6 @@ Windows/Mac use the term "Folder" instead of "Directory" -->
|
||||
<!ENTITY aboutSupport.appBasicsEnabledPlugins "Enabled Plugins">
|
||||
<!ENTITY aboutSupport.appBasicsBuildConfig "Build Configuration">
|
||||
<!ENTITY aboutSupport.appBasicsUserAgent "User Agent">
|
||||
<!ENTITY aboutSupport.appBasicsCrashIDs "Crash Reports">
|
||||
<!ENTITY aboutSupport.appBasicsMemoryUse "Memory Use">
|
||||
|
||||
<!ENTITY aboutSupport.showDir.label "Open Directory">
|
||||
|
@ -2,6 +2,31 @@
|
||||
# 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/.
|
||||
|
||||
# LOCALIZATION NOTE (downloadsTitleFiles): Semi-colon list of plural forms.
|
||||
# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
|
||||
# #1 number of days relevant with relevant crash reports
|
||||
crashesTitle=Crash Reports for the Last #1 Day;Crash Reports for the Last #1 Days
|
||||
|
||||
# LOCALIZATION NOTE (crashesTimeMinutes): Semi-colon list of plural forms.
|
||||
# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
|
||||
# #1 number of minutes (between 1 and 59) which have passed since the crash
|
||||
crashesTimeMinutes=#1 minute ago;#1 minutes ago
|
||||
|
||||
# LOCALIZATION NOTE (crashesTimeHours): Semi-colon list of plural forms.
|
||||
# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
|
||||
# #1 number of hours (between 1 and 23) which have passed since the crash
|
||||
crashesTimeHours=#1 hour ago;#1 hours ago
|
||||
|
||||
# LOCALIZATION NOTE (crashesTimeDays): Semi-colon list of plural forms.
|
||||
# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
|
||||
# #1 number of days (1 or more) which have passed since the crash
|
||||
crashesTimeDays=#1 day ago;#1 days ago
|
||||
|
||||
# LOCALIZATION NOTE (downloadsTitleFiles): Semi-colon list of plural forms.
|
||||
# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
|
||||
# #1 number of pending crash reports
|
||||
pendingReports=All Crash Reports (including #1 pending crash in the given time range);All Crash Reports (including #1 pending crashes in the given time range)
|
||||
|
||||
# LOCALIZATION NOTE In the following strings, "Direct2D", "DirectWrite" and "ClearType"
|
||||
# are proper nouns and should not be translated. Feel free to leave english strings if
|
||||
# there are no good translations, these are only used in about:support
|
||||
|
@ -8,8 +8,12 @@ this.EXPORTED_SYMBOLS = [
|
||||
|
||||
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/AddonManager.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
Cu.import("resource://gre/modules/CrashReports.jsm");
|
||||
#endif
|
||||
|
||||
// We use a preferences whitelist to make sure we only show preferences that
|
||||
// are useful for support and won't compromise the user's privacy. Note that
|
||||
@ -104,6 +108,8 @@ this.Troubleshoot = {
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
kMaxCrashAge: 3 * 24 * 60 * 60 * 1000, // 3 days
|
||||
};
|
||||
|
||||
// Each data provider is a name => function mapping. When a snapshot is
|
||||
@ -134,6 +140,18 @@ let dataProviders = {
|
||||
done(data);
|
||||
},
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
crashes: function crashes(done) {
|
||||
let reports = CrashReports.getReports();
|
||||
let now = new Date();
|
||||
let reportsNew = reports.filter(report => (now - report.date < Troubleshoot.kMaxCrashAge));
|
||||
let reportsSubmitted = reportsNew.filter(report => (!report.pending));
|
||||
let reportsPendingCount = reportsNew.length - reportsSubmitted.length;
|
||||
let data = {submitted : reportsSubmitted, pending : reportsPendingCount};
|
||||
done(data);
|
||||
},
|
||||
#endif
|
||||
|
||||
extensions: function extensions(done) {
|
||||
AddonManager.getAddonsByTypes(["extension"], function (extensions) {
|
||||
extensions.sort(function (a, b) {
|
||||
|
@ -100,6 +100,37 @@ const SNAPSHOT_SCHEMA = {
|
||||
},
|
||||
},
|
||||
},
|
||||
crashes: {
|
||||
required: false,
|
||||
type: "object",
|
||||
properties: {
|
||||
pending: {
|
||||
required: true,
|
||||
type: "number",
|
||||
},
|
||||
submitted: {
|
||||
required: true,
|
||||
type: "array",
|
||||
items: {
|
||||
type: "object",
|
||||
properties: {
|
||||
id: {
|
||||
required: true,
|
||||
type: "string",
|
||||
},
|
||||
date: {
|
||||
required: true,
|
||||
type: "number",
|
||||
},
|
||||
pending: {
|
||||
required: true,
|
||||
type: "boolean",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
extensions: {
|
||||
required: true,
|
||||
type: "array",
|
||||
|
Loading…
Reference in New Issue
Block a user