Bug 1462673 - Part 0. Copy LightWeightThemeWebInstallListener code from content.js to a jsm. r=mconley draft
authorFelipe Gomes <felipc@gmail.com>
Fri, 18 May 2018 11:54:59 -0300
changeset 796911 1dba41f5810b8726a45d8dd563add61a87be4e20
parent 796910 58b5c007532824c08bf6362ffc03d094163d4162
child 796912 8f974eeb0af70ff3e653ec6f28fb54950d68276f
push id110392
push userfelipc@gmail.com
push dateFri, 18 May 2018 14:56:01 +0000
reviewersmconley
bugs1462673
milestone62.0a1
Bug 1462673 - Part 0. Copy LightWeightThemeWebInstallListener code from content.js to a jsm. r=mconley MozReview-Commit-ID: KVvIYpxDbWv
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
@@ -1005,69 +1005,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,1020 +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",
-  Feeds: "resource:///modules/Feeds.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);
-}, { QueryInterface: ChromeUtils.generateQI([Ci.nsIFormSubmitObserver, Ci.nsISupportsWeakReference])});
-
-XPCOMUtils.defineLazyProxy(this, "PageInfoListener",
-                           "resource:///modules/PageInfoListener-content.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);
   },
@@ -1057,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,19 @@ 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("PageInfoListener-content.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")
@@ -142,16 +145,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-content.jsm',
     'PermissionUI.jsm',
     'PingCentre.jsm',
     'PluginContent.jsm',
     'ProcessHangMonitor.jsm',
     'ReaderParent.jsm',