Apply updates from designer and other functional requirements draft
authorthomasmo <thomasmo@mozilla.com>
Sun, 13 Oct 2019 03:16:36 +0000
changeset 2378206 bdc0bbbf2e6877b8cbcdcc51be12a18360c74ee6
parent 2367541 81ebffadd73ab463785bacfbcd38644fa576bacd
child 2378207 944c1a77fbd10832234790bb9a3b49f58e6852f0
push id434590
push userreviewbot
push dateSun, 13 Oct 2019 03:17:00 +0000
treeherdertry@944c1a77fbd1 [default view] [failures only]
milestone71.0a1
Apply updates from designer and other functional requirements Differential Diff: PHID-DIFF-3muoj4w45434cynpra43
browser/fxr/content/common.css
browser/fxr/content/common.js
browser/fxr/content/fxrui.css
browser/fxr/content/fxrui.html
browser/fxr/content/fxrui.js
browser/fxr/content/fxrui_blue.css
browser/fxr/content/prefs.css
browser/fxr/content/prefs.html
browser/fxr/content/prefs.js
browser/fxr/jar.mn
new file mode 100644
--- /dev/null
+++ b/browser/fxr/content/common.css
@@ -0,0 +1,44 @@
+/* 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/. */
+
+ * {
+  margin: 0;
+  padding: 0;
+  user-select: none;
+
+  font-family: 'Open Sans', sans-serif;
+}
+
+.modal_mask {
+  mask-image: linear-gradient(rgba(0, 0, 0, .5), rgba(0, 0, 0, .5));
+
+  height: 100%;
+  width: 100%;
+
+  position: absolute;
+  top: 0;
+  left: 0;
+}
+
+.modal_container {
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+  align-items: center;
+
+  height: 100%;
+  width: 100%;
+
+  position: absolute;
+  top: 0;
+  left :0;
+}
+
+.modal_hide {
+  display: none;
+}
+
+.modal_content {
+  position: absolute;
+}
new file mode 100644
--- /dev/null
+++ b/browser/fxr/content/common.js
@@ -0,0 +1,49 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
+ * 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/. */
+
+// Creates a modal container, if it doesn't exist, and adds the provided
+// content element to it
+function showModalContainer(content) {
+  var container = document.getElementById("eModalContainer");
+  if (container == null) {
+    container = document.createElement("div");
+    container.id = "eModalContainer";
+    container.classList.add("modal_container");
+
+    var mask = document.createElement("div");
+    mask.id = "eModalMask";
+    mask.classList.add("modal_mask");
+
+    document.body.appendChild(mask);
+    document.body.appendChild(container);
+  } else {
+    container.classList.replace("modal_hide", "modal_container");
+    document
+      .getElementById("eModalMask")
+      .classList.replace("modal_hide", "modal_mask");
+  }
+
+  container.appendChild(content);
+  if (content.classList.contains("modal_hide")) {
+    content.classList.replace("modal_hide", "modal_content");
+  } else {
+    content.classList.add("modal_content");
+  }
+}
+
+// Hides the modal container, and returns the contents back to the caller
+function clearModalContainer() {
+  var container = document.getElementById("eModalContainer");
+  container.classList.replace("modal_container", "modal_hide");
+  document
+    .getElementById("eModalMask")
+    .classList.replace("modal_mask", "modal_hide");
+
+  var content = container.firstElementChild;
+  container.removeChild(content);
+  content.classList.replace("modal_content", "modal_hide");
+
+  return content;
+}
--- a/browser/fxr/content/fxrui.css
+++ b/browser/fxr/content/fxrui.css
@@ -1,42 +1,36 @@
 /* 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/. */
 
 @namespace xul url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
 
-* {
-  margin: 0;
-  padding: 0;
+html, body {
+  height: 100%;
 }
 
 body {
-  max-width: 1600px;
-  min-width: 1600px;
-  max-height: 800px;
-  min-height: 800px;
-
   display: flex;
   flex-direction: column;
 }
 
 .navbar_container {
   width: 100%;
 
   margin-top: 20px;
   
   display: flex;
   flex-direction: row;
 }
 
 /* Sizing and positioning properties for all icons
    Color is determined by enabled/disabled classes below
  */
-.icon_container {
+ .icon_container {
   width: 44px;
   height: 44px;
   margin-inline-end: 10px;
 
   border-radius: 22px;
   border-width: 2px;
   border-style: solid;  
 
@@ -46,32 +40,34 @@ body {
   background-color: inherit;
 
   -moz-context-properties: fill;
 }
 
 .icon_disabled_hide:disabled {
   display:none;
 }
-
 .icon_backward {
   background-image: url("assets/icon-backward.svg");
 }
 .icon_forward {
   background-image: url("assets/icon-forward.svg");
 }
 .icon_refresh {
   background-image: url("assets/icon-refresh.svg");
 }
 .icon_stop {
   background-image: url("assets/icon-stop-reload.svg");
 }
 .icon_home {
   background-image: url("assets/icon-home.svg");
 }
+.icon_prefs {
+  font-size: 22px;
+}
 
 .urlbar_container {
   height: 40px;
   flex-grow: 1;
 
   padding: 0;
 
   border-radius: 22px;
@@ -106,12 +102,32 @@ body {
 
   mask-image: linear-gradient(to left, transparent, black 8ch);
 }
 
 .browser_container {
   width: 100%;
   flex-grow: 1;
 }
-xul|browser {
+
+.browser_instance {
   width: 100%;
   height: 100%;
-}
\ No newline at end of file
+}
+
+.browser_settings {
+  width: 600px;
+  height: 400px;
+  border-radius: 20px;
+}
+
+.license_info {
+  width: 800px;
+  height: 600px;
+}
+
+.license_close {
+  display: block;
+}
+
+.modal_mask {
+  background-color: var(--num13);
+}
--- a/browser/fxr/content/fxrui.html
+++ b/browser/fxr/content/fxrui.html
@@ -5,18 +5,20 @@
 
 <!--
   This file contains the HTML UI for the 2D window of Firefox Reality on Desktop
 -->
 
 <html width="1600" height="800">
 <head>
   <title>Firefox Reality</title>
+  <link rel="stylesheet" href="common.css" />
   <link rel="stylesheet" href="fxrui.css" />
   <link rel="stylesheet" href="fxrui_blue.css" />
+  <script src="common.js"></script>
   <script src="fxrui.js"></script>
 </head>
 
 <body>
   <div id="eBrowserContainer" class="browser_container"></div>
 
   <div class="navbar_container">
     <button id="eBack"    class="icon_container icon_backward"></button>
@@ -24,11 +26,12 @@
     <button id="eRefresh" class="icon_container icon_refresh icon_disabled_hide"></button>
     <button id="eStop"    class="icon_container icon_stop icon_disabled_hide" disabled></button>
     <button id="eHome"    class="icon_container icon_home" ></button>
     
     <div class="urlbar_container urlbar_container_normal" id="eUrlBarContainer">
       <img class="urlbar_secure_icon" id="eUrlSecure" src="assets/icon-secure.svg" alt="Secure"/>
       <input class="urlbar_input" id="eUrlInput" type="text" value="" />
     </div>
+    <button id="ePrefs" class="icon_container icon_prefs">&#x2699;</button>
   </div>
 </body>
 </html>
--- a/browser/fxr/content/fxrui.js
+++ b/browser/fxr/content/fxrui.js
@@ -1,29 +1,40 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
  * 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/. */
 
 // Configuration vars
 let homeURL = "https://www.mozilla.org/en-US/";
+// Bug 1586294 - Localize the privacy policy URL (Services.urlFormatter?)
+let privacyPolicyURL = "https://www.mozilla.org/en-US/privacy/firefox/";
+let reportIssueURL = "https://mzl.la/fxr";
 
 // https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XUL/browser
 let browser = null;
 // The following variable map to UI elements whose behavior changes depending
 // on some state from the browser control
 let urlInput = null;
 let secureIcon = null;
 let backButton = null;
 let forwardButton = null;
 let refreshButton = null;
 let stopButton = null;
 
 let { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
 
+const { XPCOMUtils } = ChromeUtils.import(
+  "resource://gre/modules/XPCOMUtils.jsm"
+);
+
+XPCOMUtils.defineLazyGetter(this, "gSystemPrincipal", () =>
+  Services.scriptSecurityManager.getSystemPrincipal()
+);
+
 window.addEventListener(
   "DOMContentLoaded",
   () => {
     urlInput = document.getElementById("eUrlInput");
     secureIcon = document.getElementById("eUrlSecure");
     backButton = document.getElementById("eBack");
     forwardButton = document.getElementById("eForward");
     refreshButton = document.getElementById("eRefresh");
@@ -39,16 +50,17 @@ window.addEventListener(
 // Create XUL browser object
 function setupBrowser() {
   // Note: createXULElement is undefined when this page is not loaded
   // via chrome protocol
   if (document.createXULElement) {
     browser = document.createXULElement("browser");
     browser.setAttribute("type", "content");
     browser.setAttribute("remote", "true");
+    browser.classList.add("browser_instance");
     document.getElementById("eBrowserContainer").appendChild(browser);
 
     urlInput.value = homeURL;
     browser.loadURI(homeURL);
 
     browser.addProgressListener(
       {
         QueryInterface: ChromeUtils.generateQI([
@@ -89,17 +101,24 @@ function setupBrowser() {
       Ci.nsIWebProgress.NOTIFY_LOCATION |
         Ci.nsIWebProgress.NOTIFY_SECURITY |
         Ci.nsIWebProgress.NOTIFY_STATE_REQUEST
     );
   }
 }
 
 function setupNavButtons() {
-  let aryNavButtons = ["eBack", "eForward", "eRefresh", "eStop", "eHome"];
+  let aryNavButtons = [
+    "eBack",
+    "eForward",
+    "eRefresh",
+    "eStop",
+    "eHome",
+    "ePrefs",
+  ];
 
   function navButtonHandler(e) {
     if (!this.disabled) {
       switch (this.id) {
         case "eBack":
           browser.goBack();
           break;
 
@@ -113,16 +132,20 @@ function setupNavButtons() {
 
         case "eStop":
           browser.stop();
           break;
 
         case "eHome":
           browser.loadURI(homeURL);
           break;
+
+        case "ePrefs":
+          openSettings();
+          break;
       }
     }
   }
 
   for (let btnName of aryNavButtons) {
     let elem = document.getElementById(btnName);
     elem.addEventListener("click", navButtonHandler);
   }
@@ -148,8 +171,58 @@ function setupUrlBar() {
     }
   });
 
   // Upon focus, highlight the whole URL
   urlInput.addEventListener("focus", function() {
     urlInput.select();
   });
 }
+
+function openSettings() {
+  let browserSettingsUI = document.createXULElement("browser");
+  browserSettingsUI.setAttribute("type", "chrome");
+  browserSettingsUI.classList.add("browser_settings");
+
+  showModalContainer(browserSettingsUI);
+
+  browserSettingsUI.loadURI("chrome://fxr/content/prefs.html", {
+    triggeringPrincipal: gSystemPrincipal,
+  });
+}
+
+function closeSettings() {
+  clearModalContainer();
+}
+
+function showPrivacyPolicy() {
+  closeSettings();
+  browser.loadURI(privacyPolicyURL);
+}
+
+function showLicenseInfo() {
+  closeSettings();
+
+  let licenseInfo = document.createXULElement("browser");
+  licenseInfo.setAttribute("type", "chrome");
+  licenseInfo.classList.add("license_info");
+
+  let licenseClose = document.createElement("button");
+  licenseClose.classList.add("icon_container", "icon_backward");
+  licenseClose.addEventListener("click", () => {
+    clearModalContainer();
+  });
+
+  let licenseContainer = document.createElement("div");
+  licenseContainer.appendChild(licenseClose);
+  licenseContainer.appendChild(licenseInfo);
+
+  showModalContainer(licenseContainer);
+
+  licenseInfo.loadURI("chrome://fxr/content/assets/license.html", {
+    triggeringPrincipal: gSystemPrincipal,
+  });
+}
+
+function showReportIssue() {
+  closeSettings();
+  browser.loadURI(reportIssueURL);
+}
--- a/browser/fxr/content/fxrui_blue.css
+++ b/browser/fxr/content/fxrui_blue.css
@@ -1,66 +1,69 @@
 /* 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/. */
 
  /* These not-very-descriptive variable names for colors come
   * from the design documents and are maintained to make it
   * easier to map between the stylesheet and the design doc.
   */
- :root {
-    --num06: #FFFFFF;
-    --num07: #00B3E3;
-    --num08: #56D9F6;
-    --num09: #0968B6;
-    --num13: #2C3A50;
-    --num14: #596677;
-    --num16: #E7EAF0;
-    
-    --secure: #f7ce4d;
-  }
-  
-  body {
-    background-color: var(--num06);
-  }
+:root {
+  --num03: #7D8896;
+  --num04: #B3BECC;
+  --num06: #FFFFFF;
+  --num07: #00B3E3;
+  --num08: #56D9F6;
+  --num09: #0968B6;
+  --num13: #2C3A50;
+  --num14: #596677;
+  --num16: #E7EAF0;
+  --num19: #FFFFFF;
   
-  .icon_container {
-    border-color: var(--num08);
-    background-color: var(--num06);
-    fill: var(--num08);
-  }
-  .icon_container:hover {
-    background-color: var(--num07);  
-    border-color: var(--num07);
-    fill: var(--num06);
-  }
-  .icon_container:active {
-    background-color: var(--num09);  
-    border-color: var(--num09);
-    fill: var(--num06);
-  }
-  .icon_container:disabled {
-    background-color: var(--num16);  
-    border-color: var(--num16);
-    fill: var(--num14);
-  }
-  
-  .urlbar_container {  
-    border-color:var(--num08);
-    background-color: var(--num06);
-  }
-  .urlbar_container:hover {
-    border-color:var(--num07);
-  }
-  .urlbar_container:focus-within {
-    border-color:var(--num08);
-  }
-  
-  .urlbar_secure_icon {
-    fill: var(--secure);
-  }
-  
-  .urlbar_input {  
-    color: var(--num13);
-  }
-  .urlbar_input::selection {
-    background-color: var(--num08);
-  }
+  --secure: #f7ce4d;
+}
+
+body {
+  background-color: var(--num06);
+}
+
+.icon_container {
+  border-color: var(--num08);
+  background-color: var(--num06);
+  fill: var(--num08);
+}
+.icon_container:hover {
+  background-color: var(--num07);  
+  border-color: var(--num07);
+  fill: var(--num06);
+}
+.icon_container:active {
+  background-color: var(--num09);  
+  border-color: var(--num09);
+  fill: var(--num06);
+}
+.icon_container:disabled {
+  background-color: var(--num16);  
+  border-color: var(--num16);
+  fill: var(--num14);
+}
+
+.urlbar_container {  
+  border-color:var(--num08);
+  background-color: var(--num06);
+}
+.urlbar_container:hover {
+  border-color:var(--num07);
+}
+.urlbar_container:focus-within {
+  border-color:var(--num08);
+}
+
+.urlbar_secure_icon {
+  fill: var(--secure);
+}
+
+.urlbar_input {  
+  color: var(--num13);
+}
+.urlbar_input::selection {
+  background-color: var(--num08);
+}
new file mode 100644
--- /dev/null
+++ b/browser/fxr/content/prefs.css
@@ -0,0 +1,172 @@
+/* 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 {
+  margin: 10px 50px;
+}
+
+.plain_button {
+  border: none;
+  background-color: transparent;
+}
+
+.settings_header{
+  display: flex;
+  flex-direction: row;
+}
+
+.icon_backward {
+  height: 30px;
+  width: 30px;
+
+  margin: 20px 70px 70px 20px;
+
+  background-image: url("assets/icon-backward.svg");
+  -moz-context-properties: fill;
+  fill: var(--num14);
+}
+.icon_backward:hover {
+  height: 40px;
+  width: 40px;
+  margin: 15px 65px 65px 15px;
+
+  fill: var(--num07);
+}
+.icon_backward:active {
+  height: 40px;
+  width: 40px;
+  margin: 15px 65px 65px 15px;
+
+  fill: var(--num09);
+}
+
+.about_container {
+  flex-grow: 1;
+  text-align: center;
+}
+
+.fxr_logo {
+  width: 72px;
+  height: 72px;
+  background-color: orange;
+}
+
+.version_text {
+  font-size: 10px;
+  color: var(--num14);
+}
+
+.button_report_issue {
+  height: 50px;
+  width: 110px;
+  margin: 20px 0px 70px 10px;
+  
+  font-size: 10px;
+  text-align: start;
+}
+
+.button_report_issue_icon {
+  float:left;
+}
+
+.button_report_text {
+  color: var(--num13);
+}
+
+.button_report_url {
+  color: var(--num14);
+}
+
+.settings_title {
+  font-size: 22px;
+  font-weight: bold;
+  color: var(--num13);
+  text-align: center;
+
+  flex-grow: 1;
+}
+
+.divider {
+  border-style: solid;
+  border-width: 1px;
+  border-color:  var(--num04);
+  margin: 10px;
+}
+
+.setting_container {
+  display: flex;
+  flex-direction: row;
+
+  margin: 10px 5px;
+}
+
+.setting_name {
+  font-size: 14px;
+  color: var(--num13);
+  
+  flex-grow: 1;
+}
+
+.setting_description {
+  font-size: 10px;
+  color: var(--num14);
+  margin: 0 10px;
+}
+
+.setting_control {
+  min-width: 120px;
+  margin: 5px 0px;
+}
+
+button.setting_control {
+  height: 30px;
+
+  font-size: 14px;
+  font-weight: bold;
+
+  border-color: var(--num08);
+  border-width: 2px;
+  border-style: solid;
+  border-radius: 5px;
+
+  background-color: var(--num06);
+}
+button.setting_control:hover {
+  background-color: var(--num07);
+  border-color: var(--num07);
+}
+button.setting_control:active {
+  background-color: var(--num09);
+  border-color: var(--num09);
+  color: var(--num19);
+}
+button.setting_control:disabled {
+  background-color: var(--num06);
+  border-color: var(--num08);
+  color: var(--num03);
+}
+
+.clear_confirmation {
+  padding: 20px;
+  background-color: var(--num19);
+  border-radius: 20px;
+}
+
+/*TODO: replace bg-color with bg-image when assets are available*/
+.setting_control_chk {
+  opacity: 0;
+}
+.setting_control_chk + label {
+  background-color: red;
+}
+.setting_control_chk:checked + label {
+  background-color: green;
+}
+.setting_control_chk:disabled + label {
+  background-color: gray;
+}
+
+.modal_mask {
+  background-color: var(--num14);
+}
new file mode 100644
--- /dev/null
+++ b/browser/fxr/content/prefs.html
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<!-- 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/. -->
+
+<!--
+  This file contains the Settings UI for Firefox Reality on Desktop
+-->
+
+<html width="800" height="400">
+<head>
+  <title>Firefox Reality Settings</title>
+  <link rel="stylesheet" href="prefs.css" />
+  <link rel="stylesheet" href="common.css" />
+  <link rel="stylesheet" href="fxrui_blue.css" />
+  <script src="prefs.js"></script>
+  <script src="common.js"></script>
+</head>
+
+<body>
+  <div class="settings_header">
+    <button id="eCloseSettings" class="plain_button icon_backward"></button>
+    <div class="about_container">
+      <img class="fxr_logo" />
+      <div class="version_text">version 1</div>
+      <div class="version_text">(2019-xx-xx)</div>
+      <div class="version_text">Firefox Version NN</div>
+    </div>  
+    <button id="eReportIssue" class="plain_button button_report_issue">
+      <div class="button_report_issue_icon">&#x1f4ac;</div>
+      <div class="button_report_text">Report an issue</div>
+      <div class="button_report_url">mzl.la/fxr</div>
+    </button>
+  </div>
+
+  <div class="settings_title">Settings</div>
+  <hr class="divider"/>
+
+  <div class="setting_container">
+    <div class="setting_name">Mozilla's Privacy Policy Page</div>
+    <button id="ePrivacyPolicy" class="setting_control">Open</button>
+  </div>
+
+  <div class="setting_container">
+    <div class="setting_name">Firefox Reality Licensing Information</div>
+    <button id="eLicenseInfo" class="setting_control">Open</button>
+  </div>
+
+  <div class="setting_container">
+    <div class="setting_name">
+      Cookies, Site Data, and Cached Web Content
+      <div class="setting_description">
+        Clearing may sign you out of websites and will require websites to reload images and data.
+      </div>
+    </div>
+    <button class="setting_control" id="eClearTry">Clear Data</button>
+  </div>
+  <div class="clear_confirmation modal_hide" id="eClearPrompt">
+      Are you sure you want to clear all data?
+      <div>
+        <button id="eClearCancel"  class="setting_control">Cancel</button>
+        <button id="eClearConfirm" class="setting_control">Clear</button>
+      </div>
+  </div>
+
+  <div class="setting_container">
+    <div class="setting_name">
+      Allow Firefox to Anonymously Collect and Use Technical and Interaction Data
+    </div>
+    <input id="eCrashConfig" type="checkbox" class="setting_control_chk" />
+    <label class="setting_control" for="eCrashConfig"></label>
+  </div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/browser/fxr/content/prefs.js
@@ -0,0 +1,101 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
+ * 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/. */
+
+const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
+
+var { AppConstants } = ChromeUtils.import(
+  "resource://gre/modules/AppConstants.jsm"
+);
+
+const PREF_UPLOAD_ENABLED = "datareporting.healthreport.uploadEnabled";
+
+window.addEventListener(
+  "DOMContentLoaded",
+  () => {
+    initClearAllData();
+    initSubmitHealthReport();
+    initParentDependencies();
+  },
+  { once: true }
+);
+
+function initClearAllData() {
+  let eClearPrompt = document.getElementById("eClearPrompt");
+
+  let eClearTry = document.getElementById("eClearTry");
+  eClearTry.addEventListener("click", () => {
+    showModalContainer(eClearPrompt);
+  });
+
+  let eClearCancel = document.getElementById("eClearCancel");
+  eClearCancel.addEventListener("click", () => {
+    document.body.appendChild(clearModalContainer());
+  });
+
+  // When the confirm option is visible, do the work to actually clear the data
+  document.getElementById("eClearConfirm").addEventListener("click", () => {
+    Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_ALL, function(
+      aFailedFlags
+    ) {
+      if (aFailedFlags == 0) {
+        eClearTry.textContent = "Data cleared";
+        eClearTry.disabled = true;
+        document.body.appendChild(clearModalContainer());
+      } else {
+        eClearTry.textContent = "Error";
+      }
+    });
+  });
+}
+
+// Based on https://searchfox.org/mozilla-central/source/browser/components/preferences/in-content/privacy.js
+function initSubmitHealthReport() {
+  let checkbox = document.getElementById("eCrashConfig");
+
+  // Telemetry is only sending data if MOZ_TELEMETRY_REPORTING is defined.
+  // We still want to display the preferences panel if that's not the case, but
+  // we want it to be disabled and unchecked.
+  if (
+    Services.prefs.prefIsLocked(PREF_UPLOAD_ENABLED) ||
+    !AppConstants.MOZ_TELEMETRY_REPORTING
+  ) {
+    checkbox.disabled = true;
+  } else {
+    checkbox.addEventListener("change", updateSubmitHealthReport);
+
+    checkbox.checked =
+      Services.prefs.getBoolPref(PREF_UPLOAD_ENABLED) &&
+      AppConstants.MOZ_TELEMETRY_REPORTING;
+  }
+}
+
+/**
+ * Update the health report preference with state from checkbox.
+ */
+function updateSubmitHealthReport() {
+  let checkbox = document.getElementById("eCrashConfig");
+  Services.prefs.setBoolPref(PREF_UPLOAD_ENABLED, checkbox.checked);
+  console.log("Updated " + PREF_UPLOAD_ENABLED + " : " + checkbox.checked);
+}
+
+function initParentDependencies() {
+  if (window.parent != window) {
+    document.getElementById("eCloseSettings").addEventListener("click", () => {
+      window.parent.closeSettings();
+    });
+
+    document.getElementById("ePrivacyPolicy").addEventListener("click", () => {
+      window.parent.showPrivacyPolicy();
+    });
+
+    document.getElementById("eLicenseInfo").addEventListener("click", () => {
+      window.parent.showLicenseInfo();
+    });
+
+    document.getElementById("eReportIssue").addEventListener("click", () => {
+      window.parent.showReportIssue();
+    });
+  }
+}
--- a/browser/fxr/jar.mn
+++ b/browser/fxr/jar.mn
@@ -1,19 +1,25 @@
 # 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/.
 
 #if defined(NIGHTLY_BUILD) && defined(XP_WIN) 
 browser.jar:
 %  content fxr %content/browser/fxr/
+   content/browser/fxr/common.css       (content/common.css)
+   content/browser/fxr/common.js        (content/common.js)
    content/browser/fxr/fxrui.html       (content/fxrui.html)
    content/browser/fxr/fxrui.css        (content/fxrui.css)
    content/browser/fxr/fxrui_blue.css   (content/fxrui_blue.css)
    content/browser/fxr/fxrui.js         (content/fxrui.js)
+   content/browser/fxr/prefs.html       (content/prefs.html)
+   content/browser/fxr/prefs.css        (content/prefs.css)
+   content/browser/fxr/prefs.js         (content/prefs.js)
    
    content/browser/fxr/assets/icon-backward.svg         (content/assets/icon-backward.svg)
    content/browser/fxr/assets/icon-forward.svg          (content/assets/icon-forward.svg)
    content/browser/fxr/assets/icon-home.svg             (content/assets/icon-home.svg)
    content/browser/fxr/assets/icon-refresh.svg          (content/assets/icon-refresh.svg)
    content/browser/fxr/assets/icon-secure.svg           (content/assets/icon-secure.svg)
    content/browser/fxr/assets/icon-stop-reload.svg      (content/assets/icon-stop-reload.svg)
+   content/browser/fxr/assets/license.html              (content/assets/license.html)
 #endif