Bug 1462673 - Part 0. Copy LightWeightThemeWebInstallListener code from content.js to a jsm. r=mconley
authorFelipe Gomes <felipc@gmail.com>
Fri, 25 May 2018 14:22:14 -0300
changeset 419902 5327b22f40b0ca16ac797e1a2df4a34262c26b31
parent 419901 b7733393d2e3f80d53d2945fceccbdb46a5b699a
child 419903 37f13f4b96e2e19c313f412182712ca767a45ec6
push id103655
push userfelipc@gmail.com
push dateFri, 25 May 2018 17:22:32 +0000
treeherdermozilla-inbound@abb1759701b3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmconley
bugs1462673
milestone62.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1462673 - Part 0. Copy LightWeightThemeWebInstallListener code from content.js to a jsm. r=mconley
browser/base/content/content.js
browser/modules/LightWeightThemeWebInstallListener.jsm
browser/modules/moz.build
--- a/browser/base/content/content.js
+++ b/browser/base/content/content.js
@@ -1007,69 +1007,16 @@ PageMetadataMessenger.init();
 addMessageListener("Bookmarks:GetPageDetails", (message) => {
   let doc = content.document;
   let isErrorPage = /^about:(neterror|certerror|blocked)/.test(doc.documentURI);
   sendAsyncMessage("Bookmarks:GetPageDetails:Result",
                    { isErrorPage,
                      description: PlacesUIUtils.getDescriptionFromDocument(doc) });
 });
 
-var LightWeightThemeWebInstallListener = {
-  _previewWindow: null,
-
-  init() {
-    addEventListener("InstallBrowserTheme", this, false, true);
-    addEventListener("PreviewBrowserTheme", this, false, true);
-    addEventListener("ResetBrowserThemePreview", this, false, true);
-  },
-
-  handleEvent(event) {
-    switch (event.type) {
-      case "InstallBrowserTheme": {
-        sendAsyncMessage("LightWeightThemeWebInstaller:Install", {
-          baseURI: event.target.baseURI,
-          principal: event.target.nodePrincipal,
-          themeData: event.target.getAttribute("data-browsertheme"),
-        });
-        break;
-      }
-      case "PreviewBrowserTheme": {
-        sendAsyncMessage("LightWeightThemeWebInstaller:Preview", {
-          baseURI: event.target.baseURI,
-          principal: event.target.nodePrincipal,
-          themeData: event.target.getAttribute("data-browsertheme"),
-        });
-        this._previewWindow = event.target.ownerGlobal;
-        this._previewWindow.addEventListener("pagehide", this, true);
-        break;
-      }
-      case "pagehide": {
-        sendAsyncMessage("LightWeightThemeWebInstaller:ResetPreview");
-        this._resetPreviewWindow();
-        break;
-      }
-      case "ResetBrowserThemePreview": {
-        if (this._previewWindow) {
-          sendAsyncMessage("LightWeightThemeWebInstaller:ResetPreview",
-                           {principal: event.target.nodePrincipal});
-          this._resetPreviewWindow();
-        }
-        break;
-      }
-    }
-  },
-
-  _resetPreviewWindow() {
-    this._previewWindow.removeEventListener("pagehide", this, true);
-    this._previewWindow = null;
-  }
-};
-
-LightWeightThemeWebInstallListener.init();
-
 let OfflineApps = {
   _docId: 0,
   _docIdMap: new Map(),
 
   _docManifestSet: new Set(),
 
   _observerAdded: false,
   registerWindow(aWindow) {
copy from browser/base/content/content.js
copy to browser/modules/LightWeightThemeWebInstallListener.jsm
--- a/browser/base/content/content.js
+++ b/browser/modules/LightWeightThemeWebInstallListener.jsm
@@ -1,1022 +1,12 @@
-/* -*- 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/. */
 
-/* This content script should work in any browser or iframe and should not
- * depend on the frame being contained in tabbrowser. */
-
-/* eslint-env mozilla/frame-script */
-
-ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
-ChromeUtils.import("resource://gre/modules/Services.jsm");
-
-// TabChildGlobal
-var global = this;
-
-XPCOMUtils.defineLazyModuleGetters(this, {
-  BrowserUtils: "resource://gre/modules/BrowserUtils.jsm",
-  ContentLinkHandler: "resource:///modules/ContentLinkHandler.jsm",
-  ContentMetaHandler: "resource:///modules/ContentMetaHandler.jsm",
-  ContentWebRTC: "resource:///modules/ContentWebRTC.jsm",
-  InlineSpellCheckerContent: "resource://gre/modules/InlineSpellCheckerContent.jsm",
-  LoginManagerContent: "resource://gre/modules/LoginManagerContent.jsm",
-  LoginFormFactory: "resource://gre/modules/LoginManagerContent.jsm",
-  InsecurePasswordUtils: "resource://gre/modules/InsecurePasswordUtils.jsm",
-  PluginContent: "resource:///modules/PluginContent.jsm",
-  PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.jsm",
-  FormSubmitObserver: "resource:///modules/FormSubmitObserver.jsm",
-  PageMetadata: "resource://gre/modules/PageMetadata.jsm",
-  PlacesUIUtils: "resource:///modules/PlacesUIUtils.jsm",
-  SafeBrowsing: "resource://gre/modules/SafeBrowsing.jsm",
-  Utils: "resource://gre/modules/sessionstore/Utils.jsm",
-  WebNavigationFrames: "resource://gre/modules/WebNavigationFrames.jsm",
-  ContextMenu: "resource:///modules/ContextMenu.jsm",
-});
-
-XPCOMUtils.defineLazyGetter(this, "gPipNSSBundle", function() {
-  return Services.strings.createBundle("chrome://pipnss/locale/pipnss.properties");
-});
-XPCOMUtils.defineLazyGetter(this, "gNSSErrorsBundle", function() {
-  return Services.strings.createBundle("chrome://pipnss/locale/nsserrors.properties");
-});
-
-XPCOMUtils.defineLazyProxy(this, "contextMenu", () => {
-  return new ContextMenu(global);
-});
-
-XPCOMUtils.defineLazyProxy(this, "formSubmitObserver", () => {
-  return new FormSubmitObserver(content, this);
-}, {
-  // stub QI
-  QueryInterface: ChromeUtils.generateQI([Ci.nsIFormSubmitObserver, Ci.nsISupportsWeakReference])
-});
-
-XPCOMUtils.defineLazyProxy(this, "PageInfoListener",
-                           "resource:///modules/PageInfoListener.jsm");
-
-Services.els.addSystemEventListener(global, "contextmenu", contextMenu, false);
-
-Services.obs.addObserver(formSubmitObserver, "invalidformsubmit", true);
-
-addMessageListener("PageInfo:getData", PageInfoListener);
-
-addMessageListener("RemoteLogins:fillForm", function(message) {
-  // intercept if ContextMenu.jsm had sent a plain object for remote targets
-  message.objects.inputElement = contextMenu.getTarget(message, "inputElement");
-  LoginManagerContent.receiveMessage(message, content);
-});
-addEventListener("DOMFormHasPassword", function(event) {
-  LoginManagerContent.onDOMFormHasPassword(event, content);
-  let formLike = LoginFormFactory.createFromForm(event.originalTarget);
-  InsecurePasswordUtils.reportInsecurePasswords(formLike);
-});
-addEventListener("DOMInputPasswordAdded", function(event) {
-  LoginManagerContent.onDOMInputPasswordAdded(event, content);
-  let formLike = LoginFormFactory.createFromField(event.originalTarget);
-  InsecurePasswordUtils.reportInsecurePasswords(formLike);
-});
-addEventListener("pageshow", function(event) {
-  LoginManagerContent.onPageShow(event, content);
-});
-addEventListener("DOMAutoComplete", function(event) {
-  LoginManagerContent.onUsernameInput(event);
-});
-addEventListener("blur", function(event) {
-  LoginManagerContent.onUsernameInput(event);
-});
-
-const SEC_ERROR_BASE          = Ci.nsINSSErrorsService.NSS_SEC_ERROR_BASE;
-const MOZILLA_PKIX_ERROR_BASE = Ci.nsINSSErrorsService.MOZILLA_PKIX_ERROR_BASE;
-
-const SEC_ERROR_EXPIRED_CERTIFICATE                = SEC_ERROR_BASE + 11;
-const SEC_ERROR_UNKNOWN_ISSUER                     = SEC_ERROR_BASE + 13;
-const SEC_ERROR_UNTRUSTED_ISSUER                   = SEC_ERROR_BASE + 20;
-const SEC_ERROR_UNTRUSTED_CERT                     = SEC_ERROR_BASE + 21;
-const SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE         = SEC_ERROR_BASE + 30;
-const SEC_ERROR_CA_CERT_INVALID                    = SEC_ERROR_BASE + 36;
-const SEC_ERROR_OCSP_FUTURE_RESPONSE               = SEC_ERROR_BASE + 131;
-const SEC_ERROR_OCSP_OLD_RESPONSE                  = SEC_ERROR_BASE + 132;
-const SEC_ERROR_REUSED_ISSUER_AND_SERIAL           = SEC_ERROR_BASE + 138;
-const SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED  = SEC_ERROR_BASE + 176;
-const MOZILLA_PKIX_ERROR_NOT_YET_VALID_CERTIFICATE = MOZILLA_PKIX_ERROR_BASE + 5;
-const MOZILLA_PKIX_ERROR_NOT_YET_VALID_ISSUER_CERTIFICATE = MOZILLA_PKIX_ERROR_BASE + 6;
-const MOZILLA_PKIX_ERROR_SELF_SIGNED_CERT          = MOZILLA_PKIX_ERROR_BASE + 14;
-const MOZILLA_PKIX_ERROR_MITM_DETECTED             = MOZILLA_PKIX_ERROR_BASE + 15;
-
-
-const SSL_ERROR_BASE = Ci.nsINSSErrorsService.NSS_SSL_ERROR_BASE;
-const SSL_ERROR_SSL_DISABLED  = SSL_ERROR_BASE + 20;
-const SSL_ERROR_SSL2_DISABLED  = SSL_ERROR_BASE + 14;
-
-const PREF_SERVICES_SETTINGS_CLOCK_SKEW_SECONDS = "services.settings.clock_skew_seconds";
-const PREF_SERVICES_SETTINGS_LAST_FETCHED       = "services.settings.last_update_seconds";
-
-const PREF_SSL_IMPACT_ROOTS = ["security.tls.version.", "security.ssl3."];
-
-
-function getSerializedSecurityInfo(docShell) {
-  let serhelper = Cc["@mozilla.org/network/serialization-helper;1"]
-                    .getService(Ci.nsISerializationHelper);
-
-  let securityInfo = docShell.failedChannel && docShell.failedChannel.securityInfo;
-  if (!securityInfo) {
-    return "";
-  }
-  securityInfo.QueryInterface(Ci.nsITransportSecurityInfo)
-              .QueryInterface(Ci.nsISerializable);
-
-  return serhelper.serializeToString(securityInfo);
-}
-
-function getSiteBlockedErrorDetails(docShell) {
-  let blockedInfo = {};
-  if (docShell.failedChannel) {
-    let classifiedChannel = docShell.failedChannel.
-                            QueryInterface(Ci.nsIClassifiedChannel);
-    if (classifiedChannel) {
-      let httpChannel = docShell.failedChannel.QueryInterface(Ci.nsIHttpChannel);
-
-      let reportUri = httpChannel.URI.clone();
-
-      // Remove the query to avoid leaking sensitive data
-      if (reportUri instanceof Ci.nsIURL) {
-        reportUri = reportUri.mutate()
-                             .setQuery("")
-                             .finalize();
-      }
-
-      blockedInfo = { list: classifiedChannel.matchedList,
-                      provider: classifiedChannel.matchedProvider,
-                      uri: reportUri.asciiSpec };
-    }
-  }
-  return blockedInfo;
-}
-
-var AboutBlockedSiteListener = {
-  init(chromeGlobal) {
-    addMessageListener("DeceptiveBlockedDetails", this);
-    chromeGlobal.addEventListener("AboutBlockedLoaded", this, false, true);
-  },
-
-  get isBlockedSite() {
-    return content.document.documentURI.startsWith("about:blocked");
-  },
-
-  receiveMessage(msg) {
-    if (!this.isBlockedSite) {
-      return;
-    }
-
-    if (msg.name == "DeceptiveBlockedDetails") {
-      sendAsyncMessage("DeceptiveBlockedDetails:Result", {
-        blockedInfo: getSiteBlockedErrorDetails(docShell),
-      });
-    }
-  },
-
-  handleEvent(aEvent) {
-    if (!this.isBlockedSite) {
-      return;
-    }
-
-    if (aEvent.type != "AboutBlockedLoaded") {
-      return;
-    }
-
-    let blockedInfo = getSiteBlockedErrorDetails(docShell);
-    let provider = blockedInfo.provider || "";
-
-    let doc = content.document;
-
-    /**
-    * Set error description link in error details.
-    * For example, the "reported as a deceptive site" link for
-    * blocked phishing pages.
-    */
-    let desc = Services.prefs.getCharPref(
-      "browser.safebrowsing.provider." + provider + ".reportURL", "");
-    if (desc) {
-      doc.getElementById("error_desc_link").setAttribute("href", desc + aEvent.detail.url);
-    }
-
-    // Set other links in error details.
-    switch (aEvent.detail.err) {
-      case "malware":
-        doc.getElementById("report_detection").setAttribute("href",
-          (SafeBrowsing.getReportURL("MalwareMistake", blockedInfo) ||
-           "https://www.stopbadware.org/firefox"));
-        doc.getElementById("learn_more_link").setAttribute("href",
-          "https://www.stopbadware.org/firefox");
-        break;
-      case "unwanted":
-        doc.getElementById("learn_more_link").setAttribute("href",
-          "https://www.google.com/about/unwanted-software-policy.html");
-        break;
-      case "phishing":
-        doc.getElementById("report_detection").setAttribute("href",
-          (SafeBrowsing.getReportURL("PhishMistake", blockedInfo) ||
-           "https://safebrowsing.google.com/safebrowsing/report_error/?tpl=mozilla"));
-        doc.getElementById("learn_more_link").setAttribute("href",
-          "https://www.antiphishing.org//");
-        break;
-    }
-
-    // Set the firefox support url.
-    doc.getElementById("firefox_support").setAttribute("href",
-      Services.urlFormatter.formatURLPref("app.support.baseURL") + "phishing-malware");
-
-    // Show safe browsing details on load if the pref is set to true.
-    let showDetails = Services.prefs.getBoolPref("browser.xul.error_pages.show_safe_browsing_details_on_load");
-    if (showDetails) {
-      let details = content.document.getElementById("errorDescriptionContainer");
-      details.removeAttribute("hidden");
-    }
-
-    // Set safe browsing advisory link.
-    let advisoryUrl = Services.prefs.getCharPref(
-      "browser.safebrowsing.provider." + provider + ".advisoryURL", "");
-    if (!advisoryUrl) {
-      let el = content.document.getElementById("advisoryDesc");
-      el.remove();
-      return;
-    }
-
-    let advisoryLinkText = Services.prefs.getCharPref(
-      "browser.safebrowsing.provider." + provider + ".advisoryName", "");
-    if (!advisoryLinkText) {
-      let el = content.document.getElementById("advisoryDesc");
-      el.remove();
-      return;
-    }
-
-    let anchorEl = content.document.getElementById("advisory_provider");
-    anchorEl.setAttribute("href", advisoryUrl);
-    anchorEl.textContent = advisoryLinkText;
-  },
-};
-
-var AboutNetAndCertErrorListener = {
-  init(chromeGlobal) {
-    addMessageListener("CertErrorDetails", this);
-    addMessageListener("Browser:CaptivePortalFreed", this);
-    chromeGlobal.addEventListener("AboutNetErrorLoad", this, false, true);
-    chromeGlobal.addEventListener("AboutNetErrorOpenCaptivePortal", this, false, true);
-    chromeGlobal.addEventListener("AboutNetErrorSetAutomatic", this, false, true);
-    chromeGlobal.addEventListener("AboutNetErrorResetPreferences", this, false, true);
-  },
-
-  isAboutNetError(doc) {
-    return doc.documentURI.startsWith("about:neterror");
-  },
-
-  isAboutCertError(doc) {
-    return doc.documentURI.startsWith("about:certerror");
-  },
-
-  receiveMessage(msg) {
-    if (msg.name == "CertErrorDetails") {
-      let frameDocShell = WebNavigationFrames.findDocShell(msg.data.frameId, docShell);
-      // We need nsIWebNavigation to access docShell.document.
-      frameDocShell && frameDocShell.QueryInterface(Ci.nsIWebNavigation);
-      if (!frameDocShell || !this.isAboutCertError(frameDocShell.document)) {
-        return;
-      }
-
-      this.onCertErrorDetails(msg, frameDocShell);
-    } else if (msg.name == "Browser:CaptivePortalFreed") {
-      // TODO: This check is not correct for frames.
-      if (!this.isAboutCertError(content.document)) {
-        return;
-      }
-
-      this.onCaptivePortalFreed(msg);
-    }
-  },
-
-  _getCertValidityRange(docShell) {
-    let {securityInfo} = docShell.failedChannel;
-    securityInfo.QueryInterface(Ci.nsITransportSecurityInfo);
-    let certs = securityInfo.failedCertChain.getEnumerator();
-    let notBefore = 0;
-    let notAfter = Number.MAX_SAFE_INTEGER;
-    while (certs.hasMoreElements()) {
-      let cert = certs.getNext();
-      cert.QueryInterface(Ci.nsIX509Cert);
-      notBefore = Math.max(notBefore, cert.validity.notBefore);
-      notAfter = Math.min(notAfter, cert.validity.notAfter);
-    }
-    // nsIX509Cert reports in PR_Date terms, which uses microseconds. Convert:
-    notBefore /= 1000;
-    notAfter /= 1000;
-    return {notBefore, notAfter};
-  },
-
-  _setTechDetails(input, doc) {
-    // CSS class and error code are set from nsDocShell.
-    let searchParams = new URLSearchParams(doc.documentURI.split("?")[1]);
-    let cssClass = searchParams.get("s");
-    let error = searchParams.get("e");
-    let technicalInfo = doc.getElementById("badCertTechnicalInfo");
-    technicalInfo.textContent = "";
-
-    let uri = Services.io.newURI(input.data.url);
-    let hostString = uri.host;
-    if (uri.port != 443 && uri.port != -1) {
-      hostString = uri.hostPort;
-    }
-
-    let msg1 = gPipNSSBundle.formatStringFromName("certErrorIntro",
-                                                  [hostString], 1);
-    msg1 += "\n\n";
-
-    if (input.data.certIsUntrusted) {
-      switch (input.data.code) {
-        // We only want to measure MitM rates for now. Treat it as unkown issuer.
-        case MOZILLA_PKIX_ERROR_MITM_DETECTED:
-        case SEC_ERROR_UNKNOWN_ISSUER:
-          msg1 += gPipNSSBundle.GetStringFromName("certErrorTrust_UnknownIssuer") + "\n";
-          msg1 += gPipNSSBundle.GetStringFromName("certErrorTrust_UnknownIssuer2") + "\n";
-          msg1 += gPipNSSBundle.GetStringFromName("certErrorTrust_UnknownIssuer3") + "\n";
-          break;
-        case SEC_ERROR_CA_CERT_INVALID:
-          msg1 += gPipNSSBundle.GetStringFromName("certErrorTrust_CaInvalid") + "\n";
-          break;
-        case SEC_ERROR_UNTRUSTED_ISSUER:
-          msg1 += gPipNSSBundle.GetStringFromName("certErrorTrust_Issuer") + "\n";
-          break;
-        case SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED:
-          msg1 += gPipNSSBundle.GetStringFromName("certErrorTrust_SignatureAlgorithmDisabled") + "\n";
-          break;
-        case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
-          msg1 += gPipNSSBundle.GetStringFromName("certErrorTrust_ExpiredIssuer") + "\n";
-          break;
-        case MOZILLA_PKIX_ERROR_SELF_SIGNED_CERT:
-          msg1 += gPipNSSBundle.GetStringFromName("certErrorTrust_SelfSigned") + "\n";
-          break;
-        default:
-          msg1 += gPipNSSBundle.GetStringFromName("certErrorTrust_Untrusted") + "\n";
-      }
-    }
-
-    technicalInfo.appendChild(doc.createTextNode(msg1));
-
-    if (input.data.isDomainMismatch) {
-      let subjectAltNames = input.data.certSubjectAltNames.split(",");
-      let numSubjectAltNames = subjectAltNames.length;
-      let msgPrefix = "";
-      if (numSubjectAltNames != 0) {
-        if (numSubjectAltNames == 1) {
-          msgPrefix = gPipNSSBundle.GetStringFromName("certErrorMismatchSinglePrefix");
-
-          // Let's check if we want to make this a link.
-          let okHost = input.data.certSubjectAltNames;
-          let href = "";
-          let thisHost = doc.location.hostname;
-          let proto = doc.location.protocol + "//";
-          // If okHost is a wildcard domain ("*.example.com") let's
-          // use "www" instead.  "*.example.com" isn't going to
-          // get anyone anywhere useful. bug 432491
-          okHost = okHost.replace(/^\*\./, "www.");
-          /* case #1:
-           * example.com uses an invalid security certificate.
-           *
-           * The certificate is only valid for www.example.com
-           *
-           * Make sure to include the "." ahead of thisHost so that
-           * a MitM attack on paypal.com doesn't hyperlink to "notpaypal.com"
-           *
-           * We'd normally just use a RegExp here except that we lack a
-           * library function to escape them properly (bug 248062), and
-           * domain names are famous for having '.' characters in them,
-           * which would allow spurious and possibly hostile matches.
-           */
-          if (okHost.endsWith("." + thisHost)) {
-            href = proto + okHost;
-          }
-          /* case #2:
-           * browser.garage.maemo.org uses an invalid security certificate.
-           *
-           * The certificate is only valid for garage.maemo.org
-           */
-          if (thisHost.endsWith("." + okHost)) {
-            href = proto + okHost;
-          }
-
-          // If we set a link, meaning there's something helpful for
-          // the user here, expand the section by default
-          if (href && cssClass != "expertBadCert") {
-            doc.getElementById("badCertAdvancedPanel").style.display = "block";
-            if (error == "nssBadCert") {
-              // Toggling the advanced panel must ensure that the debugging
-              // information panel is hidden as well, since it's opened by the
-              // error code link in the advanced panel.
-              var div = doc.getElementById("certificateErrorDebugInformation");
-              div.style.display = "none";
-            }
-          }
-
-          // Set the link if we want it.
-          if (href) {
-            let referrerlink = doc.createElement("a");
-            referrerlink.append(input.data.certSubjectAltNames);
-            referrerlink.title = input.data.certSubjectAltNames;
-            referrerlink.id = "cert_domain_link";
-            referrerlink.href = href;
-            let fragment = BrowserUtils.getLocalizedFragment(doc, msgPrefix,
-                                                             referrerlink);
-            technicalInfo.appendChild(fragment);
-          } else {
-            let fragment = BrowserUtils.getLocalizedFragment(doc,
-                                                             msgPrefix,
-                                                             input.data.certSubjectAltNames);
-            technicalInfo.appendChild(fragment);
-          }
-          technicalInfo.append("\n");
-        } else {
-          let msg = gPipNSSBundle.GetStringFromName("certErrorMismatchMultiple") + "\n";
-          for (let i = 0; i < numSubjectAltNames; i++) {
-            msg += subjectAltNames[i];
-            if (i != (numSubjectAltNames - 1)) {
-              msg += ", ";
-            }
-          }
-          technicalInfo.append(msg + "\n");
-        }
-      } else {
-        let msg = gPipNSSBundle.formatStringFromName("certErrorMismatch",
-                                                     [hostString], 1);
-        technicalInfo.append(msg + "\n");
-      }
-    }
-
-    if (input.data.isNotValidAtThisTime) {
-      let nowTime = new Date().getTime() * 1000;
-      let dateOptions = { year: "numeric", month: "long", day: "numeric", hour: "numeric", minute: "numeric" };
-      let now = new Services.intl.DateTimeFormat(undefined, dateOptions).format(new Date());
-      let msg = "";
-      if (input.data.validity.notBefore) {
-        if (nowTime > input.data.validity.notAfter) {
-          msg += gPipNSSBundle.formatStringFromName("certErrorExpiredNow",
-                                                    [input.data.validity.notAfterLocalTime, now], 2) + "\n";
-        } else {
-          msg += gPipNSSBundle.formatStringFromName("certErrorNotYetValidNow",
-                                                    [input.data.validity.notBeforeLocalTime, now], 2) + "\n";
-        }
-      } else {
-        // If something goes wrong, we assume the cert expired.
-        msg += gPipNSSBundle.formatStringFromName("certErrorExpiredNow",
-                                                  ["", now], 2) + "\n";
-      }
-      technicalInfo.append(msg);
-    }
-    technicalInfo.append("\n");
-
-    // Add link to certificate and error message.
-    let linkPrefix = gPipNSSBundle.GetStringFromName("certErrorCodePrefix3");
-    let detailLink = doc.createElement("a");
-    detailLink.append(input.data.codeString);
-    detailLink.title = input.data.codeString;
-    detailLink.id = "errorCode";
-    let fragment = BrowserUtils.getLocalizedFragment(doc, linkPrefix, detailLink);
-    technicalInfo.appendChild(fragment);
-    var errorCode = doc.getElementById("errorCode");
-    if (errorCode) {
-      errorCode.href = "javascript:void(0)";
-      errorCode.addEventListener("click", () => {
-        let debugInfo = doc.getElementById("certificateErrorDebugInformation");
-        debugInfo.style.display = "block";
-        debugInfo.scrollIntoView({block: "start", behavior: "smooth"});
-      });
-    }
-  },
-
-  onCertErrorDetails(msg, docShell) {
-    let doc = docShell.document;
-
-    let div = doc.getElementById("certificateErrorText");
-    div.textContent = msg.data.info;
-    this._setTechDetails(msg, doc);
-    let learnMoreLink = doc.getElementById("learnMoreLink");
-    let baseURL = Services.urlFormatter.formatURLPref("app.support.baseURL");
-
-    switch (msg.data.code) {
-      case SEC_ERROR_UNKNOWN_ISSUER:
-      case MOZILLA_PKIX_ERROR_MITM_DETECTED:
-      case MOZILLA_PKIX_ERROR_SELF_SIGNED_CERT:
-        learnMoreLink.href = baseURL + "security-error";
-        break;
-
-      // In case the certificate expired we make sure the system clock
-      // matches the remote-settings service (blocklist via Kinto) ping time
-      // and is not before the build date.
-      case SEC_ERROR_EXPIRED_CERTIFICATE:
-      case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
-      case SEC_ERROR_OCSP_FUTURE_RESPONSE:
-      case SEC_ERROR_OCSP_OLD_RESPONSE:
-      case MOZILLA_PKIX_ERROR_NOT_YET_VALID_CERTIFICATE:
-      case MOZILLA_PKIX_ERROR_NOT_YET_VALID_ISSUER_CERTIFICATE:
-
-        // We check against the remote-settings server time first if available, because that allows us
-        // to give the user an approximation of what the correct time is.
-        let difference = Services.prefs.getIntPref(PREF_SERVICES_SETTINGS_CLOCK_SKEW_SECONDS, 0);
-        let lastFetched = Services.prefs.getIntPref(PREF_SERVICES_SETTINGS_LAST_FETCHED, 0) * 1000;
-
-        let now = Date.now();
-        let certRange = this._getCertValidityRange(docShell);
-
-        let approximateDate = now - difference * 1000;
-        // If the difference is more than a day, we last fetched the date in the last 5 days,
-        // and adjusting the date per the interval would make the cert valid, warn the user:
-        if (Math.abs(difference) > 60 * 60 * 24 && (now - lastFetched) <= 60 * 60 * 24 * 5 &&
-            certRange.notBefore < approximateDate && certRange.notAfter > approximateDate) {
-          let formatter = new Services.intl.DateTimeFormat(undefined, {
-            dateStyle: "short"
-          });
-          let systemDate = formatter.format(new Date());
-          // negative difference means local time is behind server time
-          approximateDate = formatter.format(new Date(approximateDate));
-
-          doc.getElementById("wrongSystemTime_URL").textContent = doc.location.hostname;
-          doc.getElementById("wrongSystemTime_systemDate").textContent = systemDate;
-          doc.getElementById("wrongSystemTime_actualDate").textContent = approximateDate;
-
-          doc.getElementById("errorShortDesc").style.display = "none";
-          doc.getElementById("wrongSystemTimePanel").style.display = "block";
-
-        // If there is no clock skew with Kinto servers, check against the build date.
-        // (The Kinto ping could have happened when the time was still right, or not at all)
-        } else {
-          let appBuildID = Services.appinfo.appBuildID;
-
-          let year = parseInt(appBuildID.substr(0, 4), 10);
-          let month = parseInt(appBuildID.substr(4, 2), 10) - 1;
-          let day = parseInt(appBuildID.substr(6, 2), 10);
-
-          let buildDate = new Date(year, month, day);
-          let systemDate = new Date();
-
-          // We don't check the notBefore of the cert with the build date,
-          // as it is of course almost certain that it is now later than the build date,
-          // so we shouldn't exclude the possibility that the cert has become valid
-          // since the build date.
-          if (buildDate > systemDate && new Date(certRange.notAfter) > buildDate) {
-            let formatter = new Services.intl.DateTimeFormat(undefined, {
-              dateStyle: "short"
-            });
-
-            doc.getElementById("wrongSystemTimeWithoutReference_URL")
-              .textContent = doc.location.hostname;
-            doc.getElementById("wrongSystemTimeWithoutReference_systemDate")
-              .textContent = formatter.format(systemDate);
-
-            doc.getElementById("errorShortDesc").style.display = "none";
-            doc.getElementById("wrongSystemTimeWithoutReferencePanel").style.display = "block";
-          }
-        }
-        learnMoreLink.href = baseURL + "time-errors";
-        break;
-    }
-  },
-
-  onCaptivePortalFreed(msg) {
-    content.dispatchEvent(new content.CustomEvent("AboutNetErrorCaptivePortalFreed"));
-  },
-
-  handleEvent(aEvent) {
-    let doc;
-    if (aEvent.originalTarget instanceof Ci.nsIDOMDocument) {
-      doc = aEvent.originalTarget;
-    } else {
-      doc = aEvent.originalTarget.ownerDocument;
-    }
-
-    if (!this.isAboutNetError(doc) && !this.isAboutCertError(doc)) {
-      return;
-    }
-
-    switch (aEvent.type) {
-    case "AboutNetErrorLoad":
-      this.onPageLoad(aEvent.originalTarget, doc.defaultView);
-      break;
-    case "AboutNetErrorOpenCaptivePortal":
-      this.openCaptivePortalPage(aEvent);
-      break;
-    case "AboutNetErrorSetAutomatic":
-      this.onSetAutomatic(aEvent);
-      break;
-    case "AboutNetErrorResetPreferences":
-      this.onResetPreferences(aEvent);
-      break;
-    }
-  },
-
-  changedCertPrefs() {
-    let prefSSLImpact = PREF_SSL_IMPACT_ROOTS.reduce((prefs, root) => {
-       return prefs.concat(Services.prefs.getChildList(root));
-    }, []);
-    for (let prefName of prefSSLImpact) {
-      if (Services.prefs.prefHasUserValue(prefName)) {
-        return true;
-      }
-    }
-
-    return false;
-  },
-
-   _getErrorMessageFromCode(securityInfo, doc) {
-     let uri = Services.io.newURI(doc.location);
-     let hostString = uri.host;
-     if (uri.port != 443 && uri.port != -1) {
-       hostString = uri.hostPort;
-     }
-
-     let id_str = "";
-     switch (securityInfo.errorCode) {
-       case SSL_ERROR_SSL_DISABLED:
-         id_str = "PSMERR_SSL_Disabled";
-         break;
-       case SSL_ERROR_SSL2_DISABLED:
-         id_str = "PSMERR_SSL2_Disabled";
-         break;
-       case SEC_ERROR_REUSED_ISSUER_AND_SERIAL:
-         id_str = "PSMERR_HostReusedIssuerSerial";
-         break;
-     }
-     let nss_error_id_str = securityInfo.errorCodeString;
-     let msg2 = "";
-     if (id_str) {
-       msg2 = gPipNSSBundle.GetStringFromName(id_str) + "\n";
-     } else if (nss_error_id_str) {
-       msg2 = gNSSErrorsBundle.GetStringFromName(nss_error_id_str) + "\n";
-     }
-
-     if (!msg2) {
-       // We couldn't get an error message. Use the error string.
-       // Note that this is different from before where we used PR_ErrorToString.
-       msg2 = nss_error_id_str;
-     }
-     let msg = gPipNSSBundle.formatStringFromName("SSLConnectionErrorPrefix2",
-                                                  [hostString, msg2], 2);
-
-     if (nss_error_id_str) {
-       msg += gPipNSSBundle.formatStringFromName("certErrorCodePrefix3",
-                                                 [nss_error_id_str], 1) + "\n";
-     }
-     return msg;
-   },
-
-  onPageLoad(originalTarget, win) {
-    // Values for telemtery bins: see TLS_ERROR_REPORT_UI in Histograms.json
-    const TLS_ERROR_REPORT_TELEMETRY_UI_SHOWN = 0;
-
-    let hideAddExceptionButton = false;
-
-    if (this.isAboutCertError(win.document)) {
-      ClickEventHandler.onCertError(originalTarget, win);
-      hideAddExceptionButton =
-        Services.prefs.getBoolPref("security.certerror.hideAddException", false);
-    }
-    if (this.isAboutNetError(win.document)) {
-      let docShell = win.document.docShell;
-      if (docShell) {
-        let {securityInfo} = docShell.failedChannel;
-        // We don't have a securityInfo when this is for example a DNS error.
-        if (securityInfo) {
-          securityInfo.QueryInterface(Ci.nsITransportSecurityInfo);
-          let msg = this._getErrorMessageFromCode(securityInfo,
-                                                  win.document);
-          let id = win.document.getElementById("errorShortDescText");
-          id.textContent = msg;
-        }
-      }
-    }
-
-    let automatic = Services.prefs.getBoolPref("security.ssl.errorReporting.automatic");
-    win.dispatchEvent(new win.CustomEvent("AboutNetErrorOptions", {
-      detail: JSON.stringify({
-        enabled: Services.prefs.getBoolPref("security.ssl.errorReporting.enabled"),
-        changedCertPrefs: this.changedCertPrefs(),
-        automatic,
-        hideAddExceptionButton,
-      })
-    }));
-
-    sendAsyncMessage("Browser:SSLErrorReportTelemetry",
-                     {reportStatus: TLS_ERROR_REPORT_TELEMETRY_UI_SHOWN});
-  },
-
-  openCaptivePortalPage(evt) {
-    sendAsyncMessage("Browser:OpenCaptivePortalPage");
-  },
-
-
-  onResetPreferences(evt) {
-    sendAsyncMessage("Browser:ResetSSLPreferences");
-  },
-
-  onSetAutomatic(evt) {
-    sendAsyncMessage("Browser:SetSSLErrorReportAuto", {
-      automatic: evt.detail
-    });
-
-    // If we're enabling reports, send a report for this failure.
-    if (evt.detail) {
-      let win = evt.originalTarget.ownerGlobal;
-      let docShell = win.document.docShell;
-
-      let {securityInfo} = docShell.failedChannel;
-      securityInfo.QueryInterface(Ci.nsITransportSecurityInfo);
-      let {host, port} = win.document.mozDocumentURIIfNotForErrorPages;
-
-      let errorReporter = Cc["@mozilla.org/securityreporter;1"]
-                            .getService(Ci.nsISecurityReporter);
-      errorReporter.reportTLSError(securityInfo, host, port);
-    }
-  },
-};
-
-AboutNetAndCertErrorListener.init(this);
-AboutBlockedSiteListener.init(this);
-
-var ClickEventHandler = {
-  init: function init() {
-    Services.els.addSystemEventListener(global, "click", this, true);
-  },
-
-  handleEvent(event) {
-    if (!event.isTrusted || event.defaultPrevented || event.button == 2) {
-      return;
-    }
-
-    let originalTarget = event.originalTarget;
-    let ownerDoc = originalTarget.ownerDocument;
-    if (!ownerDoc) {
-      return;
-    }
-
-    // Handle click events from about pages
-    if (event.button == 0) {
-      if (AboutNetAndCertErrorListener.isAboutCertError(ownerDoc)) {
-        this.onCertError(originalTarget, ownerDoc.defaultView);
-        return;
-      } else if (ownerDoc.documentURI.startsWith("about:blocked")) {
-        this.onAboutBlocked(originalTarget, ownerDoc);
-        return;
-      } else if (AboutNetAndCertErrorListener.isAboutNetError(ownerDoc)) {
-        this.onAboutNetError(event, ownerDoc.documentURI);
-        return;
-      }
-    }
-
-    let [href, node, principal] = this._hrefAndLinkNodeForClickEvent(event);
-
-    // get referrer attribute from clicked link and parse it
-    // if per element referrer is enabled, the element referrer overrules
-    // the document wide referrer
-    let referrerPolicy = ownerDoc.referrerPolicy;
-    if (node) {
-      let referrerAttrValue = Services.netUtils.parseAttributePolicyString(node.
-                              getAttribute("referrerpolicy"));
-      if (referrerAttrValue !== Ci.nsIHttpChannel.REFERRER_POLICY_UNSET) {
-        referrerPolicy = referrerAttrValue;
-      }
-    }
-
-    let frameOuterWindowID = WebNavigationFrames.getFrameId(ownerDoc.defaultView);
-
-    let json = { button: event.button, shiftKey: event.shiftKey,
-                 ctrlKey: event.ctrlKey, metaKey: event.metaKey,
-                 altKey: event.altKey, href: null, title: null,
-                 bookmark: false, frameOuterWindowID, referrerPolicy,
-                 triggeringPrincipal: principal,
-                 originAttributes: principal ? principal.originAttributes : {},
-                 isContentWindowPrivate: PrivateBrowsingUtils.isContentWindowPrivate(ownerDoc.defaultView)};
-
-    if (href) {
-      try {
-        BrowserUtils.urlSecurityCheck(href, principal);
-      } catch (e) {
-        return;
-      }
-
-      json.href = href;
-      if (node) {
-        json.title = node.getAttribute("title");
-        if (event.button == 0 && !event.ctrlKey && !event.shiftKey &&
-            !event.altKey && !event.metaKey) {
-          json.bookmark = node.getAttribute("rel") == "sidebar";
-          if (json.bookmark) {
-            event.preventDefault(); // Need to prevent the pageload.
-          }
-        }
-      }
-      json.noReferrer = BrowserUtils.linkHasNoReferrer(node);
-
-      // Check if the link needs to be opened with mixed content allowed.
-      // Only when the owner doc has |mixedContentChannel| and the same origin
-      // should we allow mixed content.
-      json.allowMixedContent = false;
-      let docshell = ownerDoc.docShell;
-      if (docShell.mixedContentChannel) {
-        const sm = Services.scriptSecurityManager;
-        try {
-          let targetURI = Services.io.newURI(href);
-          sm.checkSameOriginURI(docshell.mixedContentChannel.URI, targetURI, false);
-          json.allowMixedContent = true;
-        } catch (e) {}
-      }
-      json.originPrincipal = ownerDoc.nodePrincipal;
-      json.triggeringPrincipal = ownerDoc.nodePrincipal;
-
-      sendAsyncMessage("Content:Click", json);
-      return;
-    }
-
-    // This might be middle mouse navigation.
-    if (event.button == 1) {
-      sendAsyncMessage("Content:Click", json);
-    }
-  },
-
-  onCertError(targetElement, win) {
-    let docShell = win.document.docShell;
-    sendAsyncMessage("Browser:CertExceptionError", {
-      frameId: WebNavigationFrames.getFrameId(win),
-      location: win.document.location.href,
-      elementId: targetElement.getAttribute("id"),
-      isTopFrame: (win.parent === win),
-      securityInfoAsString: getSerializedSecurityInfo(docShell),
-    });
-  },
-
-  onAboutBlocked(targetElement, ownerDoc) {
-    var reason = "phishing";
-    if (/e=malwareBlocked/.test(ownerDoc.documentURI)) {
-      reason = "malware";
-    } else if (/e=unwantedBlocked/.test(ownerDoc.documentURI)) {
-      reason = "unwanted";
-    } else if (/e=harmfulBlocked/.test(ownerDoc.documentURI)) {
-      reason = "harmful";
-    }
-
-    let docShell = ownerDoc.defaultView.QueryInterface(Ci.nsIInterfaceRequestor)
-                                       .getInterface(Ci.nsIWebNavigation)
-                                      .QueryInterface(Ci.nsIDocShell);
-
-    sendAsyncMessage("Browser:SiteBlockedError", {
-      location: ownerDoc.location.href,
-      reason,
-      elementId: targetElement.getAttribute("id"),
-      isTopFrame: (ownerDoc.defaultView.parent === ownerDoc.defaultView),
-      blockedInfo: getSiteBlockedErrorDetails(docShell),
-    });
-  },
-
-  onAboutNetError(event, documentURI) {
-    let elmId = event.originalTarget.getAttribute("id");
-    if (elmId == "returnButton") {
-      sendAsyncMessage("Browser:SSLErrorGoBack", {});
-      return;
-    }
-    if (elmId != "errorTryAgain" || !/e=netOffline/.test(documentURI)) {
-      return;
-    }
-    // browser front end will handle clearing offline mode and refreshing
-    // the page *if* we're in offline mode now. Otherwise let the error page
-    // handle the click.
-    if (Services.io.offline) {
-      event.preventDefault();
-      sendAsyncMessage("Browser:EnableOnlineMode", {});
-    }
-  },
-
-  /**
-   * Extracts linkNode and href for the current click target.
-   *
-   * @param event
-   *        The click event.
-   * @return [href, linkNode, linkPrincipal].
-   *
-   * @note linkNode will be null if the click wasn't on an anchor
-   *       element. This includes SVG links, because callers expect |node|
-   *       to behave like an <a> element, which SVG links (XLink) don't.
-   */
-  _hrefAndLinkNodeForClickEvent(event) {
-    function isHTMLLink(aNode) {
-      // Be consistent with what nsContextMenu.js does.
-      return ((aNode instanceof content.HTMLAnchorElement && aNode.href) ||
-              (aNode instanceof content.HTMLAreaElement && aNode.href) ||
-              aNode instanceof content.HTMLLinkElement);
-    }
-
-    let node = event.target;
-    while (node && !isHTMLLink(node)) {
-      node = node.parentNode;
-    }
-
-    if (node)
-      return [node.href, node, node.ownerDocument.nodePrincipal];
-
-    // If there is no linkNode, try simple XLink.
-    let href, baseURI;
-    node = event.target;
-    while (node && !href) {
-      if (node.nodeType == content.Node.ELEMENT_NODE &&
-          (node.localName == "a" ||
-           node.namespaceURI == "http://www.w3.org/1998/Math/MathML")) {
-        href = node.getAttribute("href") ||
-               node.getAttributeNS("http://www.w3.org/1999/xlink", "href");
-        if (href) {
-          baseURI = node.ownerDocument.baseURIObject;
-          break;
-        }
-      }
-      node = node.parentNode;
-    }
-
-    // In case of XLink, we don't return the node we got href from since
-    // callers expect <a>-like elements.
-    // Note: makeURI() will throw if aUri is not a valid URI.
-    return [href ? Services.io.newURI(href, null, baseURI).spec : null, null,
-            node && node.ownerDocument.nodePrincipal];
-  }
-};
-ClickEventHandler.init();
-
-ContentLinkHandler.init(this);
-ContentMetaHandler.init(this);
-
-// TODO: Load this lazily so the JSM is run only if a relevant event/message fires.
-var pluginContent = new PluginContent(global);
-
-addEventListener("DOMWindowFocus", function(event) {
-  sendAsyncMessage("DOMWindowFocus", {});
-}, false);
-
-// We use this shim so that ContentWebRTC.jsm will not be loaded until
-// it is actually needed.
-var ContentWebRTCShim = message => ContentWebRTC.receiveMessage(message);
-
-addMessageListener("rtcpeer:Allow", ContentWebRTCShim);
-addMessageListener("rtcpeer:Deny", ContentWebRTCShim);
-addMessageListener("webrtc:Allow", ContentWebRTCShim);
-addMessageListener("webrtc:Deny", ContentWebRTCShim);
-addMessageListener("webrtc:StopSharing", ContentWebRTCShim);
-
-addEventListener("pageshow", function(event) {
-  if (event.target == content.document) {
-    sendAsyncMessage("PageVisibility:Show", {
-      persisted: event.persisted,
-    });
-  }
-});
-addEventListener("pagehide", function(event) {
-  if (event.target == content.document) {
-    sendAsyncMessage("PageVisibility:Hide", {
-      persisted: event.persisted,
-    });
-  }
-});
-
-var PageMetadataMessenger = {
-  init() {
-    addMessageListener("PageMetadata:GetPageData", this);
-    addMessageListener("PageMetadata:GetMicroformats", this);
-  },
-  receiveMessage(message) {
-    switch (message.name) {
-      case "PageMetadata:GetPageData": {
-        let target = contextMenu.getTarget(message);
-        let result = PageMetadata.getData(content.document, target);
-        sendAsyncMessage("PageMetadata:PageDataResult", result);
-        break;
-      }
-      case "PageMetadata:GetMicroformats": {
-        let target = contextMenu.getTarget(message);
-        let result = PageMetadata.getMicroformats(content.document, target);
-        sendAsyncMessage("PageMetadata:MicroformatsResult", result);
-        break;
-      }
-    }
-  }
-};
-PageMetadataMessenger.init();
-
-addMessageListener("Bookmarks:GetPageDetails", (message) => {
-  let doc = content.document;
-  let isErrorPage = /^about:(neterror|certerror|blocked)/.test(doc.documentURI);
-  sendAsyncMessage("Bookmarks:GetPageDetails:Result",
-                   { isErrorPage,
-                     description: PlacesUIUtils.getDescriptionFromDocument(doc) });
-});
-
 var LightWeightThemeWebInstallListener = {
   _previewWindow: null,
 
   init() {
     addEventListener("InstallBrowserTheme", this, false, true);
     addEventListener("PreviewBrowserTheme", this, false, true);
     addEventListener("ResetBrowserThemePreview", this, false, true);
   },
@@ -1059,114 +49,8 @@ var LightWeightThemeWebInstallListener =
 
   _resetPreviewWindow() {
     this._previewWindow.removeEventListener("pagehide", this, true);
     this._previewWindow = null;
   }
 };
 
 LightWeightThemeWebInstallListener.init();
-
-let OfflineApps = {
-  _docId: 0,
-  _docIdMap: new Map(),
-
-  _docManifestSet: new Set(),
-
-  _observerAdded: false,
-  registerWindow(aWindow) {
-    if (!this._observerAdded) {
-      this._observerAdded = true;
-      Services.obs.addObserver(this, "offline-cache-update-completed", true);
-    }
-    let manifestURI = this._getManifestURI(aWindow);
-    this._docManifestSet.add(manifestURI.spec);
-  },
-
-  handleEvent(event) {
-    if (event.type == "MozApplicationManifest") {
-      this.offlineAppRequested(event.originalTarget.defaultView);
-    }
-  },
-
-  _getManifestURI(aWindow) {
-    if (!aWindow.document.documentElement)
-      return null;
-
-    var attr = aWindow.document.documentElement.getAttribute("manifest");
-    if (!attr)
-      return null;
-
-    try {
-      return Services.io.newURI(attr, aWindow.document.characterSet,
-                                Services.io.newURI(aWindow.location.href));
-    } catch (e) {
-      return null;
-    }
-  },
-
-  offlineAppRequested(aContentWindow) {
-    this.registerWindow(aContentWindow);
-    if (!Services.prefs.getBoolPref("browser.offline-apps.notify")) {
-      return;
-    }
-
-    let currentURI = aContentWindow.document.documentURIObject;
-    // don't bother showing UI if the user has already made a decision
-    if (Services.perms.testExactPermission(currentURI, "offline-app") != Services.perms.UNKNOWN_ACTION)
-      return;
-
-    try {
-      if (Services.prefs.getBoolPref("offline-apps.allow_by_default")) {
-        // all pages can use offline capabilities, no need to ask the user
-        return;
-      }
-    } catch (e) {
-      // this pref isn't set by default, ignore failures
-    }
-    let docId = ++this._docId;
-    this._docIdMap.set(docId, Cu.getWeakReference(aContentWindow.document));
-    sendAsyncMessage("OfflineApps:RequestPermission", {
-      uri: currentURI.spec,
-      docId,
-    });
-  },
-
-  _startFetching(aDocument) {
-    if (!aDocument.documentElement)
-      return;
-
-    let manifestURI = this._getManifestURI(aDocument.defaultView);
-    if (!manifestURI)
-      return;
-
-    var updateService = Cc["@mozilla.org/offlinecacheupdate-service;1"].
-                        getService(Ci.nsIOfflineCacheUpdateService);
-    updateService.scheduleUpdate(manifestURI, aDocument.documentURIObject,
-                                 aDocument.nodePrincipal, aDocument.defaultView);
-  },
-
-  receiveMessage(aMessage) {
-    if (aMessage.name == "OfflineApps:StartFetching") {
-      let doc = this._docIdMap.get(aMessage.data.docId);
-      doc = doc && doc.get();
-      if (doc) {
-        this._startFetching(doc);
-      }
-      this._docIdMap.delete(aMessage.data.docId);
-    }
-  },
-
-  observe(aSubject, aTopic, aState) {
-    if (aTopic == "offline-cache-update-completed") {
-      let cacheUpdate = aSubject.QueryInterface(Ci.nsIOfflineCacheUpdate);
-      let uri = cacheUpdate.manifestURI;
-      if (uri && this._docManifestSet.has(uri.spec)) {
-        sendAsyncMessage("OfflineApps:CheckUsage", {uri: uri.spec});
-      }
-    }
-  },
-  QueryInterface: ChromeUtils.generateQI([Ci.nsIObserver,
-                                          Ci.nsISupportsWeakReference]),
-};
-
-addEventListener("MozApplicationManifest", OfflineApps, false);
-addMessageListener("OfflineApps:StartFetching", OfflineApps);
--- a/browser/modules/moz.build
+++ b/browser/modules/moz.build
@@ -65,16 +65,22 @@ with Files("ContentWebRTC.jsm"):
     BUG_COMPONENT = ("Firefox", "Device Permissions")
 
 with Files("ExtensionsUI.jsm"):
     BUG_COMPONENT = ("Toolkit", "WebExtensions: General")
 
 with Files("LaterRun.jsm"):
     BUG_COMPONENT = ("Firefox", "Tours")
 
+with Files("LightWeightThemeWebInstallListener.jsm"):
+    BUG_COMPONENT = ("Firefox", "Theme")
+
+with Files("OpenInTabsUtils.jsm"):
+    BUG_COMPONENT = ("Firefox", "Tabbed Browser")
+
 with Files("PageInfoListener.jsm"):
     BUG_COMPONENT = ("Firefox", "Page Info Window")
 
 with Files("PermissionUI.jsm"):
    BUG_COMPONENT = ("Firefox", "Site Identity and Permission Panels")
 
 with Files("PluginContent.jsm"):
     BUG_COMPONENT = ("Core", "Plug-ins")
@@ -89,19 +95,16 @@ with Files("Sanitizer.jsm"):
     BUG_COMPONENT = ("Firefox", "Preferences")
 
 with Files("SiteDataManager.jsm"):
     BUG_COMPONENT = ("Firefox", "Preferences")
 
 with Files("SitePermissions.jsm"):
     BUG_COMPONENT = ("Firefox", "Site Identity and Permission Panels")
 
-with Files("OpenInTabsUtils.jsm"):
-    BUG_COMPONENT = ("Firefox", "Tabbed Browser")
-
 with Files("ThemeVariableMap.jsm"):
     BUG_COMPONENT = ("Toolkit", "WebExtensions: Themes")
 
 with Files("TransientPrefs.jsm"):
     BUG_COMPONENT = ("Firefox", "Preferences")
 
 with Files("Windows8WindowFrameColor.jsm"):
     BUG_COMPONENT = ("Firefox", "Theme")
@@ -141,16 +144,17 @@ EXTRA_JS_MODULES += [
     'ContentSearch.jsm',
     'ContentWebRTC.jsm',
     'ContextMenu.jsm',
     'ExtensionsUI.jsm',
     'Feeds.jsm',
     'FormSubmitObserver.jsm',
     'FormValidationHandler.jsm',
     'LaterRun.jsm',
+    'LightWeightThemeWebInstallListener.jsm',
     'OpenInTabsUtils.jsm',
     'PageActions.jsm',
     'PageInfoListener.jsm',
     'PermissionUI.jsm',
     'PingCentre.jsm',
     'PluginContent.jsm',
     'ProcessHangMonitor.jsm',
     'ReaderParent.jsm',