Merge mozilla-central to inbound. a=merge CLOSED TREE
authorNoemi Erli <nerli@mozilla.com>
Sat, 10 Mar 2018 12:15:32 +0200
changeset 407501 a0014a24f1e72bb1746cb9975068953d1f3451e2
parent 407441 e620f50bbdcfe0d8ca5f328a88fb253bd909a9bf (current diff)
parent 407500 0817a733d45a48800e68c9e2a5035fd17bfcdee2 (diff)
child 407502 e805bff87d630994704d70b1b38871efda4b12a4
push id100696
push usernerli@mozilla.com
push dateSat, 10 Mar 2018 10:16:05 +0000
treeherdermozilla-inbound@a0014a24f1e7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone60.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
Merge mozilla-central to inbound. a=merge CLOSED TREE
gfx/webrender/res/brush_picture.glsl
--- a/accessible/ipc/win/handler/HandlerDataCleanup.h
+++ b/accessible/ipc/win/handler/HandlerDataCleanup.h
@@ -2,17 +2,17 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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/. */
 
 #ifndef mozilla_a11y_HandlerDataCleanup_h
 #define mozilla_a11y_HandlerDataCleanup_h
 
-#include <OleAuto.h>
+#include <oleauto.h>
 #include "HandlerData.h"
 
 namespace mozilla {
 namespace a11y {
 
 inline void
 ReleaseStaticIA2DataInterfaces(StaticIA2Data& aData)
 {
--- a/browser/app/blocklist.xml
+++ b/browser/app/blocklist.xml
@@ -1,10 +1,10 @@
 <?xml version='1.0' encoding='UTF-8'?>
-<blocklist lastupdate="1520358450708" xmlns="http://www.mozilla.org/2006/addons-blocklist">
+<blocklist lastupdate="1520527480321" xmlns="http://www.mozilla.org/2006/addons-blocklist">
   <emItems>
     <emItem blockID="i334" id="{0F827075-B026-42F3-885D-98981EE7B1AE}">
       <prefs/>
       <versionRange minVersion="0" maxVersion="*" severity="3"/>
     </emItem>
     <emItem blockID="i1211" id="flvto@hotger.com">
       <prefs/>
       <versionRange minVersion="0" maxVersion="*" severity="1"/>
@@ -2218,16 +2218,20 @@
     <emItem blockID="0cd723fe-d33d-43a0-b84f-7a3cad253212" id="{42baa93e-0cff-4289-b79e-6ae88df668c4}">
       <prefs/>
       <versionRange minVersion="0" maxVersion="*" severity="3"/>
     </emItem>
     <emItem blockID="f58729ec-f93c-41d9-870d-dd9c9fd811b6" id="/^(addon@fasterweb\.com|\{5f398d3f-25db-47f5-b422-aa2364ff6c0b\}|addon@fasterp\.com|addon@calculator)$/">
       <prefs/>
       <versionRange minVersion="0" maxVersion="*" severity="3"/>
     </emItem>
+    <emItem blockID="3d55fab0-ec1a-4bca-84c9-3b74f5d01509" id="/^.*extension.*@asdf\.pl$/">
+      <prefs/>
+      <versionRange minVersion="0" maxVersion="*" severity="3"/>
+    </emItem>
   </emItems>
   <pluginItems>
     <pluginItem blockID="p332">
       <match exp="libflashplayer\.so" name="filename"/>
       <match exp="^Shockwave Flash 11.(0|1) r[0-9]{1,3}$" name="description"/>
       <infoURL>https://get.adobe.com/flashplayer/</infoURL>
       <versionRange severity="0" vulnerabilitystatus="1">
         <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -581,17 +581,17 @@
   </popupset>
   <box id="appMenu-viewCache" hidden="true"/>
 
 #ifdef CAN_DRAW_IN_TITLEBAR
 <vbox id="titlebar">
   <hbox id="titlebar-content">
     <spacer id="titlebar-spacer" flex="1"/>
     <hbox id="titlebar-buttonbox-container">
-      <hbox id="titlebar-buttonbox">
+      <hbox id="titlebar-buttonbox" class="titlebar-color">
         <toolbarbutton class="titlebar-button" id="titlebar-min" oncommand="window.minimize();"/>
         <toolbarbutton class="titlebar-button" id="titlebar-max" oncommand="onTitlebarMaxClick();"/>
         <toolbarbutton class="titlebar-button" id="titlebar-close" command="cmd_closeWindow"/>
       </hbox>
     </hbox>
 #ifdef XP_MACOSX
     <!-- OS X does not natively support RTL for its titlebar items, so we prevent this secondary
          buttonbox from reversing order in RTL by forcing an LTR direction. -->
@@ -602,17 +602,19 @@
     </hbox>
 #endif
   </hbox>
 </vbox>
 #endif
 
   <toolbox id="navigator-toolbox">
     <!-- Menu -->
-    <toolbar type="menubar" id="toolbar-menubar" class="chromeclass-menubar" customizable="true"
+    <toolbar type="menubar" id="toolbar-menubar"
+             class="chromeclass-menubar titlebar-color"
+             customizable="true"
              mode="icons"
 #ifdef MENUBAR_CAN_AUTOHIDE
              toolbarname="&menubarCmd.label;"
              accesskey="&menubarCmd.accesskey;"
              autohide="true"
 #endif
              context="toolbar-context-menu">
       <toolbaritem id="menubar-items" align="center">
@@ -625,16 +627,17 @@
 #ifndef XP_MACOSX
       <hbox class="titlebar-placeholder" type="caption-buttons" ordinal="1000"
             skipintoolbarset="true"/>
 #endif
 #endif
     </toolbar>
 
     <toolbar id="TabsToolbar"
+             class="titlebar-color"
              fullscreentoolbar="true"
              customizable="true"
              mode="icons"
              aria-label="&tabsToolbar.label;"
              context="toolbar-context-menu"
              collapsed="true">
 
 #ifdef CAN_DRAW_IN_TITLEBAR
--- a/browser/base/content/test/webrtc/browser_devices_get_user_media.js
+++ b/browser/base/content/test/webrtc/browser_devices_get_user_media.js
@@ -510,17 +510,17 @@ var gTests = [
     if ("nsISystemStatusBar" in Ci) {
       let activeStreams = webrtcUI.getActiveStreams(true, false, false);
       webrtcUI.showSharingDoorhanger(activeStreams[0]);
     } else {
       let win =
         Services.wm.getMostRecentWindow("Browser:WebRTCGlobalIndicator");
       let elt = win.document.getElementById("audioVideoButton");
       EventUtils.synthesizeMouseAtCenter(elt, {}, win);
-      await promiseWaitForCondition(() => !gIdentityHandler._identityPopup.hidden);
+      await TestUtils.waitForCondition(() => !gIdentityHandler._identityPopup.hidden);
     }
     ok(!gIdentityHandler._identityPopup.hidden, "control center should be open");
 
     gIdentityHandler._identityPopup.hidden = true;
     await expectNoObserverCalled();
 
     await closeStream();
   }
--- a/browser/base/content/webext-panels.js
+++ b/browser/base/content/webext-panels.js
@@ -84,17 +84,26 @@ var gBrowser = {
   getTabModalPromptBox(browser) {
     if (!browser.tabModalPromptBox) {
       browser.tabModalPromptBox = new TabModalPromptBox(browser);
     }
     return browser.tabModalPromptBox;
   },
 };
 
-async function loadPanel(extensionId, extensionUrl, browserStyle) {
+function loadPanel(extensionId, extensionUrl, browserStyle) {
+  let browserEl = document.getElementById("webext-panels-browser");
+  if (browserEl) {
+    if (browserEl.currentURI.spec === extensionUrl) {
+      return;
+    }
+    // Forces runtime disconnect.  Remove the stack (parent).
+    browserEl.parentNode.remove();
+  }
+
   let policy = WebExtensionPolicy.getByID(extensionId);
   let sidebar = {
     uri: extensionUrl,
     remote: policy.extension.remote,
     browserStyle,
   };
   getBrowser(sidebar).then(browser => {
     let uri = Services.io.newURI(policy.getURL());
--- a/browser/components/customizableui/PanelMultiView.jsm
+++ b/browser/components/customizableui/PanelMultiView.jsm
@@ -1318,16 +1318,20 @@ var PanelView = class extends Associated
 
         items.push({ element });
       }
     };
     if (allowSyncReflows) {
       collectItems();
     } else {
       await this.window.promiseDocumentFlushed(collectItems);
+      // Bail out if the panel was closed in the meantime.
+      if (!this.node.panelMultiView) {
+        return;
+      }
     }
 
     // Removing the 'height' property will only cause a layout flush in the next
     // loop below if it was set.
     for (let item of items) {
       item.element.style.removeProperty("height");
     }
 
@@ -1337,16 +1341,20 @@ var PanelView = class extends Associated
       for (let item of items) {
         item.bounds = item.element.getBoundingClientRect();
       }
     };
     if (allowSyncReflows) {
       measureItems();
     } else {
       await this.window.promiseDocumentFlushed(measureItems);
+      // Bail out if the panel was closed in the meantime.
+      if (!this.node.panelMultiView) {
+        return;
+      }
     }
 
     // Now we can make all the necessary DOM changes at once.
     for (let { element, bounds } of items) {
       gMultiLineElementsMap.set(element, { bounds, textContent: element.textContent });
       element.style.height = bounds.height + "px";
     }
   }
--- a/browser/components/extensions/test/browser/browser-common.ini
+++ b/browser/components/extensions/test/browser/browser-common.ini
@@ -33,16 +33,17 @@ support-files =
   serviceWorker.js
   searchSuggestionEngine.xml
   searchSuggestionEngine.sjs
   ../../../../../toolkit/components/extensions/test/mochitest/head_webrequest.js
   ../../../../../toolkit/components/extensions/test/mochitest/redirection.sjs
   ../../../../../toolkit/components/reader/test/readerModeNonArticle.html
   ../../../../../toolkit/components/reader/test/readerModeArticle.html
 
+[browser_ext_addon_debugging_netmonitor.js]
 [browser_ext_browserAction_area.js]
 [browser_ext_browserAction_experiment.js]
 [browser_ext_browserAction_context.js]
 skip-if = os == 'win' || os == 'mac' # Bug 1405453
 [browser_ext_browserAction_contextMenu.js]
 # bug 1369197
 skip-if = os == 'linux'
 [browser_ext_browserAction_disabled.js]
@@ -134,16 +135,17 @@ disabled = bug 1438663
 [browser_ext_sessions_restore.js]
 [browser_ext_sessions_window_tab_value.js]
 [browser_ext_settings_overrides_default_search.js]
 [browser_ext_settings_overrides_search.js]
 [browser_ext_sidebarAction.js]
 [browser_ext_sidebarAction_browser_style.js]
 [browser_ext_sidebarAction_context.js]
 [browser_ext_sidebarAction_contextMenu.js]
+[browser_ext_sidebarAction_runtime.js]
 [browser_ext_sidebarAction_tabs.js]
 [browser_ext_sidebarAction_windows.js]
 [browser_ext_simple.js]
 [browser_ext_slow_script.js]
 skip-if = !e10s || debug || asan
 [browser_ext_tab_runtimeConnect.js]
 [browser_ext_tabs_audio.js]
 [browser_ext_tabs_captureTab.js]
new file mode 100644
--- /dev/null
+++ b/browser/components/extensions/test/browser/browser_ext_addon_debugging_netmonitor.js
@@ -0,0 +1,132 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+"use strict";
+
+ChromeUtils.defineModuleGetter(this, "BrowserToolboxProcess",
+                               "resource://devtools/client/framework/ToolboxProcess.jsm");
+
+async function setupToolboxProcessTest(toolboxProcessScript) {
+  // Enable addon debugging.
+  await SpecialPowers.pushPrefEnv({
+    "set": [
+      // Force enabling of addons debugging
+      ["devtools.chrome.enabled", true],
+      ["devtools.debugger.remote-enabled", true],
+      // Disable security prompt
+      ["devtools.debugger.prompt-connection", false],
+      // Enable Browser toolbox test script execution via env variable
+      ["devtools.browser-toolbox.allow-unsafe-script", true],
+    ],
+  });
+
+  let env = Cc["@mozilla.org/process/environment;1"]
+              .getService(Ci.nsIEnvironment);
+  env.set("MOZ_TOOLBOX_TEST_SCRIPT", `(${toolboxProcessScript})();`);
+  registerCleanupFunction(() => {
+    env.set("MOZ_TOOLBOX_TEST_SCRIPT", "");
+  });
+}
+
+add_task(async function test_addon_debugging_netmonitor_panel() {
+  const EXTENSION_ID = "test-monitor-panel@mozilla";
+
+  function background() {
+    let expectedURL;
+    window.doFetchHTTPRequest = async function(urlToFetch) {
+      expectedURL = urlToFetch;
+      await fetch(urlToFetch);
+    };
+    window.testNetworkRequestReceived = async function(requests) {
+      browser.test.log("Addon Debugging Netmonitor panel collected requests: " +
+                       JSON.stringify(requests));
+      browser.test.assertEq(1, requests.length, "Got one request logged");
+      browser.test.assertEq("GET", requests[0].method, "Got a GET request");
+      browser.test.assertEq(expectedURL, requests[0].url, "Got the expected request url");
+
+      browser.test.notifyPass("netmonitor_request_logged");
+    };
+    browser.test.sendMessage("ready");
+  }
+
+  let extension = ExtensionTestUtils.loadExtension({
+    background,
+    useAddonManager: "temporary",
+    manifest: {
+      permissions: ["http://mochi.test/"],
+      applications: {
+        gecko: {id: EXTENSION_ID},
+      },
+    },
+  });
+
+  await extension.startup();
+  await extension.awaitMessage("ready");
+
+  // Be careful, this JS function is going to be executed in the addon toolbox,
+  // which lives in another process. So do not try to use any scope variable!
+  const toolboxProcessScript = async function() {
+    /* eslint-disable no-undef */
+    async function waitFor(condition) {
+      while (!condition()) {
+        // eslint-disable-next-line mozilla/no-arbitrary-setTimeout
+        await new Promise(done => window.setTimeout(done, 1000));
+      }
+    }
+
+    const console = await toolbox.selectTool("webconsole");
+    const {hud} = console;
+    const {jsterm} = hud;
+
+    const netmonitor = await toolbox.selectTool("netmonitor");
+
+    const expectedURL = "http://mochi.test:8888/?test_netmonitor=1";
+
+    // Call a function defined in the target extension to make it
+    // fetch from an expected http url.
+    await jsterm.execute(`doFetchHTTPRequest("${expectedURL}");`);
+
+    await waitFor(() => {
+      return !netmonitor.panelWin.document.querySelector(".request-list-empty-notice");
+    });
+
+    let {store} = netmonitor.panelWin;
+
+    // NOTE: we need to filter the requests to the ones that we expect until
+    // the network monitor is not yet filtering out the requests that are not
+    // coming from an extension window or a descendent of an extension window,
+    // in both oop and non-oop extension mode (filed as Bug 1442621).
+    function filterRequest(request) {
+      return request.url === expectedURL;
+    }
+
+    let requests;
+
+    await waitFor(() => {
+      requests = Array.from(store.getState().requests.requests.values())
+                      .filter(filterRequest);
+
+      return requests.length > 0;
+    });
+
+    // Call a function defined in the target extension to make assertions
+    // on the network requests collected by the netmonitor panel.
+    await jsterm.execute(`testNetworkRequestReceived(${JSON.stringify(requests)});`);
+    /* eslint-enable no-undef */
+  };
+
+  await setupToolboxProcessTest(toolboxProcessScript);
+  const browserToolboxProcess = new BrowserToolboxProcess({
+    addonID: EXTENSION_ID,
+  });
+
+  await extension.awaitFinish("netmonitor_request_logged");
+
+  let onToolboxClose = browserToolboxProcess.once("close");
+  await browserToolboxProcess.close();
+
+  await onToolboxClose;
+
+  info("Addon Toolbox closed");
+
+  await extension.unload();
+});
new file mode 100644
--- /dev/null
+++ b/browser/components/extensions/test/browser/browser_ext_sidebarAction_runtime.js
@@ -0,0 +1,65 @@
+"use strict";
+
+function background() {
+  browser.runtime.onConnect.addListener(port => {
+    browser.test.assertEq(port.name, "ernie", "port name correct");
+    port.onDisconnect.addListener(() => {
+      browser.test.assertEq(null, port.error, "The port is implicitly closed without errors when the other context unloads");
+      port.disconnect();
+      browser.test.sendMessage("disconnected");
+    });
+    browser.test.sendMessage("connected");
+  });
+}
+
+let extensionData = {
+  background,
+  manifest: {
+    sidebar_action: {
+      default_panel: "sidebar.html",
+    },
+  },
+  useAddonManager: "temporary",
+
+  files: {
+    "sidebar.html": `
+      <!DOCTYPE html>
+      <html>
+      <head><meta charset="utf-8"/>
+      <script src="sidebar.js"></script>
+      </head>
+      <body>
+      A Test Sidebar
+      </body></html>
+    `,
+
+    "sidebar.js": function() {
+      window.onload = () => {
+        browser.runtime.connect({name: "ernie"});
+      };
+    },
+  },
+};
+
+add_task(async function test_sidebar_disconnect() {
+  let extension = ExtensionTestUtils.loadExtension(extensionData);
+  let connected = extension.awaitMessage("connected");
+  await extension.startup();
+  await connected;
+
+  // switching sidebar to another extension
+  let extension2 = ExtensionTestUtils.loadExtension(extensionData);
+  let switched = Promise.all([
+    extension.awaitMessage("disconnected"),
+    extension2.awaitMessage("connected")]);
+  await extension2.startup();
+  await switched;
+
+  // switching sidebar to built-in sidebar
+  let disconnected = extension2.awaitMessage("disconnected");
+  window.SidebarUI.show("viewBookmarksSidebar");
+  await disconnected;
+
+  await extension.unload();
+  await extension2.unload();
+});
--- a/browser/components/nsBrowserContentHandler.js
+++ b/browser/components/nsBrowserContentHandler.js
@@ -409,16 +409,17 @@ nsBrowserContentHandler.prototype = {
           // access to private browsing has been disabled.
           forcePrivate = false;
           resolvedURI = Services.io.newURI("about:privatebrowsing");
         } else {
           resolvedURI = resolveURIInternal(cmdLine, privateWindowParam);
         }
         handURIToExistingBrowser(resolvedURI, nsIBrowserDOMWindow.OPEN_NEWTAB, cmdLine, forcePrivate,
                                  Services.scriptSecurityManager.getSystemPrincipal());
+        cmdLine.preventDefault = true;
       }
     } catch (e) {
       if (e.result != Cr.NS_ERROR_INVALID_ARG) {
         throw e;
       }
       // NS_ERROR_INVALID_ARG is thrown when flag exists, but has no param.
       if (cmdLine.handleFlag("private-window", false)) {
         let features = "chrome,dialog=no,all";
--- a/browser/components/preferences/in-content/main.xul
+++ b/browser/components/preferences/in-content/main.xul
@@ -28,17 +28,17 @@
           data-category="paneGeneral"
           hidden="true">
   <caption><label data-l10n-id="startup-header"/></caption>
 
 #ifdef MOZ_DEV_EDITION
   <vbox id="separateProfileBox">
     <checkbox id="separateProfileMode"
               data-l10n-id="separate-profile-mode"/>
-    <hbox aid="sync-dev-edition-root" lign="center" class="indent">
+    <hbox id="sync-dev-edition-root" lign="center" class="indent">
       <label id="useFirefoxSync" data-l10n-id="use-firefox-sync"/>
       <deck id="getStarted">
         <label class="text-link" data-l10n-id="get-started-not-logged-in"/>
         <label class="text-link" data-l10n-id="get-started-configured"/>
       </deck>
     </hbox>
   </vbox>
 #endif
--- a/browser/extensions/onboarding/content/onboarding.js
+++ b/browser/extensions/onboarding/content/onboarding.js
@@ -62,22 +62,22 @@ function createOnboardingTourContent(div
 
   div.appendChild(section);
   return section;
 }
 
 /**
  * Helper function to create the tour button UI element.
  */
-function createOnboardingTourButton(div, buttonId, l10nId) {
+function createOnboardingTourButton(div, buttonId, l10nId, buttonElementTagName = "button") {
   let doc = div.ownerDocument;
   let aside = doc.createElement("aside");
   aside.className = "onboarding-tour-button-container";
 
-  let button = doc.createElement("button");
+  let button = doc.createElement(buttonElementTagName);
   button.id = buttonId;
   button.className = "onboarding-tour-action-button";
   button.setAttribute("data-l10n-id", l10nId);
   aside.appendChild(button);
 
   div.appendChild(aside);
   return aside;
 }
@@ -398,19 +398,21 @@ var onboardingTourset = {
       // Screenshot tour opens the screenshot page directly, see below a#onboarding-tour-screenshots-button.
       // The screenshots page should be responsible for highlighting the Screenshots button
 
       createOnboardingTourDescription(div,
         "onboarding.tour-screenshots.title", "onboarding.tour-screenshots.description");
       createOnboardingTourContent(div, "resource://onboarding/img/figure_screenshots.svg");
 
       let aside = createOnboardingTourButton(div,
-        "onboarding-tour-screenshots-button", "onboarding.tour-screenshots.button");
+                                             "onboarding-tour-screenshots-button",
+                                             "onboarding.tour-screenshots.button",
+                                             "a");
 
-      let button = aside.querySelector("button");
+      let button = aside.querySelector("a");
       button.setAttribute("href", "https://screenshots.firefox.com/#tour");
       button.setAttribute("target", "_blank");
 
       return div;
     },
   },
 };
 
--- a/browser/themes/shared/controlcenter/panel.inc.css
+++ b/browser/themes/shared/controlcenter/panel.inc.css
@@ -377,39 +377,40 @@ description#identity-popup-content-verif
 .identity-popup-permission-remove-button {
   -moz-appearance: none;
   margin: 0;
   border-width: 0;
   border-radius: 50%;
   min-width: 0;
   padding: 2px;
   background-color: transparent;
+  opacity: 0.6;
 }
 
 .identity-popup-permission-remove-button > .button-box {
   padding: 0;
 }
 
 .identity-popup-permission-remove-button > .button-box > .button-icon {
   margin: 0;
   width: 16px;
   height: 16px;
   list-style-image: url(chrome://browser/skin/panel-icon-cancel.svg);
   -moz-context-properties: fill;
-  fill: graytext;
+  fill: currentColor;
 }
 
 .identity-popup-permission-remove-button > .button-box > .button-text {
   display: none;
 }
 
 /* swap foreground / background colors on hover */
 .identity-popup-permission-remove-button:not(:-moz-focusring):hover {
-  background-color: graytext;
+  background-color: currentColor;
 }
 
 .identity-popup-permission-remove-button:not(:-moz-focusring):hover > .button-box > .button-icon {
-  fill: -moz-field;
+  fill: var(--arrowpanel-background);
 }
 
 .identity-popup-permission-remove-button:not(:-moz-focusring):hover:active {
-  background-color: -moz-fieldtext;
+  opacity: 0.8;
 }
--- a/browser/themes/shared/customizableui/panelUI.inc.css
+++ b/browser/themes/shared/customizableui/panelUI.inc.css
@@ -856,19 +856,20 @@ panelview .toolbarbutton-1,
 
 .subviewbutton[shortcut]::after {
   content: attr(shortcut);
   float: right;
   color: GrayText;
 }
 
 .PanelUI-subView .subviewbutton-nav::after {
-  -moz-context-properties: fill;
+  -moz-context-properties: fill, fill-opacity;
   content: url(chrome://browser/skin/back-12.svg);
-  fill: GrayText;
+  fill: currentColor;
+  fill-opacity: 0.6;
   float: right;
   transform: translateY(1px);
 }
 
 #main-window:not([customizing]) .subviewbutton-nav[disabled=true]::after {
   opacity: 0.4;
 }
 
@@ -887,20 +888,20 @@ panelview .toolbarbutton-1,
 }
 
 .subviewbutton[type="highlight-history"]::after {
   content: url("chrome://browser/skin/history.svg");
 }
 
 .subviewbutton[type="highlight-bookmark"]::after,
 .subviewbutton[type="highlight-history"]::after {
-  -moz-context-properties: fill;
-  fill: GrayText;
+  -moz-context-properties: fill, fill-opacity;
+  fill: currentColor;
+  fill-opacity: 0.4;
   float: right;
-  opacity: .5;
   /* Centers the icon and resizes it to 12px square. */
   transform: translateY(2px) scaleX(.75);
 }
 
 /* This is a <label> but it should fit in with the menu font- and colorwise. */
 #PanelUI-characterEncodingView-autodetect-label {
   font: menu;
   color: inherit;
@@ -1257,25 +1258,26 @@ toolbaritem[overflowedItem=true],
 }
 
 .widget-overflow-list .toolbarbutton-1 {
   -moz-box-align: center;
   -moz-box-orient: horizontal;
 }
 
 .widget-overflow-list .subviewbutton-nav:-moz-locale-dir(ltr)::after {
-    transform: scaleX(-1);
+  transform: scaleX(-1);
 }
 
 .widget-overflow-list .subviewbutton-nav::after {
-    margin-inline-start: 10px;
-    -moz-context-properties: fill;
-    content: url(chrome://browser/skin/back-12.svg);
-    fill: GrayText;
-    float: right;
+  margin-inline-start: 10px;
+  -moz-context-properties: fill, fill-opacity;
+  content: url(chrome://browser/skin/back-12.svg);
+  fill: currentColor;
+  fill-opacity: 0.6;
+  float: right;
 }
 
 toolbarpaletteitem[place="menu-panel"] > .subviewbutton-nav::after {
   opacity: 0.5;
 }
 
 .widget-overflow-list .toolbarbutton-1:not(.toolbarbutton-combined) > .toolbarbutton-text {
   text-align: start;
@@ -1537,35 +1539,36 @@ menuitem[checked="true"].subviewbutton >
 
 .subviewbutton.download > .toolbarbutton-text > .status-text {
   color: GrayText;
   font-size: .9em;
 }
 
 .subviewbutton.download > .action-button {
   -moz-appearance: none; /* To avoid native Windows hover styling */
-  -moz-context-properties: fill;
+  -moz-context-properties: fill, fill-opacity;
   fill: currentColor;
+  fill-opacity: 1;
 %ifdef XP_MACOSX
   list-style-image: url("chrome://browser/skin/search-glass.svg");
 %else
   list-style-image: url("chrome://browser/skin/folder.svg");
 %endif
   /* Measurement to vertically center this button: 1 line of text minus half of 4px top margin. */
   margin: calc(1em - 2px) 0 0;
   padding: 4px;
 }
 
 .subviewbutton.download[retryLabel] > .action-button {
   list-style-image: url("chrome://browser/skin/reload.svg");
 }
 
 .subviewbutton.download:not([openLabel]):not([retryLabel]) > .action-button {
-  fill: GrayText;
-  opacity: .5;
+  fill: currentColor;
+  fill-opacity: 0.4;
 }
 
 .subviewbutton.download:-moz-any([openLabel],[retryLabel]) > .action-button@buttonStateHover@ {
   background-color: var(--arrowpanel-dimmed-further);
 }
 
 .subviewbutton.download:-moz-any([openLabel],[retryLabel]) > .action-button@buttonStateActive@ {
   background-color: var(--arrowpanel-dimmed-even-further);
--- a/browser/themes/shared/notification-icons.inc.css
+++ b/browser/themes/shared/notification-icons.inc.css
@@ -1,18 +1,19 @@
 %if 0
 /* 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/. */
 %endif
 
 .popup-notification-icon,
 .identity-popup-permission-icon {
-  -moz-context-properties: fill;
-  fill: GrayText;
+  -moz-context-properties: fill, fill-opacity;
+  fill: currentColor;
+  fill-opacity: 0.6;
 }
 
 #notification-popup-box {
   padding: 5px 0px;
   margin: -5px 0px;
   margin-inline-end: -5px;
   padding-inline-end: 5px;
 }
--- a/browser/themes/windows/browser-aero.css
+++ b/browser/themes/windows/browser-aero.css
@@ -35,24 +35,28 @@
 
         :root:not(:-moz-lwtheme) {
           background-color: hsl(0, 0%, 78%);
         }
 
         @media (-moz-windows-accent-color-in-titlebar: 0) {
           :root[tabsintitlebar]:not(:-moz-lwtheme) {
             background-color: hsl(235,33%,19%);
-            --titlebar-text-color: hsl(240,9%,98%);
+          }
+          :root[tabsintitlebar] .titlebar-color:not(:-moz-lwtheme) {
+            color: hsl(240,9%,98%);
           }
         }
 
         @media (-moz-windows-accent-color-in-titlebar) {
           :root[tabsintitlebar]:not(:-moz-window-inactive):not(:-moz-lwtheme) {
             background-color: -moz-win-accentcolor;
-            --titlebar-text-color: -moz-win-accentcolortext;
+          }
+          :root[tabsintitlebar] .titlebar-color:not(:-moz-window-inactive):not(:-moz-lwtheme) {
+            color: -moz-win-accentcolortext;
           }
         }
 
         :root[tabsintitlebar] .tab-label:-moz-window-inactive {
           /* Calculated to match the opacity change of Windows Explorer
              titlebar text change for inactive windows. */
           opacity: .6;
         }
@@ -77,17 +81,17 @@
         -moz-appearance: none !important;
       }
 
       .titlebar-button {
         border: none;
         margin: 0 !important;
         padding: 8px 17px;
         -moz-context-properties: stroke;
-        stroke: var(--titlebar-text-color);
+        stroke: currentColor;
       }
 
       .titlebar-button > .toolbarbutton-icon {
         width: 12px;
         height: 12px;
       }
 
       #titlebar-min {
@@ -274,18 +278,18 @@
      */
     @media not all and (-moz-os-version: windows-win7) {
       #toolbar-menubar:not(:-moz-lwtheme):-moz-window-inactive {
         color: ThreeDShadow;
       }
     }
   }
 
-  :root[darkwindowframe="true"]:not(:-moz-lwtheme):not(:-moz-window-inactive) {
-    --titlebar-text-color: white;
+  :root[darkwindowframe="true"] .titlebar-color:not(:-moz-window-inactive):not(:-moz-lwtheme) {
+    color: white;
   }
 
   /* Show borders on Win 7 & 8, but not on 10 and later: */
   @media (-moz-os-version: windows-win7),
          (-moz-os-version: windows-win8) {
     /* Vertical toolbar border */
     #main-window[sizemode=normal] #navigator-toolbox > toolbar:not(#toolbar-menubar):not(#TabsToolbar):not(:-moz-lwtheme),
     #main-window[sizemode=normal] #navigator-toolbox > toolbar:-moz-lwtheme {
--- a/browser/themes/windows/browser.css
+++ b/browser/themes/windows/browser.css
@@ -7,18 +7,16 @@
 @namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
 @namespace html url("http://www.w3.org/1999/xhtml");
 
 %include ../shared/browser.inc.css
 %filter substitution
 %define glassShadowColor hsla(240,5%,5%,0.3)
 
 :root {
-  --titlebar-text-color: currentColor;
-
   --toolbar-non-lwt-bgcolor: -moz-dialog;
   --toolbar-non-lwt-textcolor: -moz-dialogtext;
   --toolbar-non-lwt-bgimage: linear-gradient(rgba(255,255,255,.15), rgba(255,255,255,.15));
   --toolbar-bgcolor: var(--toolbar-non-lwt-bgcolor);
   --toolbar-bgimage: var(--toolbar-non-lwt-bgimage);
 
   --toolbarbutton-vertical-text-padding: calc(var(--toolbarbutton-inner-padding) - 1px);
   --toolbarbutton-border-radius: 2px;
@@ -109,21 +107,16 @@
 
 #navigator-toolbox > toolbar:not(#toolbar-menubar):not(#TabsToolbar) {
   background-color: var(--toolbar-bgcolor);
   background-image: var(--toolbar-bgimage);
   background-clip: padding-box;
   color: var(--toolbar-color, inherit);
 }
 
-#toolbar-menubar,
-#TabsToolbar {
-  color: var(--titlebar-text-color);
-}
-
 /*
  * Windows 7 draws the chrome background color as the tab background
  * instead of in the tabs toolbar.
  */
 @media (-moz-os-version: windows-win7) {
   @media (-moz-windows-default-theme) {
     #navigator-toolbox:not(:-moz-lwtheme) {
       --tabs-border-color: @glassShadowColor@;
@@ -165,22 +158,22 @@
   }
 }
 
 @media (-moz-windows-compositor: 0),
        (-moz-windows-default-theme: 0) {
   /* Please keep the menu text colors in this media block in sync with
    * compacttheme.css, minus the :not(:-moz-lwtheme) condition - see Bug 1165718.
    */
-  :root[tabsintitlebar]:not([inFullscreen]):not(:-moz-lwtheme) {
-    --titlebar-text-color: CaptionText;
+  :root[tabsintitlebar]:not([inFullscreen]) .titlebar-color:not(:-moz-lwtheme) {
+    color: CaptionText;
   }
 
-  :root[tabsintitlebar]:not([inFullscreen]):not(:-moz-lwtheme):-moz-window-inactive {
-    --titlebar-text-color: InactiveCaptionText;
+  :root[tabsintitlebar]:not([inFullscreen]) .titlebar-color:not(:-moz-lwtheme):-moz-window-inactive {
+    color: InactiveCaptionText;
   }
 }
 
 @media (-moz-windows-compositor: 0) {
   #main-window[tabsintitlebar] #titlebar:-moz-lwtheme {
     visibility: hidden;
   }
 
--- a/browser/themes/windows/compacttheme.css
+++ b/browser/themes/windows/compacttheme.css
@@ -122,22 +122,22 @@
   #TabsToolbar,
   #navigator-toolbox {
     background-color: transparent;
   }
 
   /* Use proper menu text styling in Win7 classic mode (copied from browser.css) */
   @media (-moz-windows-compositor: 0),
          (-moz-windows-default-theme: 0) {
-    :root[tabsintitlebar]:not([inFullscreen]) {
-      --titlebar-text-color: CaptionText;
+    :root[tabsintitlebar]:not([inFullscreen]) .titlebar-color {
+      color: CaptionText;
     }
 
-    :root[tabsintitlebar]:not([inFullscreen]):-moz-window-inactive {
-      --titlebar-text-color: InactiveCaptionText;
+    :root[tabsintitlebar]:not([inFullscreen]) .titlebar-color:-moz-window-inactive {
+      color: InactiveCaptionText;
     }
 
     #main-window[tabsintitlebar] #main-menubar > menu {
       color: inherit;
     }
   }
 }
 
--- a/browser/themes/windows/customizableui/menu-arrow.svg
+++ b/browser/themes/windows/customizableui/menu-arrow.svg
@@ -1,7 +1,6 @@
 <!-- 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/. -->
-<svg xmlns="http://www.w3.org/2000/svg"
-     height="16" width="16" viewBox="0 0 16 16">
-  <path fill="context-fill" d="m 6,4 0,8 5,-4 z"/>
+<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16" viewBox="0 0 16 16">
+  <path fill="context-fill" fill-opacity="context-fill-opacity" d="m 6,4 0,8 5,-4 z"/>
 </svg>
--- a/browser/themes/windows/customizableui/panelUI.css
+++ b/browser/themes/windows/customizableui/panelUI.css
@@ -43,30 +43,24 @@ menuitem[type="checkbox"].subviewbutton 
   /* This is 16px for an icon + 3px for its margins + 1px for its padding +
    * 2px for its border, see above */
   min-height: 22px;
 }
 
 menu.subviewbutton > .menu-right {
   -moz-appearance: none;
   list-style-image: url(chrome://browser/skin/customizableui/menu-arrow.svg);
-  -moz-context-properties: fill;
-  fill: MenuText;
+  -moz-context-properties: fill, fill-opacity;
+  fill: currentColor;
   /* Reset the rect we inherit from the button: */
   -moz-image-region: auto;
 }
 
 menu[disabled="true"].subviewbutton > .menu-right {
-  fill: GrayText;
-}
-
-@media (-moz-windows-default-theme: 0) {
-  menu[_moz-menuactive].subviewbutton > .menu-right {
-    fill: HighlightText;
-  }
+  fill-opacity: 0.6;
 }
 
 menu.subviewbutton > .menu-right:-moz-locale-dir(rtl) {
   transform: scaleX(-1);
 }
 
 /* Win8 and beyond. */
 @media not all and (-moz-os-version: windows-win7) {
--- a/devtools/client/aboutdebugging/components/addons/Target.js
+++ b/devtools/client/aboutdebugging/components/addons/Target.js
@@ -188,27 +188,28 @@ class AddonTarget extends Component {
     }
   }
 
   uninstall() {
     let { target } = this.props;
     uninstallAddon(target.addonID);
   }
 
-  reload() {
+  async reload() {
     let { client, target } = this.props;
-    // This function sometimes returns a partial promise that only
-    // implements then().
-    client.request({
-      to: target.addonActor,
-      type: "reload"
-    }).then(() => {}, error => {
-      throw new Error(
-        "Error reloading addon " + target.addonID + ": " + error);
-    });
+    let { AboutDebugging } = window;
+    try {
+      await client.request({
+        to: target.addonActor,
+        type: "reload"
+      });
+      AboutDebugging.emit("addon-reload");
+    } catch (e) {
+      throw new Error("Error reloading addon " + target.addonID + ": " + e.message);
+    }
   }
 
   render() {
     let { target, debugDisabled } = this.props;
 
     return dom.li(
       { className: "addon-target-container", "data-addon-id": target.addonID },
       dom.div({ className: "target" },
--- a/devtools/client/aboutdebugging/initializer.js
+++ b/devtools/client/aboutdebugging/initializer.js
@@ -19,16 +19,17 @@ loader.lazyRequireGetter(this, "Telemetr
 
 const { require } = BrowserLoader({
   baseURI: "resource://devtools/client/aboutdebugging/",
   window
 });
 
 const { createFactory } = require("devtools/client/shared/vendor/react");
 const { render, unmountComponentAtNode } = require("devtools/client/shared/vendor/react-dom");
+const EventEmitter = require("devtools/shared/event-emitter");
 
 const AboutDebuggingApp = createFactory(require("./components/Aboutdebugging"));
 const { createClient } = require("./modules/connect");
 
 var AboutDebugging = {
   async init() {
     if (!Services.prefs.getBoolPref("devtools.enabled", true)) {
       // If DevTools are disabled, navigate to about:devtools.
@@ -52,15 +53,18 @@ var AboutDebugging = {
 
     if (this.client) {
       this.client.close();
       this.client = null;
     }
   },
 };
 
+// Used to track async requests in tests.  See bug 1444424 for better ideas.
+EventEmitter.decorate(AboutDebugging);
+
 window.addEventListener("DOMContentLoaded", function () {
   AboutDebugging.init();
 }, {once: true});
 
 window.addEventListener("unload", function () {
   AboutDebugging.destroy();
 }, {once: true});
--- a/devtools/client/aboutdebugging/test/browser.ini
+++ b/devtools/client/aboutdebugging/test/browser.ini
@@ -26,17 +26,17 @@ skip-if = coverage # Bug 1387827
 [browser_addons_debug_info.js]
 [browser_addons_debug_webextension.js]
 tags = webextensions
 [browser_addons_debug_webextension_inspector.js]
 tags = webextensions
 [browser_addons_debug_webextension_nobg.js]
 tags = webextensions
 [browser_addons_debug_webextension_popup.js]
-skip-if = coverage # Bug 1387827
+skip-if = coverage || (verify && debug) # coverage: Bug 1387827, verify: crashes on shutdown
 tags = webextensions
 [browser_addons_debugging_initial_state.js]
 [browser_addons_install.js]
 [browser_addons_reload.js]
 [browser_addons_remove.js]
 [browser_addons_toggle_debug.js]
 [browser_page_not_found.js]
 [browser_service_workers.js]
--- a/devtools/client/aboutdebugging/test/browser_addons_debug_bootstrapped.js
+++ b/devtools/client/aboutdebugging/test/browser_addons_debug_bootstrapped.js
@@ -1,12 +1,17 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 "use strict";
 
+// There are shutdown issues for which multiple rejections are left uncaught.
+// See bug 1018184 for resolving these issues.
+const { PromiseTestUtils } = scopedCuImport("resource://testing-common/PromiseTestUtils.jsm");
+PromiseTestUtils.whitelistRejectionsGlobally(/File closed/);
+
 // Avoid test timeouts that can occur while waiting for the "addon-console-works" message.
 requestLongerTimeout(2);
 
 const ADDON_ID = "test-devtools@mozilla.org";
 const ADDON_NAME = "test-devtools";
 
 const { BrowserToolboxProcess } = ChromeUtils.import("resource://devtools/client/framework/ToolboxProcess.jsm", {});
 
--- a/devtools/client/aboutdebugging/test/browser_addons_debug_webextension.js
+++ b/devtools/client/aboutdebugging/test/browser_addons_debug_webextension.js
@@ -1,13 +1,18 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 /* eslint-disable mozilla/no-arbitrary-setTimeout */
 "use strict";
 
+// There are shutdown issues for which multiple rejections are left uncaught.
+// See bug 1018184 for resolving these issues.
+const { PromiseTestUtils } = scopedCuImport("resource://testing-common/PromiseTestUtils.jsm");
+PromiseTestUtils.whitelistRejectionsGlobally(/File closed/);
+
 // Avoid test timeouts that can occur while waiting for the "addon-console-works" message.
 requestLongerTimeout(2);
 
 const ADDON_ID = "test-devtools-webextension@mozilla.org";
 const ADDON_NAME = "test-devtools-webextension";
 const ADDON_MANIFEST_PATH = "addons/test-devtools-webextension/manifest.json";
 
 const {
--- a/devtools/client/aboutdebugging/test/browser_addons_debug_webextension_inspector.js
+++ b/devtools/client/aboutdebugging/test/browser_addons_debug_webextension_inspector.js
@@ -1,12 +1,17 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 "use strict";
 
+// There are shutdown issues for which multiple rejections are left uncaught.
+// See bug 1018184 for resolving these issues.
+const { PromiseTestUtils } = scopedCuImport("resource://testing-common/PromiseTestUtils.jsm");
+PromiseTestUtils.whitelistRejectionsGlobally(/File closed/);
+
 // Avoid test timeouts that can occur while waiting for the "addon-console-works" message.
 requestLongerTimeout(2);
 
 const ADDON_ID = "test-devtools-webextension@mozilla.org";
 const ADDON_NAME = "test-devtools-webextension";
 const ADDON_PATH = "addons/test-devtools-webextension/manifest.json";
 
 const {
--- a/devtools/client/aboutdebugging/test/browser_addons_debug_webextension_nobg.js
+++ b/devtools/client/aboutdebugging/test/browser_addons_debug_webextension_nobg.js
@@ -1,12 +1,17 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 "use strict";
 
+// There are shutdown issues for which multiple rejections are left uncaught.
+// See bug 1018184 for resolving these issues.
+const { PromiseTestUtils } = scopedCuImport("resource://testing-common/PromiseTestUtils.jsm");
+PromiseTestUtils.whitelistRejectionsGlobally(/File closed/);
+
 // Avoid test timeouts that can occur while waiting for the "addon-console-works" message.
 requestLongerTimeout(2);
 
 const ADDON_NOBG_ID = "test-devtools-webextension-nobg@mozilla.org";
 const ADDON_NOBG_NAME = "test-devtools-webextension-nobg";
 const ADDON_NOBG_PATH = "addons/test-devtools-webextension-nobg/manifest.json";
 
 const {
--- a/devtools/client/aboutdebugging/test/browser_addons_debug_webextension_popup.js
+++ b/devtools/client/aboutdebugging/test/browser_addons_debug_webextension_popup.js
@@ -1,12 +1,17 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 "use strict";
 
+// There are shutdown issues for which multiple rejections are left uncaught.
+// See bug 1018184 for resolving these issues.
+const { PromiseTestUtils } = scopedCuImport("resource://testing-common/PromiseTestUtils.jsm");
+PromiseTestUtils.whitelistRejectionsGlobally(/File closed/);
+
 // Avoid test timeouts that can occur while waiting for the "addon-console-works" message.
 requestLongerTimeout(2);
 
 const ADDON_ID = "test-devtools-webextension@mozilla.org";
 const ADDON_NAME = "test-devtools-webextension";
 const ADDON_MANIFEST_PATH = "addons/test-devtools-webextension/manifest.json";
 
 const {
--- a/devtools/client/aboutdebugging/test/browser_addons_reload.js
+++ b/devtools/client/aboutdebugging/test/browser_addons_reload.js
@@ -56,17 +56,18 @@ class TempWebExt {
   }
 
   remove() {
     return this.tmpDir.remove(true);
   }
 }
 
 add_task(function* reloadButtonReloadsAddon() {
-  const { tab, document } = yield openAboutDebugging("addons");
+  const { tab, document, window } = yield openAboutDebugging("addons");
+  const { AboutDebugging } = window;
   yield waitForInitialAddonList(document);
   yield installAddon({
     document,
     path: "addons/unpacked/install.rdf",
     name: ADDON_NAME,
   });
 
   const reloadButton = getReloadButton(document, ADDON_NAME);
@@ -76,29 +77,32 @@ add_task(function* reloadButtonReloadsAd
   const onBootstrapInstallCalled = new Promise(done => {
     Services.obs.addObserver(function listener() {
       Services.obs.removeObserver(listener, ADDON_NAME);
       info("Add-on was re-installed: " + ADDON_NAME);
       done();
     }, ADDON_NAME);
   });
 
+  let reloaded = once(AboutDebugging, "addon-reload");
   reloadButton.click();
+  yield reloaded;
 
   const [reloadedAddon] = yield onInstalled;
   is(reloadedAddon.name, ADDON_NAME,
      "Add-on was reloaded: " + reloadedAddon.name);
 
   yield onBootstrapInstallCalled;
   yield tearDownAddon(reloadedAddon);
   yield closeAboutDebugging(tab);
 });
 
 add_task(function* reloadButtonRefreshesMetadata() {
-  const { tab, document } = yield openAboutDebugging("addons");
+  const { tab, document, window } = yield openAboutDebugging("addons");
+  const { AboutDebugging } = window;
   yield waitForInitialAddonList(document);
 
   const manifestBase = {
     "manifest_version": 2,
     "name": "Temporary web extension",
     "version": "1.0",
     "applications": {
       "gecko": {
@@ -120,17 +124,19 @@ add_task(function* reloadButtonRefreshes
   yield waitUntilAddonContainer("Temporary web extension", document);
 
   const newName = "Temporary web extension (updated)";
   tempExt.writeManifest(Object.assign({}, manifestBase, {name: newName}));
 
   // Wait for the add-on list to be updated with the reloaded name.
   const onReInstall = promiseAddonEvent("onInstalled");
   const reloadButton = getReloadButton(document, manifestBase.name);
+  let reloaded = once(AboutDebugging, "addon-reload");
   reloadButton.click();
+  yield reloaded;
 
   info("Wait until addon onInstalled event is received again");
   const [reloadedAddon] = yield onReInstall;
 
   info("Wait until addon name is updated in about:debugging#addons");
   yield waitUntilAddonContainer(newName, document);
 
   yield tearDownAddon(reloadedAddon);
--- a/devtools/client/debugger/new/test/mochitest/browser_dbg-chrome-create.js
+++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-chrome-create.js
@@ -2,16 +2,22 @@
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 /**
  * Tests that a chrome debugger can be created in a new process.
  */
 
+// There are shutdown issues for which multiple rejections are left uncaught.
+// See bug 1018184 for resolving these issues.
+const { PromiseTestUtils } = scopedCuImport("resource://testing-common/PromiseTestUtils.jsm");
+PromiseTestUtils.whitelistRejectionsGlobally(/File closed/);
+PromiseTestUtils.whitelistRejectionsGlobally(/NS_ERROR_FAILURE/);
+
 const { BrowserToolboxProcess } = ChromeUtils.import(
   "resource://devtools/client/framework/ToolboxProcess.jsm",
   {}
 );
 let gProcess = undefined;
 
 function initChromeDebugger() {
   info("Initializing a chrome debugger process.");
--- a/devtools/client/debugger/test/mochitest/browser.ini
+++ b/devtools/client/debugger/test/mochitest/browser.ini
@@ -200,17 +200,17 @@ skip-if = e10s && debug
 skip-if = e10s && debug
 [browser_dbg_breakpoints-pane.js]
 skip-if = e10s && debug
 [browser_dbg_breakpoints-reload.js]
 skip-if = e10s && debug
 [browser_dbg_bug-896139.js]
 skip-if = e10s && debug
 [browser_dbg_chrome-create.js]
-skip-if = e10s && debug
+skip-if = (e10s && debug) || (verify && os == "linux") # Exit code mismatch with verify
 [browser_dbg_chrome-debugging.js]
 skip-if = e10s && debug
 [browser_dbg_clean-exit-window.js]
 skip-if = true # Bug 933950 (leaky test)
 [browser_dbg_clean-exit.js]
 skip-if = true # Bug 1044985 (racy test)
 [browser_dbg_closure-inspection.js]
 skip-if = e10s && debug
--- a/devtools/client/debugger/test/mochitest/browser_dbg_chrome-create.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_chrome-create.js
@@ -2,16 +2,22 @@
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 /**
  * Tests that a chrome debugger can be created in a new process.
  */
 
+// There are shutdown issues for which multiple rejections are left uncaught.
+// See bug 1018184 for resolving these issues.
+const { PromiseTestUtils } = scopedCuImport("resource://testing-common/PromiseTestUtils.jsm");
+PromiseTestUtils.whitelistRejectionsGlobally(/File closed/);
+PromiseTestUtils.whitelistRejectionsGlobally(/NS_ERROR_FAILURE/);
+
 var gProcess;
 
 function test() {
   // Windows XP and 8.1 test slaves are terribly slow at this test.
   requestLongerTimeout(5);
   Services.prefs.setBoolPref("devtools.chrome.enabled", true);
   Services.prefs.setBoolPref("devtools.debugger.remote-enabled", true);
 
--- a/devtools/client/debugger/test/mochitest/browser_dbg_worker-console-04.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_worker-console-04.js
@@ -1,19 +1,16 @@
 // Check that the date and regexp previewers work in the console of a worker debugger.
 
 "use strict";
 
-// The following intermittent rejection should not be left uncaught. This test
-// has been whitelisted until the issue is fixed.
-//
-// NOTE: Whitelisting a class of rejections should be limited. Normally you
-//       should use "expectUncaughtRejection" to flag individual failures.
-ChromeUtils.import("resource://testing-common/PromiseTestUtils.jsm", this);
-PromiseTestUtils.whitelistRejectionsGlobally(/[object Object]/);
+// There are shutdown issues for which multiple rejections are left uncaught.
+// See bug 1018184 for resolving these issues.
+const { PromiseTestUtils } = scopedCuImport("resource://testing-common/PromiseTestUtils.jsm");
+PromiseTestUtils.whitelistRejectionsGlobally(/connection just closed/);
 
 const TAB_URL = EXAMPLE_URL + "doc_WorkerActor.attachThread-tab.html";
 const WORKER_URL = "code_WorkerActor.attachThread-worker.js";
 
 add_task(function* testPausedByConsole() {
   let {client, tab, workerClient, toolbox} =
     yield initWorkerDebugger(TAB_URL, WORKER_URL);
 
--- a/devtools/client/framework/ToolboxProcess.jsm
+++ b/devtools/client/framework/ToolboxProcess.jsm
@@ -341,31 +341,33 @@ BrowserToolboxProcess.prototype = {
   /**
    * Closes the remote debugging server and kills the toolbox process.
    */
   close: async function () {
     if (this.closed) {
       return;
     }
 
+    this.closed = true;
+
     dumpn("Cleaning up the chrome debugging process.");
+
     Services.obs.removeObserver(this.close, "quit-application");
 
     this._dbgProcess.stdout.close();
     await this._dbgProcess.kill();
 
     this._telemetry.toolClosed("jsbrowserdebugger");
     if (this.debuggerServer) {
       this.debuggerServer.off("connectionchange", this._onConnectionChange);
       this.debuggerServer.destroy();
       this.debuggerServer = null;
     }
 
     dumpn("Chrome toolbox is now closed...");
-    this.closed = true;
     this.emit("close", this);
     processes.delete(this);
 
     this._dbgProcess = null;
     this._options = null;
     if (this.loader) {
       this.loader.destroy();
     }
--- a/devtools/client/framework/test/browser_browser_toolbox.js
+++ b/devtools/client/framework/test/browser_browser_toolbox.js
@@ -1,12 +1,17 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
+// There are shutdown issues for which multiple rejections are left uncaught.
+// See bug 1018184 for resolving these issues.
+const { PromiseTestUtils } = scopedCuImport("resource://testing-common/PromiseTestUtils.jsm");
+PromiseTestUtils.whitelistRejectionsGlobally(/File closed/);
+
 // On debug test slave, it takes about 50s to run the test.
 requestLongerTimeout(4);
 
 add_task(async function() {
   await new Promise(done => {
     let options = {"set": [
       ["devtools.debugger.prompt-connection", false],
       ["devtools.debugger.remote-enabled", true],
--- a/devtools/client/framework/test/browser_browser_toolbox_debugger.js
+++ b/devtools/client/framework/test/browser_browser_toolbox_debugger.js
@@ -2,16 +2,21 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // This test asserts that the new debugger works from the browser toolbox process
 // Its pass a big piece of Javascript string to the browser toolbox process via
 // MOZ_TOOLBOX_TEST_SCRIPT env variable. It does that as test resources fetched from
 // chrome://mochitests/ package isn't available from browser toolbox process.
 
+// There are shutdown issues for which multiple rejections are left uncaught.
+// See bug 1018184 for resolving these issues.
+const { PromiseTestUtils } = scopedCuImport("resource://testing-common/PromiseTestUtils.jsm");
+PromiseTestUtils.whitelistRejectionsGlobally(/File closed/);
+
 // On debug test runner, it takes about 50s to run the test.
 requestLongerTimeout(4);
 
 const { fetch } = require("devtools/shared/DevToolsUtils");
 
 const debuggerHeadURL = CHROME_URL_ROOT + "../../debugger/new/test/mochitest/head.js";
 const testScriptURL = CHROME_URL_ROOT + "test_browser_toolbox_debugger.js";
 
--- a/devtools/client/framework/test/browser_source_map-01.js
+++ b/devtools/client/framework/test/browser_source_map-01.js
@@ -4,16 +4,22 @@
 "use strict";
 
 /**
  * Tests the SourceMapService updates generated sources when source maps
  * are subsequently found. Also checks when no column is provided, and
  * when tagging an already source mapped location initially.
  */
 
+// There are shutdown issues for which multiple rejections are left uncaught.
+// See bug 1018184 for resolving these issues.
+const { PromiseTestUtils } = scopedCuImport("resource://testing-common/PromiseTestUtils.jsm");
+PromiseTestUtils.whitelistRejectionsGlobally(/this\.worker is null/);
+PromiseTestUtils.whitelistRejectionsGlobally(/Component not initialized/);
+
 // Empty page
 const PAGE_URL = `${URL_ROOT}doc_empty-tab-01.html`;
 const JS_URL = `${URL_ROOT}code_binary_search.js`;
 const COFFEE_URL = `${URL_ROOT}code_binary_search.coffee`;
 
 add_task(function* () {
   yield pushPref("devtools.debugger.new-debugger-frontend", true);
 
--- a/devtools/client/framework/test/browser_source_map-absolute.js
+++ b/devtools/client/framework/test/browser_source_map-absolute.js
@@ -1,15 +1,20 @@
 /* Any copyright is dedicated to the Public Domain.
  http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Test that an absolute sourceRoot works.
 
 "use strict";
 
+// There are shutdown issues for which multiple rejections are left uncaught.
+// See bug 1018184 for resolving these issues.
+const { PromiseTestUtils } = scopedCuImport("resource://testing-common/PromiseTestUtils.jsm");
+PromiseTestUtils.whitelistRejectionsGlobally(/this\.worker is null/);
+
 // Empty page
 const PAGE_URL = `${URL_ROOT}doc_empty-tab-01.html`;
 const JS_URL = `${URL_ROOT}code_binary_search_absolute.js`;
 const ORIGINAL_URL = `${URL_ROOT}code_binary_search.coffee`;
 
 add_task(function* () {
   yield pushPref("devtools.debugger.new-debugger-frontend", true);
 
--- a/devtools/client/framework/test/browser_source_map-inline.js
+++ b/devtools/client/framework/test/browser_source_map-inline.js
@@ -1,15 +1,21 @@
 /* Any copyright is dedicated to the Public Domain.
  http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Test that inline source maps work.
 
 "use strict";
 
+// There are shutdown issues for which multiple rejections are left uncaught.
+// See bug 1018184 for resolving these issues.
+const { PromiseTestUtils } = scopedCuImport("resource://testing-common/PromiseTestUtils.jsm");
+PromiseTestUtils.whitelistRejectionsGlobally(/this\.worker is null/);
+PromiseTestUtils.whitelistRejectionsGlobally(/Component not initialized/);
+
 const TEST_ROOT = "http://example.com/browser/devtools/client/framework/test/";
 // Empty page
 const PAGE_URL = `${TEST_ROOT}doc_empty-tab-01.html`;
 const JS_URL = `${TEST_ROOT}code_inline_bundle.js`;
 const ORIGINAL_URL = "webpack:///code_inline_original.js";
 
 add_task(function* () {
   yield pushPref("devtools.debugger.new-debugger-frontend", true);
--- a/devtools/client/inspector/boxmodel/test/browser_boxmodel_computed-accordion-state.js
+++ b/devtools/client/inspector/boxmodel/test/browser_boxmodel_computed-accordion-state.js
@@ -1,16 +1,21 @@
 /* Any copyright is dedicated to the Public Domain.
  http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 // Tests that the box model's accordion state is persistent through hide/show in the
 // computed view.
 
+// There are shutdown issues for which multiple rejections are left uncaught.
+// See bug 1018184 for resolving these issues.
+const { PromiseTestUtils } = scopedCuImport("resource://testing-common/PromiseTestUtils.jsm");
+PromiseTestUtils.whitelistRejectionsGlobally(/Connection closed/);
+
 const TEST_URI = `
   <style>
     #div1 {
       margin: 10px;
       padding: 3px;
     }
   </style>
   <div id="div1"></div>
--- a/devtools/client/inspector/markup/test/browser_markup_accessibility_semantics.js
+++ b/devtools/client/inspector/markup/test/browser_markup_accessibility_semantics.js
@@ -66,35 +66,33 @@ add_task(function* () {
   ok(!spanContainer.tagLine.hasAttribute("aria-expanded"),
     "Non expandable tree items should not have aria-expanded attribute");
   ok(!headerContainer.tagLine.hasAttribute("aria-expanded"),
     "Non expandable tree items should not have aria-expanded attribute");
   is(listContainer.tagLine.getAttribute("aria-expanded"), "false",
     "Closed tree item should have aria-expanded unset");
 
   info("Selecting and expanding list container");
-  let updated = waitForMultipleChildrenUpdates(inspector);
   yield selectNode("ul", inspector);
   EventUtils.synthesizeKey("VK_RIGHT", {}, win);
-  yield updated;
+  yield waitForMultipleChildrenUpdates(inspector);
 
   is(rootElt.getAttribute("aria-activedescendant"),
     listContainer.tagLine.getAttribute("id"),
     "Active descendant should not be set to list container tagLine");
   is(listContainer.tagLine.getAttribute("aria-expanded"), "true",
     "Open tree item should have aria-expanded set");
   let listItemContainer = yield getContainerForSelector("li", inspector);
   is(listItemContainer.tagLine.getAttribute("aria-level"),
     TOP_CONTAINER_LEVEL + 1,
     "Grand child container tagLine should have nested level up to date");
   is(listItemContainer.children.getAttribute("role"), "presentation",
     "Container with no children should have its children element ignored by " +
     "accessibility");
 
   info("Collapsing list container");
-  updated = waitForMultipleChildrenUpdates(inspector);
   EventUtils.synthesizeKey("VK_LEFT", {}, win);
-  yield updated;
+  yield waitForMultipleChildrenUpdates(inspector);
 
   is(listContainer.tagLine.getAttribute("aria-expanded"), "false",
     "Closed tree item should have aria-expanded unset");
 });
 
--- a/devtools/client/inspector/markup/test/browser_markup_load_01.js
+++ b/devtools/client/inspector/markup/test/browser_markup_load_01.js
@@ -44,26 +44,25 @@ add_task(function* () {
   // Select an element while the tab is in the middle of a slow reload.
   testActor.eval("location.reload()");
 
   info("Wait for DOMContentLoaded");
   yield domContentLoaded;
 
   info("Inspect element via context menu");
   let markupLoaded = inspector.once("markuploaded");
-  let multipleChildrenUpdates = waitForMultipleChildrenUpdates(inspector);
   yield chooseWithInspectElementContextMenu("img", tab);
 
   info("Wait for load");
   yield pageLoaded;
 
   info("Wait for markup-loaded after element inspection");
   yield markupLoaded;
   info("Wait for multiple children updates after element inspection");
-  yield multipleChildrenUpdates;
+  yield waitForMultipleChildrenUpdates(inspector);
 
   ok(inspector.markup, "There is a markup view");
   is(inspector.markup._elt.children.length, 1, "The markup view is rendering");
 });
 
 function* chooseWithInspectElementContextMenu(selector, tab) {
   yield BrowserTestUtils.synthesizeMouseAtCenter(selector, {
     type: "contextmenu",
--- a/devtools/client/inspector/test/browser_inspector_breadcrumbs_visibility.js
+++ b/devtools/client/inspector/test/browser_inspector_breadcrumbs_visibility.js
@@ -1,16 +1,21 @@
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 "use strict";
 
 // Test that the start and end buttons on the breadcrumb trail bring the right
 // crumbs into the visible area, for both LTR and RTL
 
+// There are shutdown issues for which multiple rejections are left uncaught.
+// See bug 1018184 for resolving these issues.
+const { PromiseTestUtils } = scopedCuImport("resource://testing-common/PromiseTestUtils.jsm");
+PromiseTestUtils.whitelistRejectionsGlobally(/Connection closed/);
+
 let { Toolbox } = require("devtools/client/framework/toolbox");
 
 const TEST_URI = URL_ROOT + "doc_inspector_breadcrumbs_visibility.html";
 const NODE_ONE = "div#aVeryLongIdToExceedTheBreadcrumbTruncationLimit";
 const NODE_TWO = "div#anotherVeryLongIdToExceedTheBreadcrumbTruncationLimit";
 const NODE_THREE = "div#aThirdVeryLongIdToExceedTheTruncationLimit";
 const NODE_FOUR = "div#aFourthOneToExceedTheTruncationLimit";
 const NODE_FIVE = "div#aFifthOneToExceedTheTruncationLimit";
--- a/devtools/client/inspector/test/browser_inspector_textbox-menu.js
+++ b/devtools/client/inspector/test/browser_inspector_textbox-menu.js
@@ -1,16 +1,21 @@
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 "use strict";
 
 // Test that when right-clicking on various text boxes throughout the inspector does use
 // the toolbox's context menu (copy/cut/paste/selectAll/Undo).
 
+// There are shutdown issues for which multiple rejections are left uncaught.
+// See bug 1018184 for resolving these issues.
+const { PromiseTestUtils } = scopedCuImport("resource://testing-common/PromiseTestUtils.jsm");
+PromiseTestUtils.whitelistRejectionsGlobally(/Connection closed/);
+
 add_task(function* () {
   yield addTab(`data:text/html;charset=utf-8,
                 <style>h1 { color: red; }</style>
                 <h1 id="title">textbox context menu test</h1>`);
   let {toolbox, inspector} = yield openInspector();
   yield selectNode("h1", inspector);
 
   info("Testing the markup-view tagname");
--- a/devtools/client/inspector/test/head.js
+++ b/devtools/client/inspector/test/head.js
@@ -528,23 +528,23 @@ const getHighlighterHelperFor = (type) =
       }
     };
   }
 );
 
 // The expand all operation of the markup-view calls itself recursively and
 // there's not one event we can wait for to know when it's done so use this
 // helper function to wait until all recursive children updates are done.
-function* waitForMultipleChildrenUpdates(inspector) {
+async function waitForMultipleChildrenUpdates(inspector) {
   // As long as child updates are queued up while we wait for an update already
   // wait again
   if (inspector.markup._queuedChildUpdates &&
         inspector.markup._queuedChildUpdates.size) {
-    yield waitForChildrenUpdated(inspector);
-    return yield waitForMultipleChildrenUpdates(inspector);
+    await waitForChildrenUpdated(inspector);
+    return waitForMultipleChildrenUpdates(inspector);
   }
   return null;
 }
 
 /**
  * Using the markupview's _waitForChildren function, wait for all queued
  * children updates to be handled.
  * @param {InspectorPanel} inspector The instance of InspectorPanel currently
--- a/devtools/client/netmonitor/test/browser_net_simple-request-data.js
+++ b/devtools/client/netmonitor/test/browser_net_simple-request-data.js
@@ -2,25 +2,16 @@
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 /**
  * Tests if requests render correct information in the menu UI.
  */
 
-// The following intermittent rejections should not be left uncaught. This test
-// has been whitelisted until the issue is fixed.
-//
-// NOTE: Whitelisting a class of rejections should be limited. Normally you
-//       should use "expectUncaughtRejection" to flag individual failures.
-ChromeUtils.import("resource://testing-common/PromiseTestUtils.jsm", this);
-PromiseTestUtils.whitelistRejectionsGlobally(/cookies is undefined/);
-PromiseTestUtils.whitelistRejectionsGlobally(/requestItem is undefined/);
-
 function test() {
   // Disable tcp fast open, because it is setting a response header indicator
   // (bug 1352274). TCP Fast Open is not present on all platforms therefore the
   // number of response headers will vary depending on the platform.
   Services.prefs.setBoolPref("network.tcp.tcp_fastopen_enable", false);
 
   let { L10N } = require("devtools/client/netmonitor/src/utils/l10n");
 
--- a/devtools/client/netmonitor/test/browser_net_view-source-debugger.js
+++ b/devtools/client/netmonitor/test/browser_net_view-source-debugger.js
@@ -1,13 +1,18 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
+// There are shutdown issues for which multiple rejections are left uncaught.
+// See bug 1018184 for resolving these issues.
+const { PromiseTestUtils } = scopedCuImport("resource://testing-common/PromiseTestUtils.jsm");
+PromiseTestUtils.whitelistRejectionsGlobally(/Component not initialized/);
+
 /**
  * Tests if on clicking the stack frame, UI switches to the Debugger panel.
  */
 add_task(async function () {
   // Set a higher panel height in order to get full CodeMirror content
   await pushPref("devtools.toolbox.footer.height", 400);
 
   let { tab, monitor, toolbox } = await initNetMonitor(POST_DATA_URL);
--- a/devtools/client/responsive.html/test/browser/browser_ext_messaging.js
+++ b/devtools/client/responsive.html/test/browser/browser_ext_messaging.js
@@ -4,16 +4,17 @@
 /* eslint-env webextensions */
 
 "use strict";
 
 const TEST_URL = "http://example.com/";
 
 // These allowed rejections are copied from
 // browser/components/extensions/test/browser/head.js.
+const { PromiseTestUtils } = scopedCuImport("resource://testing-common/PromiseTestUtils.jsm");
 PromiseTestUtils.whitelistRejectionsGlobally(/Message manager disconnected/);
 PromiseTestUtils.whitelistRejectionsGlobally(/Receiving end does not exist/);
 
 add_task(async function () {
   let tab = await addTab(TEST_URL);
   await openRDM(tab);
 
   let extension = ExtensionTestUtils.loadExtension({
--- a/devtools/client/shared/test/browser_toolbar_basic.js
+++ b/devtools/client/shared/test/browser_toolbar_basic.js
@@ -1,15 +1,20 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 // Tests that the developer toolbar works properly
 
+// There are shutdown issues for which multiple rejections are left uncaught.
+// See bug 1018184 for resolving these issues.
+const { PromiseTestUtils } = scopedCuImport("resource://testing-common/PromiseTestUtils.jsm");
+PromiseTestUtils.whitelistRejectionsGlobally(/Connection closed/);
+
 const {gDevToolsBrowser} = require("devtools/client/framework/devtools-browser");
 
 const TEST_URI = TEST_URI_ROOT + "doc_toolbar_basic.html";
 
 add_task(function* () {
   info("Starting browser_toolbar_basic.js");
   yield addTab(TEST_URI);
 
--- a/devtools/client/shared/test/shared-head.js
+++ b/devtools/client/shared/test/shared-head.js
@@ -14,34 +14,16 @@ const {classes: Cc, interfaces: Ci, util
   = Components;
 
 function scopedCuImport(path) {
   const scope = {};
   ChromeUtils.import(path, scope);
   return scope;
 }
 
-// There are shutdown issues for which multiple rejections are left uncaught.
-// This bug should be fixed, but for the moment devtools are whitelisted.
-//
-// NOTE: Entire directory whitelisting should be kept to a minimum. Normally you
-//       should use "expectUncaughtRejection" to flag individual failures.
-const {PromiseTestUtils} = scopedCuImport("resource://testing-common/PromiseTestUtils.jsm");
-PromiseTestUtils.whitelistRejectionsGlobally(/Component not initialized/);
-PromiseTestUtils.whitelistRejectionsGlobally(/Connection closed/);
-PromiseTestUtils.whitelistRejectionsGlobally(/destroy/);
-PromiseTestUtils.whitelistRejectionsGlobally(/File closed/);
-PromiseTestUtils.whitelistRejectionsGlobally(/is no longer, usable/);
-PromiseTestUtils.whitelistRejectionsGlobally(/NS_ERROR_FAILURE/);
-PromiseTestUtils.whitelistRejectionsGlobally(/this\._urls is null/);
-PromiseTestUtils.whitelistRejectionsGlobally(/this\.tabTarget is null/);
-PromiseTestUtils.whitelistRejectionsGlobally(/this\.toolbox is null/);
-PromiseTestUtils.whitelistRejectionsGlobally(/this\.webConsoleClient is null/);
-PromiseTestUtils.whitelistRejectionsGlobally(/this\.worker is null/);
-
 const {ScratchpadManager} = scopedCuImport("resource://devtools/client/scratchpad/scratchpad-manager.jsm");
 const {loader, require} = scopedCuImport("resource://devtools/shared/Loader.jsm");
 
 const {gDevTools} = require("devtools/client/framework/devtools");
 const {TargetFactory} = require("devtools/client/framework/target");
 const DevToolsUtils = require("devtools/shared/DevToolsUtils");
 const flags = require("devtools/shared/flags");
 let promise = require("promise");
--- a/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_location_debugger_link.js
+++ b/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_location_debugger_link.js
@@ -4,16 +4,22 @@
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 /* import-globals-from head.js */
 
 // Test that message source links for js errors and console API calls open in
 // the jsdebugger when clicked.
 
 "use strict";
+
+// There are shutdown issues for which multiple rejections are left uncaught.
+// See bug 1018184 for resolving these issues.
+const { PromiseTestUtils } = scopedCuImport("resource://testing-common/PromiseTestUtils.jsm");
+PromiseTestUtils.whitelistRejectionsGlobally(/this\.worker is null/);
+
 requestLongerTimeout(2);
 
 const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" +
                  "new-console-output/test/mochitest/test-location-debugger-link.html";
 
 add_task(async function () {
   // Force the new debugger UI, in case this gets uplifted with the old
   // debugger still turned on
--- a/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_stacktrace_location_debugger_link.js
+++ b/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_stacktrace_location_debugger_link.js
@@ -5,16 +5,22 @@
 
 /* import-globals-from head.js */
 
 // Test that message source links for js errors and console API calls open in
 // the jsdebugger when clicked.
 
 "use strict";
 
+// There are shutdown issues for which multiple rejections are left uncaught.
+// See bug 1018184 for resolving these issues.
+const { PromiseTestUtils } = scopedCuImport("resource://testing-common/PromiseTestUtils.jsm");
+PromiseTestUtils.whitelistRejectionsGlobally(/Component not initialized/);
+PromiseTestUtils.whitelistRejectionsGlobally(/this\.worker is null/);
+
 const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" +
                  "new-console-output/test/mochitest/" +
                  "test-stacktrace-location-debugger-link.html";
 
 add_task(async function () {
   // Force the new debugger UI, in case this gets uplifted with the old
   // debugger still turned on
   Services.prefs.setBoolPref("devtools.debugger.new-debugger-frontend", true);
--- a/devtools/client/webconsole/test/browser_webconsole_bug_766001_JS_Console_in_Debugger.js
+++ b/devtools/client/webconsole/test/browser_webconsole_bug_766001_JS_Console_in_Debugger.js
@@ -3,16 +3,21 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Test that message source links for js errors and console API calls open in
 // the jsdebugger when clicked.
 
 "use strict";
 
+// There are shutdown issues for which multiple rejections are left uncaught.
+// See bug 1018184 for resolving these issues.
+const { PromiseTestUtils } = scopedCuImport("resource://testing-common/PromiseTestUtils.jsm");
+PromiseTestUtils.whitelistRejectionsGlobally(/this\.worker is null/);
+
 const TEST_URI = "http://example.com/browser/devtools/client/webconsole/test" +
                  "/test-bug-766001-js-console-links.html";
 
 // Force the new debugger UI, in case this gets uplifted with the old
 // debugger still turned on
 Services.prefs.setBoolPref("devtools.debugger.new-debugger-frontend", true);
 registerCleanupFunction(function* () {
   Services.prefs.clearUserPref("devtools.debugger.new-debugger-frontend");
--- a/devtools/client/webconsole/test/browser_webconsole_output_dom_elements_01.js
+++ b/devtools/client/webconsole/test/browser_webconsole_output_dom_elements_01.js
@@ -5,16 +5,21 @@
 
 // Whitelisting this test.
 // As part of bug 1077403, the leaking uncaught rejections should be fixed.
 
 "use strict";
 
 // Test the webconsole output for various types of DOM Nodes.
 
+// There are shutdown issues for which multiple rejections are left uncaught.
+// See bug 1018184 for resolving these issues.
+const { PromiseTestUtils } = scopedCuImport("resource://testing-common/PromiseTestUtils.jsm");
+PromiseTestUtils.whitelistRejectionsGlobally(/this\.toolbox is null/);
+
 const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" +
                  "test/test-console-output-dom-elements.html";
 
 var inputTests = [
   {
     input: "testBodyNode()",
     output: '<body class="body-class" id="body-id">',
     printOutput: "[object HTMLBodyElement]",
--- a/devtools/server/actors/webconsole.js
+++ b/devtools/server/actors/webconsole.js
@@ -81,17 +81,16 @@ function WebConsoleActor(connection, par
             this._onChangedToplevelDocument);
   this._onObserverNotification = this._onObserverNotification.bind(this);
   if (this.parentActor.isRootActor) {
     Services.obs.addObserver(this._onObserverNotification,
                              "last-pb-context-exited");
   }
 
   this.traits = {
-    customNetworkRequest: !this._parentIsContentActor,
     evaluateJSAsync: true,
     transferredResponseSize: true,
     selectedObjectActor: true, // 44+
   };
 }
 
 WebConsoleActor.prototype =
 {
@@ -159,26 +158,16 @@ WebConsoleActor.prototype =
 
   /**
    * List of supported features by the console actor.
    * @type object
    */
   traits: null,
 
   /**
-   * Boolean getter that tells if the parent actor is a ContentActor.
-   *
-   * @private
-   * @type boolean
-   */
-  get _parentIsContentActor() {
-    return this.parentActor.constructor.name == "ContentActor";
-  },
-
-  /**
    * The window or sandbox we work with.
    * Note that even if it is named `window` it refers to the current
    * global we are debugging, which can be a Sandbox for addons
    * or browser content toolbox.
    *
    * @type nsIDOMWindow or Sandbox
    */
   get window() {
@@ -582,17 +571,26 @@ WebConsoleActor.prototype =
    * @return object
    *         The response object which holds the startedListeners array.
    */
   onStartListeners: function (request) {
     let startedListeners = [];
     let window = !this.parentActor.isRootActor ? this.window : null;
     let messageManager = null;
 
-    if (this._parentIsContentActor) {
+    // Check if the actor is running in a child process (but only if
+    // Services.appinfo exists, to prevent onStartListeners to fail
+    // when the target is a Worker).
+    let processBoundary = Services.appinfo && (
+      Services.appinfo.processType != Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT
+    );
+
+    // Retrieve a message manager from the parent actor if this actor is
+    // not currently running in the main process.
+    if (processBoundary) {
       messageManager = this.parentActor.messageManager;
     }
 
     while (request.listeners.length > 0) {
       let listener = request.listeners.shift();
       switch (listener) {
         case "PageError":
           // Workers don't support this message type yet
@@ -624,18 +622,16 @@ WebConsoleActor.prototype =
           if (!this.networkMonitor) {
             // Create a StackTraceCollector that's going to be shared both by
             // the NetworkMonitorChild (getting messages about requests from
             // parent) and by the NetworkMonitor that directly watches service
             // workers requests.
             this.stackTraceCollector = new StackTraceCollector({ window });
             this.stackTraceCollector.init();
 
-            let processBoundary = Services.appinfo.processType !=
-                                  Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
             if (messageManager && processBoundary) {
               // Start a network monitor in the parent process to listen to
               // most requests than happen in parent
               this.networkMonitor =
                 new NetworkMonitorChild(this.parentActor.outerWindowID,
                                         messageManager, this.conn, this);
               this.networkMonitor.init();
               // Spawn also one in the child to listen to service workers
--- a/devtools/server/actors/webextension.js
+++ b/devtools/server/actors/webextension.js
@@ -55,16 +55,28 @@ const FALLBACK_DOC_MESSAGE = "Your addon
  */
 function WebExtensionChildActor(conn, chromeGlobal, prefix, addonId) {
   ChromeActor.call(this, conn);
 
   this._chromeGlobal = chromeGlobal;
   this._prefix = prefix;
   this.id = addonId;
 
+  // Redefine the messageManager getter to return the chromeGlobal
+  // as the messageManager for this actor (which is the browser XUL
+  // element used by the parent actor running in the main process to
+  // connect to the extension process).
+  Object.defineProperty(this, "messageManager", {
+    enumerable: true,
+    configurable: true,
+    get: () => {
+      return this._chromeGlobal;
+    }
+  });
+
   // Bind the _allowSource helper to this, it is used in the
   // TabActor to lazily create the TabSources instance.
   this._allowSource = this._allowSource.bind(this);
   this._onParentExit = this._onParentExit.bind(this);
 
   this._chromeGlobal.addMessageListener("debug:webext_parent_exit", this._onParentExit);
 
   // Set the consoleAPIListener filtering options
--- a/devtools/server/main.js
+++ b/devtools/server/main.js
@@ -12,17 +12,16 @@ var { Ci, Cc } = require("chrome");
 var Services = require("Services");
 var { ActorPool, OriginalLocation, RegisteredActorFactory,
       ObservedActorFactory } = require("devtools/server/actors/common");
 var { LocalDebuggerTransport, ChildDebuggerTransport, WorkerDebuggerTransport } =
   require("devtools/shared/transport/transport");
 var DevToolsUtils = require("devtools/shared/DevToolsUtils");
 var { dumpn } = DevToolsUtils;
 var flags = require("devtools/shared/flags");
-var SyncPromise = require("devtools/shared/deprecated-sync-thenables");
 
 DevToolsUtils.defineLazyGetter(this, "DebuggerSocket", () => {
   let { DebuggerSocket } = require("devtools/shared/security/socket");
   return DebuggerSocket;
 });
 DevToolsUtils.defineLazyGetter(this, "Authentication", () => {
   return require("devtools/shared/security/auth");
 });
@@ -1626,25 +1625,33 @@ DebuggerServerConnection.prototype = {
     dumpn(errorString);
     return {
       error: "unknownError",
       message: errorString
     };
   },
 
   _queueResponse: function (from, type, responseOrPromise) {
-    let pendingResponse = this._actorResponses.get(from) || SyncPromise.resolve(null);
+    let pendingResponse = this._actorResponses.get(from) || Promise.resolve(null);
     let responsePromise = pendingResponse.then(() => {
       return responseOrPromise;
     }).then(response => {
+      if (!this.transport) {
+        throw new Error(`Connection closed, pending response from ${from}, ` +
+                        `type ${type} failed`);
+      }
       if (!response.from) {
         response.from = from;
       }
       this.transport.send(response);
     }).catch((e) => {
+      if (!this.transport) {
+        throw new Error(`Connection closed, pending error from ${from}, ` +
+                        `type ${type} failed`);
+      }
       let errorPacket = this._unknownError(
         "error occurred while processing '" + type, e);
       errorPacket.from = from;
       this.transport.send(errorPacket);
     });
 
     this._actorResponses.set(from, responsePromise);
   },
@@ -1656,17 +1663,17 @@ DebuggerServerConnection.prototype = {
    *        The ID of the add-on to pass the options to
    * @param options object
    *        The options.
    * @return a promise that will be resolved when complete.
    */
   setAddonOptions(id, options) {
     let addonList = this.rootActor._parameters.addonList;
     if (!addonList) {
-      return SyncPromise.resolve();
+      return Promise.resolve();
     }
     return addonList.getList().then((addonActors) => {
       for (let actor of addonActors) {
         if (actor.id != id) {
           continue;
         }
         actor.setOptions(options);
         return;
--- a/dom/animation/ComputedTimingFunction.h
+++ b/dom/animation/ComputedTimingFunction.h
@@ -2,19 +2,24 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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/. */
 
 #ifndef mozilla_ComputedTimingFunction_h
 #define mozilla_ComputedTimingFunction_h
 
+#include "nsDebug.h"
 #include "nsSMILKeySpline.h"  // nsSMILKeySpline
+#include "nsStringFwd.h"
 #include "nsTimingFunction.h"
 
+#include "mozilla/Assertions.h"
+#include "mozilla/Maybe.h"
+
 namespace mozilla {
 
 class ComputedTimingFunction
 {
 public:
   static ComputedTimingFunction
   CubicBezier(double x1, double y1, double x2, double y2)
   {
--- a/dom/base/nsGlobalWindowInner.cpp
+++ b/dom/base/nsGlobalWindowInner.cpp
@@ -7420,17 +7420,17 @@ nsGlobalWindowInner::PromiseDocumentFlus
   RefPtr<Promise> resultPromise = Promise::Create(global, aError);
   if (aError.Failed()) {
     return nullptr;
   }
 
   UniquePtr<PromiseDocumentFlushedResolver> flushResolver(
     new PromiseDocumentFlushedResolver(resultPromise, aCallback));
 
-  if (!shell->NeedFlush(FlushType::Style)) {
+  if (!shell->NeedStyleFlush() && !shell->NeedLayoutFlush()) {
     flushResolver->Call();
     return resultPromise.forget();
   }
 
   if (!mObservingDidRefresh) {
     bool success = shell->AddPostRefreshObserver(this);
     if (!success) {
       aError.Throw(NS_ERROR_FAILURE);
@@ -7515,20 +7515,21 @@ nsGlobalWindowInner::DidRefresh()
     mObservingDidRefresh = false;
   });
 
   MOZ_ASSERT(mDoc);
 
   nsIPresShell* shell = mDoc->GetShell();
   MOZ_ASSERT(shell);
 
-  if (shell->NeedStyleFlush() || shell->HasPendingReflow()) {
+  if (shell->NeedStyleFlush() || shell->NeedLayoutFlush()) {
     // By the time our observer fired, something has already invalidated
-    // style and maybe layout. We'll wait until the next refresh driver
-    // tick instead.
+    // style or layout - or perhaps we're still in the middle of a flush that
+    // was interrupted. In either case, we'll wait until the next refresh driver
+    // tick instead and try again.
     rejectionGuard.release();
     return;
   }
 
   bool success = shell->RemovePostRefreshObserver(this);
   if (!success) {
     return;
   }
--- a/dom/base/test/browser_promiseDocumentFlushed.js
+++ b/dom/base/test/browser_promiseDocumentFlushed.js
@@ -26,26 +26,30 @@ const gWindowUtils = window.QueryInterfa
                            .getInterface(Ci.nsIDOMWindowUtils);
 
 /**
  * Asserts that no style or layout flushes are required by the
  * current window.
  */
 function assertNoFlushesRequired() {
   Assert.ok(!gWindowUtils.needsFlush(Ci.nsIDOMWindowUtils.FLUSH_STYLE),
-            "No flushes are required.");
+            "No style flushes are required.");
+  Assert.ok(!gWindowUtils.needsFlush(Ci.nsIDOMWindowUtils.FLUSH_LAYOUT),
+            "No layout flushes are required.");
 }
 
 /**
  * Asserts that the DOM has been dirtied, and so style and layout flushes
  * are required.
  */
 function assertFlushesRequired() {
+  Assert.ok(gWindowUtils.needsFlush(Ci.nsIDOMWindowUtils.FLUSH_STYLE),
+            "Style flush required.");
   Assert.ok(gWindowUtils.needsFlush(Ci.nsIDOMWindowUtils.FLUSH_LAYOUT),
-            "Style and layout flushes are required.");
+            "Layout flush required.");
 }
 
 /**
  * Removes style changes from dirtyTheDOM() from the browser window,
  * and resolves once the refresh driver ticks.
  */
 async function cleanTheDOM() {
   gNavToolbox.style.padding = "";
--- a/dom/media/systemservices/CamerasParent.h
+++ b/dom/media/systemservices/CamerasParent.h
@@ -69,18 +69,19 @@ public:
   friend CamerasParent;
 
 private:
   ~InputObserver() {}
 
   RefPtr<CamerasParent> mParent;
 };
 
-class CamerasParent :  public PCamerasParent,
-                       public nsIObserver
+class CamerasParent final
+  : public PCamerasParent
+  , public nsIObserver
 {
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIOBSERVER
 
 public:
   static already_AddRefed<CamerasParent> Create();
 
   // Messages received form the child. These run on the IPC/PBackground thread.
--- a/dom/media/webaudio/ConvolverNode.cpp
+++ b/dom/media/webaudio/ConvolverNode.cpp
@@ -241,17 +241,17 @@ ConvolverNode::SetBuffer(JSContext* aCx,
   if (aBuffer) {
     switch (aBuffer->NumberOfChannels()) {
     case 1:
     case 2:
     case 4:
       // Supported number of channels
       break;
     default:
-      aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
+      aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
       return;
     }
   }
 
   // Send the buffer to the stream
   AudioNodeStream* ns = mStream;
   MOZ_ASSERT(ns, "Why don't we have a stream here?");
   if (aBuffer) {
--- a/dom/payments/PaymentRequest.cpp
+++ b/dom/payments/PaymentRequest.cpp
@@ -26,25 +26,27 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(PaymentRequest,
                                                   DOMEventTargetHelper)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mResultPromise)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAcceptPromise)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAbortPromise)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mResponse)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mShippingAddress)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFullShippingAddress)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(PaymentRequest,
                                                 DOMEventTargetHelper)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mResultPromise)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mAcceptPromise)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mAbortPromise)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mResponse)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mShippingAddress)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mFullShippingAddress)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PaymentRequest)
 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
 
 NS_IMPL_ADDREF_INHERITED(PaymentRequest, DOMEventTargetHelper)
 NS_IMPL_RELEASE_INHERITED(PaymentRequest, DOMEventTargetHelper)
 
@@ -738,16 +740,20 @@ PaymentRequest::RespondShowPayment(const
   MOZ_ASSERT(ReadyForUpdate());
   MOZ_ASSERT(mState == eInteractive);
 
   if (NS_FAILED(aRv)) {
     RejectShowPayment(aRv);
     return;
   }
 
+  // https://github.com/w3c/payment-request/issues/692
+  mShippingAddress.swap(mFullShippingAddress);
+  mFullShippingAddress = nullptr;
+
   RefPtr<PaymentResponse> paymentResponse =
     new PaymentResponse(GetOwner(), mInternalId, mId, aMethodName,
                         mShippingOption, mShippingAddress, aDetails,
                         aPayerName, aPayerEmail, aPayerPhone);
   mResponse = paymentResponse;
   mAcceptPromise->MaybeResolve(paymentResponse);
 
   mState = eClosed;
@@ -935,21 +941,25 @@ PaymentRequest::UpdateShippingAddress(co
                                       const nsAString& aDependentLocality,
                                       const nsAString& aPostalCode,
                                       const nsAString& aSortingCode,
                                       const nsAString& aLanguageCode,
                                       const nsAString& aOrganization,
                                       const nsAString& aRecipient,
                                       const nsAString& aPhone)
 {
-  mShippingAddress = new PaymentAddress(GetOwner(), aCountry, aAddressLine,
+  nsTArray<nsString> emptyArray;
+  mShippingAddress = new PaymentAddress(GetOwner(), aCountry, emptyArray,
                                         aRegion, aCity, aDependentLocality,
                                         aPostalCode, aSortingCode, aLanguageCode,
-                                        aOrganization, aRecipient, aPhone);
-
+                                        EmptyString(), EmptyString(), EmptyString());
+  mFullShippingAddress = new PaymentAddress(GetOwner(), aCountry, aAddressLine,
+                                            aRegion, aCity, aDependentLocality,
+                                            aPostalCode, aSortingCode, aLanguageCode,
+                                            aOrganization, aRecipient, aPhone);
   // Fire shippingaddresschange event
   return DispatchUpdateEvent(NS_LITERAL_STRING("shippingaddresschange"));
 }
 
 void
 PaymentRequest::SetShippingOption(const nsAString& aShippingOption)
 {
   mShippingOption = aShippingOption;
--- a/dom/payments/PaymentRequest.h
+++ b/dom/payments/PaymentRequest.h
@@ -156,18 +156,20 @@ protected:
   // Promise for "PaymentRequest::CanMakePayment"
   RefPtr<Promise> mResultPromise;
   // Promise for "PaymentRequest::Show"
   RefPtr<Promise> mAcceptPromise;
   // Promise for "PaymentRequest::Abort"
   RefPtr<Promise> mAbortPromise;
   // Resolve mAcceptPromise with mResponse if user accepts the request.
   RefPtr<PaymentResponse> mResponse;
-  // It is populated when the user provides a shipping address.
+  // The redacted shipping address.
   RefPtr<PaymentAddress> mShippingAddress;
+  // The full shipping address to be used in the response upon payment.
+  RefPtr<PaymentAddress> mFullShippingAddress;
   // It is populated when the user chooses a shipping option.
   nsString mShippingOption;
 
   Nullable<PaymentShippingType> mShippingType;
 
   // "true" when there is a pending updateWith() call to update the payment request
   // and "false" otherwise.
   bool mUpdating;
--- a/dom/payments/test/ShowPaymentChromeScript.js
+++ b/dom/payments/test/ShowPaymentChromeScript.js
@@ -16,21 +16,21 @@ const shippingAddress = Cc["@mozilla.org
 const addressLine = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray);
 const address = Cc["@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString);
 address.data = "Easton Ave";
 addressLine.appendElement(address);
 shippingAddress.init("USA",              // country
                      addressLine,        // address line
                      "CA",               // region
                      "San Bruno",        // city
-                     "",                 // dependent locality
+                     "Test locality",    // dependent locality
                      "94066",            // postal code
                      "123456",           // sorting code
                      "en",               // language code
-                     "",                 // organization
+                     "Testing Org",      // organization
                      "Bill A. Pacheco",  // recipient
                      "+1-434-441-3879"); // phone
 
 const NormalUIService = {
   shippingOptionChanged: false,
   showPayment: function(requestId) {
     paymentSrv.changeShippingAddress(requestId, shippingAddress);
   },
--- a/dom/payments/test/test_showPayment.html
+++ b/dom/payments/test/test_showPayment.html
@@ -18,17 +18,17 @@ https://bugzilla.mozilla.org/show_bug.cg
 
   function testFailHandler(message) {
     ok(false, message);
   }
   gScript.addMessageListener("test-fail", testFailHandler);
 
   const defaultMethods = [{
     supportedMethods: "basic-card",
-    data: { 
+    data: {
       supportedNetworks: ['unionpay', 'visa', 'mastercard', 'amex', 'discover',
                           'diners', 'jcb', 'mir',
       ],
       supportedTypes: ['prepaid', 'debit', 'credit'],
     },
   }, {
     supportedMethods: "testing-payment-method",
   }];
@@ -155,40 +155,61 @@ https://bugzilla.mozilla.org/show_bug.cg
     });
   }
 
   function testShow() {
     gScript.sendAsyncMessage("set-normal-ui-service");
     return new Promise((resolve, reject) => {
       const payRequest = new PaymentRequest(defaultMethods, defaultDetails, defaultOptions);
       payRequest.addEventListener("shippingaddresschange", event => {
+        is(payRequest.shippingAddress.country, "USA", "payRequest.shippingAddress.country should be 'USA' from event.");
+        is(payRequest.shippingAddress.addressLine.length, 0, "payRequest.shippingAddress.addressLine.length should be 0 from event.");
+        is(payRequest.shippingAddress.region, "CA", "payRequest.shippingAddress.region should be 'CA' from event.");
+        is(payRequest.shippingAddress.city, "San Bruno", "payRequest.shippingAddress.city should be 'San Bruno' from event.");
+        is(payRequest.shippingAddress.dependentLocality, "Test locality", "payRequest.shippingAddress.dependentLocality should be 'Test locality' from event.");
+        is(payRequest.shippingAddress.postalCode, "94066", "payRequest.shippingAddress.postalCode should be '94066' from event.");
+        is(payRequest.shippingAddress.sortingCode, "123456", "payRequest.shippingAddress.sortingCode should be '123456' from event.");
+        is(payRequest.shippingAddress.organization, "", "payRequest.shippingAddress.organization should be empty from event.");
+        is(payRequest.shippingAddress.recipient, "", "payRequest.shippingAddress.recipient should be empty from event.");
+        is(payRequest.shippingAddress.phone, "", "payRequest.shippingAddress.phone should be empty from event.");
         event.updateWith(updateWithShippingAddress());
       });
       payRequest.addEventListener("shippingoptionchange", event => {
         event.updateWith(updateWithShippingOption());
       });
       payRequest.show().then(response => {
         is(response.requestId, "test payment", "response.requestId should be 'test payment'.");
         is(response.methodName, "testing-payment-method", "response.methodName should be 'testing-payment-method'.");
         is(response.details.paymentToken, "6880281f-0df3-4b8e-916f-66575e2457c1", "response.details.paymentToken should be '6880281f-0df3-4b8e-916f-66575e2457c1'.");
         is(response.shippingAddress.country, "USA", "response.shippingAddress.country should be 'USA'.");
         is(response.shippingAddress.addressLine.length, 1, "response.shippingAddress.addressLine.length should be 1.");
         is(response.shippingAddress.addressLine[0], "Easton Ave", "response.shippingAddress.addressLine[0] should be 'Easton Ave'.");
         is(response.shippingAddress.region, "CA", "response.shippingAddress.region should be 'CA'.");
         is(response.shippingAddress.city, "San Bruno", "response.shippingAddress.city should be 'San Bruno'.");
-        is(response.shippingAddress.dependentLocality, "", "response.shippingAddress.dependentLocality should be empty.");
+        is(response.shippingAddress.dependentLocality, "Test locality", "response.shippingAddress.dependentLocality should be 'Test locality'.");
         is(response.shippingAddress.postalCode, "94066", "response.shippingAddress.postalCode should be '94066'.");
         is(response.shippingAddress.sortingCode, "123456", "response.shippingAddress.sortingCode should be '123456'.");
-        is(response.shippingAddress.organization, "", "response.shippingAddress.organization should be empty.");
+        is(response.shippingAddress.organization, "Testing Org", "response.shippingAddress.organization should be 'Testing Org'.");
         is(response.shippingAddress.recipient, "Bill A. Pacheco", "response.shippingAddress.recipient should be 'Bill A. Pacheco'.");
         is(response.shippingAddress.phone, "+1-434-441-3879", "response.shippingAddress.phone should be '+1-434-441-3879'.");
         is(response.shippingOption, "FastShipping", "response.shippingOption should be 'FastShipping'.");
         is(response.payerName, "Bill A. Pacheco", "response.payerName should be 'Bill A. Pacheco'.");
-        ok(!response.payerEamil, "response.payerEmail should be empty");
+        ok(!response.payerEmail, "response.payerEmail should be empty");
         ok(!response.payerPhone, "response.payerPhone should be empty");
+        is(payRequest.shippingAddress.country, "USA", "payRequest.shippingAddress.country should be 'USA' from promise.");
+        is(payRequest.shippingAddress.addressLine.length, 1, "payRequest.shippingAddress.addressLine.length should be 1 from promise.");
+        is(payRequest.shippingAddress.addressLine[0], "Easton Ave", "payRequest.shippingAddress.addressLine[0] should be 'Easton Ave' from promise.");
+        is(payRequest.shippingAddress.region, "CA", "payRequest.shippingAddress.region should be 'CA' from promise.");
+        is(payRequest.shippingAddress.city, "San Bruno", "payRequest.shippingAddress.city should be 'San Bruno' from promise.");
+        is(payRequest.shippingAddress.dependentLocality, "Test locality", "payRequest.shippingAddress.dependentLocality should be 'Test locality' from promise.");
+        is(payRequest.shippingAddress.postalCode, "94066", "payRequest.shippingAddress.postalCode should be '94066' from promise.");
+        is(payRequest.shippingAddress.sortingCode, "123456", "payRequest.shippingAddress.sortingCode should be '123456' from promise.");
+        is(payRequest.shippingAddress.organization, "Testing Org", "payRequest.shippingAddress.organization should be 'Testing Org' from promise.");
+        is(payRequest.shippingAddress.recipient, "Bill A. Pacheco", "payRequest.shippingAddress.recipient should be 'Bill A. Pacheco' from promise.");
+        is(payRequest.shippingAddress.phone, "+1-434-441-3879", "payRequest.shippingAddress.phone should be '+1-434-441-3879' from promise.");
         response.complete("success").then(() =>{
           resolve();
         }).catch(e => {
           ok(false, "Unexpected error: " + e.name);
           resolve();
         });
       }).catch( e => {
         ok(false, "Unexpected error: " + e.name);
--- a/dom/performance/Performance.cpp
+++ b/dom/performance/Performance.cpp
@@ -317,19 +317,32 @@ Performance::Measure(const nsAString& aN
   InsertUserEntry(performanceMeasure);
 
 #ifdef MOZ_GECKO_PROFILER
   if (profiler_is_active()) {
     TimeStamp startTimeStamp = CreationTimeStamp() +
                                TimeDuration::FromMilliseconds(startTime);
     TimeStamp endTimeStamp = CreationTimeStamp() +
                              TimeDuration::FromMilliseconds(endTime);
+
+    // Convert to Maybe values so that Optional types do not need to be used in
+    // the profiler.
+    Maybe<nsString> startMark;
+    if (aStartMark.WasPassed()) {
+      startMark.emplace(aStartMark.Value());
+    }
+    Maybe<nsString> endMark;
+    if (aEndMark.WasPassed()) {
+      endMark.emplace(aEndMark.Value());
+    }
+
     profiler_add_marker(
       "UserTiming",
-      MakeUnique<UserTimingMarkerPayload>(aName, startTimeStamp, endTimeStamp));
+      MakeUnique<UserTimingMarkerPayload>(aName, startMark, endMark,
+                                          startTimeStamp, endTimeStamp));
   }
 #endif
 }
 
 void
 Performance::ClearMeasures(const Optional<nsAString>& aName)
 {
   ClearUserEntries(aName, NS_LITERAL_STRING("measure"));
--- a/gfx/layers/FrameMetrics.h
+++ b/gfx/layers/FrameMetrics.h
@@ -16,16 +16,17 @@
 #include "mozilla/gfx/Rect.h"           // for RoundedIn
 #include "mozilla/gfx/ScaleFactor.h"    // for ScaleFactor
 #include "mozilla/gfx/Logging.h"        // for Log
 #include "mozilla/layers/LayersTypes.h" // for ScrollDirection
 #include "mozilla/StaticPtr.h"          // for StaticAutoPtr
 #include "mozilla/TimeStamp.h"          // for TimeStamp
 #include "nsString.h"
 #include "nsStyleCoord.h"               // for nsStyleCoord
+#include "PLDHashTable.h"               // for PLDHashNumber
 
 namespace IPC {
 template <typename T> struct ParamTraits;
 } // namespace IPC
 
 namespace mozilla {
 namespace layers {
 
new file mode 100644
--- /dev/null
+++ b/gfx/layers/apz/test/mochitest/helper_hittest_checkerboard.html
@@ -0,0 +1,64 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>APZ hit-testing over a checkerboarded area</title>
+  <script type="application/javascript" src="apz_test_utils.js"></script>
+  <script type="application/javascript" src="apz_test_native_event_utils.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
+  <meta name="viewport" content="width=device-width"/>
+</head>
+<body>
+ <div id="scroller" style="width: 300px; height: 300px; overflow:scroll; margin-top: 100px; margin-left: 50px">
+  <!-- Make the contents tall enough to be sure we can checkerboard -->
+  <div id="contents" style="width: 100%; height: 5000px; background-image: linear-gradient(blue,red)">
+  </div>
+ </div>
+ <div id="make_root_scrollable" style="height: 5000px"></div>
+</body>
+<script type="application/javascript">
+
+function centerOf(element) {
+  var bounds = element.getBoundingClientRect();
+  return { x: bounds.x + (bounds.width / 2), y: bounds.y + (bounds.height / 2) };
+}
+
+function* test(testDriver) {
+  var config = getHitTestConfig();
+  var utils = config.utils;
+
+  var scroller = document.getElementById('scroller');
+
+  // Activate the scrollframe but keep the main-thread scroll position at 0.
+  // Also apply an async scroll offset in the y-direction such that the
+  // scrollframe scrolls all the way to the bottom of its range, where it's
+  // sure to checkerboard.
+  utils.setDisplayPortForElement(0, 0, 300, 1000, scroller, 1);
+  yield waitForAllPaints(testDriver);
+  var scrollY = scroller.scrollTopMax;
+  utils.setAsyncScrollOffset(scroller, 0, scrollY);
+  if (config.isWebRender) {
+    // Tick the refresh driver once to make sure the compositor has applied the
+    // async scroll offset (for APZ hit-testing this doesn't matter, but for
+    // WebRender hit-testing we need to make sure WR has the latest info).
+    utils.advanceTimeAndRefresh(16);
+    utils.restoreNormalRefresh();
+  }
+
+  var scrollerViewId = utils.getViewId(scroller);
+
+  // Hit-test the middle of the scrollframe, which is now inside the
+  // checkerboarded region, and check that we hit the scrollframe and
+  // not its parent.
+  var {hitInfo, scrollId} = hitTest(centerOf(scroller));
+  is(hitInfo, APZHitResultFlags.VISIBLE,
+     "active scrollframe hit info");
+  is(scrollId, scrollerViewId,
+     "active scrollframe scrollid");
+
+  subtestDone();
+}
+
+waitUntilApzStable().then(runContinuation(test));
+
+</script>
+</html>
--- a/gfx/layers/apz/test/mochitest/mochitest.ini
+++ b/gfx/layers/apz/test/mochitest/mochitest.ini
@@ -15,16 +15,17 @@
     helper_click.html
     helper_div_pan.html
     helper_drag_click.html
     helper_drag_scroll.html
     helper_iframe_pan.html
     helper_iframe1.html
     helper_iframe2.html
     helper_hittest_basic.html
+    helper_hittest_checkerboard.html
     helper_hittest_subframe_float.html
     helper_key_scroll.html
     helper_long_tap.html
     helper_override_root.html
     helper_override_subdoc.html
     helper_scroll_inactive_perspective.html
     helper_scroll_inactive_zindex.html
     helper_scroll_on_position_fixed.html
--- a/gfx/layers/apz/test/mochitest/test_group_hittest.html
+++ b/gfx/layers/apz/test/mochitest/test_group_hittest.html
@@ -24,16 +24,17 @@ var prefs = [
   ["test.events.async.enabled", true],
   // Turns on APZTestData logging which we use to obtain the hit test results.
   ["apz.test.logging_enabled", true]
 ];
 
 var subtests = [
   {'file': 'helper_hittest_basic.html', 'prefs': prefs},
   {'file': 'helper_hittest_subframe_float.html', 'prefs': prefs},
+  {'file': 'helper_hittest_checkerboard.html', 'prefs': prefs},
 ];
 
 if (isApzEnabled()) {
   SimpleTest.waitForExplicitFinish();
   window.onload = function() {
     runSubtestsSeriallyInFreshWindows(subtests)
     .then(SimpleTest.finish, SimpleTest.finish);
   };
--- a/gfx/layers/d3d11/CompositorD3D11.cpp
+++ b/gfx/layers/d3d11/CompositorD3D11.cpp
@@ -30,21 +30,17 @@
 
 #include "mozilla/EnumeratedArray.h"
 #include "mozilla/Telemetry.h"
 #include "BlendShaderConstants.h"
 
 #include "D3D11ShareHandleImage.h"
 #include "DeviceAttachmentsD3D11.h"
 
-#ifdef __MINGW32__
 #include <versionhelpers.h> // For IsWindows8OrGreater
-#else
-#include <VersionHelpers.h> // For IsWindows8OrGreater
-#endif
 #include <winsdkver.h>
 
 namespace mozilla {
 
 using namespace gfx;
 
 namespace layers {
 
--- a/gfx/webrender/res/brush_image.glsl
+++ b/gfx/webrender/res/brush_image.glsl
@@ -8,22 +8,28 @@
 
 #ifdef WR_FEATURE_ALPHA_PASS
 varying vec2 vLocalPos;
 #endif
 
 varying vec3 vUv;
 flat varying vec4 vUvBounds;
 flat varying vec4 vColor;
+
+#ifdef WR_FEATURE_ALPHA_PASS
 flat varying vec2 vSelect;
+#endif
+
 #ifdef WR_VERTEX_SHADER
 
-#define IMAGE_SOURCE_COLOR              0
-#define IMAGE_SOURCE_ALPHA              1
-#define IMAGE_SOURCE_MASK_FROM_COLOR    2
+#ifdef WR_FEATURE_ALPHA_PASS
+    #define IMAGE_SOURCE_COLOR              0
+    #define IMAGE_SOURCE_ALPHA              1
+    #define IMAGE_SOURCE_MASK_FROM_COLOR    2
+#endif
 
 void brush_vs(
     VertexInfo vi,
     int prim_address,
     RectWithSize local_rect,
     ivec3 user_data,
     PictureTask pic_task
 ) {
@@ -48,41 +54,42 @@ void brush_vs(
 
     // Handle case where the UV coords are inverted (e.g. from an
     // external image).
     vUvBounds = vec4(
         min(uv0, uv1) + vec2(0.5),
         max(uv0, uv1) - vec2(0.5)
     ) / texture_size.xyxy;
 
+#ifdef WR_FEATURE_ALPHA_PASS
     switch (user_data.y) {
         case IMAGE_SOURCE_COLOR:
             vSelect = vec2(0.0, 0.0);
             break;
         case IMAGE_SOURCE_ALPHA:
             vSelect = vec2(0.0, 1.0);
             break;
         case IMAGE_SOURCE_MASK_FROM_COLOR:
             vSelect = vec2(1.0, 1.0);
             break;
     }
 
-#ifdef WR_FEATURE_ALPHA_PASS
     vLocalPos = vi.local_pos;
 #endif
 }
 #endif
 
 #ifdef WR_FRAGMENT_SHADER
 vec4 brush_fs() {
     vec2 uv = clamp(vUv.xy, vUvBounds.xy, vUvBounds.zw);
 
     vec4 texel = TEX_SAMPLE(sColor0, vec3(uv, vUv.z));
-    vec4 mask = mix(texel.rrrr, texel.aaaa, vSelect.x);
-    vec4 color = mix(texel, vColor * mask, vSelect.y);
 
 #ifdef WR_FEATURE_ALPHA_PASS
-    color *= init_transform_fs(vLocalPos);
+    vec4 mask = mix(texel.rrrr, texel.aaaa, vSelect.x);
+    vec4 color = mix(texel, vColor * mask, vSelect.y) * init_transform_fs(vLocalPos);
+#else
+    vec4 color = texel;
 #endif
 
     return color;
 }
 #endif
deleted file mode 100644
--- a/gfx/webrender/res/brush_picture.glsl
+++ /dev/null
@@ -1,114 +0,0 @@
-/* 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/. */
-
-#define VECS_PER_SPECIFIC_BRUSH 1
-
-#include shared,prim_shared,brush
-
-#ifdef WR_FEATURE_ALPHA_PASS
-varying vec2 vLocalPos;
-#endif
-
-varying vec3 vUv;
-flat varying int vImageKind;
-flat varying vec4 vUvBounds;
-flat varying vec4 vUvBounds_NoClamp;
-flat varying vec4 vParams;
-flat varying vec4 vColor;
-
-#define BRUSH_PICTURE_SIMPLE      0
-#define BRUSH_PICTURE_NINEPATCH   1
-
-#ifdef WR_VERTEX_SHADER
-
-struct Picture {
-    vec4 color;
-};
-
-Picture fetch_picture(int address) {
-    vec4 data = fetch_from_resource_cache_1(address);
-    return Picture(data);
-}
-
-void brush_vs(
-    VertexInfo vi,
-    int prim_address,
-    RectWithSize local_rect,
-    ivec3 user_data,
-    PictureTask pic_task
-) {
-    vImageKind = user_data.y;
-
-    Picture pic = fetch_picture(prim_address);
-    ImageResource res = fetch_image_resource(user_data.x);
-    vec2 texture_size = vec2(textureSize(sColor1, 0).xy);
-    vColor = pic.color;
-    vec2 uv0 = res.uv_rect.p0;
-    vec2 uv1 = res.uv_rect.p1;
-    vec2 src_size = (uv1 - uv0) * res.user_data.x;
-    vUv.z = res.layer;
-
-    // TODO(gw): In the future we'll probably draw these as segments
-    //           with the brush shader. When that occurs, we can
-    //           modify the UVs for each segment in the VS, and the
-    //           FS can become a simple shader that doesn't need
-    //           to adjust the UVs.
-
-    switch (vImageKind) {
-        case BRUSH_PICTURE_SIMPLE: {
-            vec2 f = (vi.local_pos - local_rect.p0) / local_rect.size;
-            vUv.xy = mix(uv0, uv1, f);
-            vUv.xy /= texture_size;
-            break;
-        }
-        case BRUSH_PICTURE_NINEPATCH: {
-            vec2 local_src_size = src_size / uDevicePixelRatio;
-            vUv.xy = (vi.local_pos - local_rect.p0) / local_src_size;
-            vParams.xy = vec2(0.5);
-            vParams.zw = (local_rect.size / local_src_size - 0.5);
-            break;
-        }
-        default:
-            vUv.xy = vec2(0.0);
-            vParams = vec4(0.0);
-    }
-
-    vUvBounds = vec4(uv0 + vec2(0.5), uv1 - vec2(0.5)) / texture_size.xyxy;
-    vUvBounds_NoClamp = vec4(uv0, uv1) / texture_size.xyxy;
-
-#ifdef WR_FEATURE_ALPHA_PASS
-    vLocalPos = vi.local_pos;
-#endif
-}
-#endif
-
-#ifdef WR_FRAGMENT_SHADER
-vec4 brush_fs() {
-    vec2 uv;
-
-    switch (vImageKind) {
-        case BRUSH_PICTURE_SIMPLE: {
-            uv = clamp(vUv.xy, vUvBounds.xy, vUvBounds.zw);
-            break;
-        }
-        case BRUSH_PICTURE_NINEPATCH: {
-            uv = clamp(vUv.xy, vec2(0.0), vParams.xy);
-            uv += max(vec2(0.0), vUv.xy - vParams.zw);
-            uv = mix(vUvBounds_NoClamp.xy, vUvBounds_NoClamp.zw, uv);
-            uv = clamp(uv, vUvBounds.xy, vUvBounds.zw);
-            break;
-        }
-        default:
-            uv = vec2(0.0);
-    }
-
-    vec4 color = vColor * texture(sColor1, vec3(uv, vUv.z)).r;
-
-#ifdef WR_FEATURE_ALPHA_PASS
-    color *= init_transform_fs(vLocalPos);
-#endif
-
-    return color;
-}
-#endif
--- a/gfx/webrender/res/clip_shared.glsl
+++ b/gfx/webrender/res/clip_shared.glsl
@@ -48,17 +48,25 @@ RectWithSize intersect_rect(RectWithSize
 
 // The transformed vertex function that always covers the whole clip area,
 // which is the intersection of all clip instances of a given primitive
 ClipVertexInfo write_clip_tile_vertex(RectWithSize local_clip_rect,
                                       ClipScrollNode scroll_node,
                                       ClipArea area) {
     vec2 actual_pos = area.screen_origin + aPosition.xy * area.common_data.task_rect.size;
 
-    vec4 node_pos = get_node_pos(actual_pos / uDevicePixelRatio, scroll_node);
+    vec4 node_pos;
+
+    // Select the local position, based on whether we are rasterizing this
+    // clip mask in local- or sccreen-space.
+    if (area.local_space) {
+        node_pos = vec4(actual_pos / uDevicePixelRatio, 0.0, 1.0);
+    } else {
+        node_pos = get_node_pos(actual_pos / uDevicePixelRatio, scroll_node);
+    }
 
     // compute the point position inside the scroll node, in CSS space
     vec2 vertex_pos = actual_pos +
                       area.common_data.task_rect.p0 -
                       area.screen_origin;
 
     gl_Position = uTransform * vec4(vertex_pos, 0.0, 1);
 
--- a/gfx/webrender/res/cs_blur.glsl
+++ b/gfx/webrender/res/cs_blur.glsl
@@ -19,27 +19,25 @@ flat varying int vBlurRadius;
 
 in int aBlurRenderTaskAddress;
 in int aBlurSourceTaskAddress;
 in int aBlurDirection;
 
 struct BlurTask {
     RenderTaskCommonData common_data;
     float blur_radius;
-    float scale_factor;
     vec4 color;
 };
 
 BlurTask fetch_blur_task(int address) {
     RenderTaskData task_data = fetch_render_task_data(address);
 
     BlurTask task = BlurTask(
         task_data.common_data,
         task_data.data1.x,
-        task_data.data1.y,
         task_data.data2
     );
 
     return task;
 }
 
 void main(void) {
     BlurTask blur_task = fetch_blur_task(aBlurRenderTaskAddress);
new file mode 100644
--- /dev/null
+++ b/gfx/webrender/res/cs_clip_box_shadow.glsl
@@ -0,0 +1,82 @@
+/* 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/. */
+
+#include shared,prim_shared,clip_shared
+
+varying vec3 vPos;
+varying vec2 vUv;
+flat varying vec4 vUvBounds;
+flat varying float vLayer;
+flat varying vec4 vEdge;
+flat varying vec4 vUvBounds_NoClamp;
+flat varying float vClipMode;
+
+#ifdef WR_VERTEX_SHADER
+
+struct BoxShadowData {
+    vec2 src_rect_size;
+    float clip_mode;
+    RectWithSize dest_rect;
+};
+
+BoxShadowData fetch_data(ivec2 address) {
+    vec4 data[2] = fetch_from_resource_cache_2_direct(address);
+    RectWithSize dest_rect = RectWithSize(data[1].xy, data[1].zw);
+    BoxShadowData bs_data = BoxShadowData(data[0].xy, data[0].z, dest_rect);
+    return bs_data;
+}
+
+void main(void) {
+    ClipMaskInstance cmi = fetch_clip_item();
+    ClipArea area = fetch_clip_area(cmi.render_task_address);
+    ClipScrollNode scroll_node = fetch_clip_scroll_node(cmi.scroll_node_id);
+    BoxShadowData bs_data = fetch_data(cmi.clip_data_address);
+    ImageResource res = fetch_image_resource_direct(cmi.resource_address);
+
+    ClipVertexInfo vi = write_clip_tile_vertex(bs_data.dest_rect,
+                                               scroll_node,
+                                               area);
+
+    vLayer = res.layer;
+    vPos = vi.local_pos;
+    vClipMode = bs_data.clip_mode;
+
+    vec2 uv0 = res.uv_rect.p0;
+    vec2 uv1 = res.uv_rect.p1;
+
+    vec2 texture_size = vec2(textureSize(sColor0, 0));
+    vec2 local_pos = vPos.xy / vPos.z;
+
+    vEdge.xy = vec2(0.5);
+    vEdge.zw = (bs_data.dest_rect.size / bs_data.src_rect_size) - vec2(0.5);
+    vUv = (local_pos - bs_data.dest_rect.p0) / bs_data.src_rect_size;
+
+    vUvBounds = vec4(uv0 + vec2(0.5), uv1 - vec2(0.5)) / texture_size.xyxy;
+    vUvBounds_NoClamp = vec4(uv0, uv1) / texture_size.xyxy;
+}
+#endif
+
+#ifdef WR_FRAGMENT_SHADER
+void main(void) {
+    vec2 local_pos = vPos.xy / vPos.z;
+
+    vec2 uv = clamp(vUv.xy, vec2(0.0), vEdge.xy);
+    uv += max(vec2(0.0), vUv.xy - vEdge.zw);
+
+    uv = mix(vUvBounds_NoClamp.xy, vUvBounds_NoClamp.zw, uv);
+    uv = clamp(uv, vUvBounds.xy, vUvBounds.zw);
+
+    float in_shadow_rect = point_inside_rect(
+        local_pos,
+        vLocalBounds.xy,
+        vLocalBounds.zw
+    );
+
+    float texel = TEX_SAMPLE(sColor0, vec3(uv, vLayer)).r;
+
+    float alpha = mix(texel, 1.0 - texel, vClipMode);
+
+    oFragColor = vec4(mix(vClipMode, alpha, in_shadow_rect));
+}
+#endif
--- a/gfx/webrender/res/prim_shared.glsl
+++ b/gfx/webrender/res/prim_shared.glsl
@@ -81,31 +81,22 @@ vec4[2] fetch_from_resource_cache_2(int 
 uniform HIGHP_SAMPLER_FLOAT sampler2D sClipScrollNodes;
 uniform HIGHP_SAMPLER_FLOAT sampler2D sLocalClipRects;
 uniform HIGHP_SAMPLER_FLOAT sampler2D sRenderTasks;
 
 // Instanced attributes
 in ivec4 aData0;
 in ivec4 aData1;
 
-// Work around Angle bug that forgets to update sampler metadata,
-// by making the use of those samplers uniform across programs.
-// https://github.com/servo/webrender/wiki/Driver-issues#texturesize-in-vertex-shaders
-void markCacheTexturesUsed() {
-    vec2 size = vec2(textureSize(sCacheA8, 0)) + vec2(textureSize(sCacheRGBA8, 0));
-    if (size.x > 1000000.0) {
-        gl_Position = vec4(0.0);
-    }
-}
-
 // get_fetch_uv is a macro to work around a macOS Intel driver parsing bug.
 // TODO: convert back to a function once the driver issues are resolved, if ever.
 // https://github.com/servo/webrender/pull/623
 // https://github.com/servo/servo/issues/13953
-#define get_fetch_uv(i, vpi)  ivec2(vpi * (i % (WR_MAX_VERTEX_TEXTURE_WIDTH/vpi)), i / (WR_MAX_VERTEX_TEXTURE_WIDTH/vpi))
+// Do the division with unsigned ints because that's more efficient with D3D
+#define get_fetch_uv(i, vpi)  ivec2(int(uint(vpi) * (uint(i) % uint(WR_MAX_VERTEX_TEXTURE_WIDTH/vpi))), int(uint(i) / uint(WR_MAX_VERTEX_TEXTURE_WIDTH/vpi)))
 
 
 vec4[8] fetch_from_resource_cache_8(int address) {
     ivec2 uv = get_resource_cache_uv(address);
     return vec4[8](
         TEXEL_FETCH(sResourceCache, uv, 0, ivec2(0, 0)),
         TEXEL_FETCH(sResourceCache, uv, 0, ivec2(1, 0)),
         TEXEL_FETCH(sResourceCache, uv, 0, ivec2(2, 0)),
@@ -254,17 +245,16 @@ RenderTaskCommonData fetch_render_task_c
         texel1.x
     );
 
     return data;
 }
 
 #define PIC_TYPE_IMAGE          1
 #define PIC_TYPE_TEXT_SHADOW    2
-#define PIC_TYPE_BOX_SHADOW     3
 
 /*
  The dynamic picture that this brush exists on. Right now, it
  contains minimal information. In the future, it will describe
  the transform mode of primitives on this picture, among other things.
  */
 struct PictureTask {
     RenderTaskCommonData common_data;
@@ -284,32 +274,35 @@ PictureTask fetch_picture_task(int addre
     );
 
     return task;
 }
 
 struct ClipArea {
     RenderTaskCommonData common_data;
     vec2 screen_origin;
+    bool local_space;
 };
 
 ClipArea fetch_clip_area(int index) {
     ClipArea area;
 
     if (index == 0x7FFF) { //special sentinel task index
         area.common_data = RenderTaskCommonData(
             RectWithSize(vec2(0.0), vec2(0.0)),
             0.0
         );
         area.screen_origin = vec2(0.0);
+        area.local_space = false;
     } else {
         RenderTaskData task_data = fetch_render_task_data(index);
 
         area.common_data = task_data.common_data;
         area.screen_origin = task_data.data1.xy;
+        area.local_space = task_data.data1.z == 0.0;
     }
 
     return area;
 }
 
 struct Glyph {
     vec2 offset;
 };
@@ -370,18 +363,16 @@ PrimitiveInstance fetch_prim_instance() 
     pi.clip_task_index = aData0.z;
     pi.clip_chain_rect_index = aData0.w / 65536;
     pi.scroll_node_id = aData0.w % 65536;
     pi.z = aData1.x;
     pi.user_data0 = aData1.y;
     pi.user_data1 = aData1.z;
     pi.user_data2 = aData1.w;
 
-    markCacheTexturesUsed();
-
     return pi;
 }
 
 struct CompositeInstance {
     int render_task_index;
     int src_task_index;
     int backdrop_task_index;
     int user_data0;
@@ -399,18 +390,16 @@ CompositeInstance fetch_composite_instan
     ci.backdrop_task_index = aData0.z;
     ci.z = float(aData0.w);
 
     ci.user_data0 = aData1.x;
     ci.user_data1 = aData1.y;
     ci.user_data2 = aData1.z;
     ci.user_data3 = aData1.w;
 
-    markCacheTexturesUsed();
-
     return ci;
 }
 
 struct Primitive {
     ClipScrollNode scroll_node;
     ClipArea clip_area;
     PictureTask task;
     RectWithSize local_rect;
@@ -817,17 +806,17 @@ float init_transform_fs(vec2 local_pos) 
 
 float do_clip() {
     // anything outside of the mask is considered transparent
     bvec4 inside = lessThanEqual(
         vec4(vClipMaskUvBounds.xy, vClipMaskUv.xy),
         vec4(vClipMaskUv.xy, vClipMaskUvBounds.zw));
     // check for the dummy bounds, which are given to the opaque objects
     return vClipMaskUvBounds.xy == vClipMaskUvBounds.zw ? 1.0:
-        all(inside) ? texelFetch(sSharedCacheA8, ivec3(vClipMaskUv), 0).r : 0.0;
+        all(inside) ? texelFetch(sCacheA8, ivec3(vClipMaskUv), 0).r : 0.0;
 }
 
 #ifdef WR_FEATURE_DITHERING
 vec4 dither(vec4 color) {
     const int matrix_mask = 7;
 
     ivec2 pos = ivec2(gl_FragCoord.xy) & ivec2(matrix_mask);
     float noise_normalized = (texelFetch(sDither, pos, 0).r * 255.0 + 0.5) / 64.0;
--- a/gfx/webrender/src/batch.rs
+++ b/gfx/webrender/src/batch.rs
@@ -11,17 +11,17 @@ use clip::{ClipSource, ClipStore, ClipWo
 use clip_scroll_tree::{CoordinateSystemId};
 use euclid::{TypedTransform3D, vec3};
 use glyph_rasterizer::GlyphFormat;
 use gpu_cache::{GpuCache, GpuCacheAddress};
 use gpu_types::{BrushFlags, BrushInstance, ClipChainRectIndex};
 use gpu_types::{ClipMaskInstance, ClipScrollNodeIndex};
 use gpu_types::{CompositePrimitiveInstance, PrimitiveInstance, SimplePrimitiveInstance};
 use internal_types::{FastHashMap, SavedTargetIndex, SourceTexture};
-use picture::{ContentOrigin, PictureCompositeMode, PictureKind, PicturePrimitive, PictureSurface};
+use picture::{ContentOrigin, PictureCompositeMode, PictureKind, PicturePrimitive};
 use plane_split::{BspSplitter, Polygon, Splitter};
 use prim_store::{CachedGradient, ImageSource, PrimitiveIndex, PrimitiveKind, PrimitiveMetadata, PrimitiveStore};
 use prim_store::{BrushPrimitive, BrushKind, DeferredResolve, EdgeAaSegmentMask, PrimitiveRun};
 use render_task::{RenderTaskAddress, RenderTaskId, RenderTaskKind, RenderTaskTree};
 use renderer::{BlendMode, ImageBufferKind};
 use renderer::BLOCKS_PER_UV_RECT;
 use resource_cache::{CacheItem, GlyphFetchResult, ImageRequest, ResourceCache};
 use std::{usize, f32, i32};
@@ -50,17 +50,16 @@ pub enum BrushImageSourceKind {
     //Alpha = 1,            // Unused for now, but left here as shaders need to match.
     ColorAlphaMask = 2,
 }
 
 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 pub enum BrushBatchKind {
-    Picture,
     Solid,
     Line,
     Image(ImageBufferKind),
     Blend,
     MixBlend {
         task_id: RenderTaskId,
         source_id: RenderTaskId,
         backdrop_id: RenderTaskId,
@@ -517,20 +516,17 @@ impl AlphaBatchBuilder {
                 BatchKind::SplitComposite,
                 BlendMode::PremultipliedAlpha,
                 BatchTextures::no_texture(),
             );
             let pic_metadata = &ctx.prim_store.cpu_metadata[prim_index.0];
             let pic = &ctx.prim_store.cpu_pictures[pic_metadata.cpu_prim_index.0];
             let batch = self.batch_list.get_suitable_batch(key, &pic_metadata.screen_rect.as_ref().expect("bug").clipped);
 
-            let render_task_id = match pic.surface {
-                Some(PictureSurface::RenderTask(render_task_id)) => render_task_id,
-                Some(PictureSurface::TextureCache(..)) | None => panic!("BUG: unexpected surface in splitting"),
-            };
+            let render_task_id = pic.surface.expect("BUG: unexpected surface in splitting");
             let source_task_address = render_tasks.get_task_address(render_task_id);
             let gpu_address = gpu_handle.as_int(gpu_cache);
 
             let instance = CompositePrimitiveInstance::new(
                 task_address,
                 source_task_address,
                 RenderTaskAddress(0),
                 gpu_address,
@@ -569,17 +565,17 @@ impl AlphaBatchBuilder {
             // Now that we walk the primitive runs in order to add
             // items to batches, we need to check if they are
             // visible here.
             // We currently only support culling on normal (Image)
             // picture types.
             // TODO(gw): Support culling on shadow image types.
             let is_image = match pic.kind {
                 PictureKind::Image { .. } => true,
-                PictureKind::BoxShadow { .. } | PictureKind::TextShadow { .. } => false,
+                PictureKind::TextShadow { .. } => false,
             };
 
             if !is_image || metadata.screen_rect.is_some() {
                 self.add_prim_to_batch(
                     metadata.clip_chain_rect_index,
                     scroll_id,
                     prim_index,
                     ctx,
@@ -796,17 +792,17 @@ impl AlphaBatchBuilder {
                 let batch = self.batch_list.get_suitable_batch(key, &task_relative_bounding_rect);
                 batch.push(base_instance.build(cache_item.uv_rect_handle.as_int(gpu_cache), 0, 0));
             }
             PrimitiveKind::TextRun => {
                 let text_cpu =
                     &ctx.prim_store.cpu_text_runs[prim_metadata.cpu_prim_index.0];
                 let is_shadow = match pic.kind {
                     PictureKind::TextShadow { .. } => true,
-                    PictureKind::BoxShadow { .. } | PictureKind::Image { .. } => false,
+                    PictureKind::Image { .. } => false,
                 };
 
                 // TODO(gw): It probably makes sense to base this decision on the content
                 //           origin field in the future (once that's configurable).
                 let font_transform = if is_shadow {
                     None
                 } else {
                     Some(scroll_node.transform)
@@ -889,48 +885,17 @@ impl AlphaBatchBuilder {
                     },
                 );
             }
             PrimitiveKind::Picture => {
                 let picture =
                     &ctx.prim_store.cpu_pictures[prim_metadata.cpu_prim_index.0];
 
                 match picture.surface {
-                    Some(PictureSurface::TextureCache(ref cache_item)) => {
-                        match picture.kind {
-                            PictureKind::TextShadow { .. } |
-                            PictureKind::Image { .. } => {
-                                panic!("BUG: only supported as render tasks for now");
-                            }
-                            PictureKind::BoxShadow { image_kind, .. } => {
-                                let textures = BatchTextures::color(cache_item.texture_id);
-                                let kind = BrushBatchKind::Picture;
-
-                                self.add_brush_to_batch(
-                                    &picture.brush,
-                                    prim_metadata,
-                                    kind,
-                                    specified_blend_mode,
-                                    non_segmented_blend_mode,
-                                    textures,
-                                    clip_chain_rect_index,
-                                    clip_task_address,
-                                    &task_relative_bounding_rect,
-                                    prim_cache_address,
-                                    scroll_id,
-                                    task_address,
-                                    transform_kind,
-                                    z,
-                                    render_tasks,
-                                    [cache_item.uv_rect_handle.as_int(gpu_cache), image_kind as i32, 0],
-                                );
-                            }
-                        }
-                    }
-                    Some(PictureSurface::RenderTask(cache_task_id)) => {
+                    Some(cache_task_id) => {
                         let cache_task_address = render_tasks.get_task_address(cache_task_id);
                         let textures = BatchTextures::render_target_cache();
 
                         match picture.kind {
                             PictureKind::TextShadow { .. } => {
                                 let kind = BatchKind::Brush(
                                     BrushBatchKind::Image(ImageBufferKind::Texture2DArray)
                                 );
@@ -954,19 +919,16 @@ impl AlphaBatchBuilder {
                                     user_data: [
                                         uv_rect_address,
                                         BrushImageSourceKind::Color as i32,
                                         0,
                                     ],
                                 };
                                 batch.push(PrimitiveInstance::from(instance));
                             }
-                            PictureKind::BoxShadow { .. } => {
-                                panic!("BUG: should be handled as a texture cache surface");
-                            }
                             PictureKind::Image {
                                 composite_mode,
                                 secondary_render_task_id,
                                 is_in_3d_context,
                                 reference_frame_index,
                                 real_local_rect,
                                 ref extra_gpu_data_handle,
                                 ..
@@ -1442,19 +1404,16 @@ impl BrushPrimitive {
                     textures,
                     [
                         uv_rect_addresses[0],
                         uv_rect_addresses[1],
                         uv_rect_addresses[2],
                     ],
                 ))
             }
-            BrushKind::Mask { .. } => {
-                unreachable!("bug: mask brushes not expected in normal alpha pass");
-            }
         }
     }
 }
 
 trait AlphaBatchHelpers {
     fn get_blend_mode(
         &self,
         metadata: &PrimitiveMetadata,
@@ -1482,17 +1441,16 @@ impl AlphaBatchHelpers for PrimitiveStor
                     }
                     BrushKind::Image { alpha_type, .. } => {
                         match alpha_type {
                             AlphaType::PremultipliedAlpha => BlendMode::PremultipliedAlpha,
                             AlphaType::Alpha => BlendMode::Alpha,
                         }
                     }
                     BrushKind::Solid { .. } |
-                    BrushKind::Mask { .. } |
                     BrushKind::Line { .. } |
                     BrushKind::YuvImage { .. } |
                     BrushKind::RadialGradient { .. } |
                     BrushKind::LinearGradient { .. } |
                     BrushKind::Picture => {
                         BlendMode::PremultipliedAlpha
                     }
                 }
@@ -1594,28 +1552,46 @@ fn make_polygon(
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 pub struct ClipBatcher {
     /// Rectangle draws fill up the rectangles with rounded corners.
     pub rectangles: Vec<ClipMaskInstance>,
     /// Image draws apply the image masking.
     pub images: FastHashMap<SourceTexture, Vec<ClipMaskInstance>>,
     pub border_clears: Vec<ClipMaskInstance>,
     pub borders: Vec<ClipMaskInstance>,
+    pub box_shadows: FastHashMap<SourceTexture, Vec<ClipMaskInstance>>,
 }
 
 impl ClipBatcher {
     pub fn new() -> Self {
         ClipBatcher {
             rectangles: Vec::new(),
             images: FastHashMap::default(),
             border_clears: Vec::new(),
             borders: Vec::new(),
+            box_shadows: FastHashMap::default(),
         }
     }
 
+    pub fn add_clip_region(
+        &mut self,
+        task_address: RenderTaskAddress,
+        clip_data_address: GpuCacheAddress,
+    ) {
+        let instance = ClipMaskInstance {
+            render_task_address: task_address,
+            scroll_node_data_index: ClipScrollNodeIndex(0),
+            segment: 0,
+            clip_data_address,
+            resource_address: GpuCacheAddress::invalid(),
+        };
+
+        self.rectangles.push(instance);
+    }
+
     pub fn add(
         &mut self,
         task_address: RenderTaskAddress,
         clips: &[ClipWorkItem],
         coordinate_system_id: CoordinateSystemId,
         resource_cache: &ResourceCache,
         gpu_cache: &GpuCache,
         clip_store: &ClipStore,
@@ -1654,16 +1630,28 @@ impl ClipBatcher {
                                     ..instance
                                 });
                         } else {
                             warn!("Warnings: skip a image mask");
                             debug!("Key:{:?} Rect::{:?}", mask.image, mask.rect);
                             continue;
                         }
                     }
+                    ClipSource::BoxShadow(ref info) => {
+                        debug_assert_ne!(info.cache_item.texture_id, SourceTexture::Invalid);
+
+                        self.box_shadows
+                            .entry(info.cache_item.texture_id)
+                            .or_insert(Vec::new())
+                            .push(ClipMaskInstance {
+                                clip_data_address: gpu_address,
+                                resource_address: gpu_cache.get_address(&info.cache_item.uv_rect_handle),
+                                ..instance
+                            });
+                    }
                     ClipSource::Rectangle(..) => {
                         if work_item.coordinate_system_id != coordinate_system_id {
                             self.rectangles.push(ClipMaskInstance {
                                 clip_data_address: gpu_address,
                                 ..instance
                             });
                             coordinate_system_id = work_item.coordinate_system_id;
                         }
--- a/gfx/webrender/src/box_shadow.rs
+++ b/gfx/webrender/src/box_shadow.rs
@@ -1,97 +1,131 @@
 /* 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/. */
 
-use api::{BorderRadius, BoxShadowClipMode, ClipMode, ColorF, ComplexClipRegion, LayerPoint};
+use api::{BorderRadius, BoxShadowClipMode, ClipMode, ColorF, ComplexClipRegion};
 use api::{LayerPrimitiveInfo, LayerRect, LayerSize, LayerVector2D, LayoutSize, LocalClip};
-use api::PipelineId;
-use app_units::Au;
+use api::{DeviceIntSize};
 use clip::ClipSource;
 use display_list_flattener::DisplayListFlattener;
-use gpu_types::BrushImageKind;
+use gpu_cache::GpuCacheHandle;
 use prim_store::{BrushKind, BrushPrimitive, PrimitiveContainer};
 use prim_store::ScrollNodeAndClipChain;
-use picture::PicturePrimitive;
-use render_task::MAX_BLUR_STD_DEVIATION;
+use resource_cache::CacheItem;
 use util::RectHelpers;
 
+#[derive(Debug)]
+pub struct BoxShadowClipSource {
+    // Parameters that define the shadow and are constant.
+    pub shadow_radius: BorderRadius,
+    pub blur_radius: f32,
+    pub clip_mode: BoxShadowClipMode,
+
+    // The current cache key (in device-pixels), and handles
+    // to the cached clip region and blurred texture.
+    pub cache_key: Option<(DeviceIntSize, BoxShadowCacheKey)>,
+    pub cache_item: CacheItem,
+    pub clip_data_handle: GpuCacheHandle,
+
+    // Local-space size of the required render task size.
+    pub shadow_rect_alloc_size: LayerSize,
+
+    // The minimal shadow rect for the parameters above,
+    // used when drawing the shadow rect to be blurred.
+    pub minimal_shadow_rect: LayerRect,
+
+    // Local space rect for the shadow to be drawn or
+    // stretched in the shadow primitive.
+    pub prim_shadow_rect: LayerRect,
+}
+
 // The blur shader samples BLUR_SAMPLE_SCALE * blur_radius surrounding texels.
 pub const BLUR_SAMPLE_SCALE: f32 = 3.0;
 
 // Maximum blur radius.
 // Taken from https://searchfox.org/mozilla-central/rev/c633ffa4c4611f202ca11270dcddb7b29edddff8/layout/painting/nsCSSRendering.cpp#4412
 pub const MAX_BLUR_RADIUS : f32 = 300.;
 
-#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq)]
+// A cache key that uniquely identifies a minimally sized
+// and blurred box-shadow rect that can be stored in the
+// texture cache and applied to clip-masks.
+#[derive(Debug, Clone, Eq, Hash, PartialEq)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 pub struct BoxShadowCacheKey {
-    pub width: Au,
-    pub height: Au,
-    pub blur_radius: Au,
-    pub spread_radius: Au,
-    pub offset_x: Au,
-    pub offset_y: Au,
-    pub br_top_left_w: Au,
-    pub br_top_left_h: Au,
-    pub br_top_right_w: Au,
-    pub br_top_right_h: Au,
-    pub br_bottom_left_w: Au,
-    pub br_bottom_left_h: Au,
-    pub br_bottom_right_w: Au,
-    pub br_bottom_right_h: Au,
+    pub blur_radius_dp: i32,
     pub clip_mode: BoxShadowClipMode,
+    pub rect_size: DeviceIntSize,
+    pub br_top_left: DeviceIntSize,
+    pub br_top_right: DeviceIntSize,
+    pub br_bottom_right: DeviceIntSize,
+    pub br_bottom_left: DeviceIntSize,
 }
 
 impl<'a> DisplayListFlattener<'a> {
     pub fn add_box_shadow(
         &mut self,
-        pipeline_id: PipelineId,
         clip_and_scroll: ScrollNodeAndClipChain,
         prim_info: &LayerPrimitiveInfo,
         box_offset: &LayerVector2D,
         color: &ColorF,
         mut blur_radius: f32,
         spread_radius: f32,
         border_radius: BorderRadius,
         clip_mode: BoxShadowClipMode,
     ) {
         if color.a == 0.0 {
             return;
         }
 
-        let (spread_amount, brush_clip_mode) = match clip_mode {
+        // Inset shadows get smaller as spread radius increases.
+        let (spread_amount, prim_clip_mode) = match clip_mode {
             BoxShadowClipMode::Outset => {
-                (spread_radius, ClipMode::Clip)
+                (spread_radius, ClipMode::ClipOut)
             }
             BoxShadowClipMode::Inset => {
-                (-spread_radius, ClipMode::ClipOut)
+                (-spread_radius, ClipMode::Clip)
             }
         };
 
+        // Ensure the blur radius is somewhat sensible.
         blur_radius = f32::min(blur_radius, MAX_BLUR_RADIUS);
+
+        // Adjust the border radius of the box shadow per CSS-spec.
         let shadow_radius = adjust_border_radius_for_box_shadow(
             border_radius,
             spread_amount,
         );
+
+        // Apply parameters that affect where the shadow rect
+        // exists in the local space of the primitive.
         let shadow_rect = prim_info.rect
             .translate(box_offset)
             .inflate(spread_amount, spread_amount);
 
+        // If blur radius is zero, we can use a fast path with
+        // no blur applied.
         if blur_radius == 0.0 {
-            if box_offset.x == 0.0 && box_offset.y == 0.0 && spread_amount == 0.0 {
+            // Trivial reject of box-shadows that are not visible.
+            if box_offset.x == 0.0 &&
+               box_offset.y == 0.0 &&
+               spread_amount == 0.0 {
                 return;
             }
+
             let mut clips = Vec::with_capacity(2);
             clips.push(ClipSource::Rectangle(*prim_info.local_clip.clip_rect()));
 
             let fast_info = match clip_mode {
                 BoxShadowClipMode::Outset => {
+                    if !shadow_rect.is_well_formed_and_nonempty() {
+                        return;
+                    }
+
                     // TODO(gw): Add a fast path for ClipOut + zero border radius!
                     clips.push(ClipSource::new_rounded_rect(
                         prim_info.rect,
                         border_radius,
                         ClipMode::ClipOut
                     ));
 
                     LayerPrimitiveInfo::with_clip(
@@ -102,21 +136,23 @@ impl<'a> DisplayListFlattener<'a> {
                                 shadow_rect,
                                 shadow_radius,
                                 ClipMode::Clip,
                             ),
                         ),
                     )
                 }
                 BoxShadowClipMode::Inset => {
-                    clips.push(ClipSource::new_rounded_rect(
-                        shadow_rect,
-                        shadow_radius,
-                        ClipMode::ClipOut
-                    ));
+                    if shadow_rect.is_well_formed_and_nonempty() {
+                        clips.push(ClipSource::new_rounded_rect(
+                            shadow_rect,
+                            shadow_radius,
+                            ClipMode::ClipOut
+                        ));
+                    }
 
                     LayerPrimitiveInfo::with_clip(
                         prim_info.rect,
                         LocalClip::RoundedRect(
                             prim_info.rect,
                             ComplexClipRegion::new(
                                 prim_info.rect,
                                 border_radius,
@@ -135,223 +171,93 @@ impl<'a> DisplayListFlattener<'a> {
                     BrushPrimitive::new(BrushKind::Solid {
                             color: *color,
                         },
                         None,
                     )
                 ),
             );
         } else {
+            // Normal path for box-shadows with a valid blur radius.
             let blur_offset = BLUR_SAMPLE_SCALE * blur_radius;
             let mut extra_clips = vec![];
 
-            let cache_key = BoxShadowCacheKey {
-                width: Au::from_f32_px(shadow_rect.size.width),
-                height: Au::from_f32_px(shadow_rect.size.height),
-                blur_radius: Au::from_f32_px(blur_radius),
-                spread_radius: Au::from_f32_px(spread_radius),
-                offset_x: Au::from_f32_px(box_offset.x),
-                offset_y: Au::from_f32_px(box_offset.y),
-                br_top_left_w: Au::from_f32_px(border_radius.top_left.width),
-                br_top_left_h: Au::from_f32_px(border_radius.top_left.height),
-                br_top_right_w: Au::from_f32_px(border_radius.top_right.width),
-                br_top_right_h: Au::from_f32_px(border_radius.top_right.height),
-                br_bottom_left_w: Au::from_f32_px(border_radius.bottom_left.width),
-                br_bottom_left_h: Au::from_f32_px(border_radius.bottom_left.height),
-                br_bottom_right_w: Au::from_f32_px(border_radius.bottom_right.width),
-                br_bottom_right_h: Au::from_f32_px(border_radius.bottom_right.height),
+            // Add a normal clip mask to clip out the contents
+            // of the surrounding primitive.
+            extra_clips.push(ClipSource::new_rounded_rect(
+                prim_info.rect,
+                border_radius,
+                prim_clip_mode,
+            ));
+
+            // Get the local rect of where the shadow will be drawn,
+            // expanded to include room for the blurred region.
+            let dest_rect = shadow_rect.inflate(blur_offset, blur_offset);
+
+            // Draw the box-shadow as a solid rect, using a box-shadow
+            // clip mask source.
+            let prim = BrushPrimitive::new(
+                BrushKind::Solid {
+                    color: *color,
+                },
+                None,
+            );
+
+            // Create the box-shadow clip source.
+            let shadow_clip_source = ClipSource::new_box_shadow(
+                shadow_rect,
+                shadow_radius,
+                dest_rect,
+                blur_radius,
                 clip_mode,
-            };
+            );
 
-            match clip_mode {
+            let prim_info = match clip_mode {
                 BoxShadowClipMode::Outset => {
-                    let mut width;
-                    let mut height;
-                    let brush_prim;
-                    let mut image_kind = BrushImageKind::NinePatch;
-
+                    // Certain spread-radii make the shadow invalid.
                     if !shadow_rect.is_well_formed_and_nonempty() {
                         return;
                     }
 
-                    // Create a minimal size primitive mask to blur. In this
-                    // case, we ensure the size of each corner is the same,
-                    // to simplify the shader logic that stretches the blurred
-                    // result across the primitive.
-                    let max_width = shadow_radius.top_left.width
-                                        .max(shadow_radius.bottom_left.width)
-                                        .max(shadow_radius.top_right.width)
-                                        .max(shadow_radius.bottom_right.width);
-                    let max_height = shadow_radius.top_left.height
-                                        .max(shadow_radius.bottom_left.height)
-                                        .max(shadow_radius.top_right.height)
-                                        .max(shadow_radius.bottom_right.height);
-
-                    width = 2.0 * max_width + BLUR_SAMPLE_SCALE * blur_radius;
-                    height = 2.0 * max_height + BLUR_SAMPLE_SCALE * blur_radius;
-
-                    // If the width or height ends up being bigger than the original
-                    // primitive shadow rect, just blur the entire rect and draw that
-                    // as a simple blit.
-                    if width > prim_info.rect.size.width || height > prim_info.rect.size.height {
-                        image_kind = BrushImageKind::Simple;
-                        width = prim_info.rect.size.width + spread_amount * 2.0;
-                        height = prim_info.rect.size.height + spread_amount * 2.0;
-                    }
-
-                    let clip_rect = LayerRect::new(
-                        LayerPoint::zero(),
-                        LayerSize::new(width, height)
-                    );
-
-                    brush_prim = BrushPrimitive::new(
-                        BrushKind::Mask {
-                            clip_mode: brush_clip_mode,
-                            rect: clip_rect,
-                            radii: shadow_radius,
-                        },
-                        None,
-                    );
+                    // Add the box-shadow clip source.
+                    extra_clips.push(shadow_clip_source);
 
-                    // Construct a mask primitive to add to the picture.
-                    let brush_rect = LayerRect::new(LayerPoint::zero(),
-                                                    LayerSize::new(width, height));
-                    let brush_info = LayerPrimitiveInfo::new(brush_rect);
-                    let brush_prim_index = self.create_primitive(
-                        &brush_info,
-                        Vec::new(),
-                        PrimitiveContainer::Brush(brush_prim),
-                    );
-
-                    // Create a box shadow picture and add the mask primitive to it.
-                    let pic_rect = shadow_rect.inflate(blur_offset, blur_offset);
-                    let mut pic_prim = PicturePrimitive::new_box_shadow(
-                        blur_radius,
-                        *color,
-                        clip_mode,
-                        image_kind,
-                        cache_key,
-                        pipeline_id,
-                    );
-                    pic_prim.add_primitive(
-                        brush_prim_index,
-                        clip_and_scroll
-                    );
-
-                    extra_clips.push(ClipSource::new_rounded_rect(
-                        prim_info.rect,
-                        border_radius,
-                        ClipMode::ClipOut,
-                    ));
-                    let pic_info = LayerPrimitiveInfo::with_clip_rect(
-                        pic_rect,
+                    // Outset shadows are expanded by the shadow
+                    // region from the original primitive.
+                    LayerPrimitiveInfo::with_clip_rect(
+                        dest_rect,
                         *prim_info.local_clip.clip_rect()
-                    );
-                    self.add_primitive(
-                        clip_and_scroll,
-                        &pic_info,
-                        extra_clips,
-                        PrimitiveContainer::Picture(pic_prim),
-                    );
+                    )
                 }
                 BoxShadowClipMode::Inset => {
-                    // TODO(gw): Inset shadows still need an optimization pass.
-                    //           We draw and blur way more pixels than needed.
-
-                    // Draw a picture that covers the area of the primitive rect.
-                    let brush_rect = LayerRect::new(
-                        LayerPoint::zero(),
-                        prim_info.rect.size
-                    );
-
-                    // Define where the inset box shadow rect is, local
-                    // to the brush rect above.
-                    let clip_rect = brush_rect.translate(box_offset)
-                                              .inflate(spread_amount, spread_amount);
-
-                    // Ensure there are more than one pixel around the edges, so that there
-                    // is non-zero data to blur, in the case of an inset shadow
-                    // with zero spread and zero offset.
-                    // The size of inflation edge is determined by std deviation because large
-                    // std deviation blur would be downscaled first. Thus, we need more thick
-                    // edge to prevent edge get blurred after downscled.
-                    let mut adjusted_blur_std_deviation = blur_radius * 0.5;
-                    let mut inflate_size = 1.0;
-                    while adjusted_blur_std_deviation > MAX_BLUR_STD_DEVIATION {
-                        adjusted_blur_std_deviation *= 0.5;
-                        inflate_size *= 2.0;
+                    // If the inner shadow rect contains the prim
+                    // rect, no pixels will be shadowed.
+                    if border_radius.is_zero() &&
+                       shadow_rect.inflate(-blur_radius, -blur_radius).contains_rect(&prim_info.rect) {
+                        return;
                     }
 
-                    let brush_rect = brush_rect.inflate(inflate_size + box_offset.x.abs(), inflate_size + box_offset.y.abs());
-                    let brush_prim = BrushPrimitive::new(
-                        BrushKind::Mask {
-                            clip_mode: brush_clip_mode,
-                            rect: clip_rect,
-                            radii: shadow_radius,
-                        },
-                        None,
-                    );
-                    let brush_info = LayerPrimitiveInfo::new(brush_rect);
-                    let brush_prim_index = self.create_primitive(
-                        &brush_info,
-                        Vec::new(),
-                        PrimitiveContainer::Brush(brush_prim),
-                    );
-
-                    // Create a box shadow picture primitive and add
-                    // the brush primitive to it.
-                    let mut pic_prim = PicturePrimitive::new_box_shadow(
-                        blur_radius,
-                        *color,
-                        BoxShadowClipMode::Inset,
-                        // TODO(gw): Make use of optimization for inset.
-                        BrushImageKind::NinePatch,
-                        cache_key,
-                        pipeline_id,
-                    );
-                    pic_prim.add_primitive(
-                        brush_prim_index,
-                        clip_and_scroll
-                    );
-
-                    let clip_rect = prim_info.local_clip.clip_rect();
-                    let clip_rect = match prim_info.rect.intersection(clip_rect) {
-                        Some(clip_rect) => clip_rect,
-                        None => return,
-                    };
-
-                    // Draw the picture one pixel outside the original
-                    // rect to account for the inflate above. This
-                    // extra edge will be clipped by the local clip
-                    // rect set below.
-                    let pic_rect = prim_info.rect.inflate(inflate_size + box_offset.x.abs(), inflate_size + box_offset.y.abs());
-                    let pic_info = LayerPrimitiveInfo::with_clip_rect(
-                        pic_rect,
-                        clip_rect
-                    );
-
-                    // Add a normal clip to ensure nothing gets drawn
-                    // outside the primitive rect.
-                    if !border_radius.is_zero() {
-                        extra_clips.push(ClipSource::new_rounded_rect(
-                            prim_info.rect,
-                            border_radius,
-                            ClipMode::Clip,
-                        ));
+                    // Inset shadows are still visible, even if the
+                    // inset shadow rect becomes invalid (they will
+                    // just look like a solid rectangle).
+                    if shadow_rect.is_well_formed_and_nonempty() {
+                        extra_clips.push(shadow_clip_source);
                     }
 
-                    // Add the picture primitive to the frame.
-                    self.add_primitive(
-                        clip_and_scroll,
-                        &pic_info,
-                        extra_clips,
-                        PrimitiveContainer::Picture(pic_prim),
-                    );
+                    // Inset shadows draw inside the original primitive.
+                    prim_info.clone()
                 }
-            }
+            };
+
+            self.add_primitive(
+                clip_and_scroll,
+                &prim_info,
+                extra_clips,
+                PrimitiveContainer::Brush(prim),
+            );
         }
     }
 }
 
 fn adjust_border_radius_for_box_shadow(
     radius: BorderRadius,
     spread_amount: f32,
 ) -> BorderRadius {
--- a/gfx/webrender/src/clip.rs
+++ b/gfx/webrender/src/clip.rs
@@ -1,22 +1,25 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 use api::{BorderRadius, ClipMode, ComplexClipRegion, DeviceIntRect, DevicePixelScale, ImageMask};
-use api::{ImageRendering, LayerRect, LayoutPoint, LayoutVector2D, LocalClip};
+use api::{ImageRendering, LayerRect, LayerSize, LayoutPoint, LayoutVector2D, LocalClip};
+use api::{BoxShadowClipMode, LayerPoint, LayerToWorldScale};
 use border::{BorderCornerClipSource, ensure_no_corner_overlap};
+use box_shadow::{BLUR_SAMPLE_SCALE, BoxShadowClipSource, BoxShadowCacheKey};
 use clip_scroll_tree::{ClipChainIndex, CoordinateSystemId};
 use ellipse::Ellipse;
 use freelist::{FreeList, FreeListHandle, WeakFreeListHandle};
 use gpu_cache::{GpuCache, GpuCacheHandle, ToGpuBlocks};
 use gpu_types::ClipScrollNodeIndex;
 use prim_store::{ClipData, ImageMaskData};
-use resource_cache::{ImageRequest, ResourceCache};
+use render_task::to_cache_size;
+use resource_cache::{CacheItem, ImageRequest, ResourceCache};
 use util::{LayerToWorldFastTransform, MaxRect, calculate_screen_bounding_rect};
 use util::extract_inner_rect_safe;
 use std::sync::Arc;
 
 pub type ClipStore = FreeList<ClipSources>;
 pub type ClipSourcesHandle = FreeListHandle<ClipSources>;
 pub type ClipSourcesWeakHandle = WeakFreeListHandle<ClipSources>;
 
@@ -73,16 +76,17 @@ pub enum ClipSource {
     Rectangle(LayerRect),
     RoundedRectangle(LayerRect, BorderRadius, ClipMode),
     Image(ImageMask),
     /// TODO(gw): This currently only handles dashed style
     /// clips, where the border style is dashed for both
     /// adjacent border edges. Expand to handle dotted style
     /// and different styles per edge.
     BorderCorner(BorderCornerClipSource),
+    BoxShadow(BoxShadowClipSource),
 }
 
 impl From<ClipRegion> for ClipSources {
     fn from(region: ClipRegion) -> ClipSources {
         let mut clips = Vec::new();
 
         if let Some(info) = region.image_mask {
             clips.push(ClipSource::Image(info));
@@ -110,16 +114,99 @@ impl ClipSource {
     ) -> ClipSource {
         ensure_no_corner_overlap(&mut radii, &rect);
         ClipSource::RoundedRectangle(
             rect,
             radii,
             clip_mode,
         )
     }
+
+    pub fn new_box_shadow(
+        shadow_rect: LayerRect,
+        shadow_radius: BorderRadius,
+        prim_shadow_rect: LayerRect,
+        blur_radius: f32,
+        clip_mode: BoxShadowClipMode,
+    ) -> ClipSource {
+        // Get the fractional offsets required to match the
+        // source rect with a minimal rect.
+        let fract_offset = LayerPoint::new(
+            shadow_rect.origin.x.fract().abs(),
+            shadow_rect.origin.y.fract().abs(),
+        );
+        let fract_size = LayerSize::new(
+            shadow_rect.size.width.fract().abs(),
+            shadow_rect.size.height.fract().abs(),
+        );
+
+        // Create a minimal size primitive mask to blur. In this
+        // case, we ensure the size of each corner is the same,
+        // to simplify the shader logic that stretches the blurred
+        // result across the primitive.
+        let max_corner_width = shadow_radius.top_left.width
+                                    .max(shadow_radius.bottom_left.width)
+                                    .max(shadow_radius.top_right.width)
+                                    .max(shadow_radius.bottom_right.width);
+        let max_corner_height = shadow_radius.top_left.height
+                                    .max(shadow_radius.bottom_left.height)
+                                    .max(shadow_radius.top_right.height)
+                                    .max(shadow_radius.bottom_right.height);
+
+        // Get maximum distance that can be affected by given blur radius.
+        let blur_region = (BLUR_SAMPLE_SCALE * blur_radius).ceil();
+
+        // If the largest corner is smaller than the blur radius, we need to ensure
+        // that it's big enough that the corners don't affect the middle segments.
+        let used_corner_width = max_corner_width.max(blur_region);
+        let used_corner_height = max_corner_height.max(blur_region);
+
+        // Minimal nine-patch size, corner + internal + corner.
+        let min_shadow_rect_size = LayerSize::new(
+            2.0 * used_corner_width + blur_region,
+            2.0 * used_corner_height + blur_region,
+        );
+
+        // The minimal rect to blur.
+        let mut minimal_shadow_rect = LayerRect::new(
+            LayerPoint::new(
+                blur_region + fract_offset.x,
+                blur_region + fract_offset.y,
+            ),
+            LayerSize::new(
+                min_shadow_rect_size.width + fract_size.width,
+                min_shadow_rect_size.height + fract_size.height,
+            ),
+        );
+
+        // If the width or height ends up being bigger than the original
+        // primitive shadow rect, just blur the entire rect and draw that
+        // as a simple blit. This is necessary for correctness, since the
+        // blur of one corner may affect the blur in another corner.
+        minimal_shadow_rect.size.width = minimal_shadow_rect.size.width.min(shadow_rect.size.width);
+        minimal_shadow_rect.size.height = minimal_shadow_rect.size.height.min(shadow_rect.size.height);
+
+        // Expand the shadow rect by enough room for the blur to take effect.
+        let shadow_rect_alloc_size = LayerSize::new(
+            2.0 * blur_region + minimal_shadow_rect.size.width.ceil(),
+            2.0 * blur_region + minimal_shadow_rect.size.height.ceil(),
+        );
+
+        ClipSource::BoxShadow(BoxShadowClipSource {
+            shadow_rect_alloc_size,
+            shadow_radius,
+            prim_shadow_rect,
+            blur_radius,
+            clip_mode,
+            cache_item: CacheItem::invalid(),
+            cache_key: None,
+            clip_data_handle: GpuCacheHandle::new(),
+            minimal_shadow_rect,
+        })
+    }
 }
 
 #[derive(Debug)]
 pub struct ClipSources {
     pub clips: Vec<(ClipSource, GpuCacheHandle)>,
     pub local_inner_rect: LayerRect,
     pub local_outer_rect: Option<LayerRect>
 }
@@ -181,16 +268,17 @@ impl ClipSources {
 
                     can_calculate_outer_rect = true;
                     local_outer = local_outer.and_then(|r| r.intersection(rect));
 
                     let inner_rect = extract_inner_rect_safe(rect, radius);
                     local_inner = local_inner
                         .and_then(|r| inner_rect.and_then(|ref inner| r.intersection(inner)));
                 }
+                ClipSource::BoxShadow(..) |
                 ClipSource::BorderCorner { .. } => {
                     can_calculate_inner_rect = false;
                     break;
                 }
             }
         }
 
         let outer = match can_calculate_outer_rect {
@@ -205,47 +293,91 @@ impl ClipSources {
 
         (inner, outer)
     }
 
     pub fn update(
         &mut self,
         gpu_cache: &mut GpuCache,
         resource_cache: &mut ResourceCache,
+        device_pixel_scale: DevicePixelScale,
     ) {
         for &mut (ref mut source, ref mut handle) in &mut self.clips {
             if let Some(mut request) = gpu_cache.request(handle) {
                 match *source {
                     ClipSource::Image(ref mask) => {
                         let data = ImageMaskData { local_rect: mask.rect };
                         data.write_gpu_blocks(request);
                     }
+                    ClipSource::BoxShadow(ref info) => {
+                        request.push([
+                            info.shadow_rect_alloc_size.width,
+                            info.shadow_rect_alloc_size.height,
+                            info.clip_mode as i32 as f32,
+                            0.0,
+                        ]);
+                        request.push(info.prim_shadow_rect);
+                    }
                     ClipSource::Rectangle(rect) => {
                         let data = ClipData::uniform(rect, 0.0, ClipMode::Clip);
                         data.write(&mut request);
                     }
                     ClipSource::RoundedRectangle(ref rect, ref radius, mode) => {
                         let data = ClipData::rounded_rect(rect, radius, mode);
                         data.write(&mut request);
                     }
                     ClipSource::BorderCorner(ref mut source) => {
                         source.write(request);
                     }
                 }
             }
 
-            if let ClipSource::Image(ref mask) = *source {
-                resource_cache.request_image(
-                    ImageRequest {
-                        key: mask.image,
-                        rendering: ImageRendering::Auto,
-                        tile: None,
-                    },
-                    gpu_cache,
-                );
+            match *source {
+                ClipSource::Image(ref mask) => {
+                    resource_cache.request_image(
+                        ImageRequest {
+                            key: mask.image,
+                            rendering: ImageRendering::Auto,
+                            tile: None,
+                        },
+                        gpu_cache,
+                    );
+                }
+                ClipSource::BoxShadow(ref mut info) => {
+                    // Quote from https://drafts.csswg.org/css-backgrounds-3/#shadow-blur
+                    // "the image that would be generated by applying to the shadow a
+                    // Gaussian blur with a standard deviation equal to half the blur radius."
+                    let blur_radius_dp = (info.blur_radius * 0.5 * device_pixel_scale.0).round();
+
+                    // Create the cache key for this box-shadow render task.
+                    let content_scale = LayerToWorldScale::new(1.0) * device_pixel_scale;
+                    let cache_size = to_cache_size(info.shadow_rect_alloc_size * content_scale);
+                    let bs_cache_key = BoxShadowCacheKey {
+                        blur_radius_dp: blur_radius_dp as i32,
+                        clip_mode: info.clip_mode,
+                        rect_size: (info.shadow_rect_alloc_size * content_scale).round().to_i32(),
+                        br_top_left: (info.shadow_radius.top_left * content_scale).round().to_i32(),
+                        br_top_right: (info.shadow_radius.top_right * content_scale).round().to_i32(),
+                        br_bottom_right: (info.shadow_radius.bottom_right * content_scale).round().to_i32(),
+                        br_bottom_left: (info.shadow_radius.bottom_left * content_scale).round().to_i32(),
+                    };
+
+                    info.cache_key = Some((cache_size, bs_cache_key));
+
+                    if let Some(mut request) = gpu_cache.request(&mut info.clip_data_handle) {
+                        let data = ClipData::rounded_rect(
+                            &info.minimal_shadow_rect,
+                            &info.shadow_radius,
+                            ClipMode::Clip,
+                        );
+
+                        data.write(&mut request);
+                    }
+                }
+                _ => {}
             }
         }
     }
 
     pub fn get_screen_bounds(
         &self,
         transform: &LayerToWorldFastTransform,
         device_pixel_scale: DevicePixelScale,
--- a/gfx/webrender/src/clip_scroll_node.rs
+++ b/gfx/webrender/src/clip_scroll_node.rs
@@ -365,17 +365,21 @@ impl ClipScrollNode {
                 (handle, clip_chain_index, clip_chain_node),
             _ => {
                 self.invertible = true;
                 return;
             }
         };
 
         let clip_sources = clip_store.get_mut(clip_sources_handle);
-        clip_sources.update(gpu_cache, resource_cache);
+        clip_sources.update(
+            gpu_cache,
+            resource_cache,
+            device_pixel_scale,
+        );
         let (screen_inner_rect, screen_outer_rect) =
             clip_sources.get_screen_bounds(&self.world_viewport_transform, device_pixel_scale);
 
         // All clipping ClipScrollNodes should have outer rectangles, because they never
         // use the BorderCorner clip type and they always have at last one non-ClipOut
         // Rectangle ClipSource.
         let screen_outer_rect = screen_outer_rect.expect("Clipping node didn't have outer rect.");
         let local_outer_rect = clip_sources.local_outer_rect.expect(
--- a/gfx/webrender/src/display_list_flattener.rs
+++ b/gfx/webrender/src/display_list_flattener.rs
@@ -736,17 +736,16 @@ impl<'a> DisplayListFlattener<'a> {
             }
             SpecificDisplayItem::BoxShadow(ref box_shadow_info) => {
                 let bounds = box_shadow_info
                     .box_bounds
                     .translate(&reference_frame_relative_offset);
                 let mut prim_info = prim_info.clone();
                 prim_info.rect = bounds;
                 self.add_box_shadow(
-                    pipeline_id,
                     clip_and_scroll,
                     &prim_info,
                     &box_shadow_info.offset,
                     &box_shadow_info.color,
                     box_shadow_info.blur_radius,
                     box_shadow_info.spread_radius,
                     box_shadow_info.border_radius,
                     box_shadow_info.clip_mode,
@@ -1307,19 +1306,18 @@ impl<'a> DisplayListFlattener<'a> {
             match parent_pic.kind {
                 PictureKind::Image { ref mut composite_mode, .. } => {
                     // If not already isolated for some other reason,
                     // make this picture as isolated.
                     if composite_mode.is_none() {
                         *composite_mode = Some(PictureCompositeMode::Blit);
                     }
                 }
-                PictureKind::TextShadow { .. } |
-                PictureKind::BoxShadow { .. } => {
-                    panic!("bug: text/box pictures invalid here");
+                PictureKind::TextShadow { .. } => {
+                    panic!("bug: text pictures invalid here");
                 }
             }
         }
 
         // Get the transform-style of the parent stacking context,
         // which determines if we *might* need to draw this on
         // an intermediate surface for plane splitting purposes.
         let parent_transform_style = match self.sc_stack.last() {
--- a/gfx/webrender/src/frame_builder.rs
+++ b/gfx/webrender/src/frame_builder.rs
@@ -8,17 +8,17 @@ use api::{LayerRect, LayerSize, Pipeline
 use clip::{ClipChain, ClipStore};
 use clip_scroll_node::{ClipScrollNode};
 use clip_scroll_tree::{ClipScrollNodeIndex, ClipScrollTree};
 use display_list_flattener::{DisplayListFlattener};
 use gpu_cache::GpuCache;
 use gpu_types::{ClipChainRectIndex, ClipScrollNodeData, PictureType};
 use hit_test::{HitTester, HitTestingRun};
 use internal_types::{FastHashMap};
-use picture::{ContentOrigin, PictureSurface};
+use picture::{ContentOrigin};
 use prim_store::{CachedGradient, PrimitiveIndex, PrimitiveRun, PrimitiveStore};
 use profiler::{FrameProfileCounters, GpuCacheProfileCounters, TextureCacheProfileCounters};
 use render_backend::FrameId;
 use render_task::{ClearMode, RenderTask, RenderTaskId, RenderTaskLocation, RenderTaskTree};
 use resource_cache::{ResourceCache};
 use scene::{ScenePipeline, SceneProperties};
 use std::{mem, f32};
 use std::sync::Arc;
@@ -230,17 +230,17 @@ impl FrameBuilder {
             ContentOrigin::Screen(DeviceIntPoint::zero()),
             PremultipliedColorF::TRANSPARENT,
             ClearMode::Transparent,
             pic_state.tasks,
             PictureType::Image,
         );
 
         let render_task_id = frame_state.render_tasks.add(root_render_task);
-        pic.surface = Some(PictureSurface::RenderTask(render_task_id));
+        pic.surface = Some(render_task_id);
         Some(render_task_id)
     }
 
     fn update_scroll_bars(&mut self, clip_scroll_tree: &ClipScrollTree, gpu_cache: &mut GpuCache) {
         static SCROLLBAR_PADDING: f32 = 8.0;
 
         for scrollbar_prim in &self.scrollbar_prims {
             let metadata = &mut self.prim_store.cpu_metadata[scrollbar_prim.prim_index.0];
--- a/gfx/webrender/src/gpu_types.rs
+++ b/gfx/webrender/src/gpu_types.rs
@@ -4,16 +4,25 @@
 
 use api::{DevicePoint, LayerToWorldTransform, PremultipliedColorF, WorldToLayerTransform};
 use gpu_cache::{GpuCacheAddress, GpuDataRequest};
 use prim_store::EdgeAaSegmentMask;
 use render_task::RenderTaskAddress;
 
 // Contains type that must exactly match the same structures declared in GLSL.
 
+#[derive(Debug, Copy, Clone)]
+#[cfg_attr(feature = "capture", derive(Serialize))]
+#[cfg_attr(feature = "replay", derive(Deserialize))]
+#[repr(C)]
+pub enum RasterizationSpace {
+    Local = 0,
+    Screen = 1,
+}
+
 #[repr(i32)]
 #[derive(Debug, Copy, Clone)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 pub enum BlurDirection {
     Horizontal = 0,
     Vertical,
 }
@@ -190,26 +199,16 @@ impl From<BrushInstance> for PrimitiveIn
                 instance.user_data[0],
                 instance.user_data[1],
                 instance.user_data[2],
             ]
         }
     }
 }
 
-// Defines how a brush image is stretched onto the primitive.
-// In the future, we may draw with segments for each portion
-// of the primitive, in which case this will be redundant.
-#[repr(C)]
-#[derive(Debug, Copy, Clone)]
-pub enum BrushImageKind {
-    Simple = 0,     // A normal rect
-    NinePatch = 1,  // A nine-patch image (stretch inside segments)
-}
-
 #[derive(Copy, Debug, Clone, PartialEq)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 #[repr(C)]
 pub struct ClipScrollNodeIndex(pub u32);
 
 #[derive(Debug)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
@@ -239,17 +238,16 @@ pub struct ClipChainRectIndex(pub usize)
 
 #[derive(Copy, Debug, Clone, PartialEq)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 #[repr(C)]
 pub enum PictureType {
     Image = 1,
     TextShadow = 2,
-    BoxShadow = 3,
 }
 
 #[derive(Debug, Copy, Clone)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 #[repr(C)]
 pub struct ImageSource {
     pub p0: DevicePoint,
--- a/gfx/webrender/src/hit_test.rs
+++ b/gfx/webrender/src/hit_test.rs
@@ -295,18 +295,20 @@ fn get_regions_for_clip_scroll_node(
     };
 
     clips.iter().map(|ref source| {
         match source.0 {
             ClipSource::Rectangle(ref rect) => HitTestRegion::Rectangle(*rect),
             ClipSource::RoundedRectangle(ref rect, ref radii, ref mode) =>
                 HitTestRegion::RoundedRectangle(*rect, *radii, *mode),
             ClipSource::Image(ref mask) => HitTestRegion::Rectangle(mask.rect),
-            ClipSource::BorderCorner(_) =>
-                unreachable!("Didn't expect to hit test against BorderCorner"),
+            ClipSource::BorderCorner(_) |
+            ClipSource::BoxShadow(_) => {
+                unreachable!("Didn't expect to hit test against BorderCorner / BoxShadow");
+            }
         }
     }).collect()
 }
 
 pub struct HitTest {
     pipeline_id: Option<PipelineId>,
     point: WorldPoint,
     flags: HitTestFlags,
--- a/gfx/webrender/src/picture.rs
+++ b/gfx/webrender/src/picture.rs
@@ -1,44 +1,28 @@
 /* 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/. */
 
-use api::{DeviceIntPoint, DeviceIntRect, DeviceIntSize, DeviceSize};
+use api::{DeviceIntPoint, DeviceIntRect};
 use api::{LayerPoint, LayerRect, LayerToWorldScale, LayerVector2D};
-use api::{BoxShadowClipMode, ColorF, FilterOp, MixBlendMode, PipelineId};
+use api::{ColorF, FilterOp, MixBlendMode, PipelineId};
 use api::{PremultipliedColorF, Shadow};
-use box_shadow::{BLUR_SAMPLE_SCALE, BoxShadowCacheKey};
+use box_shadow::{BLUR_SAMPLE_SCALE};
 use clip_scroll_tree::ClipScrollNodeIndex;
 use frame_builder::{FrameBuildingContext, FrameBuildingState, PictureState};
 use gpu_cache::{GpuCacheHandle, GpuDataRequest};
-use gpu_types::{BrushImageKind, PictureType};
+use gpu_types::{PictureType};
 use prim_store::{BrushKind, BrushPrimitive, PrimitiveIndex, PrimitiveRun, PrimitiveRunLocalRect};
 use prim_store::ScrollNodeAndClipChain;
-use render_task::{ClearMode, RenderTask, RenderTaskCacheKey};
-use render_task::{RenderTaskCacheKeyKind, RenderTaskId, RenderTaskLocation};
-use resource_cache::CacheItem;
+use render_task::{ClearMode, RenderTask};
+use render_task::{RenderTaskId, RenderTaskLocation, to_cache_size};
 use scene::{FilterOpHelpers, SceneProperties};
 use tiling::RenderTargetKind;
 
-
-// TODO(gw): Rounding the content rect here to device pixels is not
-// technically correct. Ideally we should ceil() here, and ensure that
-// the extra part pixel in the case of fractional sizes is correctly
-// handled. For now, just use rounding which passes the existing
-// Gecko tests.
-// Note: zero-square tasks are prohibited in WR task tree, so
-// we ensure each dimension to be at least the length of 1 after rounding.
-fn to_cache_size(size: DeviceSize) -> DeviceIntSize {
-    DeviceIntSize::new(
-        1.max(size.width.round() as i32),
-        1.max(size.height.round() as i32),
-    )
-}
-
 /*
  A picture represents a dynamically rendered image. It consists of:
 
  * A number of primitives that are drawn onto the picture.
  * A composite operation describing how to composite this
    picture into its parent.
  * A configuration describing how to draw the primitives on
    this picture (e.g. in screen space or local space).
@@ -70,24 +54,16 @@ pub enum ContentOrigin {
 #[derive(Debug)]
 pub enum PictureKind {
     TextShadow {
         offset: LayerVector2D,
         color: ColorF,
         blur_radius: f32,
         content_rect: LayerRect,
     },
-    BoxShadow {
-        blur_radius: f32,
-        color: ColorF,
-        clip_mode: BoxShadowClipMode,
-        image_kind: BrushImageKind,
-        content_rect: LayerRect,
-        cache_key: BoxShadowCacheKey,
-    },
     Image {
         // If a mix-blend-mode, contains the render task for
         // the readback of the framebuffer that we use to sample
         // from in the mix-blend-mode shader.
         // For drop-shadow filter, this will store the original
         // picture task which would be rendered on screen after
         // blur pass.
         secondary_render_task_id: Option<RenderTaskId>,
@@ -107,31 +83,21 @@ pub enum PictureKind {
         real_local_rect: LayerRect,
         // An optional cache handle for storing extra data
         // in the GPU cache, depending on the type of
         // picture.
         extra_gpu_data_handle: GpuCacheHandle,
     },
 }
 
-// The type of surface that a picture can be drawn to.
-// RenderTask surfaces are not retained across frames.
-// TextureCache surfaces are stored across frames, and
-// also shared between display lists.
-#[derive(Debug)]
-pub enum PictureSurface {
-    RenderTask(RenderTaskId),
-    TextureCache(CacheItem),
-}
-
 #[derive(Debug)]
 pub struct PicturePrimitive {
     // If this picture is drawn to an intermediate surface,
     // the associated target information.
-    pub surface: Option<PictureSurface>,
+    pub surface: Option<RenderTaskId>,
 
     // Details specific to this type of picture.
     pub kind: PictureKind,
 
     // List of primitive runs that make up this picture.
     pub runs: Vec<PrimitiveRun>,
 
     // The pipeline that the primitives on this picture belong to.
@@ -188,44 +154,16 @@ impl PicturePrimitive {
                     }
                     _ => true,
                 }
             }
             _ => true
         }
     }
 
-    pub fn new_box_shadow(
-        blur_radius: f32,
-        color: ColorF,
-        clip_mode: BoxShadowClipMode,
-        image_kind: BrushImageKind,
-        cache_key: BoxShadowCacheKey,
-        pipeline_id: PipelineId,
-    ) -> Self {
-        PicturePrimitive {
-            runs: Vec::new(),
-            surface: None,
-            kind: PictureKind::BoxShadow {
-                blur_radius,
-                color,
-                clip_mode,
-                image_kind,
-                content_rect: LayerRect::zero(),
-                cache_key,
-            },
-            pipeline_id,
-            cull_children: false,
-            brush: BrushPrimitive::new(
-                BrushKind::Picture,
-                None,
-            ),
-        }
-    }
-
     pub fn new_image(
         composite_mode: Option<PictureCompositeMode>,
         is_in_3d_context: bool,
         pipeline_id: PipelineId,
         reference_frame_index: ClipScrollNodeIndex,
         frame_output_pipeline_id: Option<PipelineId>,
     ) -> Self {
         PicturePrimitive {
@@ -264,18 +202,18 @@ impl PicturePrimitive {
 
         self.runs.push(PrimitiveRun {
             base_prim_index: prim_index,
             count: 1,
             clip_and_scroll,
         });
     }
 
-    pub fn update_local_rect(&mut self,
-        prim_local_rect: LayerRect,
+    pub fn update_local_rect(
+        &mut self,
         prim_run_rect: PrimitiveRunLocalRect,
     ) -> LayerRect {
         let local_content_rect = prim_run_rect.local_rect_in_actual_parent_space;
 
         match self.kind {
             PictureKind::Image { composite_mode, ref mut real_local_rect, .. } => {
                 *real_local_rect = prim_run_rect.local_rect_in_original_parent_space;
 
@@ -299,35 +237,16 @@ impl PicturePrimitive {
 
                 *content_rect = local_content_rect.inflate(
                     blur_offset,
                     blur_offset,
                 );
 
                 content_rect.translate(&offset)
             }
-            PictureKind::BoxShadow { blur_radius, clip_mode, ref mut content_rect, .. } => {
-                // We need to inflate the content rect if outset.
-                *content_rect = match clip_mode {
-                    BoxShadowClipMode::Outset => {
-                        let full_offset = blur_radius * BLUR_SAMPLE_SCALE;
-                        // For a non-uniform radii, we need to expand
-                        // the content rect on all sides for the blur.
-                        local_content_rect.inflate(
-                            full_offset,
-                            full_offset,
-                        )
-                    }
-                    BoxShadowClipMode::Inset => {
-                        local_content_rect
-                    }
-                };
-
-                prim_local_rect
-            }
         }
     }
 
     pub fn prepare_for_render(
         &mut self,
         prim_index: PrimitiveIndex,
         prim_screen_rect: &DeviceIntRect,
         prim_local_rect: &LayerRect,
@@ -357,28 +276,28 @@ impl PicturePrimitive {
                             ClearMode::Transparent,
                             pic_state_for_children.tasks,
                             PictureType::Image,
                         );
 
                         let blur_std_deviation = blur_radius * frame_context.device_pixel_scale.0;
                         let picture_task_id = frame_state.render_tasks.add(picture_task);
 
-                        let (blur_render_task, _) = RenderTask::new_blur(
+                        let blur_render_task = RenderTask::new_blur(
                             blur_std_deviation,
                             picture_task_id,
                             frame_state.render_tasks,
                             RenderTargetKind::Color,
                             ClearMode::Transparent,
                             PremultipliedColorF::TRANSPARENT,
                         );
 
                         let render_task_id = frame_state.render_tasks.add(blur_render_task);
                         pic_state.tasks.push(render_task_id);
-                        self.surface = Some(PictureSurface::RenderTask(render_task_id));
+                        self.surface = Some(render_task_id);
                     }
                     Some(PictureCompositeMode::Filter(FilterOp::DropShadow(offset, blur_radius, color))) => {
                         let rect = (prim_local_rect.translate(&-offset) * content_scale).round().to_i32();
                         let mut picture_task = RenderTask::new_picture(
                             RenderTaskLocation::Dynamic(None, rect.size),
                             prim_index,
                             RenderTargetKind::Color,
                             ContentOrigin::Screen(rect.origin),
@@ -387,30 +306,30 @@ impl PicturePrimitive {
                             pic_state_for_children.tasks,
                             PictureType::Image,
                         );
                         picture_task.mark_for_saving();
 
                         let blur_std_deviation = blur_radius * frame_context.device_pixel_scale.0;
                         let picture_task_id = frame_state.render_tasks.add(picture_task);
 
-                        let (blur_render_task, _) = RenderTask::new_blur(
+                        let blur_render_task = RenderTask::new_blur(
                             blur_std_deviation.round(),
                             picture_task_id,
                             frame_state.render_tasks,
                             RenderTargetKind::Color,
                             ClearMode::Transparent,
                             color.premultiplied(),
                         );
 
                         *secondary_render_task_id = Some(picture_task_id);
 
                         let render_task_id = frame_state.render_tasks.add(blur_render_task);
                         pic_state.tasks.push(render_task_id);
-                        self.surface = Some(PictureSurface::RenderTask(render_task_id));
+                        self.surface = Some(render_task_id);
                     }
                     Some(PictureCompositeMode::MixBlend(..)) => {
                         let picture_task = RenderTask::new_picture(
                             RenderTaskLocation::Dynamic(None, prim_screen_rect.size),
                             prim_index,
                             RenderTargetKind::Color,
                             content_origin,
                             PremultipliedColorF::TRANSPARENT,
@@ -421,17 +340,17 @@ impl PicturePrimitive {
 
                         let readback_task_id = frame_state.render_tasks.add(RenderTask::new_readback(*prim_screen_rect));
 
                         *secondary_render_task_id = Some(readback_task_id);
                         pic_state.tasks.push(readback_task_id);
 
                         let render_task_id = frame_state.render_tasks.add(picture_task);
                         pic_state.tasks.push(render_task_id);
-                        self.surface = Some(PictureSurface::RenderTask(render_task_id));
+                        self.surface = Some(render_task_id);
                     }
                     Some(PictureCompositeMode::Filter(filter)) => {
                         // If this filter is not currently going to affect
                         // the picture, just collapse this picture into the
                         // current render task. This most commonly occurs
                         // when opacity == 1.0, but can also occur on other
                         // filters and be a significant performance win.
                         if filter.is_noop() {
@@ -455,34 +374,34 @@ impl PicturePrimitive {
                                 PremultipliedColorF::TRANSPARENT,
                                 ClearMode::Transparent,
                                 pic_state_for_children.tasks,
                                 PictureType::Image,
                             );
 
                             let render_task_id = frame_state.render_tasks.add(picture_task);
                             pic_state.tasks.push(render_task_id);
-                            self.surface = Some(PictureSurface::RenderTask(render_task_id));
+                            self.surface = Some(render_task_id);
                         }
                     }
                     Some(PictureCompositeMode::Blit) => {
                         let picture_task = RenderTask::new_picture(
                             RenderTaskLocation::Dynamic(None, prim_screen_rect.size),
                             prim_index,
                             RenderTargetKind::Color,
                             content_origin,
                             PremultipliedColorF::TRANSPARENT,
                             ClearMode::Transparent,
                             pic_state_for_children.tasks,
                             PictureType::Image,
                         );
 
                         let render_task_id = frame_state.render_tasks.add(picture_task);
                         pic_state.tasks.push(render_task_id);
-                        self.surface = Some(PictureSurface::RenderTask(render_task_id));
+                        self.surface = Some(render_task_id);
                     }
                     None => {
                         pic_state.tasks.extend(pic_state_for_children.tasks);
                         self.surface = None;
                     }
                 }
             }
             PictureKind::TextShadow { blur_radius, color, content_rect, .. } => {
@@ -506,99 +425,28 @@ impl PicturePrimitive {
                     color.premultiplied(),
                     ClearMode::Transparent,
                     Vec::new(),
                     PictureType::TextShadow,
                 );
 
                 let picture_task_id = frame_state.render_tasks.add(picture_task);
 
-                let (blur_render_task, _) = RenderTask::new_blur(
+                let blur_render_task = RenderTask::new_blur(
                     blur_std_deviation,
                     picture_task_id,
                     frame_state.render_tasks,
                     RenderTargetKind::Color,
                     ClearMode::Transparent,
                     color.premultiplied(),
                 );
 
                 let render_task_id = frame_state.render_tasks.add(blur_render_task);
                 pic_state.tasks.push(render_task_id);
-                self.surface = Some(PictureSurface::RenderTask(render_task_id));
-            }
-            PictureKind::BoxShadow { blur_radius, clip_mode, color, content_rect, cache_key, .. } => {
-                // TODO(gw): Rounding the content rect here to device pixels is not
-                // technically correct. Ideally we should ceil() here, and ensure that
-                // the extra part pixel in the case of fractional sizes is correctly
-                // handled. For now, just use rounding which passes the existing
-                // Gecko tests.
-                let cache_size = to_cache_size(content_rect.size * content_scale);
-
-                // Request the texture cache item for this box-shadow key. If it
-                // doesn't exist in the cache, the closure is invoked to build
-                // a render task chain to draw the cacheable result.
-                let cache_item = frame_state.resource_cache.request_render_task(
-                    RenderTaskCacheKey {
-                        size: cache_size,
-                        kind: RenderTaskCacheKeyKind::BoxShadow(cache_key),
-                    },
-                    frame_state.gpu_cache,
-                    frame_state.render_tasks,
-                    |render_tasks| {
-                        // Quote from https://drafts.csswg.org/css-backgrounds-3/#shadow-blur
-                        // "the image that would be generated by applying to the shadow a
-                        // Gaussian blur with a standard deviation equal to half the blur radius."
-                        let device_radius = (blur_radius * frame_context.device_pixel_scale.0).round();
-                        let blur_std_deviation = device_radius * 0.5;
-
-                        let blur_clear_mode = match clip_mode {
-                            BoxShadowClipMode::Outset => {
-                                ClearMode::One
-                            }
-                            BoxShadowClipMode::Inset => {
-                                ClearMode::Zero
-                            }
-                        };
-
-                        let picture_task = RenderTask::new_picture(
-                            RenderTaskLocation::Dynamic(None, cache_size),
-                            prim_index,
-                            RenderTargetKind::Alpha,
-                            ContentOrigin::Local(content_rect.origin),
-                            color.premultiplied(),
-                            ClearMode::Zero,
-                            Vec::new(),
-                            PictureType::BoxShadow,
-                        );
-
-                        let picture_task_id = render_tasks.add(picture_task);
-
-                        let (blur_render_task, scale_factor) = RenderTask::new_blur(
-                            blur_std_deviation,
-                            picture_task_id,
-                            render_tasks,
-                            RenderTargetKind::Alpha,
-                            blur_clear_mode,
-                            color.premultiplied(),
-                        );
-
-                        let root_task_id = render_tasks.add(blur_render_task);
-                        pic_state.tasks.push(root_task_id);
-
-                        // TODO(gw): Remove the nastiness with having to pass
-                        //           the scale factor through the texture cache
-                        //           item user data. This will disappear once
-                        //           the brush_picture shader is updated to draw
-                        //           segments, since the scale factor will not
-                        //           be used at all then during drawing.
-                        (root_task_id, [scale_factor, 0.0, 0.0], false)
-                    }
-                );
-
-                self.surface = Some(PictureSurface::TextureCache(cache_item));
+                self.surface = Some(render_task_id);
             }
         }
     }
 
     pub fn write_gpu_blocks(&self, request: &mut GpuDataRequest) {
         // TODO(gw): It's unfortunate that we pay a fixed cost
         //           of 5 GPU blocks / picture, just due to the size
         //           of the color matrix. There aren't typically very
@@ -629,14 +477,11 @@ impl PicturePrimitive {
 
                         request.push([amount, 1.0 - amount, 0.0, 0.0]);
                     }
                     _ => {
                         request.push([0.0; 4]);
                     }
                 }
             }
-            PictureKind::BoxShadow { color, .. } => {
-                request.push(color.premultiplied());
-            }
         }
     }
 }
--- a/gfx/webrender/src/prim_store.rs
+++ b/gfx/webrender/src/prim_store.rs
@@ -1,13 +1,13 @@
 /* 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/. */
 
-use api::{AlphaType, BorderRadius, BuiltDisplayList, ClipMode, ColorF, ComplexClipRegion};
+use api::{AlphaType, BorderRadius, BoxShadowClipMode, BuiltDisplayList, ClipMode, ColorF, ComplexClipRegion};
 use api::{DeviceIntRect, DeviceIntSize, DevicePixelScale, Epoch, ExtendMode, FontRenderMode};
 use api::{GlyphInstance, GlyphKey, GradientStop, ImageKey, ImageRendering, ItemRange, ItemTag};
 use api::{LayerPoint, LayerRect, LayerSize, LayerToWorldTransform, LayerVector2D, LineOrientation};
 use api::{LineStyle, PremultipliedColorF, YuvColorSpace, YuvFormat};
 use border::{BorderCornerInstance, BorderEdgeKind};
 use clip_scroll_tree::{ClipChainIndex, ClipScrollNodeIndex, CoordinateSystemId};
 use clip_scroll_node::ClipScrollNode;
 use clip::{ClipChain, ClipChainNode, ClipChainNodeIter, ClipChainNodeRef, ClipSource};
@@ -185,21 +185,16 @@ pub struct PrimitiveMetadata {
 
     /// A tag used to identify this primitive outside of WebRender. This is
     /// used for returning useful data during hit testing.
     pub tag: Option<ItemTag>,
 }
 
 #[derive(Debug)]
 pub enum BrushKind {
-    Mask {
-        clip_mode: ClipMode,
-        rect: LayerRect,
-        radii: BorderRadius,
-    },
     Solid {
         color: ColorF,
     },
     Clear,
     Line {
         color: PremultipliedColorF,
         wavy_line_thickness: f32,
         style: LineStyle,
@@ -243,17 +238,16 @@ impl BrushKind {
         match *self {
             BrushKind::Solid { .. } |
             BrushKind::Picture |
             BrushKind::Image { .. } |
             BrushKind::YuvImage { .. } |
             BrushKind::RadialGradient { .. } |
             BrushKind::LinearGradient { .. } => true,
 
-            BrushKind::Mask { .. } |
             BrushKind::Clear |
             BrushKind::Line { .. } => false,
         }
     }
 }
 
 bitflags! {
     /// Each bit of the edge AA mask is:
@@ -335,37 +329,16 @@ impl BrushPrimitive {
             }
             BrushKind::Solid { color } => {
                 request.push(color.premultiplied());
             }
             BrushKind::Clear => {
                 // Opaque black with operator dest out
                 request.push(PremultipliedColorF::BLACK);
             }
-            BrushKind::Mask { clip_mode, rect, radii } => {
-                request.push([
-                    clip_mode as u32 as f32,
-                    0.0,
-                    0.0,
-                    0.0
-                ]);
-                request.push(rect);
-                request.push([
-                    radii.top_left.width,
-                    radii.top_left.height,
-                    radii.top_right.width,
-                    radii.top_right.height,
-                ]);
-                request.push([
-                    radii.bottom_right.width,
-                    radii.bottom_right.height,
-                    radii.bottom_left.width,
-                    radii.bottom_left.height,
-                ]);
-            }
             BrushKind::Line { color, wavy_line_thickness, style, orientation } => {
                 request.push(color);
                 request.push([
                     wavy_line_thickness,
                     pack_as_float(style as u32),
                     pack_as_float(orientation as u32),
                     0.0,
                 ]);
@@ -985,17 +958,16 @@ impl PrimitiveStore {
             cpu_prim_index: SpecificPrimitiveIndex(0),
         };
 
         let metadata = match container {
             PrimitiveContainer::Brush(brush) => {
                 let opacity = match brush.kind {
                     BrushKind::Clear => PrimitiveOpacity::translucent(),
                     BrushKind::Solid { ref color } => PrimitiveOpacity::from_alpha(color.a),
-                    BrushKind::Mask { .. } => PrimitiveOpacity::translucent(),
                     BrushKind::Line { .. } => PrimitiveOpacity::translucent(),
                     BrushKind::Image { .. } => PrimitiveOpacity::translucent(),
                     BrushKind::YuvImage { .. } => PrimitiveOpacity::opaque(),
                     BrushKind::RadialGradient { .. } => PrimitiveOpacity::translucent(),
                     BrushKind::LinearGradient { .. } => PrimitiveOpacity::translucent(),
                     BrushKind::Picture => {
                         // TODO(gw): This is not currently used. In the future
                         //           we should detect opaque pictures.
@@ -1201,17 +1173,17 @@ impl PrimitiveStore {
                                     );
                                     let target_to_cache_task_id = render_tasks.add(target_to_cache_task);
 
                                     // Hook this into the render task tree at the right spot.
                                     pic_state.tasks.push(target_to_cache_task_id);
 
                                     // Pass the image opacity, so that the cached render task
                                     // item inherits the same opacity properties.
-                                    (target_to_cache_task_id, [0.0; 3], image_properties.descriptor.is_opaque)
+                                    (target_to_cache_task_id, image_properties.descriptor.is_opaque)
                                 }
                             );
                         }
                         ImageSource::Default => {
                             // Normal images just reference the source texture each frame.
                             request_source_image = true;
                         }
                     }
@@ -1283,17 +1255,16 @@ impl PrimitiveStore {
                                 pic_context.display_list,
                             );
                             gradient_builder.build(
                                 reverse_stops,
                                 &mut request,
                             );
                         }
                     }
-                    BrushKind::Mask { .. } |
                     BrushKind::Solid { .. } |
                     BrushKind::Clear |
                     BrushKind::Line { .. } |
                     BrushKind::Picture { .. } => {}
                 }
             }
         }
 
@@ -1405,16 +1376,41 @@ impl PrimitiveStore {
             for &(ref clip, _) in &local_clips.clips {
                 let (local_clip_rect, radius, mode) = match *clip {
                     ClipSource::RoundedRectangle(rect, radii, clip_mode) => {
                         (rect, Some(radii), clip_mode)
                     }
                     ClipSource::Rectangle(rect) => {
                         (rect, None, ClipMode::Clip)
                     }
+                    ClipSource::BoxShadow(ref info) => {
+                        // For inset box shadows, we can clip out any
+                        // pixels that are inside the shadow region
+                        // and are beyond the inner rect, as they can't
+                        // be affected by the blur radius.
+                        let inner_clip_mode = match info.clip_mode {
+                            BoxShadowClipMode::Outset => None,
+                            BoxShadowClipMode::Inset => Some(ClipMode::ClipOut),
+                        };
+
+                        // Push a region into the segment builder where the
+                        // box-shadow can have an effect on the result. This
+                        // ensures clip-mask tasks get allocated for these
+                        // pixel regions, even if no other clips affect them.
+                        segment_builder.push_mask_region(
+                            info.prim_shadow_rect,
+                            info.prim_shadow_rect.inflate(
+                                -0.5 * info.shadow_rect_alloc_size.width,
+                                -0.5 * info.shadow_rect_alloc_size.height,
+                            ),
+                            inner_clip_mode,
+                        );
+
+                        continue;
+                    }
                     ClipSource::BorderCorner(..) |
                     ClipSource::Image(..) => {
                         // TODO(gw): We can easily extend the segment builder
                         //           to support these clip sources in the
                         //           future, but they are rarely used.
                         clip_mask_kind = BrushClipMaskKind::Global;
                         continue;
                     }
@@ -1434,17 +1430,17 @@ impl PrimitiveStore {
                     let relative_transform = prim_transform
                         .inverse()
                         .unwrap_or(WorldToLayerFastTransform::identity())
                         .pre_mul(&clip_transform.into());
 
                     relative_transform.transform_rect(&local_clip_rect)
                 };
 
-                segment_builder.push_rect(local_clip_rect, radius, mode);
+                segment_builder.push_clip_rect(local_clip_rect, radius, mode);
             }
         }
 
         match brush.segment_desc {
             Some(ref mut segment_desc) => {
                 segment_desc.clip_mask_kind = clip_mask_kind;
             }
             None => {
@@ -1526,16 +1522,20 @@ impl PrimitiveStore {
             );
 
             let intersected_rect = combined_outer_rect.intersection(&segment_screen_rect);
             segment.clip_task_id = intersected_rect.map(|bounds| {
                 let clip_task = RenderTask::new_mask(
                     bounds,
                     clips.clone(),
                     prim_run_context.scroll_node.coordinate_system_id,
+                    frame_state.clip_store,
+                    frame_state.gpu_cache,
+                    frame_state.resource_cache,
+                    frame_state.render_tasks,
                 );
 
                 let clip_task_id = frame_state.render_tasks.add(clip_task);
                 pic_state.tasks.push(clip_task_id);
 
                 clip_task_id
             })
         }
@@ -1570,16 +1570,17 @@ impl PrimitiveStore {
         let transform = &prim_run_context.scroll_node.world_content_transform;
         let extra_clip =  {
             let metadata = &self.cpu_metadata[prim_index.0];
             metadata.clip_sources.as_ref().map(|ref clip_sources| {
                 let prim_clips = frame_state.clip_store.get_mut(clip_sources);
                 prim_clips.update(
                     frame_state.gpu_cache,
                     frame_state.resource_cache,
+                    frame_context.device_pixel_scale,
                 );
                 let (screen_inner_rect, screen_outer_rect) =
                     prim_clips.get_screen_bounds(transform, frame_context.device_pixel_scale);
 
                 if let Some(outer) = screen_outer_rect {
                     combined_outer_rect = combined_outer_rect.and_then(|r| r.intersection(&outer));
                 }
 
@@ -1658,16 +1659,20 @@ impl PrimitiveStore {
         ) {
             return true;
         }
 
         let clip_task = RenderTask::new_mask(
             combined_outer_rect,
             clips,
             prim_coordinate_system_id,
+            frame_state.clip_store,
+            frame_state.gpu_cache,
+            frame_state.resource_cache,
+            frame_state.render_tasks,
         );
 
         let clip_task_id = frame_state.render_tasks.add(clip_task);
         self.cpu_metadata[prim_index.0].clip_task_id = Some(clip_task_id);
         pic_state.tasks.push(clip_task_id);
 
         true
     }
@@ -1711,17 +1716,16 @@ impl PrimitiveStore {
                     return None;
                 }
 
                 let (draw_text_transformed, original_reference_frame_index) = match pic.kind {
                     PictureKind::Image { reference_frame_index, composite_mode, .. } => {
                         may_need_clip_mask = composite_mode.is_some();
                         (true, Some(reference_frame_index))
                     }
-                    PictureKind::BoxShadow { .. } |
                     PictureKind::TextShadow { .. } => {
                         (false, None)
                     }
                 };
 
                 let display_list = &frame_context
                     .pipelines
                     .get(&pic.pipeline_id)
@@ -1751,20 +1755,17 @@ impl PrimitiveStore {
                 frame_state,
             );
 
             // Restore the dependencies (borrow check dance)
             let pic = &mut self.cpu_pictures[cpu_prim_index.0];
             pic.runs = pic_context_for_children.prim_runs;
 
             let metadata = &mut self.cpu_metadata[prim_index.0];
-            metadata.local_rect = pic.update_local_rect(
-                metadata.local_rect,
-                result,
-            );
+            metadata.local_rect = pic.update_local_rect(result);
         }
 
         let (local_rect, unclipped_device_rect) = {
             let metadata = &mut self.cpu_metadata[prim_index.0];
             if metadata.local_rect.size.width <= 0.0 ||
                metadata.local_rect.size.height <= 0.0 {
                 //warn!("invalid primitive rect {:?}", metadata.local_rect);
                 return None;
--- a/gfx/webrender/src/render_task.rs
+++ b/gfx/webrender/src/render_task.rs
@@ -1,26 +1,26 @@
 /* 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/. */
 
 use api::{DeviceIntPoint, DeviceIntRect, DeviceIntSize, ImageDescriptor, ImageFormat};
-use api::PremultipliedColorF;
-use box_shadow::BoxShadowCacheKey;
-use clip::ClipWorkItem;
+use api::{DeviceSize, PremultipliedColorF};
+use box_shadow::{BoxShadowCacheKey};
+use clip::{ClipSource, ClipStore, ClipWorkItem};
 use clip_scroll_tree::CoordinateSystemId;
 use device::TextureFilter;
-use gpu_cache::{GpuCache, GpuCacheHandle};
-use gpu_types::{ImageSource, PictureType};
+use gpu_cache::{GpuCache, GpuCacheAddress, GpuCacheHandle};
+use gpu_types::{ImageSource, PictureType, RasterizationSpace};
 use internal_types::{FastHashMap, SavedTargetIndex, SourceTexture};
 use picture::ContentOrigin;
 use prim_store::{PrimitiveIndex, ImageCacheKey};
 #[cfg(feature = "debugger")]
 use print_tree::{PrintTreePrinter};
-use resource_cache::CacheItem;
+use resource_cache::{CacheItem, ResourceCache};
 use std::{cmp, ops, usize, f32, i32};
 use texture_cache::{TextureCache, TextureCacheHandle};
 use tiling::{RenderPass, RenderTargetIndex};
 use tiling::{RenderTargetKind};
 
 const FLOATS_PER_RENDER_TASK_INFO: usize = 12;
 pub const MAX_BLUR_STD_DEVIATION: f32 = 4.0;
 pub const MIN_DOWNSCALING_RT_SIZE: i32 = 128;
@@ -152,42 +152,47 @@ pub struct CacheMaskTask {
     actual_rect: DeviceIntRect,
     pub clips: Vec<ClipWorkItem>,
     pub coordinate_system_id: CoordinateSystemId,
 }
 
 #[derive(Debug)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
+pub struct ClipRegionTask {
+    pub clip_data_address: GpuCacheAddress,
+}
+
+#[derive(Debug)]
+#[cfg_attr(feature = "capture", derive(Serialize))]
+#[cfg_attr(feature = "replay", derive(Deserialize))]
 pub struct PictureTask {
     pub prim_index: PrimitiveIndex,
     pub target_kind: RenderTargetKind,
     pub content_origin: ContentOrigin,
     pub color: PremultipliedColorF,
     pub pic_type: PictureType,
     pub uv_rect_handle: GpuCacheHandle,
 }
 
 #[derive(Debug)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 pub struct BlurTask {
     pub blur_std_deviation: f32,
     pub target_kind: RenderTargetKind,
     pub color: PremultipliedColorF,
-    pub scale_factor: f32,
     pub uv_rect_handle: GpuCacheHandle,
 }
 
 impl BlurTask {
     #[cfg(feature = "debugger")]
     fn print_with<T: PrintTreePrinter>(&self, pt: &mut T) {
         pt.add_item(format!("std deviation: {}", self.blur_std_deviation));
         pt.add_item(format!("target: {:?}", self.target_kind));
-        pt.add_item(format!("scale: {}", self.scale_factor));
     }
 }
 
 // Where the source data for a blit task can be found.
 #[derive(Debug)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 pub enum BlitSource {
@@ -214,16 +219,17 @@ pub struct RenderTaskData {
 }
 
 #[derive(Debug)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 pub enum RenderTaskKind {
     Picture(PictureTask),
     CacheMask(CacheMaskTask),
+    ClipRegion(ClipRegionTask),
     VerticalBlur(BlurTask),
     HorizontalBlur(BlurTask),
     Readback(DeviceIntRect),
     Scaling(RenderTargetKind),
     Blit(BlitTask),
 }
 
 #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
@@ -311,30 +317,115 @@ impl RenderTask {
             saved_index: None,
         }
     }
 
     pub fn new_mask(
         outer_rect: DeviceIntRect,
         clips: Vec<ClipWorkItem>,
         prim_coordinate_system_id: CoordinateSystemId,
+        clip_store: &mut ClipStore,
+        gpu_cache: &mut GpuCache,
+        resource_cache: &mut ResourceCache,
+        render_tasks: &mut RenderTaskTree,
     ) -> Self {
+        let mut children = Vec::new();
+
+        // Step through the clip sources that make up this mask. If we find
+        // any box-shadow clip sources, request that image from the render
+        // task cache. This allows the blurred box-shadow rect to be cached
+        // in the texture cache across frames.
+        // TODO(gw): Consider moving this logic outside this function, especially
+        //           as we add more clip sources that depend on render tasks.
+        // TODO(gw): If this ever shows up in a profile, we could pre-calculate
+        //           whether a ClipSources contains any box-shadows and skip
+        //           this iteration for the majority of cases.
+        for clip_item in &clips {
+            let clip_sources = clip_store.get_opt_mut(&clip_item.clip_sources).expect("bug");
+            for &mut (ref mut clip, _) in &mut clip_sources.clips {
+                match *clip {
+                    ClipSource::BoxShadow(ref mut info) => {
+                        let (cache_size, cache_key) = info.cache_key
+                            .as_ref()
+                            .expect("bug: no cache key set")
+                            .clone();
+                        let blur_radius_dp = cache_key.blur_radius_dp as f32;
+                        let clip_data_address = gpu_cache.get_address(&info.clip_data_handle);
+
+                        // Request a cacheable render task with a blurred, minimal
+                        // sized box-shadow rect.
+                        info.cache_item = resource_cache.request_render_task(
+                            RenderTaskCacheKey {
+                                size: cache_size,
+                                kind: RenderTaskCacheKeyKind::BoxShadow(cache_key),
+                            },
+                            gpu_cache,
+                            render_tasks,
+                            |render_tasks| {
+                                // Draw the rounded rect.
+                                let mask_task = RenderTask::new_rounded_rect_mask(
+                                    cache_size,
+                                    clip_data_address,
+                                );
+
+                                let mask_task_id = render_tasks.add(mask_task);
+
+                                // Blur it
+                                let blur_render_task = RenderTask::new_blur(
+                                    blur_radius_dp,
+                                    mask_task_id,
+                                    render_tasks,
+                                    RenderTargetKind::Alpha,
+                                    ClearMode::Zero,
+                                    PremultipliedColorF::TRANSPARENT,
+                                );
+
+                                let root_task_id = render_tasks.add(blur_render_task);
+                                children.push(root_task_id);
+
+                                (root_task_id, false)
+                            }
+                        );
+                    }
+                    ClipSource::Rectangle(..) |
+                    ClipSource::RoundedRectangle(..) |
+                    ClipSource::Image(..) |
+                    ClipSource::BorderCorner(..) => {}
+                }
+            }
+        }
+
         RenderTask {
-            children: Vec::new(),
+            children,
             location: RenderTaskLocation::Dynamic(None, outer_rect.size),
             kind: RenderTaskKind::CacheMask(CacheMaskTask {
                 actual_rect: outer_rect,
                 clips,
                 coordinate_system_id: prim_coordinate_system_id,
             }),
             clear_mode: ClearMode::One,
             saved_index: None,
         }
     }
 
+    pub fn new_rounded_rect_mask(
+        size: DeviceIntSize,
+        clip_data_address: GpuCacheAddress,
+    ) -> Self {
+        RenderTask {
+            children: Vec::new(),
+            location: RenderTaskLocation::Dynamic(None, size),
+            kind: RenderTaskKind::ClipRegion(ClipRegionTask {
+                clip_data_address,
+            }),
+            clear_mode: ClearMode::One,
+            saved_index: None,
+        }
+    }
+
     // Construct a render task to apply a blur to a primitive.
     // The render task chain that is constructed looks like:
     //
     //    PrimitiveCacheTask: Draw the primitives.
     //           ^
     //           |
     //    DownscalingTask(s): Each downscaling task reduces the size of render target to
     //           ^            half. Also reduce the std deviation to half until the std
@@ -350,17 +441,17 @@ impl RenderTask {
     //
     pub fn new_blur(
         blur_std_deviation: f32,
         src_task_id: RenderTaskId,
         render_tasks: &mut RenderTaskTree,
         target_kind: RenderTargetKind,
         clear_mode: ClearMode,
         color: PremultipliedColorF,
-    ) -> (Self, f32) {
+    ) -> Self {
         // Adjust large std deviation value.
         let mut adjusted_blur_std_deviation = blur_std_deviation;
         let blur_target_size = render_tasks[src_task_id].get_dynamic_size();
         let mut adjusted_blur_target_size = blur_target_size;
         let mut downscaling_src_task_id = src_task_id;
         let mut scale_factor = 1.0;
         while adjusted_blur_std_deviation > MAX_BLUR_STD_DEVIATION {
             if adjusted_blur_target_size.width < MIN_DOWNSCALING_RT_SIZE ||
@@ -372,49 +463,46 @@ impl RenderTask {
             adjusted_blur_target_size = (blur_target_size.to_f32() / scale_factor).to_i32();
             let downscaling_task = RenderTask::new_scaling(
                 target_kind,
                 downscaling_src_task_id,
                 adjusted_blur_target_size,
             );
             downscaling_src_task_id = render_tasks.add(downscaling_task);
         }
-        scale_factor = blur_target_size.width as f32 / adjusted_blur_target_size.width as f32;
 
         let blur_task_v = RenderTask {
             children: vec![downscaling_src_task_id],
             location: RenderTaskLocation::Dynamic(None, adjusted_blur_target_size),
             kind: RenderTaskKind::VerticalBlur(BlurTask {
                 blur_std_deviation: adjusted_blur_std_deviation,
                 target_kind,
                 color,
-                scale_factor,
                 uv_rect_handle: GpuCacheHandle::new(),
             }),
             clear_mode,
             saved_index: None,
         };
 
         let blur_task_v_id = render_tasks.add(blur_task_v);
 
         let blur_task_h = RenderTask {
             children: vec![blur_task_v_id],
             location: RenderTaskLocation::Dynamic(None, adjusted_blur_target_size),
             kind: RenderTaskKind::HorizontalBlur(BlurTask {
                 blur_std_deviation: adjusted_blur_std_deviation,
                 target_kind,
                 color,
-                scale_factor,
                 uv_rect_handle: GpuCacheHandle::new(),
             }),
             clear_mode,
             saved_index: None,
         };
 
-        (blur_task_h, scale_factor)
+        blur_task_h
     }
 
     pub fn new_scaling(
         target_kind: RenderTargetKind,
         src_task_id: RenderTaskId,
         target_size: DeviceIntSize,
     ) -> Self {
         RenderTask {
@@ -461,27 +549,37 @@ impl RenderTask {
                     task.color.to_array()
                 )
             }
             RenderTaskKind::CacheMask(ref task) => {
                 (
                     [
                         task.actual_rect.origin.x as f32,
                         task.actual_rect.origin.y as f32,
+                        RasterizationSpace::Screen as i32 as f32,
+                    ],
+                    [0.0; 4],
+                )
+            }
+            RenderTaskKind::ClipRegion(..) => {
+                (
+                    [
                         0.0,
+                        0.0,
+                        RasterizationSpace::Local as i32 as f32,
                     ],
                     [0.0; 4],
                 )
             }
             RenderTaskKind::VerticalBlur(ref task) |
             RenderTaskKind::HorizontalBlur(ref task) => {
                 (
                     [
                         task.blur_std_deviation,
-                        task.scale_factor,
+                        0.0,
                         0.0,
                     ],
                     task.color.to_array()
                 )
             }
             RenderTaskKind::Readback(..) |
             RenderTaskKind::Scaling(..) |
             RenderTaskKind::Blit(..) => {
@@ -516,16 +614,17 @@ impl RenderTask {
         match self.kind {
             RenderTaskKind::Picture(ref info) => {
                 &info.uv_rect_handle
             }
             RenderTaskKind::VerticalBlur(ref info) |
             RenderTaskKind::HorizontalBlur(ref info) => {
                 &info.uv_rect_handle
             }
+            RenderTaskKind::ClipRegion(..) |
             RenderTaskKind::Readback(..) |
             RenderTaskKind::Scaling(..) |
             RenderTaskKind::Blit(..) |
             RenderTaskKind::CacheMask(..) => {
                 panic!("texture handle not supported for this task kind");
             }
         }
     }
@@ -568,16 +667,17 @@ impl RenderTask {
             }
         }
     }
 
     pub fn target_kind(&self) -> RenderTargetKind {
         match self.kind {
             RenderTaskKind::Readback(..) => RenderTargetKind::Color,
 
+            RenderTaskKind::ClipRegion(..) |
             RenderTaskKind::CacheMask(..) => {
                 RenderTargetKind::Alpha
             }
 
             RenderTaskKind::VerticalBlur(ref task_info) |
             RenderTaskKind::HorizontalBlur(ref task_info) => {
                 task_info.target_kind
             }
@@ -604,18 +704,25 @@ impl RenderTask {
     // if we decide that is useful.
     pub fn is_shared(&self) -> bool {
         match self.kind {
             RenderTaskKind::Picture(..) |
             RenderTaskKind::VerticalBlur(..) |
             RenderTaskKind::Readback(..) |
             RenderTaskKind::HorizontalBlur(..) |
             RenderTaskKind::Scaling(..) |
+            RenderTaskKind::ClipRegion(..) |
             RenderTaskKind::Blit(..) => false,
-            RenderTaskKind::CacheMask(..) => true,
+
+            // TODO(gw): For now, we've disabled the shared clip mask
+            //           optimization. It's of dubious value in the
+            //           future once we start to cache clip tasks anyway.
+            //           I have left shared texture support here though,
+            //           just in case we want it in the future.
+            RenderTaskKind::CacheMask(..) => false,
         }
     }
 
     pub fn prepare_for_render(
         &mut self,
         gpu_cache: &mut GpuCache,
     ) {
         let (target_rect, target_index) = self.get_target_rect();
@@ -626,16 +733,17 @@ impl RenderTask {
                 (&mut info.uv_rect_handle, info.color)
             }
             RenderTaskKind::Picture(ref mut info) => {
                 (&mut info.uv_rect_handle, info.color)
             }
             RenderTaskKind::Readback(..) |
             RenderTaskKind::Scaling(..) |
             RenderTaskKind::Blit(..) |
+            RenderTaskKind::ClipRegion(..) |
             RenderTaskKind::CacheMask(..) => {
                 return;
             }
         };
 
         if let Some(mut request) = gpu_cache.request(cache_handle) {
             let image_source = ImageSource {
                 p0: target_rect.origin.to_f32(),
@@ -654,16 +762,19 @@ impl RenderTask {
             RenderTaskKind::Picture(ref task) => {
                 pt.new_level(format!("Picture of {:?}", task.prim_index));
                 pt.add_item(format!("kind: {:?}", task.target_kind));
             }
             RenderTaskKind::CacheMask(ref task) => {
                 pt.new_level(format!("CacheMask with {} clips", task.clips.len()));
                 pt.add_item(format!("rect: {:?}", task.actual_rect));
             }
+            RenderTaskKind::ClipRegion(..) => {
+                pt.new_level("ClipRegion".to_owned());
+            }
             RenderTaskKind::VerticalBlur(ref task) => {
                 pt.new_level("VerticalBlur".to_owned());
                 task.print_with(pt);
             }
             RenderTaskKind::HorizontalBlur(ref task) => {
                 pt.new_level("HorizontalBlur".to_owned());
                 task.print_with(pt);
             }
@@ -772,30 +883,30 @@ impl RenderTaskCache {
 
     pub fn request_render_task<F>(
         &mut self,
         key: RenderTaskCacheKey,
         texture_cache: &mut TextureCache,
         gpu_cache: &mut GpuCache,
         render_tasks: &mut RenderTaskTree,
         mut f: F,
-    ) -> CacheItem where F: FnMut(&mut RenderTaskTree) -> (RenderTaskId, [f32; 3], bool) {
+    ) -> CacheItem where F: FnMut(&mut RenderTaskTree) -> (RenderTaskId, bool) {
         // Get the texture cache handle for this cache key,
         // or create one.
         let cache_entry = self.entries
                               .entry(key)
                               .or_insert(RenderTaskCacheEntry {
                                   handle: TextureCacheHandle::new(),
                               });
 
         // Check if this texture cache handle is valie.
         if texture_cache.request(&mut cache_entry.handle, gpu_cache) {
             // Invoke user closure to get render task chain
             // to draw this into the texture cache.
-            let (render_task_id, user_data, is_opaque) = f(render_tasks);
+            let (render_task_id, is_opaque) = f(render_tasks);
             let render_task = &mut render_tasks[render_task_id];
 
             // Select the right texture page to allocate from.
             let image_format = match render_task.target_kind() {
                 RenderTargetKind::Color => ImageFormat::BGRA8,
                 RenderTargetKind::Alpha => ImageFormat::R8,
             };
 
@@ -820,17 +931,17 @@ impl RenderTaskCache {
 
             // Allocate space in the texture cache, but don't supply
             // and CPU-side data to be uploaded.
             texture_cache.update(
                 &mut cache_entry.handle,
                 descriptor,
                 TextureFilter::Linear,
                 None,
-                user_data,
+                [0.0; 3],
                 None,
                 gpu_cache,
             );
 
             // Get the allocation details in the texture cache, and store
             // this in the render task. The renderer will draw this
             // task into the appropriate layer and rect of the texture
             // cache on this frame.
@@ -844,8 +955,22 @@ impl RenderTaskCache {
             );
         }
 
         // Finally, return the texture cache handle that we know
         // is now up to date.
         texture_cache.get(&cache_entry.handle)
     }
 }
+
+// TODO(gw): Rounding the content rect here to device pixels is not
+// technically correct. Ideally we should ceil() here, and ensure that
+// the extra part pixel in the case of fractional sizes is correctly
+// handled. For now, just use rounding which passes the existing
+// Gecko tests.
+// Note: zero-square tasks are prohibited in WR task tree, so
+// we ensure each dimension to be at least the length of 1 after rounding.
+pub fn to_cache_size(size: DeviceSize) -> DeviceIntSize {
+    DeviceIntSize::new(
+        1.max(size.width.round() as i32),
+        1.max(size.height.round() as i32),
+    )
+}
--- a/gfx/webrender/src/renderer.rs
+++ b/gfx/webrender/src/renderer.rs
@@ -108,24 +108,16 @@ const GPU_TAG_BRUSH_BLEND: GpuProfileTag
 const GPU_TAG_BRUSH_IMAGE: GpuProfileTag = GpuProfileTag {
     label: "B_Image",
     color: debug_colors::SPRINGGREEN,
 };
 const GPU_TAG_BRUSH_SOLID: GpuProfileTag = GpuProfileTag {
     label: "B_Solid",
     color: debug_colors::RED,
 };
-const GPU_TAG_BRUSH_MASK: GpuProfileTag = GpuProfileTag {
-    label: "B_Mask",
-    color: debug_colors::BLACK,
-};
-const GPU_TAG_BRUSH_PICTURE: GpuProfileTag = GpuProfileTag {
-    label: "B_Picture",
-    color: debug_colors::SILVER,
-};
 const GPU_TAG_BRUSH_LINE: GpuProfileTag = GpuProfileTag {
     label: "Line",
     color: debug_colors::DARKRED,
 };
 const GPU_TAG_CACHE_CLIP: GpuProfileTag = GpuProfileTag {
     label: "C_Clip",
     color: debug_colors::PURPLE,
 };
@@ -216,17 +208,16 @@ impl TransformBatchKind {
 impl BatchKind {
     #[cfg(feature = "debugger")]
     fn debug_name(&self) -> &'static str {
         match *self {
             BatchKind::HardwareComposite => "HardwareComposite",
             BatchKind::SplitComposite => "SplitComposite",
             BatchKind::Brush(kind) => {
                 match kind {
-                    BrushBatchKind::Picture => "Brush (Picture)",
                     BrushBatchKind::Solid => "Brush (Solid)",
                     BrushBatchKind::Line => "Brush (Line)",
                     BrushBatchKind::Image(..) => "Brush (Image)",
                     BrushBatchKind::Blend => "Brush (Blend)",
                     BrushBatchKind::MixBlend { .. } => "Brush (Composite)",
                     BrushBatchKind::YuvImage(..) => "Brush (YuvImage)",
                     BrushBatchKind::RadialGradient => "Brush (RadialGradient)",
                     BrushBatchKind::LinearGradient => "Brush (LinearGradient)",
@@ -237,17 +228,16 @@ impl BatchKind {
     }
 
     fn gpu_sampler_tag(&self) -> GpuProfileTag {
         match *self {
             BatchKind::HardwareComposite => GPU_TAG_PRIM_HW_COMPOSITE,
             BatchKind::SplitComposite => GPU_TAG_PRIM_SPLIT_COMPOSITE,
             BatchKind::Brush(kind) => {
                 match kind {
-                    BrushBatchKind::Picture => GPU_TAG_BRUSH_PICTURE,
                     BrushBatchKind::Solid => GPU_TAG_BRUSH_SOLID,
                     BrushBatchKind::Line => GPU_TAG_BRUSH_LINE,
                     BrushBatchKind::Image(..) => GPU_TAG_BRUSH_IMAGE,
                     BrushBatchKind::Blend => GPU_TAG_BRUSH_BLEND,
                     BrushBatchKind::MixBlend { .. } => GPU_TAG_BRUSH_MIXBLEND,
                     BrushBatchKind::YuvImage(..) => GPU_TAG_BRUSH_YUV_IMAGE,
                     BrushBatchKind::RadialGradient => GPU_TAG_BRUSH_RADIAL_GRADIENT,
                     BrushBatchKind::LinearGradient => GPU_TAG_BRUSH_LINEAR_GRADIENT,
@@ -1597,31 +1587,30 @@ pub struct Renderer {
     // These are "cache shaders". These shaders are used to
     // draw intermediate results to cache targets. The results
     // of these shaders are then used by the primitive shaders.
     cs_text_run: LazilyCompiledShader,
     cs_blur_a8: LazilyCompiledShader,
     cs_blur_rgba8: LazilyCompiledShader,
 
     // Brush shaders
-    brush_mask_rounded_rect: LazilyCompiledShader,
-    brush_picture: BrushShader,
     brush_solid: BrushShader,
     brush_line: BrushShader,
     brush_image: Vec<Option<BrushShader>>,
     brush_blend: BrushShader,
     brush_mix_blend: BrushShader,
     brush_yuv_image: Vec<Option<BrushShader>>,
     brush_radial_gradient: BrushShader,
     brush_linear_gradient: BrushShader,
 
     /// These are "cache clip shaders". These shaders are used to
     /// draw clip instances into the cached clip mask. The results
     /// of these shaders are also used by the primitive shaders.
     cs_clip_rectangle: LazilyCompiledShader,
+    cs_clip_box_shadow: LazilyCompiledShader,
     cs_clip_image: LazilyCompiledShader,
     cs_clip_border: LazilyCompiledShader,
 
     // The are "primitive shaders". These shaders draw and blend
     // final results on screen. They are aware of tile boundaries.
     // Most draw directly to the framebuffer, but some use inputs
     // from the cache shaders to draw. Specifically, the box
     // shadow primitive shader stretches the box shadow cache
@@ -1796,24 +1785,16 @@ impl Renderer {
         let cs_text_run = try!{
             LazilyCompiledShader::new(ShaderKind::Cache(VertexArrayKind::Primitive),
                                       "cs_text_run",
                                       &[],
                                       &mut device,
                                       options.precache_shaders)
         };
 
-        let brush_mask_rounded_rect = try!{
-            LazilyCompiledShader::new(ShaderKind::Brush,
-                                      "brush_mask_rounded_rect",
-                                      &[],
-                                      &mut device,
-                                      options.precache_shaders)
-        };
-
         let brush_solid = try!{
             BrushShader::new("brush_solid",
                              &mut device,
                              &[],
                              options.precache_shaders)
         };
 
         let brush_line = try!{
@@ -1832,23 +1813,16 @@ impl Renderer {
 
         let brush_mix_blend = try!{
             BrushShader::new("brush_mix_blend",
                              &mut device,
                              &[],
                              options.precache_shaders)
         };
 
-        let brush_picture = try!{
-            BrushShader::new("brush_picture",
-                             &mut device,
-                             &[],
-                             options.precache_shaders)
-        };
-
         let brush_radial_gradient = try!{
             BrushShader::new("brush_radial_gradient",
                              &mut device,
                              if options.enable_dithering {
                                 &dithering_feature
                              } else {
                                 &[]
                              },
@@ -1885,16 +1859,24 @@ impl Renderer {
         let cs_clip_rectangle = try!{
             LazilyCompiledShader::new(ShaderKind::ClipCache,
                                       "cs_clip_rectangle",
                                       &[],
                                       &mut device,
                                       options.precache_shaders)
         };
 
+        let cs_clip_box_shadow = try!{
+            LazilyCompiledShader::new(ShaderKind::ClipCache,
+                                      "cs_clip_box_shadow",
+                                      &[],
+                                      &mut device,
+                                      options.precache_shaders)
+        };
+
         let cs_clip_image = try!{
             LazilyCompiledShader::new(ShaderKind::ClipCache,
                                       "cs_clip_image",
                                       &[],
                                       &mut device,
                                       options.precache_shaders)
         };
 
@@ -2267,27 +2249,26 @@ impl Renderer {
             device,
             active_documents: Vec::new(),
             pending_texture_updates: Vec::new(),
             pending_gpu_cache_updates: Vec::new(),
             pending_shader_updates: Vec::new(),
             cs_text_run,
             cs_blur_a8,
             cs_blur_rgba8,
-            brush_mask_rounded_rect,
-            brush_picture,
             brush_solid,
             brush_line,
             brush_image,
             brush_blend,
             brush_mix_blend,
             brush_yuv_image,
             brush_radial_gradient,
             brush_linear_gradient,
             cs_clip_rectangle,
+            cs_clip_box_shadow,
             cs_clip_border,
             cs_clip_image,
             ps_text_run,
             ps_text_run_dual_source,
             ps_image,
             ps_border_corner,
             ps_border_edge,
             ps_hw_composite,
@@ -2510,35 +2491,35 @@ impl Renderer {
             target.clip_batcher.border_clears.len(),
         );
         debug_target.add(
             debug_server::BatchKind::Clip,
             "Borders",
             target.clip_batcher.borders.len(),
         );
         debug_target.add(
+            debug_server::BatchKind::Clip,
+            "BoxShadows",
+            target.clip_batcher.box_shadows.len(),
+        );
+        debug_target.add(
             debug_server::BatchKind::Cache,
             "Vertical Blur",
             target.vertical_blurs.len(),
         );
         debug_target.add(
             debug_server::BatchKind::Cache,
             "Horizontal Blur",
             target.horizontal_blurs.len(),
         );
         debug_target.add(
             debug_server::BatchKind::Clip,
             "Rectangles",
             target.clip_batcher.rectangles.len(),
         );
-        debug_target.add(
-            debug_server::BatchKind::Cache,
-            "Rectangle Brush (Rounded Rect)",
-            target.brush_mask_rounded_rects.len(),
-        );
         for (_, items) in target.clip_batcher.images.iter() {
             debug_target.add(debug_server::BatchKind::Clip, "Image mask", items.len());
         }
 
         debug_target
     }
 
     #[cfg(feature = "debugger")]
@@ -3197,25 +3178,16 @@ impl Renderer {
                             .bind(
                                 &mut self.device,
                                 key.blend_mode,
                                 projection,
                                 0,
                                 &mut self.renderer_errors,
                             );
                     }
-                    BrushBatchKind::Picture => {
-                        self.brush_picture.bind(
-                            &mut self.device,
-                            key.blend_mode,
-                            projection,
-                            0,
-                            &mut self.renderer_errors,
-                        );
-                    }
                     BrushBatchKind::Line => {
                         self.brush_line.bind(
                             &mut self.device,
                             key.blend_mode,
                             projection,
                             0,
                             &mut self.renderer_errors,
                         );
@@ -3972,30 +3944,16 @@ impl Renderer {
                     &BatchTextures::no_texture(),
                     stats,
                 );
             }
         }
 
         self.handle_scaling(render_tasks, &target.scalings, SourceTexture::CacheA8);
 
-        if !target.brush_mask_rounded_rects.is_empty() {
-            self.device.set_blend(false);
-
-            let _timer = self.gpu_profile.start_timer(GPU_TAG_BRUSH_MASK);
-            self.brush_mask_rounded_rect
-                .bind(&mut self.device, projection, 0, &mut self.renderer_errors);
-            self.draw_instanced_batch(
-                &target.brush_mask_rounded_rects,
-                VertexArrayKind::Primitive,
-                &BatchTextures::no_texture(),
-                stats,
-            );
-        }
-
         // Draw the clip items into the tiled alpha mask.
         {
             let _timer = self.gpu_profile.start_timer(GPU_TAG_CACHE_CLIP);
 
             // If we have border corner clips, the first step is to clear out the
             // area in the clip mask. This allows drawing multiple invididual clip
             // in regions below.
             if !target.clip_batcher.border_clears.is_empty() {
@@ -4045,16 +4003,36 @@ impl Renderer {
                 );
                 self.draw_instanced_batch(
                     &target.clip_batcher.rectangles,
                     VertexArrayKind::Clip,
                     &BatchTextures::no_texture(),
                     stats,
                 );
             }
+            // draw box-shadow clips
+            for (mask_texture_id, items) in target.clip_batcher.box_shadows.iter() {
+                let _gm2 = self.gpu_profile.start_marker("box-shadows");
+                let textures = BatchTextures {
+                    colors: [
+                        mask_texture_id.clone(),
+                        SourceTexture::Invalid,
+                        SourceTexture::Invalid,
+                    ],
+                };
+                self.cs_clip_box_shadow
+                    .bind(&mut self.device, projection, 0, &mut self.renderer_errors);
+                self.draw_instanced_batch(
+                    items,
+                    VertexArrayKind::Clip,
+                    &textures,
+                    stats,
+                );
+            }
+
             // draw image masks
             for (mask_texture_id, items) in target.clip_batcher.images.iter() {
                 let _gm2 = self.gpu_profile.start_marker("clip images");
                 let textures = BatchTextures {
                     colors: [
                         mask_texture_id.clone(),
                         SourceTexture::Invalid,
                         SourceTexture::Invalid,
@@ -4678,25 +4656,24 @@ impl Renderer {
         self.texture_resolver.deinit(&mut self.device);
         self.device.delete_vao(self.prim_vao);
         self.device.delete_vao(self.clip_vao);
         self.device.delete_vao(self.blur_vao);
         self.debug.deinit(&mut self.device);
         self.cs_text_run.deinit(&mut self.device);
         self.cs_blur_a8.deinit(&mut self.device);
         self.cs_blur_rgba8.deinit(&mut self.device);
-        self.brush_mask_rounded_rect.deinit(&mut self.device);
-        self.brush_picture.deinit(&mut self.device);
         self.brush_solid.deinit(&mut self.device);
         self.brush_line.deinit(&mut self.device);
         self.brush_blend.deinit(&mut self.device);
         self.brush_mix_blend.deinit(&mut self.device);
         self.brush_radial_gradient.deinit(&mut self.device);
         self.brush_linear_gradient.deinit(&mut self.device);
         self.cs_clip_rectangle.deinit(&mut self.device);
+        self.cs_clip_box_shadow.deinit(&mut self.device);
         self.cs_clip_image.deinit(&mut self.device);
         self.cs_clip_border.deinit(&mut self.device);
         self.ps_text_run.deinit(&mut self.device);
         self.ps_text_run_dual_source.deinit(&mut self.device);
         for shader in self.brush_image {
             if let Some(shader) = shader {
                 shader.deinit(&mut self.device);
             }
--- a/gfx/webrender/src/resource_cache.rs
+++ b/gfx/webrender/src/resource_cache.rs
@@ -315,17 +315,17 @@ impl ResourceCache {
     // closure will be invoked to generate the render task
     // chain that is required to draw this task.
     pub fn request_render_task<F>(
         &mut self,
         key: RenderTaskCacheKey,
         gpu_cache: &mut GpuCache,
         render_tasks: &mut RenderTaskTree,
         f: F,
-    ) -> CacheItem where F: FnMut(&mut RenderTaskTree) -> (RenderTaskId, [f32; 3], bool) {
+    ) -> CacheItem where F: FnMut(&mut RenderTaskTree) -> (RenderTaskId, bool) {
         self.cached_render_tasks.request_render_task(
             key,
             &mut self.texture_cache,
             gpu_cache,
             render_tasks,
             f
         )
     }
--- a/gfx/webrender/src/segment.rs
+++ b/gfx/webrender/src/segment.rs
@@ -139,24 +139,24 @@ impl Event {
     }
 }
 
 // An item that provides some kind of clip region (either
 // a clip in/out rect, or a mask region).
 #[derive(Debug)]
 struct Item {
     rect: LayerRect,
-    mode: ClipMode,
+    mode: Option<ClipMode>,
     flags: ItemFlags,
 }
 
 impl Item {
     fn new(
         rect: LayerRect,
-        mode: ClipMode,
+        mode: Option<ClipMode>,
         has_mask: bool,
     ) -> Item {
         let flags = if has_mask {
             ItemFlags::HAS_MASK
         } else {
             ItemFlags::empty()
         };
 
@@ -187,37 +187,109 @@ impl SegmentBuilder {
         local_clip_rect: LayerRect,
     ) -> SegmentBuilder {
         let mut builder = SegmentBuilder {
             items: Vec::new(),
             bounding_rect: Some(local_rect),
             inner_rect,
         };
 
-        builder.push_rect(local_rect, None, ClipMode::Clip);
-        builder.push_rect(local_clip_rect, None, ClipMode::Clip);
+        builder.push_clip_rect(local_rect, None, ClipMode::Clip);
+        builder.push_clip_rect(local_clip_rect, None, ClipMode::Clip);
 
         builder
     }
 
+    // Push a region defined by an inner and outer rect where there
+    // is a mask required. This ensures that segments which intersect
+    // with these areas will get a clip mask task allocated. This
+    // is currently used to mark where a box-shadow region can affect
+    // the pixels of a clip-mask. It might be useful for other types
+    // such as dashed and dotted borders in the future.
+    pub fn push_mask_region(
+        &mut self,
+        outer_rect: LayerRect,
+        inner_rect: LayerRect,
+        inner_clip_mode: Option<ClipMode>,
+    ) {
+        debug_assert!(outer_rect.contains_rect(&inner_rect));
+
+        let p0 = outer_rect.origin;
+        let p1 = inner_rect.origin;
+        let p2 = inner_rect.bottom_right();
+        let p3 = outer_rect.bottom_right();
+
+        let segments = &[
+            LayerRect::new(
+                LayerPoint::new(p0.x, p0.y),
+                LayerSize::new(p1.x - p0.x, p1.y - p0.y),
+            ),
+            LayerRect::new(
+                LayerPoint::new(p2.x, p0.y),
+                LayerSize::new(p3.x - p2.x, p1.y - p0.y),
+            ),
+            LayerRect::new(
+                LayerPoint::new(p2.x, p2.y),
+                LayerSize::new(p3.x - p2.x, p3.y - p2.y),
+            ),
+            LayerRect::new(
+                LayerPoint::new(p0.x, p2.y),
+                LayerSize::new(p1.x - p0.x, p3.y - p2.y),
+            ),
+            LayerRect::new(
+                LayerPoint::new(p1.x, p0.y),
+                LayerSize::new(p2.x - p1.x, p1.y - p0.y),
+            ),
+            LayerRect::new(
+                LayerPoint::new(p2.x, p1.y),
+                LayerSize::new(p3.x - p2.x, p2.y - p1.y),
+            ),
+            LayerRect::new(
+                LayerPoint::new(p1.x, p2.y),
+                LayerSize::new(p2.x - p1.x, p3.y - p2.y),
+            ),
+            LayerRect::new(
+                LayerPoint::new(p0.x, p1.y),
+                LayerSize::new(p1.x - p0.x, p2.y - p1.y),
+            ),
+        ];
+
+        for segment in segments {
+            self.items.push(Item::new(
+                *segment,
+                None,
+                true
+            ));
+        }
+
+        if inner_clip_mode.is_some() {
+            self.items.push(Item::new(
+                inner_rect,
+                inner_clip_mode,
+                false,
+            ));
+        }
+    }
+
     // Push some kind of clipping region into the segment builder.
     // If radius is None, it's a simple rect.
-    pub fn push_rect(
+    pub fn push_clip_rect(
         &mut self,
         rect: LayerRect,
         radius: Option<BorderRadius>,
         mode: ClipMode,
     ) {
         // Keep track of a minimal bounding rect for the set of
         // segments that will be generated.
         if mode == ClipMode::Clip {
             self.bounding_rect = self.bounding_rect.and_then(|bounding_rect| {
                 bounding_rect.intersection(&rect)
             });
         }
+        let mode = Some(mode);
 
         match radius {
             Some(radius) => {
                 // For a rounded rect, try to create a nine-patch where there
                 // is a clip item for each corner, inner and edge region.
                 match extract_inner_rect_safe(&rect, &radius) {
                     Some(inner) => {
                         let p0 = rect.origin;
@@ -475,17 +547,17 @@ fn emit_segment_if_needed(
     //           in a hash set or similar if this ever
     //           shows up in a profile.
     let mut has_clip_mask = false;
 
     for item in items {
         if item.flags.contains(ItemFlags::X_ACTIVE | ItemFlags::Y_ACTIVE) {
             has_clip_mask |= item.flags.contains(ItemFlags::HAS_MASK);
 
-            if item.mode == ClipMode::ClipOut && !item.flags.contains(ItemFlags::HAS_MASK) {
+            if item.mode == Some(ClipMode::ClipOut) && !item.flags.contains(ItemFlags::HAS_MASK) {
                 return None;
             }
         }
     }
 
     let segment_rect = LayerRect::new(
         LayerPoint::new(
             x0.to_f32_px(),
@@ -573,17 +645,17 @@ mod test {
     ) {
         let mut sb = SegmentBuilder::new(
             local_rect,
             inner_rect,
             local_clip_rect,
         );
         let mut segments = Vec::new();
         for &(rect, radius, mode) in clips {
-            sb.push_rect(rect, radius, mode);
+            sb.push_clip_rect(rect, radius, mode);
         }
         sb.build(|segment| {
             segments.push(Segment {
                 ..*segment
             });
         });
         segments.sort_by(segment_sorter);
         expected_segments.sort_by(segment_sorter);
--- a/gfx/webrender/src/tiling.rs
+++ b/gfx/webrender/src/tiling.rs
@@ -5,25 +5,24 @@
 use api::{ColorF, DeviceIntPoint, DeviceIntRect, DeviceIntSize, DevicePixelScale, DeviceUintPoint};
 use api::{DeviceUintRect, DeviceUintSize, DocumentLayer, FilterOp, ImageFormat, LayerRect};
 use api::{MixBlendMode, PipelineId};
 use batch::{AlphaBatchBuilder, AlphaBatchContainer, ClipBatcher, resolve_image};
 use clip::{ClipStore};
 use clip_scroll_tree::{ClipScrollTree, ClipScrollNodeIndex};
 use device::{FrameId, Texture};
 use gpu_cache::{GpuCache};
-use gpu_types::{BlurDirection, BlurInstance, BrushFlags, BrushInstance, ClipChainRectIndex};
-use gpu_types::{ClipScrollNodeData, ClipScrollNodeIndex as GPUClipScrollNodeIndex};
-use gpu_types::{PrimitiveInstance};
+use gpu_types::{BlurDirection, BlurInstance};
+use gpu_types::{ClipScrollNodeData};
 use internal_types::{FastHashMap, SavedTargetIndex, SourceTexture};
 use picture::{PictureKind};
 use prim_store::{CachedGradient, PrimitiveIndex, PrimitiveKind, PrimitiveStore};
-use prim_store::{BrushKind, DeferredResolve, EdgeAaSegmentMask};
+use prim_store::{DeferredResolve};
 use profiler::FrameProfileCounters;
-use render_task::{BlitSource, RenderTaskAddress, RenderTaskId, RenderTaskKind};
+use render_task::{BlitSource, RenderTaskId, RenderTaskKind};
 use render_task::{BlurTask, ClearMode, RenderTaskLocation, RenderTaskTree};
 use resource_cache::ResourceCache;
 use std::{cmp, usize, f32, i32};
 use texture_allocator::GuillotineAllocator;
 
 const MIN_TARGET_SIZE: u32 = 2048;
 
 #[derive(Debug)]
@@ -399,16 +398,17 @@ impl RenderTarget for ColorRenderTarget 
                         }
                     }
                     _ => {
                         // No other primitives make use of primitive caching yet!
                         unreachable!()
                     }
                 }
             }
+            RenderTaskKind::ClipRegion(..) |
             RenderTaskKind::CacheMask(..) => {
                 panic!("Should not be added to color target!");
             }
             RenderTaskKind::Readback(device_rect) => {
                 self.readbacks.push(device_rect);
             }
             RenderTaskKind::Scaling(..) => {
                 self.scalings.push(ScalingInfo {
@@ -475,17 +475,16 @@ impl RenderTarget for ColorRenderTarget 
         })
     }
 }
 
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 pub struct AlphaRenderTarget {
     pub clip_batcher: ClipBatcher,
-    pub brush_mask_rounded_rects: Vec<PrimitiveInstance>,
     // List of blur operations to apply for this render target.
     pub vertical_blurs: Vec<BlurInstance>,
     pub horizontal_blurs: Vec<BlurInstance>,
     pub scalings: Vec<ScalingInfo>,
     pub zero_clears: Vec<RenderTaskId>,
     allocator: TextureAllocator,
 }
 
@@ -495,17 +494,16 @@ impl RenderTarget for AlphaRenderTarget 
     }
 
     fn new(
         size: Option<DeviceUintSize>,
         _: DeviceIntSize,
     ) -> Self {
         AlphaRenderTarget {
             clip_batcher: ClipBatcher::new(),
-            brush_mask_rounded_rects: Vec::new(),
             vertical_blurs: Vec::new(),
             horizontal_blurs: Vec::new(),
             scalings: Vec::new(),
             zero_clears: Vec::new(),
             allocator: TextureAllocator::new(size.expect("bug: alpha targets need size")),
         }
     }
 
@@ -527,16 +525,17 @@ impl RenderTarget for AlphaRenderTarget 
             ClearMode::One => {}
             ClearMode::Transparent => {
                 panic!("bug: invalid clear mode for alpha task");
             }
         }
 
         match task.kind {
             RenderTaskKind::Readback(..) |
+            RenderTaskKind::Picture(..) |
             RenderTaskKind::Blit(..) => {
                 panic!("BUG: should not be added to alpha target!");
             }
             RenderTaskKind::VerticalBlur(ref info) => {
                 info.add_instances(
                     &mut self.vertical_blurs,
                     task_id,
                     task.children[0],
@@ -548,94 +547,34 @@ impl RenderTarget for AlphaRenderTarget 
                 info.add_instances(
                     &mut self.horizontal_blurs,
                     task_id,
                     task.children[0],
                     BlurDirection::Horizontal,
                     render_tasks,
                 );
             }
-            RenderTaskKind::Picture(ref task_info) => {
-                let prim_metadata = ctx.prim_store.get_metadata(task_info.prim_index);
-
-                match prim_metadata.prim_kind {
-                    PrimitiveKind::Picture => {
-                        let prim = &ctx.prim_store.cpu_pictures[prim_metadata.cpu_prim_index.0];
-
-                        let task_index = render_tasks.get_task_address(task_id);
-
-                        for run in &prim.runs {
-                            for i in 0 .. run.count {
-                                let sub_prim_index = PrimitiveIndex(run.base_prim_index.0 + i);
-
-                                let sub_metadata = ctx.prim_store.get_metadata(sub_prim_index);
-                                let sub_prim_address =
-                                    gpu_cache.get_address(&sub_metadata.gpu_location);
-
-                                match sub_metadata.prim_kind {
-                                    PrimitiveKind::Brush => {
-                                        let instance = BrushInstance {
-                                            picture_address: task_index,
-                                            prim_address: sub_prim_address,
-                                            // TODO(gw): In the future, when brush
-                                            //           primitives on picture backed
-                                            //           tasks support clip masks and
-                                            //           transform primitives, these
-                                            //           will need to be filled out!
-                                            clip_chain_rect_index: ClipChainRectIndex(0),
-                                            scroll_id: GPUClipScrollNodeIndex(0),
-                                            clip_task_address: RenderTaskAddress(0),
-                                            z: 0,
-                                            segment_index: 0,
-                                            brush_flags: BrushFlags::PERSPECTIVE_INTERPOLATION,
-                                            edge_flags: EdgeAaSegmentMask::empty(),
-                                            user_data: [0; 3],
-                                        };
-                                        let brush = &ctx.prim_store.cpu_brushes[sub_metadata.cpu_prim_index.0];
-                                        let batch = match brush.kind {
-                                            BrushKind::Solid { .. } |
-                                            BrushKind::Clear |
-                                            BrushKind::Picture |
-                                            BrushKind::Line { .. } |
-                                            BrushKind::YuvImage { .. } |
-                                            BrushKind::RadialGradient { .. } |
-                                            BrushKind::LinearGradient { .. } |
-                                            BrushKind::Image { .. } => {
-                                                unreachable!("bug: unexpected brush here");
-                                            }
-                                            BrushKind::Mask { .. } => {
-                                                &mut self.brush_mask_rounded_rects
-                                            }
-                                        };
-                                        batch.push(PrimitiveInstance::from(instance));
-                                    }
-                                    _ => {
-                                        unreachable!("Unexpected sub primitive type");
-                                    }
-                                }
-                            }
-                        }
-                    }
-                    _ => {
-                        // No other primitives make use of primitive caching yet!
-                        unreachable!()
-                    }
-                }
-            }
             RenderTaskKind::CacheMask(ref task_info) => {
                 let task_address = render_tasks.get_task_address(task_id);
                 self.clip_batcher.add(
                     task_address,
                     &task_info.clips,
                     task_info.coordinate_system_id,
                     &ctx.resource_cache,
                     gpu_cache,
                     clip_store,
                 );
             }
+            RenderTaskKind::ClipRegion(ref task) => {
+                let task_address = render_tasks.get_task_address(task_id);
+                self.clip_batcher.add_clip_region(
+                    task_address,
+                    task.clip_data_address,
+                );
+            }
             RenderTaskKind::Scaling(..) => {
                 self.scalings.push(ScalingInfo {
                     src_task_id: task.children[0],
                     dest_task_id: task_id,
                 });
             }
         }
     }
@@ -699,16 +638,17 @@ impl TextureCacheRenderTarget {
                             source: BlitJobSource::RenderTask(task_id),
                             target_rect,
                         });
                     }
                 }
             }
             RenderTaskKind::VerticalBlur(..) |
             RenderTaskKind::Picture(..) |
+            RenderTaskKind::ClipRegion(..) |
             RenderTaskKind::CacheMask(..) |
             RenderTaskKind::Readback(..) |
             RenderTaskKind::Scaling(..) => {
                 panic!("BUG: unexpected task kind for texture cache target");
             }
         }
     }
 }
@@ -796,20 +736,19 @@ impl RenderPass {
                         clip_store,
                         deferred_resolves,
                     );
                 }
                 target.build(ctx, gpu_cache, render_tasks, deferred_resolves);
             }
             RenderPassKind::OffScreen { ref mut color, ref mut alpha, ref mut texture_cache } => {
                 let is_shared_alpha = self.tasks.iter().any(|&task_id| {
-                    match render_tasks[task_id].kind {
-                        RenderTaskKind::CacheMask(..) => true,
-                        _ => false,
-                    }
+                    let task = &render_tasks[task_id];
+                    task.is_shared() &&
+                        task.target_kind() == RenderTargetKind::Alpha
                 });
                 let saved_color = if self.tasks.iter().any(|&task_id| {
                     let t = &render_tasks[task_id];
                     t.target_kind() == RenderTargetKind::Color && t.saved_index.is_some()
                 }) {
                     Some(render_tasks.save_target())
                 } else {
                     None
--- a/gfx/webrender/tests/angle_shader_validation.rs
+++ b/gfx/webrender/tests/angle_shader_validation.rs
@@ -28,16 +28,20 @@ const SHADERS: &[Shader] = &[
         name: "cs_clip_rectangle",
         features: CLIP_FEATURES,
     },
     Shader {
         name: "cs_clip_image",
         features: CLIP_FEATURES,
     },
     Shader {
+        name: "cs_clip_box_shadow",
+        features: CLIP_FEATURES,
+    },
+    Shader {
         name: "cs_clip_border",
         features: CLIP_FEATURES,
     },
     // Cache shaders
     Shader {
         name: "cs_blur",
         features: CACHE_FEATURES,
     },
@@ -79,20 +83,16 @@ const SHADERS: &[Shader] = &[
         name: "brush_mask",
         features: &[],
     },
     Shader {
         name: "brush_solid",
         features: &[],
     },
     Shader {
-        name: "brush_picture",
-        features: &[],
-    },
-    Shader {
         name: "brush_blend",
         features: &[],
     },
     Shader {
         name: "brush_composite",
         features: &[],
     },
     Shader {
--- a/gfx/webrender_bindings/revision.txt
+++ b/gfx/webrender_bindings/revision.txt
@@ -1,1 +1,1 @@
-0da6c839b3a0e165f1115fb9fe286be7540c24ed
+5cb71f0f23719795e7c89417d91a7abad8ac20e9
--- a/js/src/vm/EnvironmentObject.h
+++ b/js/src/vm/EnvironmentObject.h
@@ -173,67 +173,83 @@ EnvironmentCoordinateFunctionScript(JSSc
  *    Does not hold 'var' bindings.
  *
  * The embedding (Gecko) uses non-syntactic envs for various things, some of
  * which are detailed below. All env chain listings below are, from top to
  * bottom, outermost to innermost.
  *
  * A. Component loading
  *
- * Components may be loaded in "reuse loader global" mode, where to save on
- * memory, all JSMs and JS-implemented XPCOM modules are loaded into a single
- * global. Each individual JSMs are compiled as functions with their own
- * FakeBackstagePass. They have the following env chain:
+ * Components may be loaded in a shared global mode where most JSMs share a
+ * single global in order to save on memory and avoid CCWs. To support this, a
+ * NonSyntacticVariablesObject is used for each JSM to provide a basic form of
+ * isolation. They have the following env chain:
  *
  *   BackstagePass global
  *       |
- *   Global lexical scope
+ *   LexicalEnvironmentObject[this=global]
  *       |
- *   WithEnvironmentObject wrapping FakeBackstagePass
+ *   NonSyntacticVariablesObject
  *       |
- *   LexicalEnvironmentObject
+ *   LexicalEnvironmentObject[this=nsvo]
  *
- * B. Subscript loading
+ * B.1 Subscript loading
  *
- * Subscripts may be loaded into a target object. They have the following
- * env chain:
+ * Subscripts may be loaded into a target object and it's associated global.
+ * They have the following env chain:
  *
- *   Loader global
+ *   Target object's global
  *       |
- *   Global lexical scope
+ *   LexicalEnvironmentObject[this=global]
  *       |
  *   WithEnvironmentObject wrapping target
  *       |
- *   LexicalEnvironmentObject
+ *   LexicalEnvironmentObject[this=target]
+ *
+ * B.2 Subscript loading (Shared-global JSM)
+ *
+ * The target object of a subscript load may be in a JSM with a shared global,
+ * in which case we will also have the NonSyntacticVariablesObject on the
+ * chain.
  *
- * C. Frame scripts
+ *   Target object's global
+ *       |
+ *   LexicalEnvironmentObject[this=global]
+ *       |
+ *   NonSyntacticVariablesObject
+ *       |
+ *   LexicalEnvironmentObject[this=nsvo]
+ *       |
+ *   WithEnvironmentObject wrapping target
+ *       |
+ *   LexicalEnvironmentObject[this=target]
+ *
+ * D. Frame scripts
  *
  * XUL frame scripts are always loaded with a NonSyntacticVariablesObject as a
  * "polluting global". This is done exclusively in
  * js::ExecuteInGlobalAndReturnScope.
  *
  *   Loader global
  *       |
- *   Global lexical scope
+ *   LexicalEnvironmentObject[this=global]
  *       |
  *   NonSyntacticVariablesObject
  *       |
- *   LexicalEnvironmentObject
+ *   LexicalEnvironmentObject[this=global]
  *
  * D. XBL and DOM event handlers
  *
  * XBL methods are compiled as functions with XUL elements on the env chain,
  * and DOM event handlers are compiled as functions with HTML elements on the
- * env chain. For a chain of elements e0,...,eN:
+ * env chain. For a chain of elements e0,e1,...:
  *
  *      ...
  *       |
- *   WithEnvironmentObject wrapping eN
- *       |
- *      ...
+ *   WithEnvironmentObject wrapping e1
  *       |
  *   WithEnvironmentObject wrapping e0
  *       |
  *   LexicalEnvironmentObject
  *
  */
 
 class EnvironmentObject : public NativeObject
--- a/layout/base/nsIPresShell.h
+++ b/layout/base/nsIPresShell.h
@@ -615,16 +615,22 @@ public:
 
   void ObserveStyleFlushes()
   {
     if (!ObservingStyleFlushes())
       DoObserveStyleFlushes();
   }
 
   bool NeedStyleFlush() const { return mNeedStyleFlush; }
+  /**
+   * Returns true if we might need to flush layout, even if we haven't scheduled
+   * one yet (as opposed to HasPendingReflow, which returns true if a flush is
+   * scheduled or will soon be scheduled).
+   */
+  bool NeedLayoutFlush() const { return mNeedLayoutFlush; }
 
   /**
    * Callbacks will be called even if reflow itself fails for
    * some reason.
    */
   virtual nsresult PostReflowCallback(nsIReflowCallback* aCallback) = 0;
   virtual void CancelReflowCallback(nsIReflowCallback* aCallback) = 0;
 
@@ -1633,16 +1639,20 @@ public:
   bool IsNeverPainting() {
     return mIsNeverPainting;
   }
 
   void SetNeverPainting(bool aNeverPainting) {
     mIsNeverPainting = aNeverPainting;
   }
 
+  /**
+   * True if a reflow event has been scheduled, or is going to be scheduled
+   * to run in the future.
+   */
   bool HasPendingReflow() const
     { return mObservingLayoutFlushes || mReflowContinueTimer; }
 
   void SyncWindowProperties(nsView* aView);
 
   virtual nsIDocument* GetPrimaryContentDocument() = 0;
 
   // aSheetType is one of the nsIStyleSheetService *_SHEET constants.
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -3576,16 +3576,32 @@ ScrollFrameHelper::BuildDisplayList(nsDi
     if (mWillBuildScrollableLayer && aBuilder->IsPaintingToWindow()) {
       asrSetter.EnterScrollFrame(sf);
     }
 
     if (mIsScrollableLayerInRootContainer) {
       aBuilder->SetActiveScrolledRootForRootScrollframe(aBuilder->CurrentActiveScrolledRoot());
     }
 
+    if (mWillBuildScrollableLayer) {
+      // Create a hit test info item for the scrolled content that's not
+      // clipped to the displayport. This ensures that within the bounds
+      // of the scroll frame, the scrolled content is always hit, even
+      // if we are checkerboarding.
+      if (aBuilder->BuildCompositorHitTestInfo()) {
+        CompositorHitTestInfo info = mScrolledFrame->GetCompositorHitTestInfo(aBuilder);
+        if (info != CompositorHitTestInfo::eInvisibleToHitTest) {
+          nsDisplayCompositorHitTestInfo* hitInfo =
+              MakeDisplayItem<nsDisplayCompositorHitTestInfo>(aBuilder, mScrolledFrame, info, 1);
+          aBuilder->SetCompositorHitTestInfo(hitInfo);
+          scrolledContent.BorderBackground()->AppendToTop(hitInfo);
+        }
+      }
+    }
+
     {
       // Clip our contents to the unsnapped scrolled rect. This makes sure that
       // we don't have display items over the subpixel seam at the edge of the
       // scrolled area.
       DisplayListClipState::AutoSaveRestore scrolledRectClipState(aBuilder);
       nsRect scrolledRectClip =
         GetUnsnappedScrolledRectInternal(mScrolledFrame->GetScrollableOverflowRect(),
                                          mScrollPort.Size()) + mScrolledFrame->GetPosition();
--- a/layout/reftests/box-shadow/reftest.list
+++ b/layout/reftests/box-shadow/reftest.list
@@ -6,17 +6,17 @@ random != boxshadow-blur-2.html boxshado
 == boxshadow-multiple.html boxshadow-multiple-ref.html
 == boxshadow-spread.html boxshadow-spread-ref.html
 == tableboxshadow-basic.html tableboxshadow-basic-ref.html
 == tableboxshadow-trshadow.html tableboxshadow-trshadow-ref.html
 == tableboxshadow-tdshadow.html tableboxshadow-tdshadow-ref.html
 == boxshadow-rounding.html boxshadow-rounding-ref.html
 # One uses old path, one uses WR box shadow.
 fails-if(Android) == boxshadow-button.html boxshadow-button-ref.html
-fuzzy-if(OSX==1010,1,24) fuzzy-if(d2d,16,999) fuzzy-if(webrender,4-4,360-360) == boxshadow-large-border-radius.html boxshadow-large-border-radius-ref.html # Bug 1209649
+fuzzy-if(OSX==1010,1,24) fuzzy-if(d2d,16,999) fuzzy-if(webrender,1-1,238-238) == boxshadow-large-border-radius.html boxshadow-large-border-radius-ref.html # Bug 1209649
 
 fails-if(Android) == boxshadow-fileupload.html boxshadow-fileupload-ref.html
 fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu),98,152) fuzzy-if(skiaContent,13,28) fuzzy-if(webrender,19-19,50-50) == boxshadow-inner-basic.html boxshadow-inner-basic-ref.svg
 random-if(layersGPUAccelerated) == boxshadow-mixed.html boxshadow-mixed-ref.html
 == boxshadow-mixed-2.html boxshadow-mixed-2-ref.html
 random-if(d2d) fuzzy-if(skiaContent,1,100) fuzzy-if(webrender,127,3528) == boxshadow-rounded-spread.html boxshadow-rounded-spread-ref.html
 fuzzy-if(skiaContent,1,50) == boxshadow-dynamic.xul boxshadow-dynamic-ref.xul
 random-if(d2d) == boxshadow-onecorner.html boxshadow-onecorner-ref.html
@@ -24,17 +24,17 @@ random-if(d2d) == boxshadow-twocorners.h
 random-if(d2d) == boxshadow-threecorners.html boxshadow-threecorners-ref.html
 fuzzy(2,440) fails-if(webrender) == boxshadow-skiprect.html boxshadow-skiprect-ref.html
 == boxshadow-opacity.html boxshadow-opacity-ref.html
 == boxshadow-color-rounding.html boxshadow-color-rounding-ref.html
 == boxshadow-color-rounding-middle.html boxshadow-color-rounding-middle-ref.html
 fuzzy(3,500) fuzzy-if(d2d,2,1080) == boxshadow-border-radius-int.html boxshadow-border-radius-int-ref.html
 == boxshadow-inset-neg-spread.html about:blank
 == boxshadow-inset-neg-spread2.html boxshadow-inset-neg-spread2-ref.html
-fuzzy(26,3610) fuzzy-if(d2d,26,5910) fuzzy-if(webrender,43,200) == boxshadow-rotated.html boxshadow-rotated-ref.html # Bug 1211264
+fuzzy(26,3610) fuzzy-if(d2d,26,5910) fuzzy-if(webrender,22-22,3258-3258) == boxshadow-rotated.html boxshadow-rotated-ref.html # Bug 1211264
 == boxshadow-inset-large-border-radius.html boxshadow-inset-large-border-radius-ref.html
 
 # fuzzy due to blur going inside, but as long as it's essentially black instead of a light gray its ok.
 fuzzy(13,9445) fuzzy-if(d2d,13,10926) fails-if(webrender) == boxshadow-inset-large-offset.html boxshadow-inset-large-offset-ref.html
 
 == overflow-not-scrollable-1.html overflow-not-scrollable-1-ref.html
 == overflow-not-scrollable-1.html overflow-not-scrollable-1-ref2.html
 == overflow-not-scrollable-2.html overflow-not-scrollable-2-ref.html
--- a/layout/reftests/css-break/reftest.list
+++ b/layout/reftests/css-break/reftest.list
@@ -1,12 +1,12 @@
 default-preferences pref(layout.css.box-decoration-break.enabled,true)
 
 == box-decoration-break-1.html box-decoration-break-1-ref.html
-fuzzy(1,20) fuzzy-if(skiaContent,1,700) fuzzy-if(webrender,11-11,8772-8924) == box-decoration-break-with-inset-box-shadow-1.html box-decoration-break-with-inset-box-shadow-1-ref.html
+fuzzy(1,20) fuzzy-if(skiaContent,1,700) fuzzy-if(webrender,28-28,5270-5270) == box-decoration-break-with-inset-box-shadow-1.html box-decoration-break-with-inset-box-shadow-1-ref.html
 fuzzy(45,460) fuzzy-if(skiaContent,57,439) fuzzy-if(Android,57,1330) fuzzy-if(styloVsGecko,45,1410) == box-decoration-break-with-outset-box-shadow-1.html box-decoration-break-with-outset-box-shadow-1-ref.html # Bug 1386543
 random-if(!gtkWidget) == box-decoration-break-border-image.html box-decoration-break-border-image-ref.html
 == box-decoration-break-block-border-padding.html box-decoration-break-block-border-padding-ref.html
 == box-decoration-break-block-margin.html box-decoration-break-block-margin-ref.html
 fuzzy-if(!Android,1,62) fuzzy-if(Android,8,6627) == box-decoration-break-first-letter.html box-decoration-break-first-letter-ref.html #Bug 1313773
 == box-decoration-break-with-bidi.html box-decoration-break-with-bidi-ref.html
 == box-decoration-break-bug-1235152.html box-decoration-break-bug-1235152-ref.html
 == box-decoration-break-bug-1249913.html box-decoration-break-bug-1249913-ref.html
--- a/layout/reftests/css-invalid/input/reftest.list
+++ b/layout/reftests/css-invalid/input/reftest.list
@@ -16,18 +16,18 @@ fuzzy(11,4) fuzzy-if(skiaContent,2,10) =
 == input-url-valid.html input-url-ref.html
 == input-pattern-valid.html input-withtext-ref.html
 == input-pattern-invalid.html input-withtext-ref.html
 == input-type-barred.html input-button-ref.html
 fuzzy(11,4) == input-type-invalid.html input-ref.html
 fuzzy-if(webrender,0-15,0-14) == input-disabled-fieldset-1.html input-fieldset-ref.html
 fuzzy-if(webrender,0-15,0-14) == input-disabled-fieldset-2.html input-fieldset-ref.html
 == input-fieldset-legend.html input-fieldset-legend-ref.html
-fuzzy-if(webrender,0-14,0-8) == input-radio-required.html input-radio-ref.html
-fuzzy-if(skiaContent,2,10) fuzzy-if(webrender,0-14,0-8) == input-radio-customerror.html input-radio-ref.html
-fuzzy-if(skiaContent,2,10) fuzzy-if(webrender,0-14,0-8) == input-radio-dyn-valid-1.html input-radio-checked-ref.html
-fuzzy-if(skiaContent,2,10) fuzzy-if(webrender,0-14,0-8) == input-radio-dyn-valid-2.html input-radio-ref.html
-fuzzy-if(skiaContent,2,10) fuzzy-if(webrender,0-14,0-8) == input-radio-nogroup-required-valid.html input-radio-ref.html
-fuzzy-if(skiaContent,2,10) fuzzy-if(webrender,0-14,0-8) == input-radio-nogroup-required-invalid.html input-radio-checked-ref.html
-fuzzy-if(skiaContent,2,10) fuzzy-if(webrender,0-14,0-8) == input-radio-focus-click.html input-radio-ref.html
+fuzzy-if(webrender,0-92,0-2) == input-radio-required.html input-radio-ref.html
+fuzzy-if(skiaContent,2,10) fuzzy-if(webrender,0-92,0-2) == input-radio-customerror.html input-radio-ref.html
+fuzzy-if(skiaContent,2,10) fuzzy-if(webrender,0-92,0-2) == input-radio-dyn-valid-1.html input-radio-checked-ref.html
+fuzzy-if(skiaContent,2,10) fuzzy-if(webrender,0-92,0-2) == input-radio-dyn-valid-2.html input-radio-ref.html
+fuzzy-if(skiaContent,2,10) fuzzy-if(webrender,0-92,0-2) == input-radio-nogroup-required-valid.html input-radio-ref.html
+fuzzy-if(skiaContent,2,10) fuzzy-if(webrender,0-92,0-2) == input-radio-nogroup-required-invalid.html input-radio-checked-ref.html
+fuzzy-if(skiaContent,2,10) fuzzy-if(webrender,0-92,0-2) == input-radio-focus-click.html input-radio-ref.html
 == input-submit.html input-submit-ref.html
 == input-image.html input-image-ref.html
 # input type='hidden' shouldn't show
--- a/layout/style/CSSStyleSheet.h
+++ b/layout/style/CSSStyleSheet.h
@@ -15,17 +15,17 @@
 #include "mozilla/StyleSheet.h"
 #include "mozilla/StyleSheetInfo.h"
 #include "mozilla/css/SheetParsingMode.h"
 
 #include "nscore.h"
 #include "nsCOMPtr.h"
 #include "nsAutoPtr.h"
 #include "nsTArrayForwardDeclare.h"
-#include "nsString.h"
+#include "nsStringFwd.h"
 #include "mozilla/CORSMode.h"
 #include "nsCycleCollectionParticipant.h"
 #include "mozilla/net/ReferrerPolicy.h"
 #include "mozilla/dom/SRIMetadata.h"
 
 class CSSRuleListImpl;
 class nsCSSRuleProcessor;
 class nsIURI;
--- a/layout/style/ServoBindings.cpp
+++ b/layout/style/ServoBindings.cpp
@@ -1203,48 +1203,16 @@ Gecko_AddRefAtom(nsAtom* aAtom)
 }
 
 void
 Gecko_ReleaseAtom(nsAtom* aAtom)
 {
   NS_RELEASE(aAtom);
 }
 
-const uint16_t*
-Gecko_GetAtomAsUTF16(nsAtom* aAtom, uint32_t* aLength)
-{
-  static_assert(sizeof(char16_t) == sizeof(uint16_t), "Servo doesn't know what a char16_t is");
-  MOZ_ASSERT(aAtom);
-  *aLength = aAtom->GetLength();
-
-  // We need to manually cast from char16ptr_t to const char16_t* to handle the
-  // MOZ_USE_CHAR16_WRAPPER we use on WIndows.
-  return reinterpret_cast<const uint16_t*>(static_cast<const char16_t*>(aAtom->GetUTF16String()));
-}
-
-bool
-Gecko_AtomEqualsUTF8(nsAtom* aAtom, const char* aString, uint32_t aLength)
-{
-  // XXXbholley: We should be able to do this without converting, I just can't
-  // find the right thing to call.
-  nsDependentAtomString atomStr(aAtom);
-  NS_ConvertUTF8toUTF16 inStr(nsDependentCSubstring(aString, aLength));
-  return atomStr.Equals(inStr);
-}
-
-bool
-Gecko_AtomEqualsUTF8IgnoreCase(nsAtom* aAtom, const char* aString, uint32_t aLength)
-{
-  // XXXbholley: We should be able to do this without converting, I just can't
-  // find the right thing to call.
-  nsDependentAtomString atomStr(aAtom);
-  NS_ConvertUTF8toUTF16 inStr(nsDependentCSubstring(aString, aLength));
-  return nsContentUtils::EqualsIgnoreASCIICase(atomStr, inStr);
-}
-
 void
 Gecko_nsTArray_FontFamilyName_AppendNamed(nsTArray<FontFamilyName>* aNames,
                                           nsAtom* aName,
                                           bool aQuoted)
 {
   FontFamilyName family;
   aName->ToString(family.mName);
   if (aQuoted) {
@@ -2416,22 +2384,16 @@ Gecko_GetBaseSize(nsAtom* aLanguage)
 
 RawGeckoElementBorrowedOrNull
 Gecko_GetBindingParent(RawGeckoElementBorrowed aElement)
 {
   nsIContent* parent = aElement->GetBindingParent();
   return parent ? parent->AsElement() : nullptr;
 }
 
-RawGeckoXBLBindingBorrowedOrNull
-Gecko_GetXBLBinding(RawGeckoElementBorrowed aElement)
-{
-  return aElement->GetXBLBinding();
-}
-
 RawServoAuthorStylesBorrowedOrNull
 Gecko_XBLBinding_GetRawServoStyles(RawGeckoXBLBindingBorrowed aXBLBinding)
 {
   return aXBLBinding->GetServoStyles();
 }
 
 bool
 Gecko_XBLBinding_InheritsStyle(RawGeckoXBLBindingBorrowed aXBLBinding)
--- a/layout/style/ServoBindings.h
+++ b/layout/style/ServoBindings.h
@@ -288,19 +288,16 @@ void Gecko_StyleTransition_SetUnsupporte
   mozilla::StyleTransition* aTransition,
   nsAtom* aAtom);
 
 // Atoms.
 nsAtom* Gecko_Atomize(const char* aString, uint32_t aLength);
 nsAtom* Gecko_Atomize16(const nsAString* aString);
 void Gecko_AddRefAtom(nsAtom* aAtom);
 void Gecko_ReleaseAtom(nsAtom* aAtom);
-const uint16_t* Gecko_GetAtomAsUTF16(nsAtom* aAtom, uint32_t* aLength);
-bool Gecko_AtomEqualsUTF8(nsAtom* aAtom, const char* aString, uint32_t aLength);
-bool Gecko_AtomEqualsUTF8IgnoreCase(nsAtom* aAtom, const char* aString, uint32_t aLength);
 
 // Font style
 void Gecko_CopyFontFamilyFrom(nsFont* dst, const nsFont* src);
 void Gecko_nsTArray_FontFamilyName_AppendNamed(nsTArray<FontFamilyName>* aNames, nsAtom* aName, bool aQuoted);
 void Gecko_nsTArray_FontFamilyName_AppendGeneric(nsTArray<FontFamilyName>* aNames, FontFamilyType aType);
 // Returns an already-AddRefed SharedFontList with an empty mNames array.
 SharedFontList* Gecko_SharedFontList_Create();
 size_t Gecko_SharedFontList_SizeOfIncludingThis(SharedFontList* fontlist);
@@ -599,17 +596,16 @@ void Gecko_nsStyleFont_PrefillDefaultFor
                                                 RawGeckoPresContextBorrowed pres_context,
                                                 uint8_t generic_id);
 void Gecko_nsStyleFont_FixupMinFontSize(nsStyleFont* font,
                                         RawGeckoPresContextBorrowed pres_context);
 FontSizePrefs Gecko_GetBaseSize(nsAtom* lang);
 
 // XBL related functions.
 RawGeckoElementBorrowedOrNull Gecko_GetBindingParent(RawGeckoElementBorrowed aElement);
-RawGeckoXBLBindingBorrowedOrNull Gecko_GetXBLBinding(RawGeckoElementBorrowed aElement);
 RawServoAuthorStylesBorrowedOrNull Gecko_XBLBinding_GetRawServoStyles(RawGeckoXBLBindingBorrowed aXBLBinding);
 bool Gecko_XBLBinding_InheritsStyle(RawGeckoXBLBindingBorrowed aXBLBinding);
 
 struct GeckoFontMetrics
 {
   nscoord mChSize;
   nscoord mXSize;
 };
--- a/layout/style/ServoCSSParser.h
+++ b/layout/style/ServoCSSParser.h
@@ -10,17 +10,17 @@
 #define mozilla_ServoCSSParser_h
 
 #include "mozilla/gfx/Types.h"
 #include "mozilla/RefPtr.h"
 #include "mozilla/ServoTypes.h"
 #include "nsColor.h"
 #include "nsCSSPropertyID.h"
 #include "nsDOMCSSDeclaration.h"
-#include "nsString.h"
+#include "nsStringFwd.h"
 
 class nsCSSValue;
 class nsIDocument;
 struct nsCSSRect;
 struct nsTimingFunction;
 struct RawServoDeclarationBlock;
 
 using RawGeckoGfxMatrix4x4 = mozilla::gfx::Float[16];
--- a/layout/style/ServoUtils.h
+++ b/layout/style/ServoUtils.h
@@ -149,19 +149,9 @@ inline bool IsInServoTraversal()
 #else
 #define MOZ_STYLO_FORWARD_CONCRETE(method_, geckoargs_, servoargs_)         \
   return AsServo()->method_ servoargs_;
 #endif
 
 #define MOZ_STYLO_FORWARD(method_, args_) \
   MOZ_STYLO_FORWARD_CONCRETE(method_, args_, args_)
 
-// Warning in MOZ_STYLO builds and non-fatally assert in regular builds.
-#define NS_ASSERTION_STYLO_WARNING_EXPAND(X) X
-#ifdef MOZ_STYLO
-#define NS_ASSERTION_STYLO_WARNING(...) \
-  NS_ASSERTION_STYLO_WARNING_EXPAND(NS_WARNING_ASSERTION(__VA_ARGS__))
-#else
-#define NS_ASSERTION_STYLO_WARNING(...) \
-  NS_ASSERTION_STYLO_WARNING_EXPAND(NS_ASSERTION(__VA_ARGS__))
-#endif
-
 #endif // mozilla_ServoUtils_h
--- a/layout/style/nsCSSProps.h
+++ b/layout/style/nsCSSProps.h
@@ -9,17 +9,17 @@
  * values they accept
  */
 
 #ifndef nsCSSProps_h___
 #define nsCSSProps_h___
 
 #include <limits>
 #include <type_traits>
-#include "nsString.h"
+#include "nsStringFwd.h"
 #include "nsCSSPropertyID.h"
 #include "nsStyleStructFwd.h"
 #include "nsCSSKeywords.h"
 #include "mozilla/CSSEnabledState.h"
 #include "mozilla/UseCounter.h"
 #include "mozilla/EnumTypeTraits.h"
 #include "mozilla/Preferences.h"
 #include "nsXULAppAPI.h"
--- a/layout/style/nsICSSDeclaration.h
+++ b/layout/style/nsICSSDeclaration.h
@@ -17,17 +17,17 @@
  * CSSStyleDeclaration; the difference is that these use nsCSSPropertyID
  * enums for the prop names instead of using strings.
  */
 
 #include "mozilla/Attributes.h"
 #include "nsCSSPropertyID.h"
 #include "mozilla/dom/CSSValue.h"
 #include "nsWrapperCache.h"
-#include "nsString.h"
+#include "nsStringFwd.h"
 #include "mozilla/ErrorResult.h"
 #include "nsCOMPtr.h"
 
 class nsINode;
 class nsIPrincipal;
 namespace mozilla {
 namespace css {
 class Rule;
--- a/layout/style/nsStyleConsts.h
+++ b/layout/style/nsStyleConsts.h
@@ -4,18 +4,19 @@
  * 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/. */
 
 /* constants used in the style struct data provided by nsStyleContext */
 
 #ifndef nsStyleConsts_h___
 #define nsStyleConsts_h___
 
-#include "gfxRect.h"
-#include "nsFont.h"
+#include <inttypes.h>
+
+#include "gfxFontConstants.h"
 #include "X11UndefineNone.h"
 
 // XXX fold this into nsStyleContext and group by nsStyleXXX struct
 
 namespace mozilla {
 
 // Basic shapes
 enum class StyleBasicShapeType : uint8_t {
--- a/layout/style/nsStyleCoord.h
+++ b/layout/style/nsStyleCoord.h
@@ -7,17 +7,19 @@
 /* representation of length values in computed style data */
 
 #ifndef nsStyleCoord_h___
 #define nsStyleCoord_h___
 
 #include <type_traits>
 
 #include "mozilla/EnumTypeTraits.h"
+#include "mozilla/gfx/Types.h"
 #include "nsCoord.h"
+#include "nsISupportsImpl.h"
 #include "nsStyleConsts.h"
 
 namespace mozilla {
 
 class WritingMode;
 
 // Logical axis, edge, side and corner constants for use in various places.
 enum LogicalAxis {
--- a/layout/style/nsStyleUtil.h
+++ b/layout/style/nsStyleUtil.h
@@ -3,17 +3,16 @@
 /* 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/. */
 #ifndef nsStyleUtil_h___
 #define nsStyleUtil_h___
 
 #include "nsCoord.h"
 #include "nsCSSPropertyID.h"
-#include "nsString.h"
 #include "nsTArrayForwardDeclare.h"
 #include "gfxFontFamilyList.h"
 #include "nsStringFwd.h"
 #include "nsStyleStruct.h"
 #include "nsCRT.h"
 
 class nsCSSValue;
 class nsStyleCoord;
new file mode 100644
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/SessionLifecycleTest.kt
@@ -0,0 +1,218 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+package org.mozilla.geckoview.test
+
+import org.mozilla.geckoview.GeckoSession
+import org.mozilla.geckoview.GeckoSessionSettings
+
+import android.support.test.filters.MediumTest
+import android.support.test.runner.AndroidJUnit4
+
+import org.hamcrest.Matchers.*
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+@MediumTest
+class SessionLifecycleTest : BaseSessionTest() {
+
+    @Test fun openWindow_allowNullContext() {
+        sessionRule.session.closeWindow()
+
+        sessionRule.session.openWindow(null)
+        sessionRule.session.reload()
+        sessionRule.session.waitForPageStop()
+    }
+
+    @Test fun openWindow_interleaved() {
+        val session1 = sessionRule.createOpenSession()
+        val session2 = sessionRule.createOpenSession()
+        session1.closeWindow()
+        val session3 = sessionRule.createOpenSession()
+        session2.closeWindow()
+        session3.closeWindow()
+
+        sessionRule.session.reload()
+        sessionRule.session.waitForPageStop()
+    }
+
+    @Test fun openWindow_repeated() {
+        for (i in 1..5) {
+            sessionRule.session.closeWindow()
+            sessionRule.session.openWindow()
+        }
+        sessionRule.session.reload()
+        sessionRule.session.waitForPageStop()
+    }
+
+    @Test fun openWindow_allowCallsWhileClosed() {
+        sessionRule.session.closeWindow()
+
+        sessionRule.session.loadUri(HELLO_HTML_PATH)
+        sessionRule.session.reload()
+
+        sessionRule.session.openWindow()
+        sessionRule.session.waitForPageStops(2)
+    }
+
+    @Test(expected = IllegalStateException::class)
+    fun openWindow_throwOnAlreadyOpen() {
+        // Throw exception if retrying to open again; otherwise we would leak the old open window.
+        sessionRule.session.openWindow()
+    }
+
+    @Test(expected = IllegalStateException::class)
+    fun setChromeURI_throwOnOpenSession() {
+        sessionRule.session.settings.setString(GeckoSessionSettings.CHROME_URI, "chrome://invalid/path/to.xul")
+    }
+
+    @Test(expected = IllegalStateException::class)
+    fun setScreenID_throwOnOpenSession() {
+        sessionRule.session.settings.setInt(GeckoSessionSettings.SCREEN_ID, 42)
+    }
+
+    @Test(expected = IllegalStateException::class)
+    fun setUsePrivateMode_throwOnOpenSession() {
+        sessionRule.session.settings.setBoolean(GeckoSessionSettings.USE_PRIVATE_MODE, true)
+    }
+
+    @Test(expected = IllegalStateException::class)
+    fun setUseMultiprocess_throwOnOpenSession() {
+        sessionRule.session.settings.setBoolean(
+                GeckoSessionSettings.USE_MULTIPROCESS,
+                !sessionRule.session.settings.getBoolean(GeckoSessionSettings.USE_MULTIPROCESS))
+    }
+
+    @Test fun readFromParcel() {
+        val session = sessionRule.createOpenSession()
+
+        session.toParcel { parcel ->
+            val newSession = sessionRule.createClosedSession()
+            newSession.readFromParcel(parcel)
+
+            assertThat("New session has same settings",
+                       newSession.settings, equalTo(session.settings))
+            assertThat("New session is open", newSession.isOpen, equalTo(true))
+
+            newSession.closeWindow()
+            assertThat("New session can be closed", newSession.isOpen, equalTo(false))
+        }
+
+        sessionRule.session.reload()
+        sessionRule.session.waitForPageStop()
+    }
+
+    @Test(expected = IllegalStateException::class)
+    fun readFromParcel_throwOnAlreadyOpen() {
+        // Throw exception if retrying to open again; otherwise we would leak the old open window.
+        sessionRule.session.toParcel { parcel ->
+            sessionRule.createOpenSession().readFromParcel(parcel)
+        }
+    }
+
+    @Test fun readFromParcel_canLoadPageAfterRead() {
+        val newSession = sessionRule.createClosedSession()
+
+        sessionRule.session.toParcel { parcel ->
+            newSession.readFromParcel(parcel)
+        }
+
+        newSession.reload()
+        newSession.waitForPageStop()
+    }
+
+    @Test fun readFromParcel_closedSession() {
+        val session = sessionRule.createClosedSession()
+
+        session.toParcel { parcel ->
+            val newSession = sessionRule.createClosedSession()
+            newSession.readFromParcel(parcel)
+            assertThat("New session should not be open",
+                       newSession.isOpen, equalTo(false))
+        }
+
+        sessionRule.session.reload()
+        sessionRule.session.waitForPageStop()
+    }
+
+    @Test fun readFromParcel_closedSessionAfterParceling() {
+        val session = sessionRule.createOpenSession()
+
+        session.toParcel { parcel ->
+            session.closeWindow()
+
+            val newSession = sessionRule.createClosedSession()
+            newSession.readFromParcel(parcel)
+            assertThat("New session should not be open",
+                       newSession.isOpen, equalTo(false))
+        }
+
+        sessionRule.session.reload()
+        sessionRule.session.waitForPageStop()
+    }
+
+    @Test fun readFromParcel_closeOpenAndLoad() {
+        val newSession = sessionRule.createClosedSession()
+
+        sessionRule.session.toParcel { parcel ->
+            newSession.readFromParcel(parcel)
+        }
+
+        newSession.closeWindow()
+        newSession.openWindow()
+
+        newSession.reload()
+        newSession.waitForPageStop()
+    }
+
+    @Test fun readFromParcel_allowCallsBeforeUnparceling() {
+        val newSession = sessionRule.createClosedSession()
+
+        newSession.loadTestPath(HELLO_HTML_PATH)
+        newSession.reload()
+
+        sessionRule.session.toParcel { parcel ->
+            newSession.readFromParcel(parcel)
+        }
+        newSession.waitForPageStops(2)
+    }
+
+    @Test fun readFromParcel_chained() {
+        val session1 = sessionRule.createClosedSession()
+        val session2 = sessionRule.createClosedSession()
+        val session3 = sessionRule.createClosedSession()
+
+        sessionRule.session.toParcel { parcel ->
+            session1.readFromParcel(parcel)
+        }
+        session1.toParcel { parcel ->
+            session2.readFromParcel(parcel)
+        }
+        session2.toParcel { parcel ->
+            session3.readFromParcel(parcel)
+        }
+
+        session3.reload()
+        session3.waitForPageStop()
+    }
+
+    @Test fun createFromParcel() {
+        val session = sessionRule.createOpenSession()
+
+        session.toParcel { parcel ->
+            val newSession = sessionRule.wrapSession(
+                    GeckoSession.CREATOR.createFromParcel(parcel))
+
+            assertThat("New session has same settings",
+                       newSession.settings, equalTo(session.settings))
+            assertThat("New session is open", newSession.isOpen, equalTo(true))
+
+            newSession.closeWindow()
+            assertThat("New session can be closed", newSession.isOpen, equalTo(false))
+        }
+
+        sessionRule.session.reload()
+        sessionRule.session.waitForPageStop()
+    }
+}
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/EventDispatcher.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/EventDispatcher.java
@@ -67,20 +67,16 @@ public final class EventDispatcher exten
     /* package */ EventDispatcher() {
         mNativeQueue = GeckoThread.getNativeQueue();
     }
 
     public EventDispatcher(final NativeQueue queue) {
         mNativeQueue = queue;
     }
 
-    public NativeQueue getNativeQueue() {
-        return mNativeQueue;
-    }
-
     private boolean isReadyForDispatchingToGecko() {
         return mNativeQueue.isReady();
     }
 
     @WrapForJNI(dispatchTo = "gecko") @Override // JNIObject
     protected native void disposeNative();
 
     @WrapForJNI private static final int DETACHED = 0;
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/process/GeckoProcessManager.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/process/GeckoProcessManager.java
@@ -156,18 +156,19 @@ public final class GeckoProcessManager e
             }
             return connection;
         }
     }
 
     public void preload(final String... types) {
         for (final String type : types) {
             final ChildConnection connection = getConnection(type);
-            connection.bind();
-            connection.getPid();
+            if (connection.bind() != null) {
+                connection.getPid();
+            }
         }
     }
 
     @WrapForJNI
     private static int start(final String type, final String[] args,
                              final int ipcFd, final int crashFd,
                              final int crashAnnotationFd) {
         return INSTANCE.start(type, args, ipcFd, crashFd, crashAnnotationFd, /* retry */ false);
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java
@@ -41,17 +41,27 @@ import android.support.annotation.Nullab
 import android.support.annotation.NonNull;
 import android.util.Log;
 
 public class GeckoSession extends LayerSession
                           implements Parcelable {
     private static final String LOGTAG = "GeckoSession";
     private static final boolean DEBUG = false;
 
-    /* package */ enum State implements NativeQueue.State {
+    // Type of changes given to onWindowChanged.
+    // Window has been cleared due to the session being closed.
+    private static final int WINDOW_CLOSE = 0;
+    // Window has been set due to the session being opened.
+    private static final int WINDOW_OPEN = 1; // Window has been opened.
+    // Window has been cleared due to the session being transferred to another session.
+    private static final int WINDOW_TRANSFER_OUT = 2; // Window has been transfer.
+    // Window has been set due to another session being transferred to this one.
+    private static final int WINDOW_TRANSFER_IN = 3;
+
+    private enum State implements NativeQueue.State {
         INITIAL(0),
         READY(1);
 
         private final int mRank;
 
         private State(int rank) {
             mRank = rank;
         }
@@ -304,16 +314,23 @@ public class GeckoSession extends LayerS
 
                     delegate.onMediaPermissionRequest(
                             GeckoSession.this, message.getString("uri"),
                             videos, audios, new PermissionCallback("media", callback));
                 }
             }
         };
 
+    /* package */ int handlersCount;
+
+    private final GeckoSessionHandler<?>[] mSessionHandlers = new GeckoSessionHandler<?>[] {
+        mContentHandler, mNavigationHandler, mProgressHandler, mScrollHandler,
+        mTrackingProtectionHandler, mPermissionHandler
+    };
+
     private static class PermissionCallback implements
         PermissionDelegate.Callback, PermissionDelegate.MediaCallback {
 
         private final String mType;
         private EventCallback mCallback;
 
         public PermissionCallback(final String type, final EventCallback callback) {
             mType = type;
@@ -390,71 +407,118 @@ public class GeckoSession extends LayerS
         public Binder asBinder() {
             if (mBinder == null) {
                 mBinder = new Binder();
                 mBinder.attachInterface(this, Window.class.getName());
             }
             return mBinder;
         }
 
+        // Create a new Gecko window and assign an initial set of Java session objects to it.
         @WrapForJNI(dispatchTo = "proxy")
-        public static native void open(Window instance, Compositor compositor,
-                                       EventDispatcher dispatcher,
-                                       GeckoBundle settings, String chromeUri,
-                                       int screenId, boolean privateMode, String id);
+        public static native void open(Window instance, NativeQueue queue,
+                                       Compositor compositor, EventDispatcher dispatcher,
+                                       GeckoBundle settings, String id, String chromeUri,
+                                       int screenId, boolean privateMode);
 
         @Override // JNIObject
-        protected void disposeNative() {
-            // Detach ourselves from the binder as well, to prevent this window from being
-            // read from any parcels.
-            asBinder().attachInterface(null, Window.class.getName());
-
-            // Reset our queue, so we don't end up with queued calls on a disposed object.
-            synchronized (this) {
-                mNativeQueue.reset(State.INITIAL);
-            }
-
+        public void disposeNative() {
             if (GeckoThread.isStateAtLeast(GeckoThread.State.PROFILE_READY)) {
                 nativeDisposeNative();
             } else {
                 GeckoThread.queueNativeCallUntil(GeckoThread.State.PROFILE_READY,
                         this, "nativeDisposeNative");
             }
         }
 
         @WrapForJNI(dispatchTo = "proxy", stubName = "DisposeNative")
         private native void nativeDisposeNative();
 
-        @WrapForJNI(dispatchTo = "proxy")
-        public native void close();
-
-        @WrapForJNI(dispatchTo = "proxy")
-        public native void transfer(Compositor compositor, EventDispatcher dispatcher,
-                                    GeckoBundle settings);
+        // Force the underlying Gecko window to close and release assigned Java objects.
+        public void close() {
+            // Reset our queue, so we don't end up with queued calls on a disposed object.
+            synchronized (this) {
+                if (mNativeQueue == null) {
+                    // Already closed elsewhere.
+                    return;
+                }
+                mNativeQueue.reset(State.INITIAL);
+                mNativeQueue = null;
+            }
 
-        @WrapForJNI(calledFrom = "gecko")
-        private synchronized void onTransfer(final EventDispatcher dispatcher) {
-            final NativeQueue nativeQueue = dispatcher.getNativeQueue();
-            if (mNativeQueue != nativeQueue) {
-                // Set new queue to the same state as the old queue,
-                // then return the old queue to its initial state if applicable,
-                // because the old queue is no longer the active queue.
-                nativeQueue.setState(mNativeQueue.getState());
-                mNativeQueue.reset(State.INITIAL);
-                mNativeQueue = nativeQueue;
+            // Detach ourselves from the binder as well, to prevent this window from being
+            // read from any parcels.
+            asBinder().attachInterface(null, Window.class.getName());
+
+            if (GeckoThread.isStateAtLeast(GeckoThread.State.PROFILE_READY)) {
+                nativeClose();
+            } else {
+                GeckoThread.queueNativeCallUntil(GeckoThread.State.PROFILE_READY,
+                        this, "nativeClose");
             }
         }
 
+        @WrapForJNI(dispatchTo = "proxy", stubName = "Close")
+        private native void nativeClose();
+
+        // Assign a new set of Java session objects to the underlying Gecko window.
+        // This replaces previously assigned objects from open() or transfer() calls.
+        public synchronized void transfer(final NativeQueue queue,
+                                          final Compositor compositor,
+                                          final EventDispatcher dispatcher,
+                                          final GeckoBundle settings) {
+            if (mNativeQueue == null) {
+                // Already closed.
+                return;
+            }
+
+            if (GeckoThread.isStateAtLeast(GeckoThread.State.PROFILE_READY)) {
+                nativeTransfer(queue, compositor, dispatcher, settings);
+            } else {
+                GeckoThread.queueNativeCallUntil(GeckoThread.State.PROFILE_READY,
+                        this, "nativeTransfer",
+                        NativeQueue.class, queue,
+                        Compositor.class, compositor,
+                        EventDispatcher.class, dispatcher,
+                        GeckoBundle.class, settings);
+            }
+
+            if (mNativeQueue != queue) {
+                // Reset the old queue to prevent old events from affecting this window.
+                // Gecko will call onReady later with the new queue if needed.
+                mNativeQueue.reset(State.INITIAL);
+                mNativeQueue = queue;
+            }
+        }
+
+        @WrapForJNI(dispatchTo = "proxy", stubName = "Transfer")
+        private native void nativeTransfer(NativeQueue queue, Compositor compositor,
+                                           EventDispatcher dispatcher, GeckoBundle settings);
+
         @WrapForJNI(dispatchTo = "proxy")
         public native void attachEditable(IGeckoEditableParent parent,
                                           GeckoEditableChild child);
 
         @WrapForJNI(calledFrom = "gecko")
-        private synchronized void onReady() {
-            if (mNativeQueue.checkAndSetState(State.INITIAL, State.READY)) {
+        private synchronized void onReady(final @Nullable NativeQueue queue) {
+            // onReady is called the first time the Gecko window is ready, with a null queue
+            // argument. In this case, we simply set the current queue to ready state.
+            //
+            // After the initial call, onReady is called again every time Window.transfer()
+            // is called, with a non-null queue argument. In this case, we only set the
+            // current queue to ready state _if_ the current queue matches the given queue,
+            // because if the queues don't match, we know there is another onReady call coming.
+
+            if ((queue == null && mNativeQueue == null) ||
+                (queue != null && mNativeQueue != queue)) {
+                return;
+            }
+
+            if (mNativeQueue.checkAndSetState(State.INITIAL, State.READY) &&
+                    queue == null) {
                 Log.i(LOGTAG, "zerdatime " + SystemClock.elapsedRealtime() +
                       " - chrome startup finished");
             }
         }
     }
 
     private class Listener implements BundleEventListener {
         /* package */ void registerListeners() {
@@ -481,47 +545,56 @@ public class GeckoSession extends LayerS
 
     public GeckoSession() {
         this(null);
     }
 
     public GeckoSession(final GeckoSessionSettings settings) {
         mSettings = new GeckoSessionSettings(settings, this);
         mListener.registerListeners();
+
+        if (BuildConfig.DEBUG && handlersCount != mSessionHandlers.length) {
+            throw new AssertionError("Add new handler to handlers list");
+        }
     }
 
     private void transferFrom(final Window window, final GeckoSessionSettings settings,
                               final String id) {
         if (isOpen()) {
             throw new IllegalStateException("Session is open");
         }
 
+        if (window != null) {
+            onWindowChanged(WINDOW_TRANSFER_IN, /* inProgress */ true);
+        }
+
         mWindow = window;
         mSettings = new GeckoSessionSettings(settings, this);
         mId = id;
 
         if (mWindow != null) {
-            if (GeckoThread.isStateAtLeast(GeckoThread.State.PROFILE_READY)) {
-                mWindow.transfer(mCompositor, mEventDispatcher, mSettings.asBundle());
-            } else {
-                GeckoThread.queueNativeCallUntil(GeckoThread.State.PROFILE_READY,
-                        mWindow, "transfer",
-                        Compositor.class, mCompositor,
-                        EventDispatcher.class, mEventDispatcher,
-                        GeckoBundle.class, mSettings.asBundle());
-            }
+            mWindow.transfer(mNativeQueue, mCompositor,
+                             mEventDispatcher, mSettings.asBundle());
+
+            onWindowChanged(WINDOW_TRANSFER_IN, /* inProgress */ false);
         }
-
-        onWindowChanged();
     }
 
     /* package */ void transferFrom(final GeckoSession session) {
+        final boolean changing = (session.mWindow != null);
+        if (changing) {
+            session.onWindowChanged(WINDOW_TRANSFER_OUT, /* inProgress */ true);
+        }
+
         transferFrom(session.mWindow, session.mSettings, session.mId);
         session.mWindow = null;
-        session.onWindowChanged();
+
+        if (changing) {
+            session.onWindowChanged(WINDOW_TRANSFER_OUT, /* inProgress */ false);
+        }
     }
 
     @Override // Parcelable
     public int describeContents() {
         return 0;
     }
 
     @Override // Parcelable
@@ -633,32 +706,36 @@ public class GeckoSession extends LayerS
 
     private void openWindow() {
         final String chromeUri = mSettings.getString(GeckoSessionSettings.CHROME_URI);
         final int screenId = mSettings.getInt(GeckoSessionSettings.SCREEN_ID);
         final boolean isPrivate = mSettings.getBoolean(GeckoSessionSettings.USE_PRIVATE_MODE);
 
         mWindow = new Window(mNativeQueue);
 
+        onWindowChanged(WINDOW_OPEN, /* inProgress */ true);
+
         if (GeckoThread.isStateAtLeast(GeckoThread.State.PROFILE_READY)) {
-            Window.open(mWindow, mCompositor, mEventDispatcher,
-                        mSettings.asBundle(), chromeUri, screenId, isPrivate, mId);
+            Window.open(mWindow, mNativeQueue, mCompositor, mEventDispatcher,
+                        mSettings.asBundle(), mId, chromeUri, screenId, isPrivate);
         } else {
             GeckoThread.queueNativeCallUntil(
                 GeckoThread.State.PROFILE_READY,
                 Window.class, "open",
                 Window.class, mWindow,
+                NativeQueue.class, mNativeQueue,
                 Compositor.class, mCompositor,
                 EventDispatcher.class, mEventDispatcher,
                 GeckoBundle.class, mSettings.asBundle(),
+                String.class, mId,
                 String.class, chromeUri,
-                screenId, isPrivate, mId);
+                screenId, isPrivate);
         }
 
-        onWindowChanged();
+        onWindowChanged(WINDOW_OPEN, /* inProgress */ false);
     }
 
     /**
      * Closes the session.
      *
      * This frees the underlying Gecko objects and unloads the current page. The session may be
      * reopened later, but page state is not restored. Call this when you are finished using
      * a GeckoSession instance.
@@ -666,31 +743,37 @@ public class GeckoSession extends LayerS
     public void close() {
         ThreadUtils.assertOnUiThread();
 
         if (!isOpen()) {
             Log.w(LOGTAG, "Attempted to close a GeckoSession that was already closed.");
             return;
         }
 
-        if (GeckoThread.isStateAtLeast(GeckoThread.State.PROFILE_READY)) {
-            mWindow.close();
-        } else {
-            GeckoThread.queueNativeCallUntil(GeckoThread.State.PROFILE_READY,
-                    mWindow, "close");
+        onWindowChanged(WINDOW_CLOSE, /* inProgress */ true);
+
+        mWindow.close();
+        mWindow.disposeNative();
+        mWindow = null;
+
+        onWindowChanged(WINDOW_CLOSE, /* inProgress */ false);
+    }
+
+    private void onWindowChanged(int change, boolean inProgress) {
+        if ((change == WINDOW_OPEN || change == WINDOW_TRANSFER_IN) && !inProgress) {
+            mTextInput.onWindowChanged(mWindow);
         }
 
-        mWindow.disposeNative();
-        mWindow = null;
-        onWindowChanged();
-    }
-
-    private void onWindowChanged() {
-        if (mWindow != null) {
-            mTextInput.onWindowChanged(mWindow);
+        if (change == WINDOW_CLOSE) {
+            // Detach when window is closing, and reattach immediately after window is closed.
+            // We reattach immediate after closing because we want any actions performed while the
+            // session is closed to be properly queued, until the session is open again.
+            for (final GeckoSessionHandler<?> handler : mSessionHandlers) {
+                handler.setSessionIsReady(getEventDispatcher(), !inProgress);
+            }
         }
     }
 
     /**
      * Get the TextInputController instance for this session.
      *
      * @return TextInputController instance.
      */
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSessionHandler.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSessionHandler.java
@@ -5,17 +5,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.geckoview;
 
 import org.mozilla.gecko.EventDispatcher;
 import org.mozilla.gecko.util.BundleEventListener;
 import org.mozilla.gecko.util.EventCallback;
 import org.mozilla.gecko.util.GeckoBundle;
-import org.mozilla.geckoview.GeckoSession;
 
 import android.util.Log;
 
 /* package */ abstract class GeckoSessionHandler<Delegate>
     implements BundleEventListener {
 
     private static final String LOGTAG = "GeckoSessionHandler";
     private static final boolean DEBUG = false;
@@ -31,71 +30,86 @@ import android.util.Log;
                                       final String[] events) {
         this(module, session, events, /* alwaysListen */ false);
     }
 
     /* package */ GeckoSessionHandler(final String module,
                                       final GeckoSession session,
                                       final String[] events,
                                       final boolean alwaysListen) {
+        session.handlersCount++;
+
         mAlwaysListen = alwaysListen;
         mModuleName = module;
         mEvents = events;
 
         if (alwaysListen) {
             register(session.getEventDispatcher());
+            setSessionIsReady(session.getEventDispatcher(), /* ready */ true);
         }
     }
 
     public Delegate getDelegate() {
         return mDelegate;
     }
 
     public void setDelegate(final Delegate delegate, final GeckoSession session) {
         final EventDispatcher eventDispatcher = session.getEventDispatcher();
         if (mDelegate == delegate) {
             return;
         }
 
-        if (!mAlwaysListen && mDelegate != null) {
+        final boolean unsettingOldDelegate = mDelegate != null &&
+                                             delegate == null;
+        final boolean settingNewDelegate = mDelegate == null &&
+                                           delegate != null;
+
+        if (!mAlwaysListen && unsettingOldDelegate) {
             unregister(eventDispatcher);
         }
 
         mDelegate = delegate;
 
-        if (!mAlwaysListen && mDelegate != null) {
+        if (!mAlwaysListen && settingNewDelegate) {
             register(eventDispatcher);
         }
     }
 
     private void unregister(final EventDispatcher eventDispatcher) {
-        final GeckoBundle msg = new GeckoBundle(1);
-        msg.putString("module", mModuleName);
-        eventDispatcher.dispatch("GeckoView:Unregister", msg);
+        setSessionIsReady(eventDispatcher, /* ready */ false);
         eventDispatcher.unregisterUiThreadListener(this, mEvents);
     }
 
     private void register(final EventDispatcher eventDispatcher) {
+        eventDispatcher.registerUiThreadListener(this, mEvents);
+        setSessionIsReady(eventDispatcher, /* ready */ true);
+    }
+
+    public void setSessionIsReady(final EventDispatcher eventDispatcher, final boolean ready) {
+        if (!mAlwaysListen && mDelegate == null) {
+            return;
+        }
+
         final GeckoBundle msg = new GeckoBundle(1);
         msg.putString("module", mModuleName);
-        eventDispatcher.dispatch("GeckoView:Register", msg);
-        eventDispatcher.registerUiThreadListener(this, mEvents);
+        eventDispatcher.dispatch(ready ? "GeckoView:Register"
+                                       : "GeckoView:Unregister", msg);
     }
 
     @Override
     public void handleMessage(final String event, final GeckoBundle message,
                               final EventCallback callback) {
         if (DEBUG) {
             Log.d(LOGTAG, mModuleName + " handleMessage: event = " + event);
         }
 
         if (mDelegate != null) {
             handleMessage(mDelegate, event, message, callback);
         } else {
-            callback.sendError("No listener registered");
+            callback.sendError("No delegate registered");
         }
     }
 
     protected abstract void handleMessage(final Delegate delegate,
                                           final String event,
                                           final GeckoBundle message,
                                           final EventCallback callback);
 }
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSessionSettings.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSessionSettings.java
@@ -173,16 +173,22 @@ public final class GeckoSessionSettings 
         return mBundle;
     }
 
     @Override
     public String toString() {
         return mBundle.toString();
     }
 
+    @Override
+    public boolean equals(final Object other) {
+        return other instanceof GeckoSessionSettings &&
+                mBundle.equals(((GeckoSessionSettings) other).mBundle);
+    }
+
     private <T> boolean valueChangedLocked(final Key<T> key, T value) {
         if (key.initOnly && mSession != null && mSession.isOpen()) {
             throw new IllegalStateException("Read-only property");
         } else if (key.values != null && !key.values.contains(value)) {
             throw new IllegalArgumentException("Invalid value");
         }
 
         final Object old = mBundle.get(key.name);
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -552,35 +552,28 @@ pref("media.getusermedia.noise_enabled",
 #endif
 pref("media.getusermedia.aec_extended_filter", true);
 pref("media.getusermedia.noise", 1);
 pref("media.getusermedia.agc_enabled", false);
 pref("media.getusermedia.agc", 3); // kAgcAdaptiveDigital
 // capture_delay: Adjustments for OS-specific input delay (lower bound)
 // playout_delay: Adjustments for OS-specific AudioStream+cubeb+output delay (lower bound)
 // full_duplex: enable cubeb full-duplex capture/playback
+pref("media.navigator.audio.full_duplex", true);
 #if defined(XP_MACOSX)
 pref("media.peerconnection.capture_delay", 50);
-pref("media.navigator.audio.full_duplex", true);
 #elif defined(XP_WIN)
 pref("media.peerconnection.capture_delay", 50);
-pref("media.navigator.audio.full_duplex", true);
 #elif defined(ANDROID)
 pref("media.peerconnection.capture_delay", 100);
-pref("media.navigator.audio.full_duplex", true);
 pref("media.navigator.hardware.vp8_encode.acceleration_enabled", true);
 pref("media.navigator.hardware.vp8_encode.acceleration_remote_enabled", true);
 pref("media.navigator.hardware.vp8_decode.acceleration_enabled", false);
-#elif defined(XP_LINUX) || defined(MOZ_SNDIO)
+#else
 pref("media.peerconnection.capture_delay", 70);
-pref("media.navigator.audio.full_duplex", true);
-#else
-// *BSD, others - merely a guess for now
-pref("media.peerconnection.capture_delay", 50);
-pref("media.navigator.audio.full_duplex", false);
 #endif
 // Use MediaDataDecoder API for WebRTC, this includes hardware acceleration for
 // decoding.
 pref("media.navigator.mediadatadecoder_enabled", false);
 #endif
 
 pref("dom.webaudio.enabled", true);
 
@@ -1361,18 +1354,18 @@ pref("dom.forms.datetime.others", false)
 pref("dom.forms.datetime.timepicker", false);
 
 // Support @autocomplete values for form autofill feature.
 pref("dom.forms.autocomplete.formautofill", false);
 
 // Enable search in <select> dropdowns (more than 40 options)
 pref("dom.forms.selectSearch", false);
 // Allow for webpages to provide custom styling for <select>
-// popups. Disabled on Linux due to bug 1338283.
-#ifdef XP_LINUX
+// popups. Disabled on GTK due to bug 1338283.
+#ifdef MOZ_WIDGET_GTK
 pref("dom.forms.select.customstyling", false);
 #else
 pref("dom.forms.select.customstyling", true);
 #endif
 pref("dom.select_popup_in_parent.enabled", false);
 // Bug 1421229 - content-select
 pref("dom.select_popup_in_content.enabled", false);
 
--- a/netwerk/dns/TRR.cpp
+++ b/netwerk/dns/TRR.cpp
@@ -41,17 +41,16 @@ extern mozilla::LazyLogModule gHostResol
 NS_IMPL_ISUPPORTS(TRR, nsIHttpPushListener, nsIInterfaceRequestor, nsIStreamListener, nsIRunnable)
 
 const uint8_t kDNS_CLASS_IN = 1;
 
 NS_IMETHODIMP
 TRR::Notify(nsITimer *aTimer)
 {
   if (aTimer == mTimeout) {
-    LOG(("TRR request for %s timed out\n", mHost.get()));
     mTimeout = nullptr;
     Cancel();
   } else {
     MOZ_CRASH("Unknown timer");
   }
 
   return NS_OK;
 }
--- a/netwerk/dns/TRRService.cpp
+++ b/netwerk/dns/TRRService.cpp
@@ -39,16 +39,17 @@ TRRService::TRRService()
   , mLock("trrservice")
   , mConfirmationNS(NS_LITERAL_CSTRING("example.com"))
   , mWaitForCaptive(true)
   , mRfc1918(false)
   , mCaptiveIsPassed(false)
   , mUseGET(false)
   , mClearTRRBLStorage(false)
   , mConfirmationState(CONFIRM_INIT)
+  , mRetryConfirmInterval(1000)
 {
   MOZ_ASSERT(NS_IsMainThread(), "wrong thread");
 }
 
 nsresult
 TRRService::Init()
 {
   MOZ_ASSERT(NS_IsMainThread(), "wrong thread");
@@ -78,23 +79,29 @@ TRRService::Init()
   LOG(("Initialized TRRService\n"));
   return NS_OK;
 }
 
 bool
 TRRService::Enabled()
 {
   if (mConfirmationState == CONFIRM_INIT && !mWaitForCaptive) {
+    LOG(("TRRService::Enabled => CONFIRM_TRYING\n"));
     mConfirmationState = CONFIRM_TRYING;
   }
 
   if (mConfirmationState == CONFIRM_TRYING) {
+    LOG(("TRRService::Enabled MaybeConfirm()\n"));
     MaybeConfirm();
   }
 
+  if (mConfirmationState != CONFIRM_OK) {
+    LOG(("TRRService::Enabled mConfirmationState=%d\n", (int)mConfirmationState));
+  }
+
   return (mConfirmationState == CONFIRM_OK);
 }
 
 void
 TRRService::GetPrefBranch(nsIPrefBranch **result)
 {
   MOZ_ASSERT(NS_IsMainThread(), "wrong thread");
   *result = nullptr;
@@ -285,16 +292,18 @@ TRRService::Observe(nsISupports *aSubjec
   return NS_OK;
 }
 
 void
 TRRService::MaybeConfirm()
 {
   if ((mMode == MODE_NATIVEONLY) || mConfirmer ||
       mConfirmationState != CONFIRM_TRYING) {
+    LOG(("TRRService:MaybeConfirm mode=%d, mConfirmer=%p mConfirmationState=%d\n",
+         (int)mMode, (void *)mConfirmer, (int)mConfirmationState));
     return;
   }
   nsAutoCString host;
   {
     MutexAutoLock lock(mLock);
     host = mConfirmationNS;
   }
   if (host.Equals("skip")) {
@@ -473,16 +482,34 @@ TRRService::TRRBlacklist(const nsACStrin
 
       // check if there's an NS entry for this name
       RefPtr<TRR> trr = new TRR(this, check, TRRTYPE_NS, privateBrowsing);
       NS_DispatchToMainThread(trr);
     }
   }
 }
 
+NS_IMETHODIMP
+TRRService::Notify(nsITimer *aTimer)
+{
+  if (aTimer == mRetryConfirmTimer) {
+    mRetryConfirmTimer = nullptr;
+    if (mConfirmationState == CONFIRM_FAILED) {
+      LOG(("TRRService retry NS of %s\n", mConfirmationNS.get()));
+      mConfirmationState = CONFIRM_TRYING;
+      MaybeConfirm();
+    }
+  } else {
+    MOZ_CRASH("Unknown timer");
+  }
+
+  return NS_OK;
+}
+
+
 AHostResolver::LookupStatus
 TRRService::CompleteLookup(nsHostRecord *rec, nsresult status, AddrInfo *aNewRRSet, bool pb)
 {
   // this is an NS check for the TRR blacklist or confirmationNS check
 
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(!rec);
 
@@ -491,16 +518,28 @@ TRRService::CompleteLookup(nsHostRecord 
 
   MOZ_ASSERT(!mConfirmer || (mConfirmationState == CONFIRM_TRYING));
   if (mConfirmationState == CONFIRM_TRYING) {
     MOZ_ASSERT(mConfirmer);
     mConfirmationState = NS_SUCCEEDED(status) ? CONFIRM_OK : CONFIRM_FAILED;
     LOG(("TRRService finishing confirmation test %s %d %X\n",
          mPrivateURI.get(), (int)mConfirmationState, (unsigned int)status));
     mConfirmer = nullptr;
+    if ((mConfirmationState == CONFIRM_FAILED) && (mMode == MODE_TRRONLY)) {
+      // in TRR-only mode; retry failed confirmations
+      NS_NewTimerWithCallback(getter_AddRefs(mRetryConfirmTimer),
+                              this, mRetryConfirmInterval,
+                              nsITimer::TYPE_ONE_SHOT);
+      if (mRetryConfirmInterval < 64000) {
+        // double the interval up to this point
+        mRetryConfirmInterval *= 2;
+      }
+    } else {
+      mRetryConfirmInterval = 1000;
+    }
     return LOOKUP_OK;
   }
 
   // when called without a host record, this is a domain name check response.
   if (NS_SUCCEEDED(status)) {
     LOG(("TRR verified %s to be fine!\n", newRRSet->mHostName));
   } else {
     LOG(("TRR says %s doesn't resove as NS!\n", newRRSet->mHostName));
--- a/netwerk/dns/TRRService.h
+++ b/netwerk/dns/TRRService.h
@@ -14,22 +14,24 @@
 
 class nsIPrefBranch;
 
 namespace mozilla {
 namespace net {
 
 class TRRService
   : public nsIObserver
+  , public nsITimerCallback
   , public nsSupportsWeakReference
   , public AHostResolver
 {
 public:
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIOBSERVER
+  NS_DECL_NSITIMERCALLBACK
 
   TRRService();
   nsresult Init();
   nsresult Start();
   bool Enabled();
 
   uint32_t Mode() { return mMode; }
   bool AllowRFC1918() { return mRfc1918; }
@@ -74,17 +76,19 @@ private:
 
   enum ConfirmationState {
     CONFIRM_INIT = 0,
     CONFIRM_TRYING = 1,
     CONFIRM_OK = 2,
     CONFIRM_FAILED = 3
   };
   Atomic<ConfirmationState, Relaxed>  mConfirmationState;
-  RefPtr<TRR>           mConfirmer;
+  RefPtr<TRR> mConfirmer;
+  nsCOMPtr<nsITimer> mRetryConfirmTimer;
+  uint32_t mRetryConfirmInterval; // milliseconds until retry
 };
 
 extern TRRService *gTRRService;
 
 } // namespace net
 } // namespace mozilla
 
 #endif // TRRService_h_
--- a/netwerk/protocol/http/nsHttpHandler.cpp
+++ b/netwerk/protocol/http/nsHttpHandler.cpp
@@ -341,17 +341,17 @@ nsHttpHandler::SetFastOpenOSSupport()
     }
 #endif
 
     LOG(("nsHttpHandler::SetFastOpenOSSupport version %s", version.get()));
 
     if (NS_SUCCEEDED(rv)) {
         // set min version minus 1.
 #if XP_MACOSX
-        int min_version[] = {17, 3};
+        int min_version[] = {17, 4}; // High Sierra 10.13.4
 #elif ANDROID
         int min_version[] = {4, 4};
 #elif XP_LINUX
         int min_version[] = {3, 6};
 #endif
         int inx = 0;
         nsCCharSeparatedTokenizer tokenizer(version, '.');
         while ((inx < 2) && tokenizer.hasMoreTokens()) {
--- a/security/manager/ssl/StaticHPKPins.h
+++ b/security/manager/ssl/StaticHPKPins.h
@@ -1158,9 +1158,9 @@ static const TransportSecurityPreload kP
   { "za.search.yahoo.com", false, true, false, -1, &kPinset_yahoo },
   { "zh.search.yahoo.com", false, true, false, -1, &kPinset_yahoo },
 };
 
 // Pinning Preload List Length = 485;
 
 static const int32_t kUnknownId = -1;
 
-static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1528920938896000);
+static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1529092618082000);
--- a/security/manager/ssl/nsSTSPreloadList.errors
+++ b/security/manager/ssl/nsSTSPreloadList.errors
@@ -12,29 +12,28 @@ 0x52.org: could not connect to host
 0xdc.io: could not connect to host
 1000serien.com: could not connect to host
 1001.best: could not connect to host
 100onrainkajino.com: could not connect to host
 10gb.io: could not connect to host
 135vv.com: could not connect to host
 13826145000.com: could not connect to host
 166166.com: could not connect to host
-18888msc.com: could not connect to host
 1912x.com: could not connect to host
 1er-secours.ch: could not connect to host
 1gsoft.com: could not connect to host
 1nian.vip: could not connect to host
 1q365a.com: could not connect to host
 249cq.com: could not connect to host
 24ip.fr: could not connect to host
 2b3b.com: could not connect to host
 2bitout.com: could not connect to host
 2fl.me: could not connect to host
 2gen.com: could not connect to host
-2programmers.net: could not connect to host
+330.net: could not connect to host
 360ds.co.in: could not connect to host
 38888msc.com: could not connect to host
 38blog.com: could not connect to host
 3bigking.com: could not connect to host
 3vlnaeet.cz: could not connect to host
 41844.de: could not connect to host
 439191.com: could not connect to host
 47tech.com: could not connect to host
@@ -57,33 +56,34 @@ 87577.com: could not connect to host
 8887999.com: could not connect to host
 88laohu.cc: could not connect to host
 88laohu.com: could not connect to host
 8ackprotect.com: could not connect to host
 8ballbombom.uk: could not connect to host
 8t88.biz: could not connect to host
 91-freedom.com: could not connect to host
 99buffets.com: could not connect to host
-9ss6.com: could not connect to host
 a-ix.net: could not connect to host
 aaron.xin: could not connect to host
 abi-fvs.de: could not connect to host
+abilma.com: could not connect to host
 abloop.com: could not connect to host
 abolition.co: could not connect to host
 abstractbarista.com: could not connect to host
 abstractbarista.net: could not connect to host
 ac.milan.it: could not connect to host
 acat.io: could not connect to host
 accolade.com.br: could not connect to host
 accwing.com: could not connect to host
 acecerts.co.uk: could not connect to host
 acgaudio.com: could not connect to host
 achterhoekseveiligheidsbeurs.nl: could not connect to host
 acpinformatique.fr: could not connect to host
 acrossgw.com: could not connect to host
+activitesaintnicaise.org: could not connect to host
 acwcerts.co.uk: could not connect to host
 ad-disruptio.fr: could not connect to host
 adamcoffee.net: could not connect to host
 adamdixon.co.uk: could not connect to host
 adec-emsa.ae: could not connect to host
 adult.properties: could not connect to host
 advaithnikhi.ml: could not connect to host
 advaithnikhi.tk: could not connect to host
@@ -95,23 +95,25 @@ affily.io: could not connect to host
 afterstack.net: could not connect to host
 agingstop.net: could not connect to host
 agoravm.tk: could not connect to host
 agowa.eu: could not connect to host
 agowa338.de: could not connect to host
 agrilinks.org: could not connect to host
 ahelos.tk: could not connect to host
 ahlz.sk: could not connect to host
+aid-web.ch: could not connect to host
 aikenorganics.com: could not connect to host
 aim-consultants.com: could not connect to host
 airclass.com: could not connect to host
 ajdiaz.me: could not connect to host
 ajetaci.cz: could not connect to host
 akiba-server.info: could not connect to host
 akita-stream.com: could not connect to host
+akoch.net: could not connect to host
 akoww.de: could not connect to host
 akul.co.in: could not connect to host
 al-f.net: could not connect to host
 alasta.info: could not connect to host
 alauda-home.de: could not connect to host
 albertify.xyz: could not connect to host
 alcatraz.online: could not connect to host
 alexandernorth.ch: could not connect to host
@@ -119,16 +121,17 @@ alexberts.ch: could not connect to host
 alexey-shamara.ru: could not connect to host
 alexmol.tk: could not connect to host
 alexperry.io: could not connect to host
 algarmatic-automatismos.pt: could not connect to host
 alilialili.ga: could not connect to host
 alldm.ru: could not connect to host
 alloutatl.com: could not connect to host
 allscammers.exposed: could not connect to host
+allthingsblogging.com: could not connect to host
 allthingsfpl.com: could not connect to host
 alocato.com: could not connect to host
 alohapartyevents.co.uk: could not connect to host
 alphabrock.cn: could not connect to host
 altahrim.net: could not connect to host
 amdouglas.uk: could not connect to host
 ameho.me: could not connect to host
 americandistribuidora.com: could not connect to host
@@ -218,25 +221,22 @@ awf0.xyz: could not connect to host
 axel-fischer.science: could not connect to host
 b-landia.net: could not connect to host
 b9winner.com: could not connect to host
 babelfisch.eu: could not connect to host
 bacimg.com: could not connect to host
 badbee.cc: could not connect to host
 bailbondsaffordable.com: could not connect to host
 balonmano.co: could not connect to host
-bananensap.nl: could not connect to host
 bandally.net: could not connect to host
 bandarifamily.com: could not connect to host
 bannisbierblog.de: could not connect to host
 bardiharborow.com: could not connect to host
 bardiharborow.tk: could not connect to host
 barracuda.blog: could not connect to host
-bartelt.name: could not connect to host
-bartula.de: could not connect to host
 bashc.at: could not connect to host
 batfoundry.com: could not connect to host
 bbb1991.me: could not connect to host
 bbdos.ru: could not connect to host
 bbwteens.org: could not connect to host
 bcnet.com.hk: could not connect to host
 bcradio.org: could not connect to host
 bcrook.com: could not connect to host
@@ -244,16 +244,17 @@ bdsmxxxpics.com: could not connect to ho
 beamitapp.com: could not connect to host
 beasel.biz: could not connect to host
 beccajoshwedding.com: could not connect to host
 beersandco.ch: could not connect to host
 beeznest.com: could not connect to host
 bellavistaoutdoor.com: could not connect to host
 belpbleibtbelp.ch: could not connect to host
 belwederczykow.eu: could not connect to host
+ben.ninja: could not connect to host
 bendemaree.com: could not connect to host
 benfairclough.com: could not connect to host
 benjamin-horvath.com: could not connect to host
 benjamin-suess.de: could not connect to host
 benzou-space.com: could not connect to host
 berduri.com: could not connect to host
 berlin-kohlefrei.de: could not connect to host
 berry.cat: could not connect to host
@@ -267,24 +268,25 @@ besthotsales.com: could not connect to h
 betonmoney.com: could not connect to host
 bey.io: could not connect to host
 bezoomnyville.com: could not connect to host
 bfi.wien: could not connect to host
 bfrailwayclub.cf: could not connect to host
 bianinapiccanovias.com: could not connect to host
 bichonmaltes.com.br: could not connect to host
 bigerbio.com: could not connect to host
-billaud.eu.org: could not connect to host
 billigpoker.dk: could not connect to host
 billpro.com.au: could not connect to host
 binam.center: could not connect to host
 bingcheung.com: could not connect to host
 binimo.com: could not connect to host
 biou.me: could not connect to host
+biovalue.eu: could not connect to host
 bip.gov.sa: could not connect to host
+birthdaytip.com: could not connect to host
 biscuits-rec.com: could not connect to host
 biscuits-shop.com: could not connect to host
 biswas.me: could not connect to host
 bitcoin-class.com: could not connect to host
 bitcoin-daijin.com: could not connect to host
 bitcoinjpn.com: could not connect to host
 bitmain.com.ua: could not connect to host
 bitmaincare.com.ua: could not connect to host
@@ -296,16 +298,17 @@ bjtxl.cn: could not connect to host
 black-khat.com: could not connect to host
 blackberrycentral.com: could not connect to host
 blackdragoninc.org: could not connect to host
 blackhelicopters.net: could not connect to host
 blackscreen.me: could not connect to host
 blantik.net: could not connect to host
 blazeit.io: could not connect to host
 blessedearth.com.au: could not connect to host
+bliesekow.net: could not connect to host
 blindaryproduction.tk: could not connect to host
 blinkenlight.co.uk: could not connect to host
 blinkenlight.com.au: could not connect to host
 blog.gparent.org: could not connect to host
 blogabout.ru: could not connect to host
 blogdieconomia.it: could not connect to host
 blueblou.com: could not connect to host
 blumen-garage.de: could not connect to host
@@ -325,19 +328,16 @@ boxdevigneron.fr: could not connect to h
 bpadvisors.eu: could not connect to host
 bqcp.net: could not connect to host
 bragaweb.com.br: could not connect to host
 brage.info: could not connect to host
 braintensive.com: could not connect to host
 brandontaylor-black.com: could not connect to host
 bratteng.me: could not connect to host
 bratteng.xyz: could not connect to host
-breatheav.com: could not connect to host
-breatheproduction.com: could not connect to host
-breathingblanket.com: could not connect to host
 brianmwaters.net: could not connect to host
 brideandgroomdirect.ie: could not connect to host
 brio-ukraine.store: could not connect to host
 broerweb.nl: could not connect to host
 brookframework.org: could not connect to host
 brrr.fr: could not connect to host
 brunner.ninja: could not connect to host
 brynnan.nl: could not connect to host
@@ -345,30 +345,27 @@ bsalyzer.com: could not connect to host
 bsktweetup.info: could not connect to host
 bslim-e-boutique.com: could not connect to host
 bsuess.de: could not connect to host
 buck.com: could not connect to host
 buenotour.ru: could not connect to host
 bugsmashed.com: could not connect to host
 bugtrack.co.uk: could not connect to host
 buka.jp: could not connect to host
-bulbgenie.com: could not connect to host
 bulletbabu.com: could not connect to host
-bumshow.ru: could not connect to host
 bunadarbankinn.is: could not connect to host
 bunnyvishal.com: could not connect to host
 businessetmarketing.com: could not connect to host
 businessfurs.info: could not connect to host
 businesshub.cz: could not connect to host
 businessmodeler.se: could not connect to host
 buyharpoon.com: could not connect to host
 buyhealth.shop: could not connect to host
 buyingsellingflorida.com: could not connect to host
 buyshoe.org: could not connect to host
-buzzdeck.com: could not connect to host
 bvexplained.co.uk: could not connect to host
 bxdev.me: could not connect to host
 by1898.com: could not connect to host
 byji.com: could not connect to host
 bynet.cz: could not connect to host
 bypass.kr: could not connect to host
 byteshift.ca: could not connect to host
 cafechesscourt.com: could not connect to host
@@ -379,18 +376,16 @@ calculatoaresecondhand.xyz: could not co
 callabs.net: could not connect to host
 calleveryday.com: could not connect to host
 callsigns.ca: could not connect to host
 calypso-tour.net: could not connect to host
 camda.online: could not connect to host
 campingcarlovers.com: could not connect to host
 cancelmyprofile.com: could not connect to host
 canifis.net: could not connect to host
-capellidipremoli.com: could not connect to host
-car-rental24.com: could not connect to host
 cardelmar.es: could not connect to host
 cardloan-manual.net: could not connect to host
 carey.bio: could not connect to host
 carloshmm.com: could not connect to host
 carloshmm.stream: could not connect to host
 carlovanwyk.com: could not connect to host
 carrando.de: could not connect to host
 casinoreal.com: could not connect to host
@@ -417,20 +412,22 @@ championnat-romand-cuisiniers-amateurs.c
 chancat.blog: could not connect to host
 channellife.asia: could not connect to host
 chaouby.com: could not connect to host
 charge.co: could not connect to host
 charmyadesara.com: could not connect to host
 cheah.xyz: could not connect to host
 cheesefusion.com: could not connect to host
 chez-janine.de: could not connect to host
+chicorycom.net: could not connect to host
 china-line.org: could not connect to host
 chinternet.xyz: could not connect to host
 chloe.re: could not connect to host
 chocolat-suisse.ch: could not connect to host
+chorkley.me: could not connect to host
 chrisebert.net: could not connect to host
 christianhoffmann.info: could not connect to host
 christianpusch.de: could not connect to host
 christiansayswords.com: could not connect to host
 chromaryu.net: could not connect to host
 chziyue.com: could not connect to host
 cipher.land: could not connect to host
 cipherli.st: could not connect to host
@@ -443,38 +440,35 @@ ckcameron.net: could not connect to host
 clashersrepublic.com: could not connect to host
 clearchatsandbox.com: could not connect to host
 clearviewwealthprojector.com.au: could not connect to host
 clic-music.com: could not connect to host
 clickclock.cc: could not connect to host
 clintonbloodworth.com: could not connect to host
 cloudberlin.goip.de: could not connect to host
 cloudbleed.info: could not connect to host
+cloudfiles.at: could not connect to host
 cloudimproved.com: could not connect to host
 cloudwarez.xyz: could not connect to host
 clownish.co.il: could not connect to host
 clycat.ru: could not connect to host
 cmcc.network: could not connect to host
 cmrss.com: could not connect to host
 cms-weble.jp: could not connect to host
 cmweller.com: could not connect to host
 cnetw.xyz: could not connect to host
 cnlic.com: could not connect to host
 cnwage.com: could not connect to host
 cnwarn.com: could not connect to host
 co-yutaka.com: could not connect to host
 cobaltlp.com: could not connect to host
-coccinellaskitchen.com: could not connect to host
-coccinellaskitchen.de: could not connect to host
-coccinellaskitchen.it: could not connect to host
 codeloop.pw: could not connect to host
 codenlife.xyz: could not connect to host
 codeofhonor.tech: could not connect to host
 codercross.com: could not connect to host
-codercy.com: could not connect to host
 coderhangout.com: could not connect to host
 codewiz.xyz: could not connect to host
 cogumelosmagicos.org: could not connect to host
 colarelli.ch: could not connect to host
 colleencornez.com: could not connect to host
 collins.kg: could not connect to host
 coloppe.com: could not connect to host
 com-in.de: could not connect to host
@@ -484,33 +478,30 @@ comicrelief.com: could not connect to ho
 communityflow.info: could not connect to host
 complex-organization.com: could not connect to host
 complt.xyz: could not connect to host
 comprehensiveihc.com: could not connect to host
 conception.sk: could not connect to host
 conniesacademy.com: could not connect to host
 conrad.am: could not connect to host
 constructive.men: could not connect to host
-contratatupoliza.com: could not connect to host
 conve.eu: could not connect to host
+coopens.com: could not connect to host
 corecdn.org: could not connect to host
 corinnanese.de: could not connect to host
 correct.horse: could not connect to host
 cosmeticosdelivery.com.br: could not connect to host
 cosmiatria.pe: could not connect to host
 cosplayer.com: could not connect to host
 cotta.dk: could not connect to host
 coumoul.fr: could not connect to host
 cpaneltips.com: could not connect to host
 crackslut.eu: could not connect to host
 crashsec.com: could not connect to host
-creativecommonscatpictures.com: could not connect to host
-creato.top: could not connect to host
 credential.eu: could not connect to host
-creditreporttips.net: could not connect to host
 cristianhares.com: could not connect to host
 criticalaim.com: could not connect to host
 crow.tw: could not connect to host
 crox.co: could not connect to host
 cryptoki.fr: could not connect to host
 cryptolosophy.io: could not connect to host
 cryptoparty.dk: could not connect to host
 cryptopartynewcastle.org: could not connect to host
@@ -534,16 +525,17 @@ cyber-computer.club: could not connect t
 cyberpeace.nl: could not connect to host
 cyberstatus.de: could not connect to host
 cype.dedyn.io: could not connect to host
 cypherpunk.ws: could not connect to host
 czlx.co: could not connect to host
 d-bood.site: could not connect to host
 d3x.pw: could not connect to host
 d4rkdeagle.tk: could not connect to host
+d4wson.com: could not connect to host
 d8studio.net: could not connect to host
 daltonedwards.me: could not connect to host
 dam74.com.ar: could not connect to host
 damedrogy.cz: could not connect to host
 daniel-stahl.net: could not connect to host
 danpiel.net: could not connect to host
 darkdestiny.ch: could not connect to host
 darlo.co.uk: could not connect to host
@@ -553,27 +545,27 @@ dashboard.yt: could not connect to host
 data-detox.com: could not connect to host
 datastream.re: could not connect to host
 datorb.com: could not connect to host
 davidgreig.uk: could not connect to host
 davidscherzer.at: could not connect to host
 davidstuff.net: could not connect to host
 davros.eu: could not connect to host
 davros.ru: could not connect to host
+daw.nz: could not connect to host
 dawnson.is: could not connect to host
 dawnsonb.com: could not connect to host
 day-peak.com: could not connect to host
 days.one: could not connect to host
 dbox.ga: could not connect to host
 dcc.moe: could not connect to host
 dden.website: could not connect to host
 dden.xyz: could not connect to host
 ddmeportal.com: could not connect to host
 de-servers.de: could not connect to host
-deborahmarinelli.eu: could not connect to host
 decoyrouting.com: could not connect to host
 dedietrich-asia.com: could not connect to host
 deepcreampie.com: could not connect to host
 deeps.cat: could not connect to host
 deloittequant.com: could not connect to host
 depedtayo.ph: could not connect to host
 derchris.me: could not connect to host
 derivativeshub.pro: could not connect to host
@@ -582,23 +574,25 @@ dermapuur.nl: could not connect to host
 designsbykerrialee.co.uk: could not connect to host
 detecte-fuite.ch: could not connect to host
 detecte.ch: could not connect to host
 detectefuite.ch: could not connect to host
 devdesco.com: could not connect to host
 developersclub.website: could not connect to host
 devops.moe: could not connect to host
 dezintranet.com: could not connect to host
+dgt-portal.de: could not connect to host
 dhl-smart.ch: could not connect to host
 dhub.xyz: could not connect to host
 dhxxls.com: could not connect to host
 diceduels.com: could not connect to host
 dicgaming.net: could not connect to host
 dick.red: could not connect to host
 didierlaumen.be: could not connect to host
+die-gruenen-teufel.de: could not connect to host
 diemogebhardt.com: could not connect to host
 dieser.me: could not connect to host
 digihyp.ch: could not connect to host
 digioccumss.ddns.net: could not connect to host
 digitalhurricane.io: could not connect to host
 digitalrxcloud.com: could not connect to host
 digitalsurge.io: could not connect to host
 digitalwasteland.net: could not connect to host
@@ -621,54 +615,51 @@ disinisharing.com: could not connect to 
 distinctivephotography.com.au: could not connect to host
 ditch.ch: could not connect to host
 diwei.vip: could not connect to host
 dixmag.com: could not connect to host
 diz.in.ua: could not connect to host
 djul.net: could not connect to host
 dlouwrink.nl: could not connect to host
 dlyl888.com: could not connect to host
-dmdre.com: could not connect to host
 dna.li: could not connect to host
 dnfc.rocks: could not connect to host
 dnmaze.com: could not connect to host
 do-it.cz: could not connect to host
 dobrisan.ro: could not connect to host
 doctafit.com: could not connect to host
 docubox.info: could not connect to host
 doesmycodehavebugs.today: could not connect to host
 dogcratereview.info: could not connect to host
 dojifish.space: could not connect to host
+doku-gilde.de: could not connect to host
 dolphin-hosting.com: could not connect to host
 domainoo.com: could not connect to host
 domengrad.ru: could not connect to host
 domfee.com: could not connect to host
 dongkexue.com: could not connect to host
 doopdidoop.com: could not connect to host
-dormiu.com.br: could not connect to host
 dougferris.id.au: could not connect to host
 doyoulyft.com: could not connect to host
 doze-cloud.tech: could not connect to host
 dragonwork.me: could not connect to host
 dranderle.com: could not connect to host
 drbethanybarnes.com: could not connect to host
 dreamaholic.club: could not connect to host
 dreaming.solutions: could not connect to host
 dreizwosechs.de: could not connect to host
+drinkplanet.eu: could not connect to host
 driving-lessons.co.uk: could not connect to host
 drivinghorror.com: could not connect to host
 drixn.cn: could not connect to host
 drixn.info: could not connect to host
 drixn.net: could not connect to host
 drizz.com.br: could not connect to host
-drkmtrx.xyz: could not connect to host
-drlazarina.net: could not connect to host
 drobniuch.pl: could not connect to host
 drogoz.moe: could not connect to host
-dronexpertos.com: could not connect to host
 droomhuis-in-zuid-holland-kopen.nl: could not connect to host
 drunkscifi.com: could not connect to host
 dubrovskiy.net: could not connect to host
 dubrovskiy.pro: could not connect to host
 duch.cloud: could not connect to host
 duelsow.eu: could not connect to host
 duesee.org: could not connect to host
 dujsq.com: could not connect to host
@@ -676,23 +667,25 @@ dujsq.top: could not connect to host
 dukefox.com: could not connect to host
 duks.com.br: could not connect to host
 duo.money: could not connect to host
 durangoenergyllc.com: could not connect to host
 dwnld.me: could not connect to host
 dynamic-networks.be: could not connect to host
 e-mak.eu: could not connect to host
 e-wishlist.net: could not connect to host
+eagle-yard.de: could not connect to host
 eagleridgecampground.com: could not connect to host
 earth-people.org: could not connect to host
 eatfitoutlet.com.br: could not connect to host
 eatry.io: could not connect to host
 ebonyriddle.com: could not connect to host
 ebrowz.com: could not connect to host
 eccux.com: could not connect to host
+ecolemathurincordier.com: could not connect to host
 ectora.com: could not connect to host
 edgecustomersportal.com: could not connect to host
 educatoys.com.br: could not connect to host
 eductf.org: could not connect to host
 eduif.nl: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 116"  data: no]
 eeb98.com: could not connect to host
 eeetrust.org: could not connect to host
 effectiveosgi.com: could not connect to host
@@ -713,17 +706,16 @@ elitesensual.com.br: could not connect t
 elonbase.com: could not connect to host
 elsword.moe: could not connect to host
 eltransportquevolem.org: could not connect to host
 elytronsecurity.com: could not connect to host
 emaily.eu: could not connect to host
 embellir-aroma.com: could not connect to host
 embellir-kyujin.com: could not connect to host
 embracethedarkness.co.uk: could not connect to host
-emilyjohnson.ga: could not connect to host
 eminhuseynov.com: could not connect to host
 emperor.blog: could not connect to host
 empire24.co: could not connect to host
 emrenovation.com: could not connect to host
 endohaus.us: could not connect to host
 endspamwith.us: could not connect to host
 enoou.com: could not connect to host
 enpalmademallorca.info: could not connect to host
@@ -731,32 +723,29 @@ envelope.co.nz: could not connect to hos
 er-music.com: could not connect to host
 erad.fr: could not connect to host
 erigrid.eu: could not connect to host
 erspro.net: could not connect to host
 erwinwensveen.nl: could not connect to host
 es888999.com: could not connect to host
 esoterik.link: could not connect to host
 esseriumani.com: could not connect to host
-eswap.cz: could not connect to host
 ethanfaust.com: could not connect to host
 ethiobaba.com: could not connect to host
-etincelle.ml: could not connect to host
 euexia.fr: could not connect to host
 eung.ga: could not connect to host
 eurostrategy.vn.ua: could not connect to host
 evankurniawan.com: could not connect to host
 eventaro.com: could not connect to host
 everyarti.st: could not connect to host
 eveshaiwu.com: could not connect to host
 eworksmedia.com: could not connect to host
 exceptionalservices.us: could not connect to host
 exo.do: could not connect to host
 exteriorservices.io: could not connect to host
-extreme-players.com: could not connect to host
 eytosh.net: could not connect to host
 f1bigpicture.com: could not connect to host
 f8842.com: could not connect to host
 faber.org.ru: could not connect to host
 fabian-kluge.de: could not connect to host
 fabienbaker.com: could not connect to host
 fabulouslyyouthfulskin.com: could not connect to host
 fabulouslyyouthfulskineyeserum.com: could not connect to host
@@ -772,21 +761,20 @@ fallenangeldrinks.eu: could not connect 
 famer.me: could not connect to host
 fameuxhosting.co.uk: could not connect to host
 faretravel.co.uk: could not connect to host
 farm24.co.uk: could not connect to host
 farmacia.pt: could not connect to host
 fastaim.de: could not connect to host
 fastbackmbg.be: could not connect to host
 faxreader.net: could not connect to host
+fcapartsdb.com: could not connect to host
 feac.us: could not connect to host
 fedn.it: could not connect to host
-fedux.com.ar: could not connect to host
 feedstringer.com: could not connect to host
-feel.aero: could not connect to host
 feirlane.org: could not connect to host
 feisbed.com: could not connect to host
 felger-times.fr: could not connect to host
 fengyadi.com: could not connect to host
 feras-alhajjaji.com: could not connect to host
 fetclips.se: could not connect to host
 fhsseniormens.club: could not connect to host
 ficklenote.net: could not connect to host
@@ -805,23 +793,21 @@ first-time-offender.com: could not conne
 fiscoeconti.it: could not connect to host
 fix-the-timeline.com: could not connect to host
 fix-the-timeline.org: could not connect to host
 fixmyglitch.com: could not connect to host
 fixthetimeline.com: could not connect to host
 fixthetimeline.org: could not connect to host
 flamingcow.tv: could not connect to host
 flexinvesting.fi: could not connect to host
-fliacuello.com.ar: could not connect to host
 floth.at: could not connect to host
 flow.su: could not connect to host
 flucky.xyz: could not connect to host
 flugplatz-edvc.de: could not connect to host
 flyingdoggy.net: could not connect to host
-fnncat.com: could not connect to host
 focalforest.com: could not connect to host
 fojing.com: could not connect to host
 foodserve.in: could not connect to host
 forcamp.ga: could not connect to host
 forsyththeatre.com: could not connect to host
 fortuna-loessnitz.de: could not connect to host
 foshanshequ.com: could not connect to host
 fossewayflowers.co.uk: could not connect to host
@@ -841,16 +827,17 @@ free8.xyz: could not connect to host
 freeassangenow.org: could not connect to host
 freedomvote.nl: could not connect to host
 freejidi.com: could not connect to host
 freeshkre.li: could not connect to host
 freesitemapgenerator.com: could not connect to host
 freshcode.nl: could not connect to host
 frickenate.com: could not connect to host
 friedhelm-wolf.de: could not connect to host
+frodriguez.xyz: could not connect to host
 frolov.net: could not connect to host
 fromlemaytoz.com: could not connect to host
 frosty-gaming.xyz: could not connect to host
 frp-roleplay.de: could not connect to host
 frydrychit.cz: could not connect to host
 fsfi.is: could not connect to host
 ftgho.com: could not connect to host
 fuckcf.cf: could not connect to host
@@ -881,32 +868,34 @@ gametium.com: could not connect to host
 gametium.es: could not connect to host
 gamhealth.net: could not connect to host
 garage-door.pro: could not connect to host
 gasbarkenora.com: could not connect to host
 gasnews.net: could not connect to host
 gautham.pro: could not connect to host
 gayforgenji.com: could not connect to host
 gaygeeks.de: could not connect to host
+gbcsummercamps.com: could not connect to host
 gc.net: could not connect to host
 gchoic.com: could not connect to host
 gdevpenze.ru: could not connect to host
 gdhzcgs.com: could not connect to host
 gdz-otvety.com: could not connect to host
 ge1.me: could not connect to host
+gear-acquisition-syndrome.community: could not connect to host
 geeks.berlin: could not connect to host
 gehrke.nrw: could not connect to host
 geigr.de: could not connect to host
 geldteveel.eu: could not connect to host
+generalpants.com.au: could not connect to host
 generationnext.pl: could not connect to host
 geneve.guide: could not connect to host
 genia-life.de: could not connect to host
 genoog.com: could not connect to host
 genossen.ru: could not connect to host
-georgescarryout.com: could not connect to host
 geri.be: could not connect to host
 gers-authentique.com: could not connect to host
 geta.pub: could not connect to host
 getdigitized.net: could not connect to host
 getfilterlive.org: could not connect to host
 getgeek.dk: could not connect to host
 getgeek.ee: could not connect to host
 getgeek.fi: could not connect to host
@@ -925,19 +914,21 @@ gh16.com.ar: could not connect to host
 ghaglund.se: could not connect to host
 gifzilla.net: could not connect to host
 gina-architektur.design: could not connect to host
 girlsforum.com: could not connect to host
 git.co: could not connect to host
 gix.net.pl: could not connect to host
 gladystudio.com: could not connect to host
 globalnewsdaily.cf: could not connect to host
+globaltennis.ca: could not connect to host
 globalvisions-events.ch: could not connect to host
 glutenfreelife.co.nz: could not connect to host
 gmanukyan.com: could not connect to host
+gmpartsdb.com: could not connect to host
 gnom.me: could not connect to host
 gnosticjade.net: could not connect to host
 goanalyse.co.uk: could not connect to host
 godrealms.com: could not connect to host
 goiaspropaganda.com.br: could not connect to host
 goldfelt.com: could not connect to host
 gongjuhao.com: could not connect to host
 goodyearsotn.co.uk: could not connect to host
@@ -954,52 +945,56 @@ graphite.org.uk: could not connect to ho
 gratisonlinesex.com: could not connect to host
 greggsfoundation.org.uk: could not connect to host
 gregmartyn.com: could not connect to host
 greuel.online: could not connect to host
 greyhash.se: could not connect to host
 gritte.net: could not connect to host
 grossmisconduct.news: could not connect to host
 growingmetrics.com: could not connect to host
-gruelang.org: could not connect to host
 grusenmeyer.be: could not connect to host
 gugaltika-ipb.org: could not connect to host
 guinea-pig.co: could not connect to host
 gunhunter.com: could not connect to host
 gus.moe: could not connect to host
 gutuia.blue: could not connect to host
 gvchannel.xyz: could not connect to host
 gxgx.org: could not connect to host
 gzpblog.com: could not connect to host
 h2cdn.cloud: could not connect to host
 h3artbl33d.nl: could not connect to host
 habeo.si: could not connect to host
+hackanders.com: could not connect to host
 hackbubble.me: could not connect to host
 hackmeplz.com: could not connect to host
 haktec.de: could not connect to host
 hakugin.me: could not connect to host
-hakurei.moe: could not connect to host
 halcyonsbastion.com: could not connect to host
 half-logic.eu.org: could not connect to host
+hallelujahsoftware.com: could not connect to host
 halta.info: could not connect to host
 hamking.tk: could not connect to host
 hammer-schnaps.com: could not connect to host
 hamu.blue: could not connect to host
+hanksservice.com: could not connect to host
+hanys.xyz: could not connect to host
 happytiger.eu: could not connect to host
 hapsfordmill.co.uk: could not connect to host
 hapvm.com: could not connect to host
 hardeman.nu: could not connect to host
 harrypottereditor.net: could not connect to host
+harvester.fr: could not connect to host
 has-no-email-set.de: could not connect to host
 hasabig.wang: could not connect to host
 hasalittle.wang: could not connect to host
 hashimah.ca: could not connect to host
 hashplex.com: could not connect to host
 hatethe.uk: could not connect to host
 hbbet.com: could not connect to host
+hbdesign.work: could not connect to host
 hbvip.com: could not connect to host
 hcstr.com: could not connect to host
 hdc.cz: could not connect to host
 hdrtranscon.com: could not connect to host
 hdy.nz: could not connect to host
 healthyandnaturalliving.com: could not connect to host
 hearingshofar.com: could not connect to host
 hearty.ink: could not connect to host
@@ -1031,26 +1026,28 @@ hintermeier-rae.at: could not connect to
 hiphop.ren: could not connect to host
 hirte-digital.de: could not connect to host
 history.pe: could not connect to host
 hitchunion.org: could not connect to host
 hjes.com.ve: could not connect to host
 hoffens.se: could not connect to host
 hohm.in: could not connect to host
 holidayincotswolds.co.uk: could not connect to host
+home-cloud.online: could not connect to host
 homesfordinner.ca: could not connect to host
 homoglyph.net: could not connect to host
 hondenoppasfraneker.nl: could not connect to host
 honeybeard.co.uk: could not connect to host
 honeytracks.com: could not connect to host
 hoodoo.io: could not connect to host
 hoodoo.tech: could not connect to host
 horvathd.eu: could not connect to host
 hosted-oswa.org: could not connect to host
 hotelmadhuwanvihar.com: could not connect to host
+hoto.us: could not connect to host
 hozinga.de: could not connect to host
 hr-tech.shop: could not connect to host
 hr-tech.store: could not connect to host
 hr98.tk: could not connect to host
 hserver.top: could not connect to host
 httptest.net: could not connect to host
 huangzenghao.cn: could not connect to host
 huangzenghao.com: could not connect to host
@@ -1058,47 +1055,49 @@ hudingyuan.cn: could not connect to host
 huiser.nl: could not connect to host
 hukaloh.com: could not connect to host
 hukkatavara.com: could not connect to host
 hunger.im: could not connect to host
 huongquynh.com: could not connect to host
 huwjones.me: could not connect to host
 huzurmetal.net: could not connect to host
 hydrante.ch: could not connect to host
+hydronyx.me: could not connect to host
 hyper-matrix.org: could not connect to host
 hypotecnicentrum.cz: could not connect to host
 hypotheques24.ch: could not connect to host
+hyvive.com: could not connect to host
 i-stats.net: could not connect to host
 i95.me: could not connect to host
 iadttaveras.com: could not connect to host
 iamsoareyou.se: could not connect to host
 ibron.co: could not connect to host
 ibsafrica.co.za: could not connect to host
 ibsglobal.co.za: could not connect to host
 iceloch.com: could not connect to host
-ichasco.com: could not connect to host
-ict-concept.nl: could not connect to host
 ictpro.info: could not connect to host
 icusignature.com: could not connect to host
 ideadozz.hu: could not connect to host
 idemo.in: could not connect to host
 identity-hash.online: could not connect to host
 idid.tk: could not connect to host
 idol-bikes.ru: could not connect to host
 idtechnowizard.com: could not connect to host
 iemb.cf: could not connect to host
 ifan.ch: could not connect to host
 ifxnet.com: could not connect to host
 igamingforums.com: could not connect to host
 ihatethissh.it: could not connect to host
 iideaz.org: could not connect to host
 iilin.com: could not connect to host
 iiong.com: could not connect to host
+iirii.com: could not connect to host
 ikenmeyer.com: could not connect to host
 ikenmeyer.eu: could not connect to host
+ikk.me: could not connect to host
 ikzoekeengoedkopeauto.nl: could not connect to host
 ildomani.it: could not connect to host
 ileat.com: could not connect to host
 imaginarymakings.me: could not connect to host
 img.ovh: could not connect to host
 imgencrypt.com: could not connect to host
 imgul.net: could not connect to host
 imguoguo.com: could not connect to host
@@ -1111,43 +1110,44 @@ imperiumnova.info: could not connect to 
 increasetestosteronelevels.org: could not connect to host
 inderagamono.net: could not connect to host
 industreiler.com: could not connect to host
 industreiler.com.br: could not connect to host
 inexpensivecomputers.net: could not connect to host
 informatik.zone: could not connect to host
 infoworm.org: could not connect to host
 infruction.com: could not connect to host
+injust.me: could not connect to host
 innovativebuildingsolutions.co.za: could not connect to host
 innovativeideaz.org: could not connect to host
 inondation.ch: could not connect to host
 inscript.pl: could not connect to host
 insouciant.org: could not connect to host
 inst.mobi: could not connect to host
 instasex.ch: could not connect to host
 int-ext-design.fr: could not connect to host
 intelldynamics.com: could not connect to host
+intensifyrsvp.com.au: could not connect to host
 interspot.nl: could not connect to host
 interviewpipeline.co.uk: could not connect to host
 intracom.com: could not connect to host
 invenio.software: could not connect to host
 investingdiary.cn: could not connect to host
 investorloanshub.com: could not connect to host
 iodu.re: could not connect to host
 ip.or.at: could not connect to host
 iphonechina.net: could not connect to host
 iplog.info: could not connect to host
 ipnetworking.net: could not connect to host
-ipsec.pl: could not connect to host
 irayo.net: could not connect to host
 irinkeby.nu: could not connect to host
 isamiok.com: could not connect to host
 isisfighters.info: could not connect to host
 iskkk.com: could not connect to host
-isocom.eu: could not connect to host
+isoroc-nidzica.pl: could not connect to host
 isscouncil.com: could not connect to host
 isthefieldcontrolsystemdown.com: could not connect to host
 istherrienstillcoach.com: could not connect to host
 itad.top: could not connect to host
 itnews-bg.com: could not connect to host
 itpro-mg.de: could not connect to host
 its-schindler.de: could not connect to host
 itsatrap.nl: could not connect to host
@@ -1175,62 +1175,59 @@ jbbd.fr: could not connect to host
 jcaicedo.tk: could not connect to host
 jccars-occasions.be: could not connect to host
 jccrew.org: could not connect to host
 jcraft.us: could not connect to host
 jean-remy.ch: could not connect to host
 jecho.cn: could not connect to host
 jeffersonregan.org: could not connect to host
 jens.hk: could not connect to host
-jessevictors.com: could not connect to host
+jerrypau.ca: could not connect to host
 jhburton.co.uk: could not connect to host
 jiangzm.com: could not connect to host
 jianyuan.pro: could not connect to host
 jiaqiang.vip: could not connect to host
-jimmycn.com: could not connect to host
 jmb.lc: could not connect to host
 jmoreau.ddns.net: could not connect to host
 jmvbmx.ch: could not connect to host
 jobmedic.com: could not connect to host
 joecod.es: could not connect to host
 joetyson.io: could not connect to host
 johntomasowa.com: could not connect to host
 jonathansanchez.pro: could not connect to host
 jonfor.net: could not connect to host
 jooto.com: could not connect to host
-jorovik.com: could not connect to host
+josc.com.au: could not connect to host
 joshharkema.com: could not connect to host
 jpod.cc: could not connect to host
 js88.sg: could not connect to host
 jsc7776.com: could not connect to host
 jsjyhzy.cc: could not connect to host
 juliaoantiguidades.com.br: could not connect to host
 juliawebber.co.za: could not connect to host
 jumbopan.com: could not connect to host
 jumbopan.net: could not connect to host
 just-pools.co.za: could not connect to host
 justinharrison.ca: could not connect to host
 justzz.xyz: could not connect to host
 juventusmania1897.com: could not connect to host
 k33k00.com: could not connect to host
-kabus.org: could not connect to host
 kaika-facilitymanagement.de: could not connect to host
 kainz.be: could not connect to host
 kalender.goip.de: could not connect to host
 kaloix.de: could not connect to host
 kamalame.co: could not connect to host
 kamitech.ch: could not connect to host
-kandalife.com: could not connect to host
 kanganer.com: could not connect to host
 kangzaber.com: could not connect to host
-kanr.in: could not connect to host
 kapo.info: could not connect to host
 karamna.com: could not connect to host
 karuneshjohri.com: could not connect to host
 kat.al: could not connect to host
+katyusha.net: could not connect to host
 kawaiiku.com: could not connect to host
 kawaiiku.de: could not connect to host
 kaydan.io: could not connect to host
 kearney.io: could not connect to host
 kellyandantony.com: could not connect to host
 kelm.me: could not connect to host
 kermadec.com: could not connect to host
 keshausconsulting.com: could not connect to host
@@ -1263,23 +1260,22 @@ koez-mangal.ch: could not connect to hos
 koketteriet.se: could not connect to host
 kollawat.me: could not connect to host
 kollega.it: could not connect to host
 kongbaofang.com: could not connect to host
 konicaprinterdriver.com: could not connect to host
 konventseliten.se: could not connect to host
 kopfsalat.eu: could not connect to host
 koppelvlak.net: could not connect to host
-kotausaha.com: could not connect to host
 kotitesti.fi: could not connect to host
 kotorimusic.ga: could not connect to host
 kozmik.co: could not connect to host
+kram.nz: could not connect to host
 krampus-fischamend.at: could not connect to host
 kriegskindernothilfe.de: could not connect to host
-ksero.center: could not connect to host
 ktube.yt: could not connect to host
 kubusadvocaten.nl: could not connect to host
 kuko-crews.org: could not connect to host
 kwikmed.eu: could not connect to host
 kwipi.com: could not connect to host
 kyberna.xyz: could not connect to host
 kyle.place: could not connect to host
 kylerwood.com: could not connect to host
@@ -1291,20 +1287,22 @@ laboutiquemarocaineduconvoyeur.ma: could
 lacasa.fr: could not connect to host
 lacasabelucci.com: could not connect to host
 lacasseroy.com: could not connect to host
 ladylikeit.com: could not connect to host
 laforetenchantee.ch: could not connect to host
 lafr4nc3.net: could not connect to host
 lafr4nc3.xyz: could not connect to host
 lakehavasuhouserentals.com: could not connect to host
+lakhesis.net: could not connect to host
 landell.ml: could not connect to host
 langbein.org: could not connect to host
 langendorf-ernaehrung-training.de: could not connect to host
 lanonfire.com: could not connect to host
+latamarissiere.eu: could not connect to host
 lateliercantaldeco.fr: could not connect to host
 lathamlabs.com: could not connect to host
 lathamlabs.net: could not connect to host
 lathamlabs.org: could not connect to host
 lazulu.com: could not connect to host
 lbarrios.es: could not connect to host
 lbrls.tk: could not connect to host
 lclarkpdx.com: could not connect to host
@@ -1314,16 +1312,17 @@ leaderoftheresistance.com: could not con
 leaderoftheresistance.net: could not connect to host
 leaks.directory: could not connect to host
 lebal.se: could not connect to host
 leebiblestudycentre.net: could not connect to host
 leebiblestudycentre.org: could not connect to host
 leefindlow.com: could not connect to host
 leelou.wedding: could not connect to host
 leerkotte.eu: could not connect to host
+leet2.com: could not connect to host
 legal.farm: could not connect to host
 legaltip.eu: could not connect to host
 leifdreizler.com: could not connect to host
 lenkunz.me: could not connect to host
 leolana.com: could not connect to host
 leonardcamacho.me: could not connect to host
 lerlivros.online: could not connect to host
 lescomptoirsdepierrot.com: could not connect to host
@@ -1338,46 +1337,45 @@ lhsj28.com: could not connect to host
 lhsj68.com: could not connect to host
 lhsj78.com: could not connect to host
 liaozheqi.cn: could not connect to host
 libertas-tech.com: could not connect to host
 librisulibri.it: could not connect to host
 libscode.com: could not connect to host
 liceserv.com: could not connect to host
 lied8.eu: could not connect to host
-lifeinsurances.pro: could not connect to host
-lifeinsurances24.com: could not connect to host
 like.lgbt: could not connect to host
 likenosis.com: could not connect to host
 lingting.vip: could not connect to host
 linkages.org: could not connect to host
 linksanitizer.com: could not connect to host
 linksextremist.at: could not connect to host
 linley.de: could not connect to host
 linux-admin-california.com: could not connect to host
 linux.sb: could not connect to host
 linuxcode.net: could not connect to host
 linvx.org: could not connect to host
 liquidcomm.net: could not connect to host
 lisieuxarquitetura.com.br: could not connect to host
 lissabon.guide: could not connect to host
 litcomphonors.com: could not connect to host
 littlelundgrenladies.com: could not connect to host
+litvideoserver.de: could not connect to host
 liukang.tech: could not connect to host
 llvm.us: could not connect to host
 loanstreet.be: could not connect to host
 lobosdomain.no-ip.info: could not connect to host
 localhorst.xyz: could not connect to host
 locker3.com: could not connect to host
 locksport.org.nz: could not connect to host
 logcat.info: could not connect to host
 logic8.ml: could not connect to host
 logicchen.com: could not connect to host
 logimagine.com: could not connect to host
-loli.net: could not connect to host
+lolicon.eu: could not connect to host
 lookyman.net: could not connect to host
 loony.info: could not connect to host
 loopower.com: could not connect to host
 loothole.com: could not connect to host
 loqyu.co: could not connect to host
 losebellyfat.pro: could not connect to host
 love4taylor.eu.org: could not connect to host
 loveandloyalty.se: could not connect to host
@@ -1385,69 +1383,67 @@ lowt.us: could not connect to host
 loyaltech.ch: could not connect to host
 lstma.com: could not connect to host
 lszj.com: could not connect to host
 ltransferts.com: could not connect to host
 lubot.net: could not connect to host
 lucascodes.com: could not connect to host
 lucidlogs.com: could not connect to host
 lucy.science: could not connect to host
+ludovic-muller.fr: could not connect to host
+luisgf.es: could not connect to host
 lukasunger.cz: could not connect to host
 lukasunger.net: could not connect to host
 lukasztkacz.com: could not connect to host
 lumer.tech: could not connect to host
 luminancy.com: could not connect to host
 luom.net: could not connect to host
 luxonetwork.com: could not connect to host
 luxwatch.com: could not connect to host
 lycly.me: could not connect to host
 m-generator.com: could not connect to host
-m-plan.com: could not connect to host
 m4570.xyz: could not connect to host
 m4g.ru: could not connect to host
 maartenterpstra.xyz: could not connect to host
 madeintucson.org: could not connect to host
-madnetwork.org: could not connect to host
 madusecurity.com: could not connect to host
-magicball.co: could not connect to host
 magnacumlaude.co: could not connect to host
 mahansexcavating.com: could not connect to host
 maik-mahlow.de: could not connect to host
 mail4geek.com: could not connect to host
 mailon.ga: could not connect to host
 makeit-so.de: could not connect to host
 makeuplove.nl: could not connect to host
 malamutedoalasca.com.br: could not connect to host
 malesbdsm.com: could not connect to host
 malgraph.net: could not connect to host
 mamastore.eu: could not connect to host
-mamuko.nl: could not connect to host
-manova.cz: could not connect to host
 marcelmarnitz.com: could not connect to host
 marche-nordic-jorat.ch: could not connect to host
 mardelcupon.com: could not connect to host
 mare92.cz: could not connect to host
 mariusschulte.de: could not connect to host
 mark-armstrong-gaming.com: could not connect to host
 marketgot.com: could not connect to host
+marketing-advertising.eu: could not connect to host
 marketingdesignu.cz: could not connect to host
 markllego.com: could not connect to host
 marko-fenster24.de: could not connect to host
 markrego.com: could not connect to host
-martijn.site: could not connect to host
 martin-mattel.com: could not connect to host
 martins.im: could not connect to host
 marxist.party: could not connect to host
 mastodon.expert: could not connect to host
 mastodon.my: could not connect to host
 matarrosabierzo.com: could not connect to host
 mathijskingma.nl: could not connect to host
 matrix.ac: could not connect to host
 matthewtester.com: could not connect to host
 matthey.nl: could not connect to host
+matviet.vn: could not connect to host
 max-moeglich.de: could not connect to host
 maybeul.com: could not connect to host
 maynardnetworks.com: could not connect to host
 mazternet.ru: could not connect to host
 mb-is.info: could not connect to host
 mbdrogenbos-usedcars.be: could not connect to host
 mbsec.net: could not connect to host
 mbwemmel-usedcars.be: could not connect to host
@@ -1478,17 +1474,16 @@ menzaijia.com: could not connect to host
 mercanix.co.uk: could not connect to host
 mes10doigts.ovh: could not connect to host
 metaether.net: could not connect to host
 metrix-money-ptc.com: could not connect to host
 metrix.design: could not connect to host
 mexior.nl: could not connect to host
 meyeraviation.com: could not connect to host
 mhjuma.com: could not connect to host
-micaiahparker.com: could not connect to host
 michaelcullen.name: could not connect to host
 michaelkuchta.me: could not connect to host
 michaelsulzer.com: could not connect to host
 michaelsulzer.eu: could not connect to host
 michasfahrschule.com: could not connect to host
 microblading.pe: could not connect to host
 microlinks.org: could not connect to host
 mieterschutzkartei.de: could not connect to host
@@ -1496,16 +1491,17 @@ mikeybot.com: could not connect to host
 millionairessecrets.com: could not connect to host
 mingy.ddns.net: could not connect to host
 mingyueli.com: could not connect to host
 minimaliston.com: could not connect to host
 minitruckin.net: could not connect to host
 minor.news: could not connect to host
 misconfigured.io: could not connect to host
 missycosmeticos.com.br: could not connect to host
+miyako-kyoto.jp: could not connect to host
 mkfs.fr: could not connect to host
 mkhsoft.eu: could not connect to host
 mkp-deutschland.de: could not connect to host
 mkplay.io: could not connect to host
 mmilog.hu: could not connect to host
 mmstick.tk: could not connect to host
 mnec.io: could not connect to host
 mneeb.de: could not connect to host
@@ -1520,16 +1516,18 @@ modded-minecraft-server-list.com: could 
 modernibytovytextil.cz: could not connect to host
 moderntld.net: could not connect to host
 moe-max.jp: could not connect to host
 moefi.xyz: could not connect to host
 moeyi.xyz: could not connect to host
 mongla168.net: could not connect to host
 mongla88.net: could not connect to host
 monitori.ng: could not connect to host
+monodukuri.cafe: could not connect to host
+monodzukuri.cafe: could not connect to host
 monotsuku.com: could not connect to host
 monozukuri.cafe: could not connect to host
 moobo.xyz: could not connect to host
 mooselook.de: could not connect to host
 moparcraft.com: could not connect to host
 moparcraft.org: could not connect to host
 mordrum.com: could not connect to host
 morepopcorn.co.nz: could not connect to host
@@ -1550,42 +1548,42 @@ mrafrohead.com: could not connect to hos
 mremallin.ca: could not connect to host
 mrizzio.com: could not connect to host
 mrjooz.com: could not connect to host
 mrliu.me: could not connect to host
 msgallery.tk: could not connect to host
 msz-fotografie.de: could not connect to host
 mtirc.co: could not connect to host
 mtn.cc: could not connect to host
+muchohentai.com: could not connect to host
 muj-svet.cz: could not connect to host
 multivpn.fr: could not connect to host
 munduch.cz: could not connect to host
+munrabi.com: could not connect to host
 murraycolin.org: could not connect to host
 murz.tv: could not connect to host
 muslimbanter.co.za: could not connect to host
-mustafa.space: could not connect to host
 mxawei.cn: could not connect to host
 mxlife.org: could not connect to host
 my-dick.ru: could not connect to host
 my-dns.co.il: could not connect to host
 my-floor.com: could not connect to host
-mybeautyjobs.de: could not connect to host
 mycamda.com: could not connect to host
+mycareersfuture.sg: could not connect to host
 myfappening.org: could not connect to host
 myfunworld.de: could not connect to host
 mygreatjob.eu: could not connect to host
 mykeepsake.xyz: could not connect to host
 myndcommunication.com: could not connect to host
+myownconference.lt: could not connect to host
 mytravelblog.de: could not connect to host
-mziulu.me: could not connect to host
 mzlog.win: could not connect to host
 n0099.cf: could not connect to host
 n3twork.net: could not connect to host
 naano.org: could not connect to host
-nalexandru.xyz: could not connect to host
 namaleaks.com: could not connect to host
 naphex.rocks: could not connect to host
 nasmocopati.com: could not connect to host
 nassi.me: could not connect to host
 nastysclaw.com: could not connect to host
 natur-udvar.hu: could not connect to host
 natuterra.com.br: could not connect to host
 ncdesigns-studio.com: could not connect to host
@@ -1603,44 +1601,43 @@ netica.fr: could not connect to host
 netscaler.expert: could not connect to host
 nevadafiber.net: could not connect to host
 newcityinfo.info: could not connect to host
 newfacialbeautycream.com: could not connect to host
 newpathintegratedtherapy.com: could not connect to host
 newtnote.com: could not connect to host
 newtonhaus.com: could not connect to host
 nexusbyte.de: could not connect to host
+nexusconnectinternational.eu: could not connect to host
 nexuscorporation.in: could not connect to host
 nfluence.org: could not connect to host
 ngiemboon.net: could not connect to host
 nginxyii.tk: could not connect to host
 nicoleoquendo.com: could not connect to host
 nienfun.com: could not connect to host
 nikksno.io: could not connect to host
-niklas.pw: could not connect to host
 nikobradshaw.com: could not connect to host
 nikolasbradshaw.com: could not connect to host
-ninofink.com: could not connect to host
 ninux.ch: could not connect to host
 niouininon.eu: could not connect to host
 nirada.info: could not connect to host
 nishikino-maki.com: could not connect to host
 niva.synology.me: could not connect to host
 nkadvertising.online: could not connect to host
+nocs.cn: could not connect to host
 nodelab-it.de: could not connect to host
 nodeselect.com: could not connect to host
 noelblog.ga: could not connect to host
 noisebridge.social: could not connect to host
 nolimits.net.nz: could not connect to host
 nonemu.ninja: could not connect to host
 norad.sytes.net: could not connect to host
 northwoodsfish.com: could not connect to host
 nosbenevolesontdutalent.com: could not connect to host
 not-a.link: could not connect to host
-notablog.xyz: could not connect to host
 note7forever.com: could not connect to host
 notesforpebble.com: could not connect to host
 notevencode.com: could not connect to host
 novascan.net: could not connect to host
 novfishing.ru: could not connect to host
 nowremindme.com: could not connect to host
 nsbfalconacademy.org: could not connect to host
 nsdev.cn: could not connect to host
@@ -1656,86 +1653,83 @@ ocsr.nl: could not connect to host
 oducs.org: could not connect to host
 off-the-clock.us: could not connect to host
 offgames.pro: could not connect to host
 office-ruru.com: could not connect to host
 oinky.ddns.net: could not connect to host
 okusiassociates.com: could not connect to host
 oldtimer-trifft-flugplatz.de: could not connect to host
 oliverspringer.eu: could not connect to host
-omnibot.tv: could not connect to host
 oneazcu.com: could not connect to host
 onewebdev.info: could not connect to host
 onsennuie.fr: could not connect to host
 onsite4u.de: could not connect to host
 onstud.com: could not connect to host
-onviga.de: could not connect to host
 onwie.fr: could not connect to host
 ooeste.com: could not connect to host
-open-future.be: could not connect to host
 openconnect.com.au: could not connect to host
+openmirrors.cf: could not connect to host
 opinion8td.com: could not connect to host
 opinionipannolini.it: could not connect to host
 orangekey.tk: could not connect to host
-oranges.tokyo: could not connect to host
 oricejoc.com: could not connect to host
 oscarmashauri.com: could not connect to host
 oscsdp.cz: could not connect to host
 oshell.me: could not connect to host
 oshinagaki.jp: could not connect to host
 osmanlitorunu.com: could not connect to host
 ospree.me: could not connect to host
 otinane.eu: could not connect to host
+otmns.net: could not connect to host
 ourchoice2016.com: could not connect to host
 overkillshop.com: could not connect to host
 owlscrap.ru: could not connect to host
 oxynux.xyz: could not connect to host
 pabloartea.ga: could not connect to host
 packetcrash.net: could not connect to host
 pactf-flag-4boxdpa21ogonzkcrs9p.com: could not connect to host
 paichai.space: could not connect to host
 painosso.org: could not connect to host
 paio2-rec.com: could not connect to host
 paio2.com: could not connect to host
 palationtrade.com: could not connect to host
 panascais.io: could not connect to host
 pandapsy.com: could not connect to host
 pangci.xyz: could not connect to host
 pardnoy.com: could not connect to host
-passphrase.today: could not connect to host
 pastie.se: could not connect to host
-pataterosviajeros.com: could not connect to host
 patrickbusch.net: could not connect to host
 patrickneuro.de: could not connect to host
 paulshir.com: could not connect to host
 paulshir.is: could not connect to host
 pay.ubuntu.com: could not connect to host
 paymon.tj: could not connect to host
 paypod.org: could not connect to host
 paytm.in: could not connect to host
 pbcknd.ml: could not connect to host
 pbscreens.com: could not connect to host
 pbytes.com: could not connect to host
 pcvirusclear.com: could not connect to host
 pear2pear.de: could not connect to host
 peerless.ae: could not connect to host
 peirong.me: could not connect to host
-pemagrid.org: could not connect to host
 pengisatelier.net: could not connect to host
 pepper.dog: could not connect to host
+perrone.co: could not connect to host
 persjrp.ca: could not connect to host
 persoform.ch: could not connect to host
 petlife.od.ua: could not connect to host
 peuf.shop: could not connect to host
 peykezamin.ir: could not connect to host
 pfudor.tk: could not connect to host
 pgmsource.com: could not connect to host
 pharmaboard.org: could not connect to host
 phdwuda.com: could not connect to host
 philippa.cool: could not connect to host
+phillippi.me: could not connect to host
 photographyforchange.com: could not connect to host
 photographyforchange.org: could not connect to host
 photops.fr: could not connect to host
 phuong.faith: could not connect to host
 pianetaottica.eu: could not connect to host
 pianetaottica.info: could not connect to host
 picallo.es: could not connect to host
 picone.com.au: could not connect to host
@@ -1751,16 +1745,17 @@ pinoyonlinetv.com: [Exception... "Compon
 pipenny.net: could not connect to host
 pitfire.io: could not connect to host
 pitot-rs.org: could not connect to host
 pixelgliders.de: could not connect to host
 plaasprodukte.com: could not connect to host
 planbox.info: could not connect to host
 planningexcellence.com.au: could not connect to host
 playsharp.com: could not connect to host
+playsource.co: could not connect to host
 please-deny.me: could not connect to host
 plussizereviews.com: could not connect to host
 pmbremer.de: could not connect to host
 pogs.us: could not connect to host
 polit.im: could not connect to host
 pookl.com: could not connect to host
 poolinstallers.co.za: could not connect to host
 popkins.cf: could not connect to host
@@ -1815,18 +1810,17 @@ pruikshop.nl: could not connect to host
 prytkov.com: could not connect to host
 psncardplus.be: could not connect to host
 psncardplus.com: could not connect to host
 psncardplus.dk: could not connect to host
 psncardplus.nl: could not connect to host
 psncardplus.se: could not connect to host
 psychoco.net: could not connect to host
 psyk.yt: could not connect to host
-psylab.cc: could not connect to host
-psylab.re: could not connect to host
+psylab.vip: could not connect to host
 publimepa.it: could not connect to host
 pugilares.com.pl: could not connect to host
 puhe.se: could not connect to host
 pwdgen.net: could not connect to host
 pwntr.com: could not connect to host
 pyjiaoyi.cf: could not connect to host
 pythia.nz: could not connect to host
 qforum.org: could not connect to host
@@ -1835,17 +1829,17 @@ qirinus.com: could not connect to host
 qnatek.org: could not connect to host
 qoqo.us: could not connect to host
 qqvips.com: could not connect to host
 qrlfinancial.com: could not connect to host
 qto.net: could not connect to host
 quietus.gq: could not connect to host
 quikpay.com.au: could not connect to host
 r-cut.fr: could not connect to host
-r2d2pc.com: could not connect to host
+r40.us: could not connect to host
 racasdecachorro.org: could not connect to host
 rackblue.com: could not connect to host
 radartatska.se: could not connect to host
 rainbin.com: could not connect to host
 rangsmo.se: could not connect to host
 ranos.org: could not connect to host
 ravengergaming.net: could not connect to host
 ravse.dk: could not connect to host
@@ -1875,77 +1869,80 @@ reignsphere.net: could not connect to ho
 reinierjonker.nl: could not connect to host
 reismil.ch: could not connect to host
 relsak.cz: could not connect to host
 renemayrhofer.com: could not connect to host
 rentbrowser.com: could not connect to host
 report-incident.de: could not connect to host
 reposaarenkuva.fi: could not connect to host
 reqognize.com: could not connect to host
-request-trent.com: could not connect to host
 research.md: could not connect to host
 resoundpro.ca: could not connect to host
 reth.ch: could not connect to host
 retube.ga: could not connect to host
+reucon.com: could not connect to host
 reykjavik.guide: could not connect to host
 ribopierre.fr: could not connect to host
 riceglue.com: could not connect to host
 richardb.me: could not connect to host
 richeza.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 116"  data: no]
 righteousendeavour.com: could not connect to host
 riversideauto.net: could not connect to host
 riverstyxgame.com: could not connect to host
 roave.com: could not connect to host
 robi-net.it: could not connect to host
-robicue.com: could not connect to host
 robomonkey.org: could not connect to host
 robust.ga: could not connect to host
 rodehutskors.net: could not connect to host
 rodzina-kupiec.eu.org: could not connect to host
 rofrank.space: could not connect to host
+roguesignal.net: could not connect to host
 rolandszabo.com: could not connect to host
+roleplayhome.com: could not connect to host
 romanticvillas.com.au: could not connect to host
 rondreis-planner.nl: could not connect to host
 ronghexx.com: could not connect to host
+rool.me: could not connect to host
 roolevoi.ru: could not connect to host
 rootbsd.at: could not connect to host
 rospa100.com: could not connect to host
 roten.email: could not connect to host
 rotterdamjazz.info: could not connect to host
 royzez.com: could not connect to host
 rozalynne-dawn.ga: could not connect to host
 rpasafrica.com: could not connect to host
 rs-devdemo.host: could not connect to host
 rsldb.com: could not connect to host
 rtc.fun: could not connect to host
 rubbix.net: could not connect to host
-rubendv.be: could not connect to host
 ruhr3.de: could not connect to host
 ruja.dk: could not connect to host
 runcarina.com: could not connect to host
 rundumcolumn.xyz: could not connect to host
-ruobr.ru: could not connect to host
 ruurdboomsma.nl: could not connect to host
 rzegroup.com: could not connect to host
 s0923.com: could not connect to host
 s16e.no: could not connect to host
 s3n.se: could not connect to host
 safedevice.net: could not connect to host
 safejourney.education: could not connect to host
 saferedirectlink.com: could not connect to host
+safeui.com: could not connect to host
 sagemontchurch.org: could not connect to host
 sallysubs.com: could not connect to host
 salzamt.tk: could not connect to host
 samaritan.tech: could not connect to host
 samsonova.de: could not connect to host
 sanael.net: could not connect to host
 sanatrans.com: could not connect to host
+sancy.de: could not connect to host
 sanmuding.com: could not connect to host
 santanderideas.com: could not connect to host
 santmark.eu: could not connect to host
+sapience.com: could not connect to host
 sapuncheta.com: could not connect to host
 sarahlicity.me.uk: could not connect to host
 sarindia.com: could not connect to host
 sarindia.de: could not connect to host
 sarndipity.com: could not connect to host
 sauenytt.no: could not connect to host
 savethedogfishfoundation.org: could not connect to host
 savingbytes.com: could not connect to host
@@ -1964,16 +1961,17 @@ scottainslie.me.uk: could not connect to
 scripthost.org: could not connect to host
 scriptjunkie.us: could not connect to host
 sctm.at: could not connect to host
 seanationals.org: could not connect to host
 seankilgarriff.com: could not connect to host
 sebastian-lutsch.de: could not connect to host
 sebi.cf: could not connect to host
 secitem.de: could not connect to host
+secpatrol.de: could not connect to host
 sectest.ml: could not connect to host
 secure-automotive-cloud.com: could not connect to host
 secure-automotive-cloud.org: could not connect to host
 secureindia.co: could not connect to host
 security.xn--q9jyb4c: could not connect to host
 securitymap.wiki: could not connect to host
 securitysoapbox.com: could not connect to host
 securitytalk.pl: could not connect to host
@@ -2007,16 +2005,17 @@ sharvey.ca: could not connect to host
 shavingks.com: could not connect to host
 shentengtu.idv.tw: could not connect to host
 sheying.tm: could not connect to host
 shh.sh: could not connect to host
 shinko-osaka.jp: could not connect to host
 shirakaba-cc.com: could not connect to host
 shred.ch: could not connect to host
 shredoptics.ch: could not connect to host
+shtorku.com: could not connect to host
 shurita.org: could not connect to host
 shuzicai.cn: could not connect to host
 shymeck.pw: could not connect to host
 siamega.com: could not connect to host
 siebens.net: could not connect to host
 sift-tool.org: could not connect to host
 signosquecombinam.com.br: could not connect to host
 sigsegv.run: could not connect to host
@@ -2032,16 +2031,17 @@ simhaf.cf: could not connect to host
 simonschmitt.ch: could not connect to host
 simplerses.com: could not connect to host
 sims4hub.ga: could not connect to host
 sinfulforums.net: could not connect to host
 sinsojb.me: could not connect to host
 siqi.wang: could not connect to host
 sitecloudify.com: could not connect to host
 sitemaxiphilippe.ch: could not connect to host
+sjdaws.com: could not connect to host
 skarox.ru: could not connect to host
 skontakt.cz: could not connect to host
 skontorp-enterprise.no: could not connect to host
 sky-aroma.com: could not connect to host
 skylocker.net: could not connect to host
 skylocker.nl: could not connect to host
 skyvault.io: could not connect to host
 sl1pkn07.wtf: could not connect to host
@@ -2056,92 +2056,90 @@ smuhelper.cn: could not connect to host
 sneed.company: could not connect to host
 snowdy.eu: could not connect to host
 soboleva-pr.com.ua: could not connect to host
 socialworkout.com: could not connect to host
 socialworkout.net: could not connect to host
 socialworkout.org: could not connect to host
 socialworkout.tv: could not connect to host
 socketize.com: could not connect to host
-sodiao.cc: could not connect to host
 sogravatas.net.br: could not connect to host
 sojingle.net: could not connect to host
 solymar.co: could not connect to host
 sonafe.info: could not connect to host
 sonja-kowa.de: could not connect to host
 sorenam.com: could not connect to host
 sortaweird.net: could not connect to host
 sourcecode.love: could not connect to host
 sowingseasons.com: could not connect to host
 sowncloud.de: could not connect to host
 sp.rw: could not connect to host
 spam.lol: could not connect to host
 spanien.guide: could not connect to host
 sparkbase.cn: could not connect to host
+spartantheatre.org: could not connect to host
 spawn.cz: could not connect to host
 sphinx.network: could not connect to host
 spicydog.tk: could not connect to host
 spicywombat.com: could not connect to host
 split.is: could not connect to host
-sportflash.info: could not connect to host
 springsoffthegrid.com: could not connect to host
 squids.space: could not connect to host
 squirtlesbians.net: could not connect to host
 sqzryang.com: could not connect to host
 sritest.io: could not connect to host
 srvonfire.com: could not connect to host
 ssnet.vip: could not connect to host
 sss3s.com: could not connect to host
 stadionmanager.com: could not connect to host
 stadtgartenla.com: could not connect to host
 starcafe.me: could not connect to host
 starplatinum.jp: could not connect to host
-starquake.nl: could not connect to host
 startup.melbourne: could not connect to host
 startupum.ru: could not connect to host
 state-of-body-and-mind.com: could not connect to host
 statgram.me: could not connect to host
 static-assets.io: could not connect to host
 static.hosting: could not connect to host
 staticisnoise.com: could not connect to host
 statusbot.io: could not connect to host
 steffi-in-australien.com: could not connect to host
 stevengoodpaster.com: could not connect to host
 stickswag.cf: could not connect to host
+stikonas.eu: could not connect to host
 stilettomoda.com.br: could not connect to host
 stoianlawfirm.com: could not connect to host
 stonefusion.org.uk: could not connect to host
 stonemanbrasil.com.br: could not connect to host
 stopakwardhandshakes.org: could not connect to host
 store10.de: could not connect to host
 stpip.com: could not connect to host
 streamer.tips: could not connect to host
 streams.dyndns.org: could not connect to host
 stressfreehousehold.com: could not connect to host
 stylle.me: could not connect to host
 subrain.com: could not connect to host
 sudo.im: could not connect to host
 sudosu.fr: could not connect to host
-suempresa.cloud: could not connect to host
 suitocracy.com: could not connect to host
-sukrie.net: could not connect to host
 summer.ga: could not connect to host
 sunbritetv.com: could not connect to host
 suneilpatel.com: could not connect to host
 sunfireshop.com.br: could not connect to host
 sunjaydhama.com: could not connect to host
 sunxchina.com: could not connect to host
 supermil.ch: could not connect to host
 superpase.com: could not connect to host
 surasak.io: could not connect to host
 surasak.org: could not connect to host
 surdam.casa: could not connect to host
 susastudentenjobs.de: could not connect to host
 suspiciousdarknet.xyz: could not connect to host
 suts.co.uk: could not connect to host
+svj-stochovska.cz: could not connect to host
 svjvn.cz: could not connect to host
 swacp.com: could not connect to host
 swaggerdile.com: could not connect to host
 swarlys-server.de: could not connect to host
 sweetlegs.jp: could not connect to host
 sweetll.me: could not connect to host
 sweetvanilla.jp: could not connect to host
 swfloshatraining.com: could not connect to host
@@ -2162,35 +2160,34 @@ t3rror.net: could not connect to host
 tab.watch: could not connect to host
 tacoma-games.com: could not connect to host
 taidu.news: could not connect to host
 takedownthissite.com: could not connect to host
 takusan.ru: could not connect to host
 talado.gr: could not connect to host
 tanak3n.xyz: could not connect to host
 tangerine.ga: could not connect to host
-tangyue.date: could not connect to host
 tangzhao.net: could not connect to host
 tapestries.tk: could not connect to host
+taranis.re: could not connect to host
 tardybaker.com: could not connect to host
 tarek.link: could not connect to host
 tazemama.biz: could not connect to host
 tcpweb.net: could not connect to host
 tdelmas.eu: could not connect to host
 tdelmas.ovh: could not connect to host
 tdsb.cf: could not connect to host
 tdsbhack.tk: could not connect to host
 teacherph.net: could not connect to host
 team-pancake.eu: could not connect to host
 tearoy.faith: could not connect to host
 tebieer.com: could not connect to host
 techask.it: could not connect to host
 techiehall.com: could not connect to host
 techpit.us: could not connect to host
-tekiro.com: could not connect to host
 tektoria.de: could not connect to host
 telekollektiv.org: could not connect to host
 tenispopular.com: could not connect to host
 terminalvelocity.co.nz: could not connect to host
 terra-x.net: could not connect to host
 terrax.net: could not connect to host
 testadron.com: could not connect to host
 testovaci.ml: could not connect to host
@@ -2219,70 +2216,69 @@ theprivacysolution.com: could not connec
 thequillmagazine.org: could not connect to host
 thermique.ch: could not connect to host
 thesehighsandlows.com: could not connect to host
 theserver201.tk: could not connect to host
 thetapirsmouth.com: could not connect to host
 thevoid.one: could not connect to host
 thinkcash.nl: could not connect to host
 thismumdoesntknowbest.com: could not connect to host
-thomas-suchon.fr: could not connect to host
 threatcentral.io: could not connect to host
-thynx.io: could not connect to host
 tianxicaipiao.com: could not connect to host
 tianxicaipiao.win: could not connect to host
 tianxicp.com: could not connect to host
 tibbitshall.ca: could not connect to host
 tibovanheule.site: could not connect to host
 tiernanx.com: could not connect to host
 tigit.co.nz: could not connect to host
 timer.fit: could not connect to host
 timtelfer.com: could not connect to host
 tink.network: could not connect to host
+tippspiel.cc: could not connect to host
 tjs.me: could not connect to host
-tmconnects.com: could not connect to host
 tmin.cf: could not connect to host
 tnb-plattform.de: could not connect to host
 toad.ga: could not connect to host
 todosrv.com: could not connect to host
 tofa-koeln.de: could not connect to host
 tokoindo.top: could not connect to host
-tokumei.co: could not connect to host
 tollsjekk.no: could not connect to host
+tomcort.com: could not connect to host
 tomharling.co.uk: could not connect to host
 tomm.yt: could not connect to host
-tomo.gr: could not connect to host
 top10mountainbikes.info: could not connect to host
 topanlage.de: could not connect to host
 topaxi.ch: could not connect to host
 topaxi.codes: could not connect to host
 topdetoxcleanse.com: could not connect to host
 topnotchendings.com: could not connect to host
 tor2web.org: could not connect to host
 tosteberg.se: could not connect to host
 totallynotaserver.com: could not connect to host
 totch.de: could not connect to host
+totolabs.com: could not connect to host
 totot.net: could not connect to host
 touch-up-net.com: could not connect to host
 towaway.ru: could not connect to host
 toxicboot.com: could not connect to host
 toxicip.com: could not connect to host
 tpblist.xyz: could not connect to host
 tpolemis.com: could not connect to host
 track.plus: could not connect to host
 tradingrooms.com: could not connect to host
 traforet.win: could not connect to host
 trainhornforums.com: could not connect to host
 trainline.io: could not connect to host
+tranglenull.xyz: could not connect to host
 transappealrights.com: could not connect to host
 transcendmotor.sg: could not connect to host
 transmithe.net: could not connect to host
+travelling.expert: could not connect to host
 travotion.com: could not connect to host
 treker.us: could not connect to host
-trentmaydew.com: could not connect to host
 triageo.com.au: could not connect to host
 tristanfarkas.one: could not connect to host
 tryfm.net: could not connect to host
 trynowrinkleseyeserum.com: could not connect to host
 tryti.me: could not connect to host
 tsaro.io: could not connect to host
 tsdom.net: could not connect to host
 tsumi.moe: could not connect to host
@@ -2299,26 +2295,27 @@ tuxhound.org: could not connect to host
 twem.ddns.net: could not connect to host
 twinkieman.com: could not connect to host
 twiri.net: could not connect to host
 twittelzie.nl: could not connect to host
 twitter.ax: could not connect to host
 twotube.ie: could not connect to host
 twuni.org: could not connect to host
 tykoon.com: could not connect to host
+tyler.rs: could not connect to host
 tylerharcourt.ca: could not connect to host
 tylerharcourt.com: could not connect to host
 tylerharcourt.net: could not connect to host
 tylerharcourt.org: could not connect to host
+tyleromeara.com: could not connect to host
 tysye.ca: could not connect to host
 tzwe.com: could not connect to host
 ubi.gg: could not connect to host
 ubicv.com: could not connect to host
 uborcare.com: could not connect to host
-ubtce.com: could not connect to host
 udo-luetkemeier.de: could not connect to host
 ueba1085.jp: could not connect to host
 ueu.me: could not connect to host
 ulalau.com: could not connect to host
 unefuite.ch: could not connect to host
 unhu.fr: could not connect to host
 uni2share.com: could not connect to host
 unicorn.li: could not connect to host
@@ -2331,16 +2328,17 @@ urcentral.org: could not connect to host
 uscp8.com: could not connect to host
 usportsgo.com: could not connect to host
 uwesander.de: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 116"  data: no]
 uwimonacs.org.jm: could not connect to host
 uygindir.ml: could not connect to host
 vaaddress.co: could not connect to host
 vacationfund.co: could not connect to host
 vadik.me: could not connect to host
+vagpartsdb.com: could not connect to host
 valecnatechnika.cz: could not connect to host
 valenhub.com: could not connect to host
 valenhub.es: could not connect to host
 valis.sx: could not connect to host
 vamosfalardesaude.pt: could not connect to host
 vanderstraeten.dynv6.net: could not connect to host
 vapemania.eu: could not connect to host
 varela-electricite.fr: could not connect to host
@@ -2350,17 +2348,16 @@ vconcept.me: could not connect to host
 vectro.me: could not connect to host
 velasense.com: could not connect to host
 velen.io: could not connect to host
 venicecomputerrepair.com: could not connect to host
 venicefloridawebsitedesign.com: could not connect to host
 venturavwparts.com: could not connect to host
 verdeandco.co.uk: could not connect to host
 versfin.net: could not connect to host
-veryyounglesbians.com: could not connect to host
 vgatest.nl: could not connect to host
 vicenage.com: could not connect to host
 viciousviscosity.xyz: could not connect to host
 videorullen.se: could not connect to host
 vikasbabyworld.de: could not connect to host
 vilaydin.com: could not connect to host
 villainsclothing.com.au: could not connect to host
 villasenor.online: could not connect to host
@@ -2385,16 +2382,17 @@ vogt.tech: could not connect to host
 voipkb.com: could not connect to host
 volcain.io: could not connect to host
 vorderklier.de: could not connect to host
 votresiteweb.ch: could not connect to host
 vow.vn: could not connect to host
 vrzl.pro: could not connect to host
 vsesrazu-raiffeisen.ru: could not connect to host
 vucdn.com: could not connect to host
+vumetric.com: could not connect to host
 vwoforangeparts.com: could not connect to host
 vxapps.com: could not connect to host
 w10club.com: could not connect to host
 wabifoggynuts.com: could not connect to host
 waixingrenfuli.vip: could not connect to host
 wanashi.com: could not connect to host
 wanda76.com: could not connect to host
 wanda78.com: could not connect to host
@@ -2408,36 +2406,36 @@ warp-radio.com: could not connect to hos
 wassim.is: could not connect to host
 watashi.bid: could not connect to host
 watchstyle.com: could not connect to host
 watchtv-online.pw: could not connect to host
 watchweasel.com: could not connect to host
 waxdramatic.com: could not connect to host
 we.serveftp.net: could not connect to host
 weareincognito.org: could not connect to host
-webaeon.org: could not connect to host
 webart-factory.de: could not connect to host
 webbson.net: could not connect to host
 webhackspro.com: could not connect to host
+webnetmail4u.com: could not connect to host
 webproject.rocks: could not connect to host
 webspotter.nl: could not connect to host
 webtar.info: could not connect to host
 webtech.com.br: could not connect to host
 webthings.com.br: could not connect to host
 webtobesocial.de: could not connect to host
 wecanvisit.com: could not connect to host
 weebsr.us: could not connect to host
+weideheuvel.org: could not connect to host
 weiji.ga: could not connect to host
 weiler.xyz: could not connect to host
 weizenke.im: could not connect to host
 wejumall.com: could not connect to host
 wekibe.de: could not connect to host
 welby.cat: could not connect to host
 wendigo.pl: could not connect to host
-werbik.at: could not connect to host
 wereldplanner.nl: could not connect to host
 werhatunsverraten.eu: could not connect to host
 werken-bij-inwork.nl: could not connect to host
 wespeakgeek.co.za: could not connect to host
 westcanal.net: could not connect to host
 wetthost.com: could not connect to host
 weyland.tech: could not connect to host
 wg-tools.de: could not connect to host
@@ -2459,18 +2457,18 @@ winsufi.biz: could not connect to host
 wisak.eu: could not connect to host
 wishesbee.com: could not connect to host
 wissl.org: could not connect to host
 wizznab.tk: could not connect to host
 wk577.com: could not connect to host
 wlsme.org: could not connect to host
 wmawri.com: could not connect to host
 wolfemg.com: could not connect to host
+wonabo.com: could not connect to host
 wonderbooks.club: could not connect to host
-woodlandsmetro.church: could not connect to host
 woomu.me: could not connect to host
 wordsofamaster.com: could not connect to host
 workemy.com: could not connect to host
 workwithgo.com: could not connect to host
 worldfree4.org: could not connect to host
 wormholevpn.net: could not connect to host
 wowhelp.it: could not connect to host
 wp-fastsearch.de: could not connect to host
@@ -2510,16 +2508,17 @@ xtom.io: could not connect to host
 xtzone.be: could not connect to host
 xuntaosms.com: could not connect to host
 xwaretech.info: could not connect to host
 xyfun.net: could not connect to host
 y3451.com: could not connect to host
 yabrt.cn: could not connect to host
 yahoo.ax: could not connect to host
 yarchives.jp: could not connect to host
+yarogneva.ru: could not connect to host
 yaucy.win: could not connect to host
 yd.io: could not connect to host
 yellowcar.website: could not connect to host
 yemalu.com: could not connect to host
 yemekbaz.az: could not connect to host
 yepbitcoin.com: could not connect to host
 yesfone.com.br: could not connect to host
 yggdar.ga: could not connect to host
@@ -2537,20 +2536,19 @@ yolo-csgo.com: could not connect to host
 yoticonnections.com: could not connect to host
 yotilabs.com: could not connect to host
 yourznc.com: could not connect to host
 yousite.by: could not connect to host
 yude.ml: could not connect to host
 yum.beer: could not connect to host
 yux.fr: could not connect to host
 z-coder.com: could not connect to host
-z-latko.info: could not connect to host
 z0rro.net: could not connect to host
 zachbolinger.com: could not connect to host
-zajazd.biz: could not connect to host
+zachpeters.org: could not connect to host
 zaoext.com: could not connect to host
 zbchen.com: could not connect to host
 zbp.at: could not connect to host
 zeitzer-turngala.de: could not connect to host
 zeloz.xyz: could not connect to host
 zenghx.tk: could not connect to host
 zero-x-baadf00d.com: could not connect to host
 zerocool.io: could not connect to host
@@ -2578,17 +2576,17 @@ zypr.pw: could not connect to host
 zyx.im: could not connect to host
 zzw.ca: could not connect to host
 00001.am: did not receive HSTS header
 00002.am: did not receive HSTS header
 0005.com: could not connect to host
 0005aa.com: could not connect to host
 007sascha.de: did not receive HSTS header
 020wifi.nl: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 116"  data: no]
-0222aa.com: did not receive HSTS header
+0222aa.com: could not connect to host
 02dl.net: did not receive HSTS header
 040fit.nl: did not receive HSTS header
 048.ag: could not connect to host
 050508.com: could not connect to host
 066928.com: could not connect to host
 066938.com: could not connect to host
 0f.io: could not connect to host
 0fl.com: did not receive HSTS header
@@ -2612,44 +2610,43 @@ 1091.jp: could not connect to host
 10ppm.com: did not receive HSTS header
 10seos.com: did not receive HSTS header
 10tacle.io: could not connect to host
 12.net: did not receive HSTS header
 120dayweightloss.com: could not connect to host
 123.gg: could not connect to host
 123movies.fyi: did not receive HSTS header
 123share.org: did not receive HSTS header
-123test.de: did not receive HSTS header
-123test.es: did not receive HSTS header
-123test.fr: did not receive HSTS header
 126ium.moe: could not connect to host
 127011-networks.ch: did not receive HSTS header
 12vpn.org: could not connect to host
 12vpnchina.com: could not connect to host
 1391kj.com: did not receive HSTS header
+1395kj.com: did not receive HSTS header
 1396.cc: did not receive HSTS header
 1536.cf: could not connect to host
 163pwd.com: could not connect to host
 16deza.com: did not receive HSTS header
 16packets.com: could not connect to host
 173vpn.cn: could not connect to host
 173vpns.com: did not receive HSTS header
 173vpnv.com: could not connect to host
 188betwarriors.co.uk: could not connect to host
 188trafalgar.ca: did not receive HSTS header
 195gm.com: could not connect to host
 1a-jva.de: could not connect to host
+1a-werkstattgeraete.de: did not receive HSTS header
 1atic.com: could not connect to host
 1co-jp.net: did not receive HSTS header
 1cover.com: could not connect to host
 1k8b.com: could not connect to host
 1s.tn: did not receive HSTS header
 1stcapital.com.sg: did not receive HSTS header
 1three1.net: did not receive HSTS header
-1xcess.com: could not connect to host
+1xcess.com: did not receive HSTS header
 1years.cc: could not connect to host
 2-cpu.de: did not receive HSTS header
 206rc.net: max-age too low: 2592000
 20hs.cn: did not receive HSTS header
 21lg.co: could not connect to host
 247quickbooks.com: did not receive HSTS header
 2488.ch: did not receive HSTS header
 24hourpaint.com: could not connect to host
@@ -2760,23 +2757,23 @@ 9tolife.be: [Exception... "Component ret
 a-plus.space: could not connect to host
 a-rickroll-n.pw: could not connect to host
 a-theme.com: could not connect to host
 a1-autopartsglasgow.com: did not receive HSTS header
 a200k.xyz: did not receive HSTS header
 a3workshop.swiss: could not connect to host
 a9c.co: could not connect to host
 aa7733.com: could not connect to host
+aaapl.com: did not receive HSTS header
 aaeblog.com: did not receive HSTS header
 aaeblog.net: did not receive HSTS header
 aaeblog.org: did not receive HSTS header
 aaoo.net: could not connect to host
 aapp.space: could not connect to host
 aaron-gustafson.com: did not receive HSTS header
-aaronkimmig.de: did not receive HSTS header
 aaronmcguire.me: did not receive HSTS header
 abareplace.com: did not receive HSTS header
 abcdentalcare.com: did not receive HSTS header
 abcdobebe.com: max-age too low: 0
 abchelp.net: did not receive HSTS header
 abearofsoap.com: could not connect to host
 abilitylist.org: did not receive HSTS header
 abioniere.de: could not connect to host
@@ -2801,17 +2798,16 @@ acai51.net: could not connect to host
 acbc.ie: max-age too low: 0
 accelerole.com: did not receive HSTS header
 accelight.co.jp: did not receive HSTS header
 accelight.jp: did not receive HSTS header
 access-sofia.org: did not receive HSTS header
 accommodation-berry.com.au: max-age too low: 300
 accountradar.com: max-age too low: 86400
 accounts-p.com: could not connect to host
-accuritpresence.com: did not receive HSTS header
 acgmoon.org: did not receive HSTS header
 acheirj.com.br: could not connect to host
 acheritage.co.uk: did not receive HSTS header
 acisonline.net: did not receive HSTS header
 acoffeeshops.com: could not connect to host
 acr.im: could not connect to host
 acrepairdrippingsprings.com: could not connect to host
 acritelli.com: did not receive HSTS header
@@ -2920,17 +2916,17 @@ akclinics.org: did not receive HSTS head
 akerek.hu: could not connect to host
 akgundemirbas.com: could not connect to host
 akkadia.cc: could not connect to host
 akombakom.net: could not connect to host
 akselimedia.fi: did not receive HSTS header
 akstudentsfirst.org: could not connect to host
 aktivist.in: did not receive HSTS header
 al-shami.net: could not connect to host
-alair.cn: did not receive HSTS header
+alair.cn: could not connect to host
 alanlee.net: could not connect to host
 alanrickmanflipstable.com: could not connect to host
 alariel.de: did not receive HSTS header
 alarme-gps.ch: could not connect to host
 alarmegps.ch: could not connect to host
 alarmsystemreviews.com: did not receive HSTS header
 albanien.guide: could not connect to host
 alberguecimballa.es: could not connect to host
@@ -2939,16 +2935,17 @@ albertopimienta.com: did not receive HST
 alcantarafleuriste.com: did not receive HSTS header
 alcazaar.com: could not connect to host
 alchemia.co.il: did not receive HSTS header
 alecvannoten.be: did not receive HSTS header
 alenan.org: could not connect to host
 alessandroz.pro: could not connect to host
 alethearose.com: did not receive HSTS header
 alexandre.sh: did not receive HSTS header
+alexbaker.org: did not receive HSTS header
 alexdodge.ca: did not receive HSTS header
 alexkidd.de: did not receive HSTS header
 alfa24.pro: could not connect to host
 alfredxing.com: did not receive HSTS header
 alistairpialek.com: max-age too low: 86400
 alittlebitcheeky.com: did not receive HSTS header
 aljmz.com: could not connect to host
 alkami.com: max-age too low: 0
@@ -2957,16 +2954,17 @@ all-subtitles.com: could not connect to 
 all.tf: could not connect to host
 all4os.com: did not receive HSTS header
 alldaymonitoring.com: could not connect to host
 allegro-inc.com: did not receive HSTS header
 allfreelancers.su: did not receive HSTS header
 allgrass.es: did not receive HSTS header
 alliance-compacts.com: did not receive HSTS header
 allinnote.com: could not connect to host
+allkindzabeats.com: did not receive HSTS header
 allmbw.com: could not connect to host
 allmystery.de: did not receive HSTS header
 allo-symo.fr: did not receive HSTS header
 allods-zone.ru: could not connect to host
 alloffice.com.ua: did not receive HSTS header
 alloinformatique.net: could not connect to host
 allpropertyservices.com: did not receive HSTS header
 allrealty.co.za: could not connect to host
@@ -3042,17 +3040,16 @@ andrewregan.me: could not connect to hos
 andrewsun.com: did not receive HSTS header
 andrewvoce.com: did not receive HSTS header
 andrewx.net: could not connect to host
 andrewyg.net: could not connect to host
 andreypopp.com: could not connect to host
 androidprosmart.com: could not connect to host
 androled.fr: max-age too low: 5184000
 androoz.se: could not connect to host
-androticsdirect.com: did not receive HSTS header
 andyclark.io: could not connect to host
 andymartin.cc: could not connect to host
 andyuk.org: could not connect to host
 anfsanchezo.co: could not connect to host
 anfsanchezo.me: could not connect to host
 angeloroberto.ch: did not receive HSTS header
 anghami.com: did not receive HSTS header
 anglesya.win: did not receive HSTS header
@@ -3100,26 +3097,28 @@ antoinemary.io: could not connect to hos
 antoineschaller.ch: did not receive HSTS header
 antoniomarques.eu: did not receive HSTS header
 antoniorequena.com.ve: could not connect to host
 antscript.com: did not receive HSTS header
 anycoin.me: could not connect to host
 anytonetech.com: did not receive HSTS header
 aocast.info: could not connect to host
 aojf.fr: could not connect to host
+aomberg.com: did not receive HSTS header
 aov.io: could not connect to host
 aozora.moe: could not connect to host
 apachelounge.com: did not receive HSTS header
 apadrinaunolivo.org: did not receive HSTS header
 apaginastore.com.br: could not connect to host
 apeasternpower.com: could not connect to host
 aperture-laboratories.science: did not receive HSTS header
 api.mega.co.nz: could not connect to host
 apibot.de: could not connect to host
 apis.world: could not connect to host
+apkriver.com: did not receive HSTS header
 apmg-certified.com: did not receive HSTS header
 apmg-cyber.com: did not receive HSTS header
 apnakliyat.com: did not receive HSTS header
 apolloyl.com: could not connect to host
 aponkral.site: could not connect to host
 aponkralsunucu.com: could not connect to host
 aponow.de: did not receive HSTS header
 app-arena.com: did not receive HSTS header
@@ -3175,16 +3174,17 @@ arpa.ph: did not receive HSTS header
 arpr.co: did not receive HSTS header
 arrayify.com: could not connect to host
 arrow-cloud.nl: could not connect to host
 arrowfunction.com: could not connect to host
 ars-design.net: could not connect to host
 art2web.net: could not connect to host
 artartefatos.com.br: could not connect to host
 artegusto.ru: did not receive HSTS header
+arterienundvenen.ch: did not receive HSTS header
 artesupra.com: did not receive HSTS header
 arthan.me: could not connect to host
 artifex21.com: could not connect to host
 artifex21.fr: could not connect to host
 artiming.com: could not connect to host
 artisavotins.com: could not connect to host
 artisphere.ch: did not receive HSTS header
 artistnetwork.nl: did not receive HSTS header
@@ -3213,23 +3213,23 @@ assekuranzjobs.de: could not connect to 
 asset-alive.com: did not receive HSTS header
 asset-alive.net: did not receive HSTS header
 assurancesmons.be: did not receive HSTS header
 astraalivankila.net: did not receive HSTS header
 astral.gq: did not receive HSTS header
 astrolpost.com: could not connect to host
 astromelody.com: did not receive HSTS header
 asuhe.cc: could not connect to host
-asun.co: did not receive HSTS header
 atacadodesandalias.com.br: did not receive HSTS header
 atavio.at: could not connect to host
 atavio.ch: could not connect to host
 atavio.de: did not receive HSTS header
 atbeckett.com: did not receive HSTS header
 atelier-rk.com: did not receive HSTS header
+ateliernihongo.ch: did not receive HSTS header
 ateliersantgervasi.com: did not receive HSTS header
 atencionbimbo.com: max-age too low: 86400
 athaliasoft.com: could not connect to host
 athenelive.com: could not connect to host
 athensbusinessresources.us: did not receive HSTS header
 athul.xyz: could not connect to host
 atlassian.net: did not receive HSTS header
 atlex.nl: did not receive HSTS header
@@ -3360,16 +3360,17 @@ balnearionaturaspa.com: did not receive 
 bambooforest.nl: could not connect to host
 bambumania.com.br: could not connect to host
 bananabandy.com: could not connect to host
 banbanchs.com: could not connect to host
 banchethai.com: could not connect to host
 bandb.xyz: could not connect to host
 bandrcrafts.com: did not receive HSTS header
 banduhn.com: did not receive HSTS header
+bangkokcity.de: did not receive HSTS header
 bangzafran.com: did not receive HSTS header
 bankmilhas.com.br: did not receive HSTS header
 banksaround.com: did not receive HSTS header
 banqingdiao.com: could not connect to host
 baobaobooks.net: did not receive HSTS header
 baobeiglass.com: did not receive HSTS header
 baptiste-destombes.fr: did not receive HSTS header
 barcel.com.mx: max-age too low: 86400
@@ -3604,17 +3605,16 @@ blog.coffee: could not connect to host
 blog.cyveillance.com: did not receive HSTS header
 blog.torproject.org: max-age too low: 1000
 blogdimoda.com: did not receive HSTS header
 blogdimotori.it: did not receive HSTS header
 bloglife-bb.com: did not receive HSTS header
 bloglikepro.com: could not connect to host
 blognone.com: did not receive HSTS header
 blogonblogspot.com: did not receive HSTS header
-blok56.nl: did not receive HSTS header
 blokuhaka.fr: did not receive HSTS header
 bloomnbud.com: did not receive HSTS header
 bloomzoomy.ru: max-age too low: 172800
 blowjs.com: could not connect to host
 bls-fiduciaire.be: did not receive HSTS header
 bltc.co: could not connect to host
 blubbablasen.de: could not connect to host
 blucas.org: did not receive HSTS header
@@ -3729,16 +3729,17 @@ brownlawoffice.us: did not receive HSTS 
 browserid.org: could not connect to host
 brrd.io: did not receive HSTS header
 brunix.net: did not receive HSTS header
 brunohenc.from.hr: did not receive HSTS header
 brunoonline.co.uk: could not connect to host
 bryanshearer.accountant: did not receive HSTS header
 bryn.xyz: could not connect to host
 bs12v.ru: did not receive HSTS header
+bsagan.fr: did not receive HSTS header
 bsdtips.com: could not connect to host
 bsklabels.com: did not receive HSTS header
 btc-e.com: did not receive HSTS header
 btcdlc.com: could not connect to host
 btcpot.ltd: did not receive HSTS header
 btxiaobai.com: did not receive HSTS header
 buben.tech: did not receive HSTS header
 bubulazi.com: did not receive HSTS header
@@ -3764,25 +3765,27 @@ builmaker.com: did not receive HSTS head
 built.by: did not receive HSTS header
 bukatv.cz: could not connect to host
 bulgarien.guide: could not connect to host
 bulkbuy.tech: could not connect to host
 bullbits.com: max-age too low: 0
 bulletpoint.cz: could not connect to host
 bullterrier.me: could not connect to host
 bulmafox.com: could not connect to host
+bumshow.ru: did not receive HSTS header
 bunaken.asia: did not receive HSTS header
 bunbomenu.de: could not connect to host
 bunsenlabs.org: max-age too low: 2592000
 bureaubolster.nl: did not receive HSTS header
 bureaugravity.com: did not receive HSTS header
 burian-server.cz: could not connect to host
 burlesquemakeup.com: did not receive HSTS header
 burningcrash.de: max-age too low: 600000
 burpsuite.site: could not connect to host
+burr.is: did not receive HSTS header
 burrow.ovh: could not connect to host
 burrowingsec.com: could not connect to host
 burtrum.top: could not connect to host
 buryat-mongol.cf: could not connect to host
 bush41.org: did not receive HSTS header
 business.lookout.com: could not connect to host
 business.medbank.com.mt: did not receive HSTS header
 businessadviceperth.com.au: did not receive HSTS header
@@ -4063,21 +4066,21 @@ cigi.site: could not connect to host
 ciicutini.ro: did not receive HSTS header
 cim2b.de: could not connect to host
 cimalando.eu: could not connect to host
 cinartelorgu.com: did not receive HSTS header
 cintdirect.com: could not connect to host
 cioconference.co.nz: could not connect to host
 ciplanutrition.com: could not connect to host
 circ-logic.com: did not receive HSTS header
-circu.ml: did not receive HSTS header
 cirrohost.com: did not receive HSTS header
 ciscohomeanalytics.com: could not connect to host
 ciscommerce.net: could not connect to host
 citiagent.cz: could not connect to host
+citybusexpress.com: did not receive HSTS header
 cityoflaurel.org: did not receive HSTS header
 cium.ru: could not connect to host
 ciurcasdan.eu: did not receive HSTS header
 cjcaron.org: could not connect to host
 claimit.ml: could not connect to host
 claireidrac.fr: max-age too low: 0
 clan-ww.com: did not receive HSTS header
 clara-baumert.de: could not connect to host
@@ -4095,16 +4098,17 @@ cleaningsquad.ca: did not receive HSTS h
 cleanmta.com: could not connect to host
 clearc.tk: could not connect to host
 clearsky.me: could not connect to host
 clerkendweller.uk: could not connect to host
 clickandgo.com: did not receive HSTS header
 clickandshoot.nl: did not receive HSTS header
 clickclickphish.com: did not receive HSTS header
 clickgram.biz: could not connect to host
+clicks.co.za: max-age too low: 1800
 clicn.bio: could not connect to host
 clicnbio.com: could not connect to host
 cliftons.com: did not receive HSTS header
 clinicaferrusbratos.com: did not receive HSTS header
 clinicasilos.com: did not receive HSTS header
 clintonbloodworth.io: could not connect to host
 clintwilson.technology: max-age too low: 2592000
 clip.ovh: did not receive HSTS header
@@ -4130,43 +4134,43 @@ cloudstoragemaus.com: could not connect 
 cloudstorm.me: could not connect to host
 cloudstrike.co: could not connect to host
 cloudwalk.io: did not receive HSTS header
 clounix.online: could not connect to host
 clovissantos.com: could not connect to host
 clowde.in: could not connect to host
 clownaroundbouncycastles.co.uk: did not receive HSTS header
 club-adulti.ro: did not receive HSTS header
-clubalfa.it: max-age too low: 3600
+clubalfa.it: did not receive HSTS header
 clubcall.com: did not receive HSTS header
 clubmix.co.kr: could not connect to host
 cluster.id: did not receive HSTS header
 clvrwebdesign.com: did not receive HSTS header
 clywedogmaths.co.uk: could not connect to host
 cmc-versand.de: did not receive HSTS header
 cmci.dk: did not receive HSTS header
 cmsbattle.com: could not connect to host
 cmscafe.ru: did not receive HSTS header
 cmso-cal.com: could not connect to host
 cncn.us: did not receive HSTS header
-cnrd.me: did not receive HSTS header
+cnrd.me: could not connect to host
 co-driversphoto.se: could not connect to host
 coach-sportif.paris: did not receive HSTS header
 coachingconsultancy.