Merge inbound to mozilla-central. a=merge
authorCosmin Sabou <csabou@mozilla.com>
Mon, 05 Mar 2018 20:12:38 +0200
changeset 406552 0ef34a9ec4fbfccd03ee0cfb26b182c03e28133a
parent 406543 abb61fa06489ddb86ee029c8c0693687c7524353 (current diff)
parent 406551 740b5c4f4cd3e7112a754d9326a2a0cd25908242 (diff)
child 406582 cb5d9017b2afedb0c813e02f393056a7ce744e47
child 406627 39717163c6c9311f321da46625ba92de9e75c5a3
push id33570
push usercsabou@mozilla.com
push dateMon, 05 Mar 2018 18:12:27 +0000
treeherdermozilla-central@0ef34a9ec4fb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone60.0a1
first release with
nightly linux32
0ef34a9ec4fb / 60.0a1 / 20180305220117 / files
nightly linux64
0ef34a9ec4fb / 60.0a1 / 20180305220117 / files
nightly mac
0ef34a9ec4fb / 60.0a1 / 20180305220117 / files
nightly win32
0ef34a9ec4fb / 60.0a1 / 20180305220117 / files
nightly win64
0ef34a9ec4fb / 60.0a1 / 20180305220117 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge inbound to mozilla-central. a=merge
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -1281,17 +1281,17 @@ var gBrowserInit = {
     // message sent between when the frame script is loaded and when
     // the listener is registered.
     DOMEventHandler.init();
     gPageStyleMenu.init();
     LanguageDetectionListener.init();
     BrowserOnClick.init();
     FeedHandler.init();
     CompactTheme.init();
-    AboutPrivateBrowsingListener.init();
+    AboutCapabilitiesListener.init();
     TrackingProtection.init();
     CaptivePortalWatcher.init();
     ZoomUI.init(window);
 
     let mm = window.getGroupMessageManager("browsers");
     mm.loadFrameScript("chrome://browser/content/tab-content.js", true);
     mm.loadFrameScript("chrome://browser/content/content.js", true);
     mm.loadFrameScript("chrome://browser/content/content-UITour.js", true);
@@ -1853,16 +1853,18 @@ var gBrowserInit = {
     gTabletModePageCounter.finish();
 
     BrowserOnClick.uninit();
 
     FeedHandler.uninit();
 
     CompactTheme.uninit();
 
+    AboutCapabilitiesListener.uninit();
+
     TrackingProtection.uninit();
 
     CaptivePortalWatcher.uninit();
 
     SidebarUI.uninit();
 
     DownloadsButton.uninit();
 
@@ -9028,35 +9030,47 @@ var PanicButtonNotifier = {
     }
   },
   close() {
     let popup = document.getElementById("panic-button-success-notification");
     popup.hidePopup();
   },
 };
 
-var AboutPrivateBrowsingListener = {
+var AboutCapabilitiesListener = {
+  _topics: [
+    "AboutCapabilities:OpenPrivateWindow",
+    "AboutCapabilities:DontShowIntroPanelAgain",
+  ],
+
   init() {
-    window.messageManager.addMessageListener(
-      "AboutPrivateBrowsing:OpenPrivateWindow",
-      msg => {
+    let mm = window.messageManager;
+    for (let topic of this._topics) {
+      mm.addMessageListener(topic, this);
+    }
+  },
+
+  uninit() {
+    let mm = window.messageManager;
+    for (let topic of this._topics) {
+      mm.removeMessageListener(topic, this);
+    }
+  },
+
+  receiveMessage(aMsg) {
+    switch (aMsg.name) {
+      case "AboutCapabilities:OpenPrivateWindow":
         OpenBrowserWindow({private: true});
-    });
-    window.messageManager.addMessageListener(
-      "AboutPrivateBrowsing:ToggleTrackingProtection",
-      msg => {
-        const PREF = "privacy.trackingprotection.pbmode.enabled";
-        Services.prefs.setBoolPref(PREF, !Services.prefs.getBoolPref(PREF));
-    });
-    window.messageManager.addMessageListener(
-      "AboutPrivateBrowsing:DontShowIntroPanelAgain",
-      msg => {
+        break;
+
+      case "AboutCapabilities:DontShowIntroPanelAgain":
         TrackingProtection.dontShowIntroPanelAgain();
-    });
-  }
+        break;
+    }
+  },
 };
 
 const SafeBrowsingNotificationBox = {
   _currentURIBaseDomain: null,
   show(title, buttons) {
     let uri = gBrowser.currentURI;
 
     // start tracking host so that we know when we leave the domain
--- a/browser/base/content/tab-content.js
+++ b/browser/base/content/tab-content.js
@@ -204,49 +204,16 @@ var AboutHomeListener = {
     }
     removeMessageListener("AboutHome:Update", this);
     removeEventListener("click", this, true);
     removeEventListener("pagehide", this, true);
   },
 };
 AboutHomeListener.init(this);
 
-var AboutPrivateBrowsingListener = {
-  init(chromeGlobal) {
-    chromeGlobal.addEventListener("AboutPrivateBrowsingOpenWindow", this,
-                                  false, true);
-    chromeGlobal.addEventListener("AboutPrivateBrowsingToggleTrackingProtection", this,
-                                  false, true);
-    chromeGlobal.addEventListener("AboutPrivateBrowsingDontShowIntroPanelAgain", this,
-                                  false, true);
-  },
-
-  get isAboutPrivateBrowsing() {
-    return content.document.documentURI.toLowerCase() == "about:privatebrowsing";
-  },
-
-  handleEvent(aEvent) {
-    if (!this.isAboutPrivateBrowsing) {
-      return;
-    }
-    switch (aEvent.type) {
-      case "AboutPrivateBrowsingOpenWindow":
-        sendAsyncMessage("AboutPrivateBrowsing:OpenPrivateWindow");
-        break;
-      case "AboutPrivateBrowsingToggleTrackingProtection":
-        sendAsyncMessage("AboutPrivateBrowsing:ToggleTrackingProtection");
-        break;
-      case "AboutPrivateBrowsingDontShowIntroPanelAgain":
-        sendAsyncMessage("AboutPrivateBrowsing:DontShowIntroPanelAgain");
-        break;
-    }
-  },
-};
-AboutPrivateBrowsingListener.init(this);
-
 var AboutReaderListener = {
 
   _articlePromise: null,
 
   _isLeavingReaderableReaderMode: false,
 
   init() {
     addEventListener("AboutReaderContentLoaded", this, false, true);
--- a/browser/components/about/AboutRedirector.cpp
+++ b/browser/components/about/AboutRedirector.cpp
@@ -50,16 +50,17 @@ static const RedirEntry kRedirMap[] = {
     nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
     nsIAboutModule::ALLOW_SCRIPT |
     nsIAboutModule::HIDE_FROM_ABOUTABOUT },
   { "feeds", "chrome://browser/content/feeds/subscribe.xhtml",
     nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
     nsIAboutModule::ALLOW_SCRIPT |
     nsIAboutModule::HIDE_FROM_ABOUTABOUT },
   { "privatebrowsing", "chrome://browser/content/aboutPrivateBrowsing.xhtml",
+    nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
     nsIAboutModule::URI_MUST_LOAD_IN_CHILD |
     nsIAboutModule::ALLOW_SCRIPT },
   { "rights",
     "chrome://global/content/aboutRights.xhtml",
     nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
     nsIAboutModule::MAKE_LINKABLE |
     nsIAboutModule::ALLOW_SCRIPT },
   { "robots", "chrome://browser/content/aboutRobots.xhtml",
new file mode 100644
--- /dev/null
+++ b/browser/components/about/aboutcapabilities.manifest
@@ -0,0 +1,2 @@
+component {4c2b1f46-e637-4a91-8108-8a9fb7aab91d} nsAboutCapabilities.js
+contract @mozilla.org/aboutcapabilities;1 {4c2b1f46-e637-4a91-8108-8a9fb7aab91d}
--- a/browser/components/about/moz.build
+++ b/browser/components/about/moz.build
@@ -12,13 +12,18 @@ EXPORTS.mozilla.browser += [
 ]
 
 XPCSHELL_TESTS_MANIFESTS += ['test/unit/xpcshell.ini']
 
 SOURCES += [
     'AboutRedirector.cpp',
 ]
 
+EXTRA_COMPONENTS += [
+    'aboutcapabilities.manifest',
+    'nsAboutCapabilities.js',
+]
+
 FINAL_LIBRARY = 'browsercomps'
 
 LOCAL_INCLUDES += [
     '../build',
 ]
new file mode 100644
--- /dev/null
+++ b/browser/components/about/nsAboutCapabilities.js
@@ -0,0 +1,74 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 4 -*- */
+/* 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/. */
+
+ChromeUtils.import("resource://gre/modules/Services.jsm");
+ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
+ChromeUtils.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
+ChromeUtils.defineModuleGetter(this, "AsyncPrefs",
+  "resource://gre/modules/AsyncPrefs.jsm");
+
+function nsAboutCapabilities() {
+}
+
+nsAboutCapabilities.prototype = {
+  init(window) {
+    this.window = window;
+    try {
+      let docShell = window.document.docShell
+                           .QueryInterface(Ci.nsIInterfaceRequestor);
+      this.mm = docShell.getInterface(Ci.nsIContentFrameMessageManager);
+    } catch (e) {
+      Cu.reportError(e);
+    }
+  },
+
+  getBoolPref(aPref, aDefaultValue) {
+    return Services.prefs.getBoolPref(aPref, aDefaultValue);
+  },
+
+  setBoolPref(aPref, aValue) {
+    return new this.window.Promise(function(resolve) {
+      AsyncPrefs.set(aPref, aValue).then(function() {
+        resolve();
+      });
+    });
+  },
+
+  getCharPref(aPref, aDefaultValue) {
+    return Services.prefs.getCharPref(aPref, aDefaultValue);
+  },
+
+  setCharPref(aPref, aValue) {
+    return new this.window.Promise(function(resolve) {
+      AsyncPrefs.set(aPref, aValue).then(function() {
+        resolve();
+      });
+    });
+  },
+
+  getStringFromBundle(aStrBundle, aStr) {
+    let bundle = Services.strings.createBundle(aStrBundle);
+    return bundle.GetStringFromName(aStr);
+  },
+
+  formatURLPref(aFormatURL) {
+    return Services.urlFormatter.formatURLPref(aFormatURL);
+  },
+
+  sendAsyncMessage(aMessage, aParams) {
+    this.mm.sendAsyncMessage("AboutCapabilities:" + aMessage, aParams);
+  },
+
+  isWindowPrivate() {
+    return PrivateBrowsingUtils.isContentWindowPrivate(this.window);
+  },
+
+  contractID: "@mozilla.org/aboutcapabilities;1",
+  classID: Components.ID("{4c2b1f46-e637-4a91-8108-8a9fb7aab91d}"),
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports,
+                                         Ci.nsIDOMGlobalPropertyInitializer])
+};
+
+this.NSGetFactory = XPCOMUtils.generateNSGetFactory([nsAboutCapabilities]);
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -2312,16 +2312,44 @@ BrowserGlue.prototype = {
                       "TabsToolbar", "toolbar-menubar"];
       for (let resourceName of ["mode", "iconsize"]) {
         for (let toolbarId of toolbars) {
           xulStore.removeValue(BROWSER_DOCURL, toolbarId, resourceName);
         }
       }
     }
 
+    if (currentUIVersion < 63 &&
+        Services.prefs.getCharPref("general.config.filename", "") == "dsengine.cfg") {
+      let searchInitializedPromise = new Promise(resolve => {
+        if (Services.search.isInitialized) {
+          resolve();
+        }
+        const SEARCH_SERVICE_TOPIC = "browser-search-service";
+        Services.obs.addObserver(function observer(subject, topic, data) {
+          if (data != "init-complete") {
+            return;
+          }
+          Services.obs.removeObserver(observer, SEARCH_SERVICE_TOPIC);
+          resolve();
+        }, SEARCH_SERVICE_TOPIC);
+      });
+      searchInitializedPromise.then(() => {
+        let engineNames = ["Bing Search Engine",
+                           "Yahoo Search Engine",
+                           "Yandex Search Engine"];
+        for (let engineName of engineNames) {
+          let engine = Services.search.getEngineByName(engineName);
+          if (engine) {
+            Services.search.removeEngine(engine);
+          }
+        }
+      });
+    }
+
     if (currentUIVersion < 64) {
       OS.File.remove(OS.Path.join(OS.Constants.Path.profileDir,
                                   "directoryLinks.json"), {ignoreAbsent: true});
     }
 
     // Update the migration version.
     Services.prefs.setIntPref("browser.migration.version", UI_VERSION);
   },
--- a/browser/components/privatebrowsing/content/aboutPrivateBrowsing.js
+++ b/browser/components/privatebrowsing/content/aboutPrivateBrowsing.js
@@ -1,87 +1,64 @@
 /* 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/. */
 
-ChromeUtils.import("resource://gre/modules/Services.jsm");
-ChromeUtils.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
-ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
+const FAVICON_QUESTION = "chrome://global/skin/icons/question-32.png";
+const STRING_BUNDLE = "chrome://browser/locale/aboutPrivateBrowsing.properties";
+const TP_ENABLED_PREF = "privacy.trackingprotection.enabled";
+const TP_PB_ENABLED_PREF = "privacy.trackingprotection.pbmode.enabled";
 
-const FAVICON_QUESTION = "chrome://global/skin/icons/question-32.png";
-
-var stringBundle = Services.strings.createBundle(
-                    "chrome://browser/locale/aboutPrivateBrowsing.properties");
+function updateTPInfo() {
+  let aboutCapabilities = document.aboutCapabilities;
+  let tpButton = document.getElementById("tpButton");
+  let tpToggle = document.getElementById("tpToggle");
+  let title = document.getElementById("title");
+  let titleTracking = document.getElementById("titleTracking");
+  let tpSubHeader = document.getElementById("tpSubHeader");
 
-var prefBranch = Services.prefs.getBranch("privacy.trackingprotection.");
-var prefObserver = {
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
-                                        Ci.nsISupportsWeakReference]),
- observe() {
-   let tpSubHeader = document.getElementById("tpSubHeader");
-   let tpToggle = document.getElementById("tpToggle");
-   let tpButton = document.getElementById("tpButton");
-   let title = document.getElementById("title");
-   let titleTracking = document.getElementById("titleTracking");
-   let globalTrackingEnabled = prefBranch.getBoolPref("enabled");
-   let trackingEnabled = globalTrackingEnabled ||
-                         prefBranch.getBoolPref("pbmode.enabled");
+  let globalTrackingEnabled = aboutCapabilities.getBoolPref(TP_ENABLED_PREF, null);
+  let trackingEnabled = globalTrackingEnabled ||
+                        aboutCapabilities.getBoolPref(TP_PB_ENABLED_PREF, null);
 
-   tpButton.classList.toggle("hide", globalTrackingEnabled);
-   tpToggle.checked = trackingEnabled;
-   title.classList.toggle("hide", trackingEnabled);
-   titleTracking.classList.toggle("hide", !trackingEnabled);
-   tpSubHeader.classList.toggle("tp-off", !trackingEnabled);
- }
-};
-prefBranch.addObserver("pbmode.enabled", prefObserver, true);
-prefBranch.addObserver("enabled", prefObserver, true);
+  // if tracking protection is enabled globally we don't even give the user
+  // a choice here by hiding the toggle completely.
+  tpButton.classList.toggle("hide", globalTrackingEnabled);
+  tpToggle.checked = trackingEnabled;
+  title.classList.toggle("hide", trackingEnabled);
+  titleTracking.classList.toggle("hide", !trackingEnabled);
+  tpSubHeader.classList.toggle("tp-off", !trackingEnabled);
+}
 
 document.addEventListener("DOMContentLoaded", function() {
- if (!PrivateBrowsingUtils.isContentWindowPrivate(window)) {
-   document.documentElement.classList.remove("private");
-   document.documentElement.classList.add("normal");
-   document.title = stringBundle.GetStringFromName("title.normal");
-   document.getElementById("favicon")
-           .setAttribute("href", FAVICON_QUESTION);
-   document.getElementById("startPrivateBrowsing")
-           .addEventListener("command", openPrivateWindow);
-   return;
- }
-
- let tpToggle = document.getElementById("tpToggle");
- document.getElementById("tpButton").addEventListener("click", () => {
-   tpToggle.click();
- });
-
- document.title = stringBundle.GetStringFromName("title.head");
- tpToggle.addEventListener("change", toggleTrackingProtection);
- document.getElementById("startTour")
-         .addEventListener("click", dontShowIntroPanelAgain);
+  let aboutCapabilities = document.aboutCapabilities;
+  if (!aboutCapabilities.isWindowPrivate()) {
+    document.documentElement.classList.remove("private");
+    document.documentElement.classList.add("normal");
+    document.title = aboutCapabilities.getStringFromBundle(STRING_BUNDLE, "title.normal");
+    document.getElementById("favicon").setAttribute("href", FAVICON_QUESTION);
+    document.getElementById("startPrivateBrowsing").addEventListener("click", function() {
+      aboutCapabilities.sendAsyncMessage("OpenPrivateWindow", null);
+    });
+    return;
+  }
 
- document.getElementById("startTour").setAttribute("href",
-   Services.urlFormatter.formatURLPref("privacy.trackingprotection.introURL"));
- document.getElementById("learnMore").setAttribute("href",
-   Services.urlFormatter.formatURLPref("app.support.baseURL") + "private-browsing");
-
- // Update state that depends on preferences.
- prefObserver.observe();
-});
+  document.title = aboutCapabilities.getStringFromBundle(STRING_BUNDLE, "title.head");
+  document.getElementById("startTour").addEventListener("click", function() {
+    aboutCapabilities.sendAsyncMessage("DontShowIntroPanelAgain", null);
+  });
+  document.getElementById("startTour").setAttribute("href",
+    aboutCapabilities.formatURLPref("privacy.trackingprotection.introURL"));
+  document.getElementById("learnMore").setAttribute("href",
+    aboutCapabilities.formatURLPref("app.support.baseURL") + "private-browsing");
 
-function openPrivateWindow() {
- // Ask chrome to open a private window
- document.dispatchEvent(
-   new CustomEvent("AboutPrivateBrowsingOpenWindow", {bubbles: true}));
-}
+  let tpToggle = document.getElementById("tpToggle");
+  document.getElementById("tpButton").addEventListener("click", () => {
+    tpToggle.click();
+  });
+  tpToggle.addEventListener("change", function() {
+    aboutCapabilities.setBoolPref(TP_PB_ENABLED_PREF, tpToggle.checked).then(function() {
+      updateTPInfo();
+    });
+  });
 
-function toggleTrackingProtection() {
- // Ask chrome to enable tracking protection
- document.dispatchEvent(
-   new CustomEvent("AboutPrivateBrowsingToggleTrackingProtection",
-                   {bubbles: true}));
-}
-
-function dontShowIntroPanelAgain() {
- // Ask chrome to disable the doorhanger
- document.dispatchEvent(
-   new CustomEvent("AboutPrivateBrowsingDontShowIntroPanelAgain",
-                   {bubbles: true}));
-}
+  updateTPInfo();
+});
--- a/browser/components/privatebrowsing/content/aboutPrivateBrowsing.xhtml
+++ b/browser/components/privatebrowsing/content/aboutPrivateBrowsing.xhtml
@@ -14,29 +14,28 @@
   <!ENTITY % browserDTD SYSTEM "chrome://browser/locale/browser.dtd">
   %browserDTD;
   <!ENTITY % aboutPrivateBrowsingDTD SYSTEM "chrome://browser/locale/aboutPrivateBrowsing.dtd">
   %aboutPrivateBrowsingDTD;
 ]>
 
 <html xmlns="http://www.w3.org/1999/xhtml" class="private">
   <head>
+    <meta http-equiv="Content-Security-Policy" content="default-src chrome:"/>
     <link id="favicon" rel="icon" type="image/png" href="chrome://browser/skin/privatebrowsing/favicon.svg"/>
     <link rel="stylesheet" href="chrome://browser/content/aboutPrivateBrowsing.css" type="text/css" media="all"/>
     <link rel="stylesheet" href="chrome://browser/skin/privatebrowsing/aboutPrivateBrowsing.css" type="text/css" media="all"/>
     <script type="application/javascript" src="chrome://browser/content/aboutPrivateBrowsing.js"></script>
   </head>
 
   <body dir="&locale.dir;">
     <p class="showNormal">&aboutPrivateBrowsing.notPrivate;</p>
-    <button xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-            id="startPrivateBrowsing"
+    <button id="startPrivateBrowsing"
             class="showNormal"
-            label="&privatebrowsingpage.openPrivateWindow.label;"
-            accesskey="&privatebrowsingpage.openPrivateWindow.accesskey;"/>
+            accesskey="&privatebrowsingpage.openPrivateWindow.accesskey;">&privatebrowsingpage.openPrivateWindow.label;</button>
     <div class="showPrivate container">
       <h1 class="title">
         <span id="title">&privateBrowsing.title;</span>
         <span id="titleTracking">&privateBrowsing.title.tracking;</span>
       </h1>
       <section class="section-main">
         <p>&aboutPrivateBrowsing.info.notsaved.before;<strong>&aboutPrivateBrowsing.info.notsaved.emphasize;</strong>&aboutPrivateBrowsing.info.notsaved.after;</p>
         <div class="list-row">
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -365,16 +365,18 @@
 @RESPATH@/browser/components/devtools-startup.manifest
 @RESPATH@/browser/components/devtools-startup.js
 @RESPATH@/browser/components/aboutdebugging-registration.js
 @RESPATH@/browser/components/aboutdebugging.manifest
 @RESPATH@/browser/components/aboutdevtools-registration.js
 @RESPATH@/browser/components/aboutdevtools.manifest
 @RESPATH@/browser/components/aboutdevtoolstoolbox-registration.js
 @RESPATH@/browser/components/aboutdevtoolstoolbox.manifest
+@RESPATH@/browser/components/nsAboutCapabilities.js
+@RESPATH@/browser/components/aboutcapabilities.manifest
 @RESPATH@/browser/components/Experiments.manifest
 @RESPATH@/browser/components/ExperimentsService.js
 @RESPATH@/browser/components/browser-newtab.xpt
 @RESPATH@/browser/components/aboutNewTabService.js
 @RESPATH@/browser/components/NewTabComponents.manifest
 @RESPATH@/browser/components/EnterprisePolicies.js
 @RESPATH@/browser/components/EnterprisePoliciesContent.js
 @RESPATH@/browser/components/EnterprisePolicies.manifest
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -47,16 +47,17 @@
 #include "nsIDocShellTreeItem.h"
 #include "nsCOMArray.h"
 #include "nsQueryObject.h"
 #include "nsDOMClassInfo.h"
 #include "mozilla/Services.h"
 #include "nsScreen.h"
 #include "ChildIterator.h"
 
+#include "mozilla/dom/AboutCapabilitiesBinding.h"
 #include "mozilla/AsyncEventDispatcher.h"
 #include "mozilla/BasicEvents.h"
 #include "mozilla/EventListenerManager.h"
 #include "mozilla/EventStateManager.h"
 
 #include "mozilla/dom/Attr.h"
 #include "mozilla/dom/BindingDeclarations.h"
 #include "mozilla/dom/Element.h"
@@ -1917,16 +1918,17 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
     cb.NoteXPCOMChild(tmp->mChildren.ChildAt(indx - 1));
   }
 
   // Traverse all nsIDocument pointer members.
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSecurityInfo)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDisplayDocument)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFontFaceSet)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mReadyForIdle)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAboutCapabilities)
 
   // Traverse all nsDocument nsCOMPtrs.
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParser)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mScriptGlobalObject)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mListenerManager)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDOMStyleSheets)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStyleSheetSetList)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mScriptLoader)
@@ -2059,16 +2061,17 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ns
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mCachedEncoder)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocumentTimeline)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mPendingAnimationTracker)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mTemplateContentsOwner)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mChildrenCollection)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mOrientationPendingPromise)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mFontFaceSet)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mReadyForIdle);
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mAboutCapabilities)
 
   tmp->mParentDocument = nullptr;
 
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mPreloadingImages)
 
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mIntersectionObservers)
 
   tmp->ClearAllBoxObjects();
@@ -3387,16 +3390,72 @@ nsDocument::GetAllowPlugins()
   if (classification == FlashClassification::Denied) {
     return false;
   }
 
   return true;
 }
 
 bool
+nsDocument::CallerIsTrustedAboutPage(JSContext* aCx, JSObject* aObject)
+{
+  /*
+   * If you want an about: page to have access to AboutCapabilities,
+   * please add it to the list of trusted about: pages underneath.
+   */
+  static const char* kTrustedAboutPages[] = {
+    "about:privatebrowsing",
+  };
+
+  nsIPrincipal* principal = nsContentUtils::SubjectPrincipal(aCx);
+  if (!principal) {
+    return false;
+  }
+  nsCOMPtr<nsIURI> uri;
+  principal->GetURI(getter_AddRefs(uri));
+  if (!uri) {
+    return false;
+  }
+  // getSpec is an expensive operation, hence we first check the scheme
+  // to see if the caller is actually an about: page.
+  bool isAboutScheme = false;
+  uri->SchemeIs("about", &isAboutScheme);
+  if (!isAboutScheme) {
+    return false;
+  }
+
+  nsAutoCString aboutSpec;
+  uri->GetSpec(aboutSpec);
+  for (auto & aboutPageEntry : kTrustedAboutPages) {
+    if (aboutSpec.EqualsIgnoreCase(aboutPageEntry)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+already_AddRefed<AboutCapabilities>
+nsIDocument::GetAboutCapabilities(ErrorResult& aRv)
+{
+  if (!mAboutCapabilities) {
+    AutoJSContext cx;
+    JS::Rooted<JSObject*> jsImplObj(cx);
+    nsIGlobalObject* sgo = GetScopeObject();
+    ConstructJSImplementation("@mozilla.org/aboutcapabilities;1", sgo, &jsImplObj, aRv);
+    if (aRv.Failed()) {
+      return nullptr;
+    }
+    mAboutCapabilities = new AboutCapabilities(jsImplObj, sgo);
+  }
+  RefPtr<AboutCapabilities> aboutCapabilities =
+    static_cast<AboutCapabilities*>(mAboutCapabilities.get());
+  return aboutCapabilities.forget();
+}
+
+bool
 nsDocument::IsElementAnimateEnabled(JSContext* aCx, JSObject* /*unused*/)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   return nsContentUtils::IsSystemCaller(aCx) ||
          nsContentUtils::AnimationsAPICoreEnabled() ||
          nsContentUtils::AnimationsAPIElementAnimateEnabled();
 }
--- a/dom/base/nsDocument.h
+++ b/dom/base/nsDocument.h
@@ -413,16 +413,17 @@ public:
   already_AddRefed<nsIPresShell> CreateShell(nsPresContext* aContext,
                                              nsViewManager* aViewManager,
                                              mozilla::StyleSetHandle aStyleSet)
     final;
   virtual void DeleteShell() override;
 
   virtual bool GetAllowPlugins() override;
 
+  static bool CallerIsTrustedAboutPage(JSContext* aCx, JSObject* aObject);
   static bool IsElementAnimateEnabled(JSContext* aCx, JSObject* aObject);
   static bool IsWebAnimationsEnabled(JSContext* aCx, JSObject* aObject);
   static bool IsWebAnimationsEnabled(mozilla::dom::CallerType aCallerType);
   virtual mozilla::dom::DocumentTimeline* Timeline() override;
   virtual void GetAnimations(
       nsTArray<RefPtr<mozilla::dom::Animation>>& aAnimations) override;
   mozilla::LinkedList<mozilla::dom::DocumentTimeline>& Timelines() override
   {
--- a/dom/base/nsIDocument.h
+++ b/dom/base/nsIDocument.h
@@ -124,16 +124,17 @@ struct URLExtraData;
 
 namespace css {
 class Loader;
 class ImageLoader;
 class Rule;
 } // namespace css
 
 namespace dom {
+class AboutCapabilities;
 class Animation;
 class AnonymousContent;
 class Attr;
 class BoxObject;
 class ClientInfo;
 class ClientState;
 class CDATASection;
 class Comment;
@@ -2862,16 +2863,20 @@ public:
                       mozilla::ErrorResult& rv);
   void SetAllowUnsafeHTML(bool aAllow) { mAllowUnsafeHTML = aAllow; }
   bool AllowUnsafeHTML() const;
   void GetInputEncoding(nsAString& aInputEncoding) const;
   already_AddRefed<mozilla::dom::Location> GetLocation() const;
   void GetReferrer(nsAString& aReferrer) const;
   void GetLastModified(nsAString& aLastModified) const;
   void GetReadyState(nsAString& aReadyState) const;
+
+  already_AddRefed<mozilla::dom::AboutCapabilities> GetAboutCapabilities(
+    ErrorResult& aRv);
+
   virtual void GetTitle(nsAString& aTitle) = 0;
   virtual void SetTitle(const nsAString& aTitle, mozilla::ErrorResult& rv) = 0;
   void GetDir(nsAString& aDirection) const;
   void SetDir(const nsAString& aDirection);
   already_AddRefed<nsContentList> GetElementsByName(const nsAString& aName)
   {
     return GetFuncStringContentList<nsCachableElementsByNameNodeList>(this,
                                                                       MatchNameAttribute,
@@ -3368,16 +3373,18 @@ protected:
   // Last time this document or a one of its sub-documents was focused.  If
   // focus has never occurred then mLastFocusTime.IsNull() will be true.
   mozilla::TimeStamp mLastFocusTime;
 
   mozilla::EventStates mDocumentState;
 
   RefPtr<mozilla::dom::Promise> mReadyForIdle;
 
+  RefPtr<mozilla::dom::AboutCapabilities> mAboutCapabilities;
+
   // True if BIDI is enabled.
   bool mBidiEnabled : 1;
   // True if a MathML element has ever been owned by this document.
   bool mMathMLEnabled : 1;
 
   // True if this document is the initial document for a window.  This should
   // basically be true only for documents that exist in newly-opened windows or
   // documents created to satisfy a GetDocument() on a window when there's no
new file mode 100644
--- /dev/null
+++ b/dom/webidl/AboutCapabilities.webidl
@@ -0,0 +1,32 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 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/.
+ */
+
+[NoInterfaceObject, JSImplementation="@mozilla.org/aboutcapabilities;1"]
+interface AboutCapabilities
+{
+  /**
+   * When using setBoolPref, one also has to whitelist the
+   * pref to be updated within AsyncPrefs.jsm
+   */
+  Promise<void> setBoolPref(DOMString aPref, boolean aValue);
+  boolean getBoolPref(DOMString aPref, boolean? aDefaultValue);
+
+  /**
+   * When using setCharPref, one also has to whitelist the
+   * pref to be updated within AsyncPrefs.jsm
+   */
+  Promise<void> setCharPref(DOMString aPref, DOMString aValue);
+  DOMString getCharPref(DOMString aPref, DOMString? aDefaultValue);
+
+  DOMString getStringFromBundle(DOMString aStrBundle, DOMString aStr);
+
+  DOMString formatURLPref(DOMString aFormatURL);
+
+  void sendAsyncMessage(DOMString aMessage, object? aParams);
+
+  /* about:privatebrowsing */
+  boolean isWindowPrivate();
+};
--- a/dom/webidl/Document.webidl
+++ b/dom/webidl/Document.webidl
@@ -472,16 +472,21 @@ enum FlashClassification {
   "allowed",        // Site is on the Flash whitelist
   "denied"          // Site is on the Flash blacklist
 };
 partial interface Document {
   [ChromeOnly]
   readonly attribute FlashClassification documentFlashClassification;
 };
 
+// Allows about: pages to query aboutCapabilities
+partial interface Document {
+  [Throws, Func="nsDocument::CallerIsTrustedAboutPage"] readonly attribute AboutCapabilities aboutCapabilities;
+};
+
 Document implements XPathEvaluator;
 Document implements GlobalEventHandlers;
 Document implements DocumentAndElementEventHandlers;
 Document implements TouchEventHandlers;
 Document implements ParentNode;
 Document implements OnErrorEventHandlerForNodes;
 Document implements GeometryUtils;
 Document implements FontFaceSource;
--- a/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -363,16 +363,17 @@ PREPROCESSED_WEBIDL_FILES = [
     'ChromeUtils.webidl',
     'Node.webidl',
     'Window.webidl',
 ]
 
 WEBIDL_FILES = [
     'AbortController.webidl',
     'AbortSignal.webidl',
+    'AboutCapabilities.webidl',
     'AbstractWorker.webidl',
     'AddonManager.webidl',
     'AnalyserNode.webidl',
     'Animatable.webidl',
     'Animation.webidl',
     'AnimationEffectReadOnly.webidl',
     'AnimationEffectTiming.webidl',
     'AnimationEffectTimingReadOnly.webidl',
--- a/extensions/pref/autoconfig/src/nsReadConfig.cpp
+++ b/extensions/pref/autoconfig/src/nsReadConfig.cpp
@@ -106,16 +106,22 @@ NS_IMETHODIMP nsReadConfig::Observe(nsIS
                 do_GetService(NS_APPSTARTUP_CONTRACTID);
             if (appStartup)
                 appStartup->Quit(nsIAppStartup::eAttemptQuit);
         }
     }
     return rv;
 }
 
+/**
+ * This is the blocklist for known bad autoconfig files.
+ */
+static const char *gBlockedConfigs[] = {
+  "dsengine.cfg"
+};
 
 nsresult nsReadConfig::readConfigFile()
 {
     nsresult rv = NS_OK;
     nsAutoCString lockFileName;
     nsAutoCString lockVendor;
     uint32_t fileNameLen = 0;
 
@@ -130,21 +136,28 @@ nsresult nsReadConfig::readConfigFile()
         return rv;
 
     // This preference is set in the all.js or all-ns.js (depending whether
     // running mozilla or netscp6)
 
     rv = defaultPrefBranch->GetCharPref("general.config.filename",
                                         lockFileName);
 
-
     MOZ_LOG(MCD, LogLevel::Debug, ("general.config.filename = %s\n", lockFileName.get()));
     if (NS_FAILED(rv))
         return rv;
 
+    for (size_t index = 0, len = mozilla::ArrayLength(gBlockedConfigs); index < len;
+         ++index) {
+      if (lockFileName == gBlockedConfigs[index]) {
+        // This is NS_OK because we don't want to show an error to the user
+        return rv;
+      }
+    }
+
     // This needs to be read only once.
     //
     if (!mRead) {
         // Initiate the new JS Context for Preference management
 
         rv = CentralizedAdminPrefManagerInit();
         if (NS_FAILED(rv))
             return rv;
--- a/layout/printing/nsPrintJob.cpp
+++ b/layout/printing/nsPrintJob.cpp
@@ -3517,26 +3517,28 @@ nsPrintJob::StartPagePrintTimer(const Un
 
   return mPagePrintTimer->Start(aPO.get());
 }
 
 /*=============== nsIObserver Interface ======================*/
 NS_IMETHODIMP
 nsPrintJob::Observe(nsISupports* aSubject, const char* aTopic, const char16_t* aData)
 {
-  nsresult rv = NS_ERROR_FAILURE;
-
-  rv = InitPrintDocConstruction(true);
+  // Only process a null topic which means the progress dialog is open.
+  if (aTopic) {
+    return NS_OK;
+  }
+
+  nsresult rv = InitPrintDocConstruction(true);
   if (!mIsDoingPrinting && mPrtPreview) {
     RefPtr<nsPrintData> printDataOfPrintPreview = mPrtPreview;
     printDataOfPrintPreview->OnEndPrinting();
   }
 
   return rv;
-
 }
 
 //---------------------------------------------------------------
 //-- PLEvent Notification
 //---------------------------------------------------------------
 class nsPrintCompletionEvent : public Runnable {
 public:
   explicit nsPrintCompletionEvent(nsIDocumentViewerPrint* docViewerPrint)
--- a/toolkit/components/printing/content/printUtils.js
+++ b/toolkit/components/printing/content/printUtils.js
@@ -385,16 +385,21 @@ var PrintUtils = {
     }
     return printSettings;
   },
 
   // This observer is called once the progress dialog has been "opened"
   _obsPP:
   {
     observe(aSubject, aTopic, aData) {
+      // Only process a null topic which means the progress dialog is open.
+      if (aTopic) {
+        return;
+      }
+
       // delay the print preview to show the content of the progress dialog
       setTimeout(function() { PrintUtils.enterPrintPreview(); }, 0);
     },
 
     QueryInterface(iid) {
       if (iid.equals(Ci.nsIObserver) ||
           iid.equals(Ci.nsISupportsWeakReference) ||
           iid.equals(Ci.nsISupports))
--- a/toolkit/components/printingui/ipc/PrintProgressDialogParent.cpp
+++ b/toolkit/components/printingui/ipc/PrintProgressDialogParent.cpp
@@ -94,20 +94,34 @@ PrintProgressDialogParent::Recv__delete_
 }
 
 // nsIObserver
 NS_IMETHODIMP
 PrintProgressDialogParent::Observe(nsISupports *aSubject, const char *aTopic,
                                    const char16_t *aData)
 {
   if (mActive) {
-    if (aTopic && !strcmp(aTopic, "cancelled")) {
-      Unused << SendCancelledCurrentJob();
+    if (aTopic) {
+      if (!strcmp(aTopic, "cancelled")) {
+        Unused << SendCancelledCurrentJob();
+        if (!mDialogOpenedSent) {
+          // We haven't already called SendDialogOpened, so call it now or it
+          // might never get sent and block the child from new printing requests.
+          // Also set mActive to false because we don't want to send it twice
+          // and our PrintProgressDialogChild will get deleted anyway.
+          Unused << SendDialogOpened();
+          mActive = false;
+        }
+      } else if (!strcmp(aTopic, "completed")) {
+        // Once printing is complete don't send any messages to the child.
+        mActive = false;
+      }
     } else {
       Unused << SendDialogOpened();
+      mDialogOpenedSent = true;
     }
   } else {
     NS_WARNING("The print progress dialog finished opening, but communications "
                "with the child have been closed.");
   }
 
   return NS_OK;
 }
--- a/toolkit/components/printingui/ipc/PrintProgressDialogParent.h
+++ b/toolkit/components/printingui/ipc/PrintProgressDialogParent.h
@@ -51,14 +51,15 @@ public:
   Recv__delete__() override;
 
 private:
   virtual ~PrintProgressDialogParent();
 
   nsCOMPtr<nsIWebProgressListener> mWebProgressListener;
   nsCOMPtr<nsIPrintProgressParams> mPrintProgressParams;
   bool mActive;
+  bool mDialogOpenedSent = false;
 };
 
 } // namespace embedding
 } // namespace mozilla
 
 #endif
--- a/toolkit/components/printingui/nsPrintProgress.cpp
+++ b/toolkit/components/printingui/nsPrintProgress.cpp
@@ -175,32 +175,48 @@ NS_IMETHODIMP nsPrintProgress::DoneIniti
   if (m_observer) {
     m_observer->Observe(nullptr, nullptr, nullptr);
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP nsPrintProgress::OnStateChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, uint32_t aStateFlags, nsresult aStatus)
 {
+  if (XRE_IsE10sParentProcess() &&
+      aStateFlags & nsIWebProgressListener::STATE_STOP) {
+    // If we're in an e10s parent, m_observer is a PrintProgressDialogParent,
+    // so we let it know that printing has completed, because it might mean that
+    // its PrintProgressDialogChild has already been deleted.
+    m_observer->Observe(nullptr, "completed", nullptr);
+  }
+
   m_pendingStateFlags = aStateFlags;
   m_pendingStateValue = aStatus;
 
   uint32_t count = m_listenerList.Count();
   for (uint32_t i = count - 1; i < count; i --)
   {
     nsCOMPtr<nsIWebProgressListener> progressListener = m_listenerList.SafeObjectAt(i);
     if (progressListener)
       progressListener->OnStateChange(aWebProgress, aRequest, aStateFlags, aStatus);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP nsPrintProgress::OnProgressChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, int32_t aCurSelfProgress, int32_t aMaxSelfProgress, int32_t aCurTotalProgress, int32_t aMaxTotalProgress)
 {
+  if (XRE_IsE10sParentProcess() && aCurSelfProgress &&
+      aCurSelfProgress >= aMaxSelfProgress) {
+    // If we're in an e10s parent, m_observer is a PrintProgressDialogParent,
+    // so we let it know that printing has completed, because it might mean that
+    // its PrintProgressDialogChild has already been deleted.
+    m_observer->Observe(nullptr, "completed", nullptr);
+  }
+
   uint32_t count = m_listenerList.Count();
   for (uint32_t i = count - 1; i < count; i --)
   {
     nsCOMPtr<nsIWebProgressListener> progressListener = m_listenerList.SafeObjectAt(i);
     if (progressListener)
       progressListener->OnProgressChange(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress);
   }
 
--- a/toolkit/modules/AsyncPrefs.jsm
+++ b/toolkit/modules/AsyncPrefs.jsm
@@ -15,16 +15,18 @@ const kAllowedPrefs = new Set([
   // anything.
   "testing.allowed-prefs.some-bool-pref",
   "testing.allowed-prefs.some-char-pref",
   "testing.allowed-prefs.some-int-pref",
 
   "narrate.rate",
   "narrate.voice",
 
+  "privacy.trackingprotection.pbmode.enabled",
+
   "reader.font_size",
   "reader.font_type",
   "reader.color_scheme",
   "reader.content_width",
   "reader.line_height",
 ]);
 
 const kPrefTypeMap = new Map([
--- a/widget/windows/nsWindowGfx.cpp
+++ b/widget/windows/nsWindowGfx.cpp
@@ -383,31 +383,27 @@ bool nsWindow::OnPaint(HDC aDC, uint32_t
             // bitmap. Now it can be read from memory bitmap to apply alpha channel and after
             // that displayed on the screen.
             mBasicLayersSurface->RedrawTransparentWindow();
           }
 #endif
         }
         break;
       case LayersBackend::LAYERS_CLIENT:
+      case LayersBackend::LAYERS_WR:
         {
           result = listener->PaintWindow(
             this, LayoutDeviceIntRegion::FromUnknownRegion(region));
           if (!gfxEnv::DisableForcePresent() && gfxWindowsPlatform::GetPlatform()->DwmCompositionEnabled()) {
             nsCOMPtr<nsIRunnable> event =
               NewRunnableMethod("nsWindow::ForcePresent", this, &nsWindow::ForcePresent);
             NS_DispatchToMainThread(event);
           }
         }
         break;
-      case LayersBackend::LAYERS_WR:
-      {
-        GetLayerManager()->ScheduleComposite();
-        break;
-      }
       default:
         NS_ERROR("Unknown layers backend used!");
         break;
     }
   }
 
   if (!aDC) {
     ::EndPaint(mWnd, &ps);