Bug 1309316 - Expose preference for auto-submitting backlogged crash reports to about:tabcrashed. r?felipe draft
authorMike Conley <mconley@mozilla.com>
Wed, 02 Nov 2016 15:04:15 -0400
changeset 437726 ab2ae4b225dbd7f7aa994ba8033b492c24a9bab4
parent 435356 aea5b4c3d165dcde027b3b6551b146a56748e9be
child 437727 09134dd032bfa4800e1ea306e95543a31aa18665
push id35503
push usermconley@mozilla.com
push dateFri, 11 Nov 2016 15:06:36 +0000
reviewersfelipe
bugs1309316
milestone52.0a1
Bug 1309316 - Expose preference for auto-submitting backlogged crash reports to about:tabcrashed. r?felipe MozReview-Commit-ID: JvhK0MO1IK
browser/base/content/aboutTabCrashed.css
browser/base/content/aboutTabCrashed.js
browser/base/content/aboutTabCrashed.xhtml
browser/base/content/test/general/browser_aboutTabCrashed_showForm.js
browser/base/content/test/general/browser_aboutTabCrashed_withoutDump.js
browser/components/sessionstore/test/browser_crashedTabs.js
browser/locales/en-US/chrome/browser/aboutTabCrashed.dtd
browser/modules/ContentCrashHandlers.jsm
browser/themes/shared/aboutTabCrashed.css
toolkit/themes/shared/in-content/common.inc.css
--- a/browser/base/content/aboutTabCrashed.css
+++ b/browser/base/content/aboutTabCrashed.css
@@ -1,8 +1,11 @@
 /* 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/. */
 
 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;
-}
+}
\ No newline at end of file
--- a/browser/base/content/aboutTabCrashed.js
+++ b/browser/base/content/aboutTabCrashed.js
@@ -57,17 +57,17 @@ var AboutTabCrashed = {
     addEventListener("DOMContentLoaded", this);
 
     document.title = this.pageData.title;
   },
 
   receiveMessage(message) {
     switch (message.name) {
       case "UpdateCount": {
-        this.showRestoreAll(message.data.count > 1);
+        this.setMultiple(message.data.count > 1);
         break;
       }
       case "SetCrashReportAvailable": {
         this.onSetCrashReportAvailable(message);
         break;
       }
       case "CrashReportSent": {
         this.onCrashReportSent();
@@ -146,48 +146,59 @@ var AboutTabCrashed = {
    * will respond with whether or not a crash report is available. This
    * method handles that message.
    *
    * @param message
    *        The message from the parent, which should contain a data
    *        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
    *          the tab that crashed.
    *
    *        emailMe (bool):
    *          Whether or not to send the email address of the user
    *          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;
       if (data.emailMe) {
         document.getElementById("email").value = data.email;
       }
 
       this.showCrashReportUI(data.sendReport);
+    } else {
+      this.showCrashReportUI(false);
+    }
+
+    if (data.requestAutoSubmit) {
+      document.getElementById("requestAutoSubmit").hidden = false;
     }
 
     let event = new CustomEvent("AboutTabCrashedReady", {bubbles:true});
     document.dispatchEvent(event);
   },
 
   /**
    * Handler for when the parent reports that the crash report associated
@@ -200,34 +211,39 @@ var AboutTabCrashed = {
 
   /**
    * Toggles the display of the crash report form.
    *
    * @param shouldShow (bool)
    *        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");
     }
   },
 
   /**
    * Sends a message to the parent in response to the user choosing
    * one of the actions available on the page. This might also send up
    * crash report information if the user has chosen to submit a crash
@@ -238,16 +254,17 @@ var AboutTabCrashed = {
    */
   sendMessage(messageName) {
     let comments = "";
     let email = "";
     let URL = "";
     let sendReport = false;
     let emailMe = false;
     let includeURL = false;
+    let autoSubmit = false;
 
     if (this.hasReport) {
       sendReport = document.getElementById("sendReport").checked;
       if (sendReport) {
         comments = document.getElementById("comments").value.trim();
 
         includeURL = document.getElementById("includeURL").checked;
         if (includeURL) {
@@ -256,20 +273,30 @@ var AboutTabCrashed = {
 
         emailMe = document.getElementById("emailMe").checked;
         if (emailMe) {
           email = document.getElementById("email").value.trim();
         }
       }
     }
 
+    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,
       email,
       emailMe,
       includeURL,
       URL,
+      autoSubmit,
     });
   },
 };
 
 AboutTabCrashed.init();
--- a/browser/base/content/aboutTabCrashed.xhtml
+++ b/browser/base/content/aboutTabCrashed.xhtml
@@ -25,47 +25,73 @@
           href="chrome://global/skin/in-content/info-pages.css"/>
     <link rel="stylesheet" type="text/css" media="all"
           href="chrome://browser/content/aboutTabCrashed.css"/>
     <link rel="stylesheet" type="text/css" media="all"
           href="chrome://browser/skin/aboutTabCrashed.css"/>
   </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>
+
+      <div class="offers">
+        <h2>&tabCrashed.offerHelp;</h2>
+        <p id="offerHelpMessageSingle">&tabCrashed.single.offerHelpMessage;</p>
+        <p id="offerHelpMessageMultiple">&tabCrashed.multiple.offerHelpMessage;</p>
       </div>
-      <p>&tabCrashed.message;</p>
+
+      <div id="reportBox">
+        <h2>&tabCrashed.requestHelp;</h2>
+        <p>&tabCrashed.requestHelpMessage;</p>
+
+        <h2>&tabCrashed.requestReport;</h2>
+
+        <div class="checkbox-with-label">
+          <input type="checkbox" id="sendReport"/>
+          <label for="sendReport">&tabCrashed.sendReport2;</label>
+        </div>
 
-      <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>
+        <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>
 
-          <ul id="options">
-            <li><input type="checkbox" id="includeURL"/>
-            <label for="includeURL">&tabCrashed.includeURL;</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>
 
-            <li><input type="checkbox" id="emailMe"/>
-            <label for="emailMe">&tabCrashed.emailMe;</label></li>
-          </ul>
-
-          <input type="text" id="email" placeholder="&tabCrashed.emailPlaceholder;"/>
+        <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>
 
       <p id="reportSent">&tabCrashed.reportSent;</p>
 
       <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>
       </div>
     </div>
   </body>
   <script type="text/javascript;version=1.8" src="chrome://browser/content/aboutTabCrashed.js"/>
 </html>
--- a/browser/base/content/test/general/browser_aboutTabCrashed_showForm.js
+++ b/browser/base/content/test/general/browser_aboutTabCrashed_showForm.js
@@ -26,13 +26,13 @@ add_task(function* test_show_form() {
 
     let doc = browser.contentDocument;
 
     // Ensure the checkbox is checked. We can safely reach into
     // the content since about:tabcrashed is an in-process URL.
     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.");
   });
 });
--- a/browser/base/content/test/general/browser_aboutTabCrashed_withoutDump.js
+++ b/browser/base/content/test/general/browser_aboutTabCrashed_withoutDump.js
@@ -27,18 +27,18 @@ add_task(function* test_without_dump() {
 
     let tabRemovedPromise = BrowserTestUtils.removeTab(tab, { dontRemove: true });
 
     yield ContentTask.spawn(browser, null, function*() {
       let doc = content.document;
       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();
     });
 
     yield tabRemovedPromise;
   });
 });
--- a/browser/components/sessionstore/test/browser_crashedTabs.js
+++ b/browser/components/sessionstore/test/browser_crashedTabs.js
@@ -387,17 +387,18 @@ add_task(function* test_hide_restore_all
 
   // Crash the tab
   yield BrowserTestUtils.crashBrowser(browser);
 
   let doc = browser.contentDocument;
   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();
   gBrowser.selectedTab = newTab;
 
   browser.loadURI(PAGE_2);
   yield promiseBrowserLoaded(browser);
 
@@ -416,17 +417,18 @@ add_task(function* test_hide_restore_all
   // Crash the first tab.
   yield BrowserTestUtils.crashBrowser(browser);
   yield otherBrowserReady;
 
   doc = browser.contentDocument;
   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);
   gBrowser.removeTab(newTab);
   gBrowser.removeTab(newTab2);
 });
 
 add_task(function* test_aboutcrashedtabzoom() {
--- a/browser/locales/en-US/chrome/browser/aboutTabCrashed.dtd
+++ b/browser/locales/en-US/chrome/browser/aboutTabCrashed.dtd
@@ -1,16 +1,30 @@
 <!-- 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/. -->
 
-<!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)">
\ No newline at end of file
--- a/browser/modules/ContentCrashHandlers.jsm
+++ b/browser/modules/ContentCrashHandlers.jsm
@@ -330,16 +330,22 @@ this.TabCrashHandler = {
    *        even if they are empty.
    */
   maybeSendCrashReport(message) {
     if (!AppConstants.MOZ_CRASHREPORTER)
       return;
 
     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)
       return
 
     if (!message.data.sendReport) {
       Services.telemetry.getHistogramById("FX_CONTENT_CRASH_NOT_SUBMITTED").add(1);
       this.prefs.setBoolPref("sendReport", false);
@@ -444,21 +450,29 @@ this.TabCrashHandler = {
     let dumpID = this.getDumpID(browser);
     if (!dumpID) {
       message.target.sendAsyncMessage("SetCrashReportAvailable", {
         hasReport: false,
       });
       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", "");
     }
 
     // Make sure to only count once even if there are multiple windows
     // that will all show about:tabcrashed.
     if (this._crashedTabCount == 1) {
       Services.telemetry.getHistogramById("FX_CONTENT_CRASH_PRESENTED").add(1);
--- a/browser/themes/shared/aboutTabCrashed.css
+++ b/browser/themes/shared/aboutTabCrashed.css
@@ -1,42 +1,79 @@
 /* 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/. */
 
+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;
   border: 1px solid var(--in-content-box-border-color);
   border-radius: 2px;
 }
 
+#reportBox > h2:first-child {
+  margin-top: 0;
+}
+
 #crash-reporter-title {
   font-weight: bold;
   margin: 0 0 14px 0;
 }
 
 input[type="text"],
 textarea {
   width: 100%;
   box-sizing: border-box;
   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;
+}
\ No newline at end of file
--- a/toolkit/themes/shared/in-content/common.inc.css
+++ b/toolkit/themes/shared/in-content/common.inc.css
@@ -69,21 +69,26 @@ html|hr {
   border-color: var(--in-content-border-color);
 }
 
 xul|caption {
   -moz-appearance: none;
   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;
 }
 
 *|*.main-content {
   padding-top: 40px;
   padding-inline-end: 44px; /* compensate the 4px margin of child elements */
   padding-bottom: 48px;
   padding-inline-start: 48px;
@@ -497,70 +502,51 @@ html|a:visited {
 html|a:hover:active,
 .text-link:hover:active {
   color: var(--in-content-link-color-active);
   text-decoration: none;
 }
 
 /* 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;
   border-radius: 2px;
   border: 1px solid var(--in-content-box-border-color);
   margin-inline-end: 10px;
   background-color: #f1f1f1;
   /* !important needed to override toolkit checked !important rule */
   background-image: linear-gradient(#fff, rgba(255,255,255,0.8)) !important;
   background-position: center center;
   background-repeat: no-repeat;
   box-shadow: 0 1px 1px 0 #fff, inset 0 2px 0 0 rgba(0,0,0,0.03);
 }
 
 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);
 }
 
 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;
 }
 
 xul|*.checkbox-label-box {
   margin-inline-start: -1px; /* negative margin for the transparent border */
   padding-inline-start: 0;
 }