Bug 1309316 - Expose preference for auto-submitting backlogged crash reports to about:tabcrashed. r=Felipe

MozReview-Commit-ID: JvhK0MO1IK

--HG--
extra : rebase_source : 1d1b1fbab92a0fa11772779c489a221c06b236c2
This commit is contained in:
Mike Conley 2016-11-02 15:04:15 -04:00
parent 04d8c62b62
commit 446ba52ae7
10 changed files with 190 additions and 81 deletions

View File

@ -3,6 +3,9 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
html:not(.crashDumpSubmitted) #reportSent,
html:not(.crashDumpAvailable) #report-box {
html:not(.crashDumpAvailable) #reportBox,
.container[multiple="true"] > .offers > #offerHelpMessageSingle,
.container[multiple="false"] > .offers > #offerHelpMessageMultiple,
.container[multiple="false"] > .button-container > #restoreAll {
display: none;
}
}

View File

@ -62,7 +62,7 @@ var AboutTabCrashed = {
receiveMessage(message) {
switch (message.name) {
case "UpdateCount": {
this.showRestoreAll(message.data.count > 1);
this.setMultiple(message.data.count > 1);
break;
}
case "SetCrashReportAvailable": {
@ -151,11 +151,11 @@ var AboutTabCrashed = {
* Object property with the following properties:
*
* hasReport (bool):
* Whether or not there is a crash report
* Whether or not there is a crash report.
*
* sendReport (bool):
* Whether or not the the user prefers to send the report
* by default
* by default.
*
* includeURL (bool):
* Whether or not the user prefers to send the URL of
@ -166,15 +166,20 @@ var AboutTabCrashed = {
* in the report.
*
* email (String):
* The email address of the user (empty if emailMe is false)
* The email address of the user (empty if emailMe is false).
*
* requestAutoSubmit (bool):
* Whether or not we should ask the user to automatically
* submit backlogged crash reports.
*
*/
onSetCrashReportAvailable(message) {
if (message.data.hasReport) {
let data = message.data;
if (data.hasReport) {
this.hasReport = true;
document.documentElement.classList.add("crashDumpAvailable");
let data = message.data;
document.getElementById("sendReport").checked = data.sendReport;
document.getElementById("includeURL").checked = data.includeURL;
document.getElementById("emailMe").checked = data.emailMe;
@ -183,6 +188,12 @@ var AboutTabCrashed = {
}
this.showCrashReportUI(data.sendReport);
} else {
this.showCrashReportUI(false);
}
if (data.requestAutoSubmit) {
document.getElementById("requestAutoSubmit").hidden = false;
}
let event = new CustomEvent("AboutTabCrashedReady", {bubbles:true});
@ -205,24 +216,29 @@ var AboutTabCrashed = {
* True if the crash report form should be shown
*/
showCrashReportUI(shouldShow) {
let container = document.getElementById("crash-reporter-container");
container.hidden = !shouldShow;
let options = document.getElementById("options");
options.hidden = !shouldShow;
},
/**
* Toggles the display of the "Restore All" button.
* Toggles whether or not the page is one of several visible pages
* showing the crash reporter. This controls some of the language
* on the page, along with what the "primary" button is.
*
* @param shouldShow (bool)
* True if the "Restore All" button should be shown
* @param hasMultiple (bool)
* True if there are multiple crash report pages being shown.
*/
showRestoreAll(shouldShow) {
let restoreAll = document.getElementById("restoreAll");
setMultiple(hasMultiple) {
let main = document.getElementById("main");
main.setAttribute("multiple", hasMultiple);
let restoreTab = document.getElementById("restoreTab");
if (shouldShow) {
restoreAll.removeAttribute("hidden");
// The "Restore All" button has the "primary" class by default, so
// we only need to modify the "Restore Tab" button.
if (hasMultiple) {
restoreTab.classList.remove("primary");
} else {
restoreAll.setAttribute("hidden", true);
restoreTab.classList.add("primary");
}
},
@ -243,6 +259,7 @@ var AboutTabCrashed = {
let sendReport = false;
let emailMe = false;
let includeURL = false;
let autoSubmit = false;
if (this.hasReport) {
sendReport = document.getElementById("sendReport").checked;
@ -261,6 +278,15 @@ var AboutTabCrashed = {
}
}
let requestAutoSubmit = document.getElementById("requestAutoSubmit");
if (requestAutoSubmit.hidden) {
// The checkbox is hidden if the user has already opted in to sending
// backlogged crash reports.
autoSubmit = true;
} else {
autoSubmit = document.getElementById("autoSubmit").checked;
}
sendAsyncMessage(messageName, {
sendReport,
comments,
@ -268,6 +294,7 @@ var AboutTabCrashed = {
emailMe,
includeURL,
URL,
autoSubmit,
});
},
};

View File

@ -30,28 +30,54 @@
</head>
<body dir="&locale.dir;">
<div class="container">
<div id="main" class="container" multiple="false">
<div class="title">
<h1 class="title-text">&tabCrashed.header;</h1>
<h1 class="title-text">&tabCrashed.header2;</h1>
</div>
<p>&tabCrashed.message;</p>
<div id="report-box">
<input type="checkbox" id="sendReport"/>
<label for="sendReport">&tabCrashed.sendReport;</label>
<div id="crash-reporter-container" hidden="true">
<p id="crash-reporter-title">&tabCrashed.crashReporter;</p>
<textarea id="comments" placeholder="&tabCrashed.commentPlaceholder;" rows="4"></textarea>
<div class="offers">
<h2>&tabCrashed.offerHelp;</h2>
<p id="offerHelpMessageSingle">&tabCrashed.single.offerHelpMessage;</p>
<p id="offerHelpMessageMultiple">&tabCrashed.multiple.offerHelpMessage;</p>
</div>
<ul id="options">
<li><input type="checkbox" id="includeURL"/>
<label for="includeURL">&tabCrashed.includeURL;</label></li>
<div id="reportBox">
<h2>&tabCrashed.requestHelp;</h2>
<p>&tabCrashed.requestHelpMessage;</p>
<li><input type="checkbox" id="emailMe"/>
<label for="emailMe">&tabCrashed.emailMe;</label></li>
</ul>
<h2>&tabCrashed.requestReport;</h2>
<input type="text" id="email" placeholder="&tabCrashed.emailPlaceholder;"/>
<div class="checkbox-with-label">
<input type="checkbox" id="sendReport"/>
<label for="sendReport">&tabCrashed.sendReport2;</label>
</div>
<ul id="options">
<li>
<textarea id="comments" placeholder="&tabCrashed.commentPlaceholder2;" rows="4"></textarea>
</li>
<li class="checkbox-with-label">
<input type="checkbox" id="includeURL"/>
<label for="includeURL">&tabCrashed.includeURL2;</label>
</li>
<li>
<div class="checkbox-with-label">
<input type="checkbox" id="emailMe"/>
<label for="emailMe">&tabCrashed.emailMe;</label>
</div>
<input type="text" id="email" placeholder="&tabCrashed.emailPlaceholder;"/>
</li>
</ul>
<div id="requestAutoSubmit" hidden="true">
<h2>&tabCrashed.requestAutoSubmit;</h2>
<div class="checkbox-with-label">
<input type="checkbox" id="autoSubmit"/>
<label for="autoSubmit">&tabCrashed.autoSubmit;</label>
</div>
</div>
</div>
@ -60,7 +86,7 @@
<div class="button-container">
<button id="closeTab">
&tabCrashed.closeTab;</button>
<button id="restoreTab">
<button id="restoreTab" class="primary">
&tabCrashed.restoreTab;</button>
<button id="restoreAll" autofocus="true" class="primary">
&tabCrashed.restoreAll;</button>

View File

@ -31,8 +31,8 @@ add_task(function* test_show_form() {
let checkbox = doc.getElementById("sendReport");
ok(checkbox.checked, "Send report checkbox is checked.");
// Ensure the form is displayed.
let container = doc.getElementById("crash-reporter-container");
ok(!container.hidden, "Showing the crash report detail form.");
// Ensure the options form is displayed.
let options = doc.getElementById("options");
ok(!options.hidden, "Showing the crash report options form.");
});
});

View File

@ -32,9 +32,9 @@ add_task(function* test_without_dump() {
Assert.ok(!doc.documentElement.classList.contains("crashDumpAvailable"),
"doesn't have crash dump");
let container = doc.getElementById("crash-reporter-container");
Assert.ok(container, "has crash-reporter-container");
Assert.ok(container.hidden, "crash-reporter-container is hidden");
let options = doc.getElementById("options");
Assert.ok(options, "has crash report options");
Assert.ok(options.hidden, "crash report options are hidden");
doc.getElementById("closeTab").click();
});

View File

@ -392,7 +392,8 @@ add_task(function* test_hide_restore_all_button() {
let restoreAllButton = doc.getElementById("restoreAll");
let restoreOneButton = doc.getElementById("restoreTab");
is(restoreAllButton.getAttribute("hidden"), "true", "Restore All button should be hidden");
let restoreAllStyles = window.getComputedStyle(restoreAllButton);
is(restoreAllStyles.display, "none", "Restore All button should be hidden");
ok(restoreOneButton.classList.contains("primary"), "Restore Tab button should have the primary class");
let newTab2 = gBrowser.addTab();
@ -421,7 +422,8 @@ add_task(function* test_hide_restore_all_button() {
restoreAllButton = doc.getElementById("restoreAll");
restoreOneButton = doc.getElementById("restoreTab");
ok(!restoreAllButton.hasAttribute("hidden"), "Restore All button should not be hidden");
restoreAllStyles = window.getComputedStyle(restoreAllButton);
isnot(restoreAllStyles.display, "none", "Restore All button should not be hidden");
ok(!(restoreOneButton.classList.contains("primary")), "Restore Tab button should not have the primary class");
yield BrowserTestUtils.closeWindow(win2);

View File

@ -2,15 +2,29 @@
- 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/. -->
<!ENTITY tabCrashed.header "Bad news first: This tab has crashed">
<!ENTITY tabCrashed.message "Now for the good news: You can just close this tab, restore it or restore all your crashed tabs.">
<!ENTITY tabCrashed.sendReport "Submit a crash report to help prevent more bad news">
<!ENTITY tabCrashed.includeURL "Include the address of the page I was on">
<!ENTITY tabCrashed.commentPlaceholder "Add a comment (comments are publicly visible)">
<!ENTITY tabCrashed.emailPlaceholder "Enter your email address here">
<!ENTITY tabCrashed.emailMe "Email me when more information is available">
<!ENTITY tabCrashed.crashReporter "Mozilla Crash Reporter">
<!ENTITY tabCrashed.reportSent "Crash report already submitted; thank you for helping make &brandShortName; better!">
<!ENTITY tabCrashed.closeTab "Close This Tab">
<!ENTITY tabCrashed.restoreTab "Restore This Tab">
<!ENTITY tabCrashed.restoreAll "Restore All Crashed Tabs">
<!-- LOCALIZATION NOTE (tabCrashed.header2): "Gah" is an English slang word
used to express surprise or frustration (or both at the same time). We
are using it to communicate in an informal way that it is both
frustrating that your tab crashed and a surprise that we didn't want to
happen. If you have a similar word or short phrase that is not profane or
vulgar, use it. If not, feel free to skip the word in your
translation. -->
<!ENTITY tabCrashed.header2 "Gah. Your tab just crashed.">
<!ENTITY tabCrashed.offerHelp "We can help you!">
<!ENTITY tabCrashed.single.offerHelpMessage "Choose &tabCrashed.restoreTab; to reload page content.">
<!ENTITY tabCrashed.multiple.offerHelpMessage "Choose &tabCrashed.restoreTab; or &tabCrashed.restoreAll; to reload page content.">
<!ENTITY tabCrashed.requestHelp "Will you help us?">
<!ENTITY tabCrashed.requestHelpMessage "Crash reports help us diagnose problems and make &brandShortName; better.">
<!ENTITY tabCrashed.requestReport "Report this tab">
<!ENTITY tabCrashed.sendReport2 "Send a crash report for the tab you are viewing">
<!ENTITY tabCrashed.commentPlaceholder2 "Optional comments (comments are publicly visible)">
<!ENTITY tabCrashed.includeURL2 "Include page URL with this crash report">
<!ENTITY tabCrashed.emailPlaceholder "Enter your email address here">
<!ENTITY tabCrashed.emailMe "Email me when more information is available">
<!ENTITY tabCrashed.reportSent "Crash report already submitted; thank you for helping make &brandShortName; better!">
<!ENTITY tabCrashed.requestAutoSubmit "Request background tabs">
<!ENTITY tabCrashed.autoSubmit "Update preferences to automatically submit backlogged crash reports (and get fewer messages like this from us in the future)">

View File

@ -335,6 +335,12 @@ this.TabCrashHandler = {
let browser = message.target.browser;
if (message.data.autoSubmit) {
// The user has opted in to autosubmitted backlogged
// crash reports in the future.
UnsubmittedCrashHandler.autoSubmit = true;
}
let childID = this.browserMap.get(browser.permanentKey);
let dumpID = this.childMap.get(childID);
if (!dumpID)
@ -449,11 +455,19 @@ this.TabCrashHandler = {
return;
}
let requestAutoSubmit = !UnsubmittedCrashHandler.autoSubmit;
let sendReport = this.prefs.getBoolPref("sendReport");
let includeURL = this.prefs.getBoolPref("includeURL");
let emailMe = this.prefs.getBoolPref("emailMe");
let data = { hasReport: true, sendReport, includeURL, emailMe };
let data = {
hasReport: true,
sendReport,
includeURL,
emailMe,
requestAutoSubmit,
};
if (emailMe) {
data.email = this.prefs.getCharPref("email", "");
}

View File

@ -2,16 +2,35 @@
* 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/. */
body {
font-size: 1.25rem;
}
.title {
background-image: url("chrome://browser/skin/tab-crashed.svg");
}
.title > h1,
.offers {
margin-left: 14px;
}
.title > h1 {
/**
* Add commentary?
*/
padding-right: 14px;
}
.container {
width: 45%;
}
#reportSent {
font-weight: bold;
}
#crash-reporter-container {
width: 80%;
#reportBox {
background-color: var(--in-content-box-background-hover);
margin: 24px 0;
padding: 14px;
@ -19,6 +38,10 @@
border-radius: 2px;
}
#reportBox > h2:first-child {
margin-top: 0;
}
#crash-reporter-title {
font-weight: bold;
margin: 0 0 14px 0;
@ -31,12 +54,26 @@ textarea {
resize: none;
}
input[type="text"],
input[type="checkbox"] {
-moz-margin-start: 0px;
}
#options {
list-style: none;
margin-inline-start: 0;
}
input[type="text"],
#options > li {
margin: 14px 0 0 0;
#options > li,
#email {
margin-top: 14px;
}
.checkbox-with-label {
display: flex;
}
.checkbox-with-label > label {
margin-top: auto;
margin-bottom: auto;
}

View File

@ -74,11 +74,16 @@ xul|caption {
margin: 0;
}
html|h2,
xul|caption > xul|checkbox,
xul|caption > xul|label {
font-size: 1.3rem;
font-weight: bold;
line-height: 22px;
}
xul|caption > xul|checkbox,
xul|caption > xul|label {
margin: 0 !important;
}
@ -502,31 +507,12 @@ html|a:hover:active,
/* Checkboxes and radio buttons */
/* Hide the actual checkbox */
html|input[type="checkbox"] {
opacity: 0;
width: 0;
pointer-events: none;
position: absolute;
}
/* Create a box to style as the checkbox */
html|input[type="checkbox"] + html|label:before {
display: inline-block;
content: "";
vertical-align: middle;
}
html|input[type="checkbox"] + html|label {
line-height: 0px;
}
xul|checkbox {
margin-inline-start: 0;
}
xul|*.checkbox-check,
html|input[type="checkbox"] + html|label:before {
html|input[type="checkbox"] {
-moz-appearance: none;
width: 23px;
height: 23px;
@ -542,7 +528,7 @@ html|input[type="checkbox"] + html|label:before {
}
xul|checkbox:not([disabled="true"]):hover > xul|*.checkbox-check,
html|input[type="checkbox"]:not(:disabled) + html|label:hover:before {
html|input[type="checkbox"]:not(:disabled):hover {
border-color: var(--in-content-border-focus);
}
@ -550,12 +536,12 @@ xul|*.checkbox-check[checked] {
list-style-image: url("chrome://global/skin/in-content/check.svg#check");
}
html|input[type="checkbox"]:checked + html|label:before {
html|input[type="checkbox"]:checked {
background-image: url("chrome://global/skin/in-content/check.svg#check"), linear-gradient(#fff, rgba(255,255,255,0.8)) !important;
}
xul|checkbox[disabled="true"] > xul|*.checkbox-check,
html|input[type="checkbox"]:disabled + html|label {
html|input[type="checkbox"]:disabled {
opacity: 0.5;
}