diff --git a/toolkit/crashreporter/content/crashes.css b/toolkit/crashreporter/content/crashes.css
index 7ddcb5753354..1a958e296e08 100644
--- a/toolkit/crashreporter/content/crashes.css
+++ b/toolkit/crashreporter/content/crashes.css
@@ -8,59 +8,68 @@
min-width: 30em;
max-width: 60em;
}
+
table {
- clear: both;
- width: 90%;
- margin: 0 auto;
+ width: 100%;
padding-bottom: 2em;
}
-th {
- font-size: 130%;
- text-align: left;
- white-space: nowrap;
-}
-th:-moz-locale-dir(rtl) {
- text-align: right;
-}
-/* name */
-th:first-child {
- padding-inline-end: 2em;
-}
-/* submitted */
-th:last-child {
- text-align: center;
-}
-:link, :visited {
- display: block;
- min-height: 17px;
-}
-/* date */
-td:first-child + td {
- width: 0;
- padding-inline-start: 1em;
- padding-inline-end: .5em;
- white-space: nowrap;
-}
-/* time */
-td:last-child {
- width: 0;
- padding-inline-start: .5em;
- white-space: nowrap;
-}
-#clear-reports {
+.float-right {
float: right;
}
-#clear-reports:-moz-locale-dir(rtl) {
- float: left;
+.hidden {
+ display: none;
+}
+.table-title-container {
+ align-items: center;
+ display: flex;
+ justify-content: space-between;
+}
+.wide-button {
+ display: block;
+ min-height: 32px;
+ padding-left: 30px;
+ padding-right: 30px;
}
-
.submitting {
background-image: url(chrome://global/skin/icons/loading.png);
+ background-position: center;
background-repeat: no-repeat;
- background-position: right;
background-size: 16px;
}
+.submitting .submit-crash-button-label {
+ display: none;
+}
+.failed-to-submit {
+ color: #ca8695;
+}
+
+a.button-as-link {
+ -moz-appearance: none;
+ min-height: 30px;
+ color: var(--in-content-text-color) !important;
+ border: 1px solid var(--in-content-box-border-color) !important;
+ border-radius: 2px;
+ background-color: var(--in-content-page-background);
+ line-height: 30px;
+ margin: 4px 8px;
+ /* Ensure font-size isn't overridden by widget styling (e.g. in forms.css) */
+ font-size: 1em;
+}
+a.button-as-link:hover {
+ background-color: var(--in-content-box-background-hover) !important;
+ text-decoration: none;
+}
+h2.lighter-font-weight {
+ font-weight: lighter;
+}
+
+html[dir=ltr] th {
+ text-align: left;
+}
+html[dir=rtl] th {
+ text-align: right;
+}
@media (min-resolution: 1.1dppx) {
.submitting {
diff --git a/toolkit/crashreporter/content/crashes.js b/toolkit/crashreporter/content/crashes.js
index b1ad0b6bc672..edfbc2464ace 100644
--- a/toolkit/crashreporter/content/crashes.js
+++ b/toolkit/crashreporter/content/crashes.js
@@ -2,182 +2,229 @@
* 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/. */
-var reportURL;
+let reportURL;
ChromeUtils.import("resource://gre/modules/CrashReports.jsm");
ChromeUtils.import("resource://gre/modules/Services.jsm");
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
ChromeUtils.import("resource://gre/modules/osfile.jsm");
-ChromeUtils.defineModuleGetter(this, "CrashSubmit",
- "resource://gre/modules/CrashSubmit.jsm");
+ChromeUtils.defineModuleGetter(this, "CrashSubmit", "resource://gre/modules/CrashSubmit.jsm");
-document.addEventListener("DOMContentLoaded", function() {
- populateReportList();
- document.getElementById("clear-reports").addEventListener("click", function() {
- clearReports().then(null, Cu.reportError);
+document.addEventListener("DOMContentLoaded", () => {
+ populateReportLists();
+ document.getElementById("clearUnsubmittedReports").addEventListener("click", () => {
+ clearUnsubmittedReports().catch(Cu.reportError);
+ });
+ document.getElementById("clearSubmittedReports").addEventListener("click", () => {
+ clearSubmittedReports().catch(Cu.reportError);
});
});
const buildID = Services.appinfo.appBuildID;
-function submitPendingReport(event) {
- let link = event.target;
- let id = link.firstChild.textContent;
- link.className = "submitting";
- CrashSubmit.submit(id, { noThrottle: true }).then(
- (remoteCrashID) => {
- link.className = "";
- // Reset the link to point at our new crash report. This way, if the
- // user clicks "Back", the link will be correct.
- link.firstChild.textContent = remoteCrashID;
- link.setAttribute("id", remoteCrashID);
- link.removeEventListener("click", submitPendingReport, true);
-
- if (reportURL) {
- link.setAttribute("href", reportURL + remoteCrashID);
- // redirect the user to their brand new crash report
- window.location.href = reportURL + remoteCrashID;
- }
- },
- () => {
- // XXX: do something more useful here
- link.className = "";
-
- // Dispatch an event, useful for testing
- let event = document.createEvent("Events");
- event.initEvent("CrashSubmitFailed", true, false);
- document.dispatchEvent(event);
- });
- event.preventDefault();
- return false;
-}
-
-function populateReportList() {
+/**
+ * Adds the crash reports with submission buttons and links
+ * to the unsubmitted and submitted crash report lists.
+ * If breakpad.reportURL is not set, displays a misconfiguration message
+ * instead.
+ */
+function populateReportLists() {
try {
reportURL = Services.prefs.getCharPref("breakpad.reportURL");
// Ignore any non http/https urls
- if (!/^https?:/i.test(reportURL))
+ if (!/^https?:/i.test(reportURL)) {
reportURL = null;
- } catch (e) { }
- if (!reportURL) {
- document.getElementById("clear-reports").style.display = "none";
- document.getElementById("reportList").style.display = "none";
- document.getElementById("noConfig").style.display = "block";
- return;
- }
- let reports = CrashReports.getReports();
-
- if (reports.length == 0) {
- document.getElementById("clear-reports").style.display = "none";
- document.getElementById("reportList").style.display = "none";
- document.getElementById("noReports").style.display = "block";
- return;
- }
-
- var dateFormatter;
- var timeFormatter;
- try {
- dateFormatter = new Services.intl.DateTimeFormat(undefined, { dateStyle: "short" });
- timeFormatter = new Services.intl.DateTimeFormat(undefined, { timeStyle: "short" });
+ }
} catch (e) {
- // XXX Fallback to be removed once bug 1215247 is complete
- // and the Intl API is available on all platforms.
- dateFormatter = {
- format(date) {
- return date.toLocaleDateString();
- }
- };
- timeFormatter = {
- format(date) {
- return date.toLocaleTimeString();
- }
- };
+ reportURL = null;
}
- var reportURI = Services.io.newURI(reportURL);
- // resolving this URI relative to /report/index
- var aboutThrottling = Services.io.newURI("../../about/throttling", null, reportURI);
+ if (!reportURL) {
+ document.getElementById("noConfig").classList.remove("hidden");
+ return;
+ }
+ const reports = CrashReports.getReports();
+ const dateFormatter = new Services.intl.DateTimeFormat(undefined, {
+ timeStyle: "short",
+ dateStyle: "short"
+ });
+ reports.forEach(report => addReportRow(report.pending, report.id, report.date, dateFormatter));
+ showAppropriateSections();
+}
- for (var i = 0; i < reports.length; i++) {
- var row = document.createElement("tr");
- var cell = document.createElement("td");
- row.appendChild(cell);
- var link = document.createElement("a");
- if (reports[i].pending) {
- link.setAttribute("href", aboutThrottling.spec);
- link.addEventListener("click", submitPendingReport, true);
- } else {
- link.setAttribute("href", reportURL + reports[i].id);
- }
- link.setAttribute("id", reports[i].id);
- link.classList.add("crashReport");
- link.appendChild(document.createTextNode(reports[i].id));
- cell.appendChild(link);
+/**
+ * Adds a crash report with the appropriate submission button
+ * or viewing link to the unsubmitted or submitted report list
+ * based on isPending.
+ *
+ * @param {Boolean} isPending whether the crash is up for submission
+ * @param {String} id the unique id of the crash report
+ * @param {Date} date either the date of crash or date of submission
+ * @param {Object} dateFormatter formatter for presenting dates to users
+ */
+function addReportRow(isPending, id, date, dateFormatter) {
+ const rowTemplate = document.getElementById("crashReportRow");
+ const row = document.importNode(rowTemplate.content, true).querySelector("tr");
+ row.id = id;
- var date = new Date(reports[i].date);
- cell = document.createElement("td");
- cell.appendChild(document.createTextNode(dateFormatter.format(date)));
- row.appendChild(cell);
- cell = document.createElement("td");
- cell.appendChild(document.createTextNode(timeFormatter.format(date)));
- row.appendChild(cell);
- if (reports[i].pending) {
- document.getElementById("unsubmitted").appendChild(row);
- } else {
- document.getElementById("submitted").appendChild(row);
- }
+ const cells = row.querySelectorAll("td");
+ cells[0].appendChild(document.createTextNode(id));
+ cells[1].appendChild(document.createTextNode(dateFormatter.format(date)));
+
+ if (isPending) {
+ const buttonTemplate = document.getElementById("crashSubmitButton");
+ const button = document.importNode(buttonTemplate.content, true).querySelector("button");
+ const buttonText = button.querySelector("span");
+ button.addEventListener("click",
+ () => submitPendingReport(id, row, button, buttonText, dateFormatter));
+ cells[2].appendChild(button);
+ document.getElementById("unsubmitted").appendChild(row);
+ } else {
+ const linkTemplate = document.getElementById("viewCrashLink");
+ const link = document.importNode(linkTemplate.content, true).querySelector("a");
+ link.href = `${reportURL}${id}`;
+ cells[2].appendChild(link);
+ document.getElementById("submitted").appendChild(row);
}
}
-var clearReports = async function() {
+/**
+ * Shows or hides each of the unsubmitted and submitted report list
+ * based on whether they contain at least one crash report.
+ * If hidden, the submitted report list is replaced by a message
+ * indicating that no crash reports have been submitted.
+ */
+function showAppropriateSections() {
+ let hasUnsubmitted = document.getElementById("unsubmitted").childElementCount > 0;
+ document.getElementById("reportListUnsubmitted").classList.toggle("hidden", !hasUnsubmitted);
+
+ let hasSubmitted = document.getElementById("submitted").childElementCount > 0;
+ document.getElementById("reportListSubmitted").classList.toggle("hidden", !hasSubmitted);
+ document.getElementById("noSubmittedReports").classList.toggle("hidden", hasSubmitted);
+}
+
+/**
+ * Changes the provided button to display a spinner. Then, tries to submit the
+ * crash report for the provided id. On success, removes the crash report from
+ * the list of unsubmitted crash reports and adds a new crash report to the list
+ * of submitted crash reports. On failure, changes the provided button to display
+ * a red error message.
+ *
+ * @param {String} reportId the unique id of the crash report
+ * @param {HTMLTableRowElement} row the table row of the crash report
+ * @param {HTMLButtonElement} button the button pressed to start the submission
+ * @param {HTMLSpanElement} buttonText the text inside the pressed button
+ * @param {Object} dateFormatter formatter for presenting dates to users
+ */
+function submitPendingReport(reportId, row, button, buttonText, dateFormatter) {
+ button.classList.add("submitting");
+ CrashSubmit.submit(reportId, { noThrottle: true }).then(remoteCrashID => {
+ document.getElementById("unsubmitted").removeChild(row);
+ const report = CrashReports.getReports().filter(report => report.id === remoteCrashID);
+ addReportRow(false, remoteCrashID, report.date, dateFormatter);
+ showAppropriateSections();
+ dispatchEvent("CrashSubmitSucceeded");
+ },
+ () => {
+ button.classList.remove("submitting");
+ button.classList.add("failed-to-submit");
+ document.l10n.setAttributes(buttonText, "submit-crash-button-failure-label");
+ dispatchEvent("CrashSubmitFailed");
+ },
+ );
+}
+
+/**
+ * Deletes unsubmitted and old crash reports from the user's device.
+ * Then, hides the list of unsubmitted crash reports.
+ */
+async function clearUnsubmittedReports() {
const [title, description] = await document.l10n.formatValues([
{id: "delete-confirm-title"},
- {id: "delete-confirm-description"},
+ {id: "delete-unsubmitted-description"},
]);
if (!Services.prompt.confirm(window, title, description)) {
return;
}
- let cleanupFolder = async function(path, filter) {
- let iterator = new OS.File.DirectoryIterator(path);
- try {
- await iterator.forEach(async function(aEntry) {
- if (!filter || (await filter(aEntry))) {
- await OS.File.remove(aEntry.path);
- }
- });
- } catch (e) {
- if (!(e instanceof OS.File.Error) || !e.becauseNoSuchFile) {
- throw e;
- }
- } finally {
- iterator.close();
- }
- };
+ await cleanupFolder(CrashReports.pendingDir.path);
+ await clearOldReports();
+ document.getElementById("reportListUnsubmitted").classList.add("hidden");
+}
- await cleanupFolder(CrashReports.submittedDir.path, function(aEntry) {
- return aEntry.name.startsWith("bp-") && aEntry.name.endsWith(".txt");
- });
+/**
+ * Deletes submitted and old crash reports from the user's device.
+ * Then, hides the list of submitted crash reports.
+ */
+async function clearSubmittedReports() {
+ const [title, description] = await document.l10n.formatValues([
+ {id: "delete-confirm-title"},
+ {id: "delete-submitted-description"},
+ ]);
+ if (!Services.prompt.confirm(window, title, description)) {
+ return;
+ }
- let oneYearAgo = Date.now() - 31586000000;
- await cleanupFolder(CrashReports.reportsDir.path, async function(aEntry) {
- if (!aEntry.name.startsWith("InstallTime") ||
- aEntry.name == "InstallTime" + buildID) {
+ await cleanupFolder(
+ CrashReports.submittedDir.path,
+ async entry => entry.name.startsWith("bp-") && entry.name.endsWith(".txt"),
+ );
+ await clearOldReports();
+ document.getElementById("reportListSubmitted").classList.add("hidden");
+ document.getElementById("noSubmittedReports").classList.remove("hidden");
+}
+
+/**
+ * Deletes old crash reports from the user's device.
+ */
+async function clearOldReports() {
+ const oneYearAgo = Date.now() - 31586000000;
+ await cleanupFolder(CrashReports.reportsDir.path, async entry => {
+ if (!entry.name.startsWith("InstallTime") || entry.name == "InstallTime" + buildID) {
return false;
}
- let date = aEntry.winLastWriteDate;
+ let date = entry.winLastWriteDate;
if (!date) {
- let stat = await OS.File.stat(aEntry.path);
+ const stat = await OS.File.stat(entry.path);
date = stat.lastModificationDate;
}
-
- return (date < oneYearAgo);
+ return date < oneYearAgo;
});
+}
- await cleanupFolder(CrashReports.pendingDir.path);
+/**
+ * Deletes files from the user's device at the specified path
+ * that match the provided filter.
+ *
+ * @param {String} path the directory location to delete form
+ * @param {Function} filter function taking in a file entry and
+ * returning whether to delete the file
+ */
+async function cleanupFolder(path, filter) {
+ const iterator = new OS.File.DirectoryIterator(path);
+ try {
+ await iterator.forEach(async entry => {
+ if (!filter || (await filter(entry))) {
+ await OS.File.remove(entry.path);
+ }
+ });
+ } catch (e) {
+ if (!(e instanceof OS.File.Error) || !e.becauseNoSuchFile) {
+ throw e;
+ }
+ } finally {
+ iterator.close();
+ }
+}
- document.getElementById("clear-reports").style.display = "none";
- document.getElementById("reportList").style.display = "none";
- document.getElementById("noReports").style.display = "block";
-};
+/**
+ * Dispatches an event with the specified name.
+ *
+ * @param {String} name the name of the event
+ */
+function dispatchEvent(name) {
+ const event = document.createEvent("Events");
+ event.initEvent(name, true, false);
+ document.dispatchEvent(event);
+}
diff --git a/toolkit/crashreporter/content/crashes.xhtml b/toolkit/crashreporter/content/crashes.xhtml
index a4e91865306d..f98b716969ce 100644
--- a/toolkit/crashreporter/content/crashes.xhtml
+++ b/toolkit/crashreporter/content/crashes.xhtml
@@ -4,48 +4,69 @@
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+ |
+ |
+ |
+
+
+
+
+
+
+
+
+
+
diff --git a/toolkit/crashreporter/test/browser/browser_aboutCrashes.js b/toolkit/crashreporter/test/browser/browser_aboutCrashes.js
index ad14ec9e8ce3..6892379a5da9 100644
--- a/toolkit/crashreporter/test/browser/browser_aboutCrashes.js
+++ b/toolkit/crashreporter/test/browser/browser_aboutCrashes.js
@@ -1,22 +1,28 @@
add_task(async function test() {
- let appD = make_fake_appdir();
- let crD = appD.clone();
+ const appD = make_fake_appdir();
+ const crD = appD.clone();
crD.append("Crash Reports");
- let crashes = add_fake_crashes(crD, 5);
+ const crashes = add_fake_crashes(crD, 5);
// sanity check
- let appDtest = Services.dirsvc.get("UAppData", Ci.nsIFile);
+ const appDtest = Services.dirsvc.get("UAppData", Ci.nsIFile);
ok(appD.equals(appDtest), "directory service provider registered ok");
- await BrowserTestUtils.withNewTab({ gBrowser, url: "about:crashes" }, function(browser) {
+ await BrowserTestUtils.withNewTab({ gBrowser, url: "about:crashes" }, browser => {
info("about:crashes loaded");
- return ContentTask.spawn(browser, crashes, function(crashes) {
- let doc = content.document;
- let crashlinks = doc.getElementById("submitted").querySelectorAll(".crashReport");
- Assert.equal(crashlinks.length, crashes.length,
- "about:crashes lists correct number of crash reports");
+ return ContentTask.spawn(browser, crashes, crashes => {
+ const doc = content.document;
+ const crashIds = doc.getElementsByClassName("crash-id");
+ Assert.equal(
+ crashIds.length,
+ crashes.length,
+ "about:crashes lists correct number of crash reports",
+ );
for (let i = 0; i < crashes.length; i++) {
- Assert.equal(crashlinks[i].firstChild.textContent, crashes[i].id,
- i + ": crash ID is correct");
+ Assert.equal(
+ crashIds[i].textContent,
+ crashes[i].id,
+ i + ": crash ID is correct",
+ );
}
});
});
diff --git a/toolkit/crashreporter/test/browser/browser_aboutCrashesResubmit.js b/toolkit/crashreporter/test/browser/browser_aboutCrashesResubmit.js
index 8f0ed52f27be..b5a5ff5d3774 100644
--- a/toolkit/crashreporter/test/browser/browser_aboutCrashesResubmit.js
+++ b/toolkit/crashreporter/test/browser/browser_aboutCrashesResubmit.js
@@ -16,21 +16,20 @@ function cleanup_and_finish() {
* NB: This function is run in the child process via ContentTask.spawn.
*/
function check_crash_list(crashes) {
- let doc = content.document;
- let crashlinks = doc.getElementsByClassName("crashReport");
- Assert.equal(crashlinks.length, crashes.length,
- "about:crashes lists correct number of crash reports");
- // no point in checking this if the lists aren't the same length
- if (crashlinks.length == crashes.length) {
- for (let i = 0; i < crashes.length; i++) {
- Assert.equal(crashlinks[i].id, crashes[i].id, i + ": crash ID is correct");
- if (crashes[i].pending) {
- // we set the breakpad.reportURL pref in test()
- Assert.equal(crashlinks[i].getAttribute("href"),
- "http://example.com/browser/toolkit/crashreporter/about/throttling",
- "pending URL links to the correct static page");
- }
- }
+ const doc = content.document;
+ const crashIds = doc.getElementsByClassName("crash-id");
+
+ Assert.equal(
+ crashIds.length,
+ crashes.length,
+ "about:crashes lists correct number of crash reports",
+ );
+ for (let i = 0; i < crashes.length; i++) {
+ Assert.equal(
+ crashIds[i].textContent,
+ crashes[i].id,
+ i + ": crash ID is correct",
+ );
}
}
@@ -43,10 +42,16 @@ function check_crash_list(crashes) {
* Additionally, click "back" and verify that the link now points to our new
*/
function check_submit_pending(tab, crashes) {
- let browser = gBrowser.getBrowserForTab(tab);
+ const browser = gBrowser.getBrowserForTab(tab);
let SubmittedCrash = null;
let CrashID = null;
let CrashURL = null;
+ function csp_onsuccess() {
+ const crashLinks = content.document.getElementsByClassName("crash-link");
+ // Get the last link since it is appended to the end of the list
+ const link = crashLinks[crashLinks.length - 1];
+ link.click();
+ }
function csp_onload() {
// loaded the crash report page
ok(true, "got submission onload");
@@ -99,47 +104,50 @@ function check_submit_pending(tab, crashes) {
ok(false, "failed to submit crash report!");
cleanup_and_finish();
}
+ browser.addEventListener("CrashSubmitSucceeded", csp_onsuccess, true);
browser.addEventListener("CrashSubmitFailed", csp_fail, true);
BrowserTestUtils.browserLoaded(browser, false, (url) => url !== "about:crashes").then(csp_onload);
function csp_pageshow() {
ContentTask.spawn(browser, { CrashID, CrashURL }, function({ CrashID, CrashURL }) {
Assert.equal(content.location.href, "about:crashes", "navigated back successfully");
- let link = content.document.getElementById(CrashID);
+ const link = content.document.getElementById(CrashID).getElementsByClassName("crash-link")[0];
Assert.notEqual(link, null, "crash report link changed correctly");
- if (link)
+ if (link) {
Assert.equal(link.href, CrashURL, "crash report link points to correct href");
+ }
}).then(cleanup_and_finish);
}
// try submitting the pending report
- for (let crash of crashes) {
+ for (const crash of crashes) {
if (crash.pending) {
SubmittedCrash = crash;
break;
}
}
- ContentTask.spawn(browser, SubmittedCrash.id, function(id) {
- let link = content.document.getElementById(id);
- link.click();
+ ContentTask.spawn(browser, SubmittedCrash.id, id => {
+ const submitButton = content.document.getElementById(id).getElementsByClassName("submit-button")[0];
+ submitButton.click();
});
}
function test() {
waitForExplicitFinish();
- let appD = make_fake_appdir();
- let crD = appD.clone();
+ const appD = make_fake_appdir();
+ const crD = appD.clone();
crD.append("Crash Reports");
- let crashes = add_fake_crashes(crD, 1);
+ const crashes = add_fake_crashes(crD, 1);
// we don't need much data here, it's not going to a real Socorro
- crashes.push(addPendingCrashreport(crD,
- crashes[crashes.length - 1].date + 60000,
- {"ServerURL": "http://example.com/browser/toolkit/crashreporter/test/browser/crashreport.sjs",
- "ProductName": "Test App",
- // test that we don't truncate
- // at = (bug 512853)
- "Foo": "ABC=XYZ"
- }));
+ crashes.push(addPendingCrashreport(
+ crD,
+ crashes[crashes.length - 1].date + 60000,
+ {
+ "ServerURL": "http://example.com/browser/toolkit/crashreporter/test/browser/crashreport.sjs",
+ "ProductName": "Test App",
+ "Foo": "ABC=XYZ", // test that we don't truncat eat = (bug 512853)
+ }
+ ));
crashes.sort((a, b) => b.date - a.date);
// set this pref so we can link to our test server
diff --git a/toolkit/crashreporter/test/browser/browser_bug471404.js b/toolkit/crashreporter/test/browser/browser_bug471404.js
index 04034268f49b..893f21e85a2e 100644
--- a/toolkit/crashreporter/test/browser/browser_bug471404.js
+++ b/toolkit/crashreporter/test/browser/browser_bug471404.js
@@ -1,16 +1,16 @@
function check_clear_visible(browser, aVisible) {
return ContentTask.spawn(browser, aVisible, function(aVisible) {
- let doc = content.document;
+ const doc = content.document;
let visible = false;
- let button = doc.getElementById("clear-reports");
- if (button) {
- let style = doc.defaultView.getComputedStyle(button);
- if (style.display != "none" &&
- style.visibility == "visible")
+ const reportListSubmitted = doc.getElementById("reportListSubmitted");
+ if (reportListSubmitted) {
+ const style = doc.defaultView.getComputedStyle(reportListSubmitted);
+ if (style.display !== "none" && style.visibility === "visible") {
visible = true;
+ }
}
Assert.equal(visible, aVisible,
- "clear reports button is " + (aVisible ? "visible" : "hidden"));
+ "clear submitted reports button is " + (aVisible ? "visible" : "hidden"));
});
}
diff --git a/toolkit/crashreporter/test/browser/browser_clearReports.js b/toolkit/crashreporter/test/browser/browser_clearReports.js
index 8181ad587e60..5b98d54b9bbb 100644
--- a/toolkit/crashreporter/test/browser/browser_clearReports.js
+++ b/toolkit/crashreporter/test/browser/browser_clearReports.js
@@ -2,41 +2,23 @@
* 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/. */
-function clickClearReports(browser) {
- let doc = content.document;
-
- let button = doc.getElementById("clear-reports");
-
- if (!button) {
- Assert.ok(false, "Button not found");
- return Promise.resolve();
+function clickClearReports() {
+ const doc = content.document;
+ const reportListUnsubmitted = doc.getElementById("reportListUnsubmitted");
+ const reportListSubmitted = doc.getElementById("reportListSubmitted");
+ if (!reportListUnsubmitted || !reportListSubmitted) {
+ Assert.ok(false, "Report list not found");
}
- let style = doc.defaultView.getComputedStyle(button);
+ const unsubmittedStyle = doc.defaultView.getComputedStyle(reportListUnsubmitted);
+ const submittedStyle = doc.defaultView.getComputedStyle(reportListSubmitted);
+ Assert.notEqual(unsubmittedStyle.display, "none", "Unsubmitted report list is visible");
+ Assert.notEqual(submittedStyle.display, "none", "Submitted report list is visible");
- Assert.notEqual(style.display, "none", "Clear reports button visible");
-
- let deferred = {};
- deferred.promise = new Promise(resolve => deferred.resolve = resolve);
- var observer = new content.MutationObserver(function(mutations) {
- for (let mutation of mutations) {
- if (mutation.type == "attributes" &&
- mutation.attributeName == "style") {
- observer.disconnect();
- Assert.equal(style.display, "none", "Clear reports button hidden");
- deferred.resolve();
- }
- }
- });
- observer.observe(button, {
- attributes: true,
- childList: true,
- characterData: true,
- attributeFilter: ["style"],
- });
-
- button.click();
- return deferred.promise;
+ const clearUnsubmittedButton = doc.getElementById("clearUnsubmittedReports");
+ const clearSubmittedButton = doc.getElementById("clearSubmittedReports");
+ clearUnsubmittedButton.click();
+ clearSubmittedButton.click();
}
var promptShown = false;
@@ -103,7 +85,10 @@ add_task(async function test() {
let existing = [ file1.path, file2.path, report1.path, report2.path,
report3.path, submitdir.path, pendingdir.path ];
- await ContentTask.spawn(browser, null, clickClearReports);
+ ContentTask.spawn(browser, null, clickClearReports);
+ await BrowserTestUtils.waitForCondition(() =>
+ content.document.getElementById("reportListUnsubmitted").classList.contains("hidden")
+ && content.document.getElementById("reportListSubmitted").classList.contains("hidden"));
for (let dir of dirs) {
let entries = dir.directoryEntries;
diff --git a/toolkit/locales/en-US/crashreporter/aboutcrashes.ftl b/toolkit/locales/en-US/crashreporter/aboutcrashes.ftl
index 45d2727fb560..aa6129a763c1 100644
--- a/toolkit/locales/en-US/crashreporter/aboutcrashes.ftl
+++ b/toolkit/locales/en-US/crashreporter/aboutcrashes.ftl
@@ -4,16 +4,22 @@
crash-reports-title = Crash Reports
-clear-all-reports-label = Remove All Reports
+delete-button-label = Clear All
delete-confirm-title = Are you sure?
-delete-confirm-description = This will delete all reports and cannot be undone.
+delete-unsubmitted-description = This will delete all unsubmitted crash reports and cannot be undone.
+delete-submitted-description = This will remove the list of submitted crash reports but will not delete the submitted data. This cannot be undone.
crashes-unsubmitted-label = Unsubmitted Crash Reports
id-heading = Report ID
date-crashed-heading = Date Crashed
+submit-crash-button-label = Submit
+# This text is used to replace the label of the crash submit button
+# if the crash submission fails.
+submit-crash-button-failure-label = Failed
crashes-submitted-label = Submitted Crash Reports
date-submitted-heading = Date Submitted
+view-crash-button-label = View
no-reports-label = No crash reports have been submitted.
no-config-label = This application has not been configured to display crash reports. The preference breakpad.reportURL
must be set.