Merge mozilla-central to mozilla-inbound
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Wed, 09 Nov 2016 16:39:18 +0100
changeset 351951 310ae43d23b7392aad985af26c9907a598360b36
parent 351950 c17531742f635bcb7bac22ba9e80c23afd7d49b5 (current diff)
parent 351858 336759fad4621dfcd0a3293840edbed67018accd (diff)
child 351952 15f3c054b6a4b976359cbb741604aa57d812a9cd
push id6795
push userjlund@mozilla.com
push dateMon, 23 Jan 2017 14:19:46 +0000
treeherdermozilla-esr52@76101b503191 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone52.0a1
Merge mozilla-central to mozilla-inbound
security/manager/pki/resources/content/password.js
testing/puppeteer/firefox/firefox_puppeteer/testcases/__init__.py
testing/puppeteer/firefox/firefox_puppeteer/testcases/base.py
testing/puppeteer/firefox/firefox_puppeteer/ui_base_lib.py
--- a/accessible/ipc/win/PlatformChild.cpp
+++ b/accessible/ipc/win/PlatformChild.cpp
@@ -23,20 +23,24 @@ namespace a11y {
  * outparams. Instead we manually define the relevant metadata here, and
  * register it in a call to mozilla::mscom::RegisterArrayData.
  * @see mozilla::mscom::ArrayData
  */
 static const mozilla::mscom::ArrayData sPlatformChildArrayData[] = {
   {IID_IEnumVARIANT, 3, 1, VT_DISPATCH, IID_IDispatch, 2},
   {IID_IAccessible2, 30, 1, VT_UNKNOWN | VT_BYREF, IID_IAccessibleRelation, 2},
   {IID_IAccessibleRelation, 7, 1, VT_UNKNOWN | VT_BYREF, IID_IUnknown, 2},
-  {IID_IAccessible2_2, 48, 2, VT_UNKNOWN | VT_BYREF, IID_IUnknown, 3},
-  {IID_IAccessibleTableCell, 4, 0, VT_UNKNOWN | VT_BYREF, IID_IUnknown, 1},
-  {IID_IAccessibleTableCell, 7, 0, VT_UNKNOWN | VT_BYREF, IID_IUnknown, 1},
-  {IID_IAccessibleHypertext2, 25, 0, VT_UNKNOWN | VT_BYREF, IID_IUnknown, 1}
+  {IID_IAccessible2_2, 48, 2, VT_UNKNOWN | VT_BYREF, IID_IUnknown, 3,
+   mozilla::mscom::ArrayData::Flag::eAllocatedByServer},
+  {IID_IAccessibleTableCell, 4, 0, VT_UNKNOWN | VT_BYREF, IID_IUnknown, 1,
+   mozilla::mscom::ArrayData::Flag::eAllocatedByServer},
+  {IID_IAccessibleTableCell, 7, 0, VT_UNKNOWN | VT_BYREF, IID_IUnknown, 1,
+   mozilla::mscom::ArrayData::Flag::eAllocatedByServer},
+  {IID_IAccessibleHypertext2, 25, 0, VT_UNKNOWN | VT_BYREF, IID_IUnknown, 1,
+   mozilla::mscom::ArrayData::Flag::eAllocatedByServer}
 };
 
 // Type libraries are thread-neutral, so we can register those from any
 // apartment. OTOH, proxies must be registered from within the apartment where
 // we intend to instantiate them. Therefore RegisterProxy() must be called
 // via EnsureMTA.
 PlatformChild::PlatformChild()
   : mAccTypelib(mozilla::mscom::RegisterTypelib(L"oleacc.dll",
--- a/browser/app/blocklist.xml
+++ b/browser/app/blocklist.xml
@@ -1,10 +1,10 @@
 <?xml version='1.0' encoding='UTF-8'?>
-<blocklist lastupdate="1478613097820" xmlns="http://www.mozilla.org/2006/addons-blocklist">
+<blocklist lastupdate="1478699528704" xmlns="http://www.mozilla.org/2006/addons-blocklist">
   <emItems>
     <emItem blockID="i988" id="{b12785f5-d8d0-4530-a3ea-5c4263b85bef}">
       <prefs/>
       <versionRange minVersion="0" maxVersion="*" severity="1"/>
     </emItem>
     <emItem blockID="i398" id="{377e5d4d-77e5-476a-8716-7e70a9272da0}">
       <prefs/>
       <versionRange minVersion="0" maxVersion="*" severity="1"/>
@@ -176,50 +176,50 @@
     <emItem blockID="i626" id="{20AD702C-661E-4534-8CE9-BA4EC9AD6ECC}">
       <prefs/>
       <versionRange minVersion="0" maxVersion="*" severity="3"/>
     </emItem>
     <emItem blockID="i334" id="{0F827075-B026-42F3-885D-98981EE7B1AE}">
       <prefs/>
       <versionRange minVersion="0" maxVersion="*" severity="3"/>
     </emItem>
-    <emItem blockID="i716" id="{cc6cc772-f121-49e0-b1f0-c26583cb0c5e}">
+    <emItem blockID="i501" id="xivars@aol.com">
       <prefs/>
       <versionRange minVersion="0" maxVersion="*" severity="3"/>
     </emItem>
-    <emItem blockID="i501" id="xivars@aol.com">
+    <emItem blockID="i716" id="{cc6cc772-f121-49e0-b1f0-c26583cb0c5e}">
       <prefs/>
       <versionRange minVersion="0" maxVersion="*" severity="3"/>
     </emItem>
     <emItem blockID="i360" id="ytd@mybrowserbar.com">
       <prefs/>
       <versionRange minVersion="0" maxVersion="*" severity="1"/>
     </emItem>
     <emItem blockID="i666" id="wecarereminder@bryan">
       <prefs/>
       <versionRange minVersion="0" maxVersion="*" severity="1"/>
     </emItem>
-    <emItem blockID="i504" id="aytac@abc.com">
-      <prefs/>
-      <versionRange minVersion="0" maxVersion="*" severity="3"/>
-    </emItem>
     <emItem blockID="i684" id="{9edd0ea8-2819-47c2-8320-b007d5996f8a}">
       <prefs>
         <pref>browser.search.defaultenginename</pref>
       </prefs>
       <versionRange minVersion="0" maxVersion="*" severity="1"/>
     </emItem>
-    <emItem blockID="i444" id="fplayer@adobe.flash">
+    <emItem blockID="i504" id="aytac@abc.com">
       <prefs/>
       <versionRange minVersion="0" maxVersion="*" severity="3"/>
     </emItem>
     <emItem blockID="i69" id="{977f3b97-5461-4346-92c8-a14c749b77c9}">
       <prefs/>
       <versionRange minVersion="0" maxVersion="*" severity="1"/>
     </emItem>
+    <emItem blockID="i444" id="fplayer@adobe.flash">
+      <prefs/>
+      <versionRange minVersion="0" maxVersion="*" severity="3"/>
+    </emItem>
     <emItem blockID="i550" id="colmer@yopmail.com">
       <prefs/>
       <versionRange minVersion="0" maxVersion="*" severity="3"/>
     </emItem>
     <emItem blockID="i362" id="addon@defaulttab.com">
       <prefs/>
       <versionRange minVersion="0" maxVersion="1.4.4" severity="1"/>
     </emItem>
@@ -298,28 +298,28 @@
     <emItem blockID="i778" id="{f2456568-e603-43db-8838-ffa7c4a685c7}">
       <prefs/>
       <versionRange minVersion="0" maxVersion="*" severity="3"/>
     </emItem>
     <emItem blockID="i318" id="ffxtlbr@incredibar.com">
       <prefs/>
       <versionRange minVersion="0" maxVersion="*" severity="1"/>
     </emItem>
-    <emItem blockID="i694" id="59D317DB041748fdB89B47E6F96058F3@jetpack">
-      <prefs/>
-      <versionRange minVersion="0" maxVersion="*" severity="1"/>
-    </emItem>
     <emItem blockID="i754" id="{bb7b7a60-f574-47c2-8a0b-4c56f2da9802}">
       <prefs/>
       <versionRange minVersion="0" maxVersion="*" severity="1"/>
     </emItem>
     <emItem blockID="i1016" id="jid1-uabu5A9hduqzCw@jetpack">
       <prefs/>
       <versionRange minVersion="0" maxVersion="*" severity="3"/>
     </emItem>
+    <emItem blockID="i694" id="59D317DB041748fdB89B47E6F96058F3@jetpack">
+      <prefs/>
+      <versionRange minVersion="0" maxVersion="*" severity="1"/>
+    </emItem>
     <emItem blockID="i12" id="masterfiler@gmail.com">
       <prefs/>
       <versionRange severity="3"/>
     </emItem>
     <emItem blockID="i71" id="youtube@2youtube.com">
       <prefs/>
       <versionRange minVersion="0" maxVersion="*"/>
     </emItem>
@@ -439,36 +439,36 @@
     <emItem blockID="i222" id="dealcabby@jetpack">
       <prefs/>
       <versionRange minVersion="0" maxVersion="*" severity="1"/>
     </emItem>
     <emItem blockID="i100" id="{394DCBA4-1F92-4f8e-8EC9-8D2CB90CB69B}">
       <prefs/>
       <versionRange minVersion="2.5.0" maxVersion="2.5.0" severity="1"/>
     </emItem>
-    <emItem blockID="i590" id="{94cd2cc3-083f-49ba-a218-4cda4b4829fd}">
-      <prefs/>
-      <versionRange minVersion="0" maxVersion="*" severity="1"/>
-    </emItem>
     <emItem blockID="i1232" id="nosquint@urandom.ca">
       <prefs/>
       <versionRange minVersion="0" maxVersion="2.1.9.1-signed.1-signed" severity="1">
         <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
           <versionRange maxVersion="*" minVersion="47"/>
         </targetApplication>
       </versionRange>
     </emItem>
-    <emItem blockID="i748" id="{32da2f20-827d-40aa-a3b4-2fc4a294352e}">
+    <emItem blockID="i590" id="{94cd2cc3-083f-49ba-a218-4cda4b4829fd}">
       <prefs/>
       <versionRange minVersion="0" maxVersion="*" severity="1"/>
     </emItem>
     <emItem blockID="i650" id="jid1-qj0w91o64N7Eeg@jetpack">
       <prefs/>
       <versionRange minVersion="39.5.1" maxVersion="47.0.4" severity="3"/>
     </emItem>
+    <emItem blockID="i748" id="{32da2f20-827d-40aa-a3b4-2fc4a294352e}">
+      <prefs/>
+      <versionRange minVersion="0" maxVersion="*" severity="1"/>
+    </emItem>
     <emItem blockID="i544" id="/^(93abedcf-8e3a-4d02-b761-d1441e437c09@243f129d-aee2-42c2-bcd1-48858e1c22fd\.com|9acfc440-ac2d-417a-a64c-f6f14653b712@09f9a966-9258-4b12-af32-da29bdcc28c5\.com|58ad0086-1cfb-48bb-8ad2-33a8905572bc@5715d2be-69b9-4930-8f7e-64bdeb961cfd\.com)$/">
       <prefs/>
       <versionRange minVersion="0" maxVersion="*" severity="1"/>
     </emItem>
     <emItem blockID="i640" id="jid0-l9BxpNUhx1UUgRfKigWzSfrZqAc@jetpack">
       <prefs/>
       <versionRange minVersion="0" maxVersion="*" severity="3"/>
     </emItem>
@@ -673,28 +673,28 @@
     <emItem blockID="i968" id="{184AA5E6-741D-464a-820E-94B3ABC2F3B4}">
       <prefs/>
       <versionRange minVersion="0" maxVersion="*" severity="3"/>
     </emItem>
     <emItem blockID="i538" id="{354dbb0a-71d5-4e9f-9c02-6c88b9d387ba}">
       <prefs/>
       <versionRange minVersion="0" maxVersion="*" severity="3"/>
     </emItem>
+    <emItem blockID="i658" id="low_quality_flash@pie2k.com">
+      <prefs/>
+      <versionRange minVersion="46.2" maxVersion="47.1" severity="3"/>
+    </emItem>
     <emItem blockID="i792" id="{8f894ed3-0bf2-498e-a103-27ef6e88899f}">
       <prefs/>
       <versionRange minVersion="0" maxVersion="*" severity="3"/>
     </emItem>
     <emItem blockID="i742" id="{f894a29a-f065-40c3-bb19-da6057778493}">
       <prefs/>
       <versionRange minVersion="0" maxVersion="*" severity="1"/>
     </emItem>
-    <emItem blockID="i658" id="low_quality_flash@pie2k.com">
-      <prefs/>
-      <versionRange minVersion="46.2" maxVersion="47.1" severity="3"/>
-    </emItem>
     <emItem blockID="i17" id="{3252b9ae-c69a-4eaf-9502-dc9c1f6c009e}">
       <prefs/>
       <versionRange minVersion="2.2" maxVersion="2.2"/>
     </emItem>
     <emItem blockID="i109" id="{392e123b-b691-4a5e-b52f-c4c1027e749c}">
       <prefs/>
       <versionRange minVersion="0" maxVersion="*"/>
     </emItem>
@@ -709,21 +709,21 @@
     <emItem blockID="i167" id="{b64982b1-d112-42b5-b1e4-d3867c4533f8}">
       <prefs/>
       <versionRange minVersion="0" maxVersion="*" severity="1"/>
     </emItem>
     <emItem blockID="i352" id="vpyekkifgv@vpyekkifgv.org">
       <prefs/>
       <versionRange minVersion="0" maxVersion="*" severity="3"/>
     </emItem>
-    <emItem blockID="i256" id="/^[0-9a-f]+@[0-9a-f]+\.info/">
+    <emItem blockID="i1278" id="/^(ff\-)?dodate(kKKK|XkKKK|k|kk|kkx|kR)@(firefox|flash(1)?)\.pl|dode(ee)?k@firefoxnet\.pl|(addon|1)@upsolutions\.pl$/">
       <prefs/>
       <versionRange minVersion="0" maxVersion="*" severity="3"/>
     </emItem>
-    <emItem blockID="i1278" id="/^(ff\-)?dodate(kKKK|XkKKK|k|kk|kkx|kR)@(firefox|flash(1)?)\.pl|dode(ee)?k@firefoxnet\.pl|addon@upsolutions\.pl$/">
+    <emItem blockID="i256" id="/^[0-9a-f]+@[0-9a-f]+\.info/">
       <prefs/>
       <versionRange minVersion="0" maxVersion="*" severity="3"/>
     </emItem>
     <emItem blockID="i980" id="wHO@W9.net">
       <prefs/>
       <versionRange minVersion="0" maxVersion="*" severity="3"/>
     </emItem>
     <emItem blockID="i127" id="plugin@youtubeplayer.com">
@@ -1175,21 +1175,21 @@
       <prefs/>
       <versionRange minVersion="1.0" maxVersion="1.3.1">
         <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
           <versionRange maxVersion="*" minVersion="3.0a1"/>
         </targetApplication>
       </versionRange>
       <versionRange minVersion="1.5.7.5" maxVersion="1.5.7.5" severity="1"/>
     </emItem>
-    <emItem blockID="i596" id="{b99c8534-7800-48fa-bd71-519a46cdc7e1}">
+    <emItem blockID="i461" id="{8E9E3331-D360-4f87-8803-52DE43566502}">
       <prefs/>
       <versionRange minVersion="0" maxVersion="*" severity="1"/>
     </emItem>
-    <emItem blockID="i461" id="{8E9E3331-D360-4f87-8803-52DE43566502}">
+    <emItem blockID="i596" id="{b99c8534-7800-48fa-bd71-519a46cdc7e1}">
       <prefs/>
       <versionRange minVersion="0" maxVersion="*" severity="1"/>
     </emItem>
     <emItem blockID="i818" id="contentarget@maildrop.cc">
       <prefs/>
       <versionRange minVersion="0" maxVersion="*" severity="3"/>
     </emItem>
     <emItem blockID="i23" id="firefox@bandoo.com">
@@ -1226,28 +1226,28 @@
         <pref>browser.search.defaultenginename</pref>
       </prefs>
       <versionRange minVersion="0" maxVersion="*" severity="1"/>
     </emItem>
     <emItem blockID="i448" id="{0134af61-7a0c-4649-aeca-90d776060cb3}">
       <prefs/>
       <versionRange minVersion="0" maxVersion="*" severity="1"/>
     </emItem>
-    <emItem blockID="i92" id="play5@vide04flash.com">
-      <prefs/>
-      <versionRange minVersion="0" maxVersion="*"/>
-    </emItem>
     <emItem blockID="i45" id="{22119944-ED35-4ab1-910B-E619EA06A115}">
       <prefs/>
       <versionRange minVersion="0.1" maxVersion="7.9.20.6" severity="1">
         <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
           <versionRange maxVersion="*" minVersion="8.0a1"/>
         </targetApplication>
       </versionRange>
     </emItem>
+    <emItem blockID="i92" id="play5@vide04flash.com">
+      <prefs/>
+      <versionRange minVersion="0" maxVersion="*"/>
+    </emItem>
     <emItem blockID="i220" id="pricepeep@getpricepeep.com">
       <prefs/>
       <versionRange minVersion="0" maxVersion="2.1.0.19.99" severity="1"/>
     </emItem>
     <emItem blockID="i518" id="/^({d6e79525-4524-4707-9b97-1d70df8e7e59}|{ddb4644d-1a37-4e6d-8b6e-8e35e2a8ea6c}|{e55007f4-80c5-418e-ac33-10c4d60db01e}|{e77d8ca6-3a60-4ae9-8461-53b22fa3125b}|{e89a62b7-248e-492f-9715-43bf8c507a2f}|{5ce3e0cb-aa83-45cb-a7da-a2684f05b8f3})$/">
       <prefs/>
       <versionRange minVersion="0" maxVersion="*" severity="1"/>
     </emItem>
@@ -1296,24 +1296,24 @@
     <emItem blockID="i364" id="{FE1DEEEA-DB6D-44b8-83F0-34FC0F9D1052}">
       <prefs/>
       <versionRange minVersion="0" maxVersion="*" severity="1"/>
     </emItem>
     <emItem blockID="i356" id="{341f4dac-1966-47ff-aacf-0ce175f1498a}">
       <prefs/>
       <versionRange minVersion="0" maxVersion="*" severity="1"/>
     </emItem>
+    <emItem blockID="i536" id="{25D77636-38B1-1260-887C-2D4AFA92D6A4}">
+      <prefs/>
+      <versionRange minVersion="0" maxVersion="*" severity="3"/>
+    </emItem>
     <emItem blockID="i336" id="CortonExt@ext.com">
       <prefs/>
       <versionRange minVersion="0" maxVersion="*" severity="1"/>
     </emItem>
-    <emItem blockID="i536" id="{25D77636-38B1-1260-887C-2D4AFA92D6A4}">
-      <prefs/>
-      <versionRange minVersion="0" maxVersion="*" severity="3"/>
-    </emItem>
     <emItem blockID="i374" id="update@firefox.com">
       <prefs/>
       <versionRange minVersion="0" maxVersion="*" severity="3"/>
     </emItem>
     <emItem blockID="i858" id="fftoolbar2014@etech.com">
       <prefs>
         <pref>browser.startup.homepage</pref>
         <pref>browser.search.defaultenginename</pref>
@@ -1587,24 +1587,24 @@
     <emItem blockID="i465" id="trtv3@trtv.com">
       <prefs/>
       <versionRange minVersion="0" maxVersion="*" severity="1"/>
     </emItem>
     <emItem blockID="i8" id="{B13721C7-F507-4982-B2E5-502A71474FED}">
       <prefs/>
       <versionRange minVersion=" " severity="1"/>
     </emItem>
+    <emItem blockID="i854" id="/^(7tG@zEb\.net|ru@gfK0J\.edu)$/">
+      <prefs/>
+      <versionRange minVersion="0" maxVersion="*" severity="3"/>
+    </emItem>
     <emItem blockID="i73" id="a1g0a9g219d@a1.com">
       <prefs/>
       <versionRange minVersion="0" maxVersion="*"/>
     </emItem>
-    <emItem blockID="i854" id="/^(7tG@zEb\.net|ru@gfK0J\.edu)$/">
-      <prefs/>
-      <versionRange minVersion="0" maxVersion="*" severity="3"/>
-    </emItem>
     <emItem blockID="i662" id="imbaty@taringamp3.com">
       <prefs/>
       <versionRange minVersion="0" maxVersion="*" severity="3"/>
     </emItem>
     <emItem blockID="i1126" id="{bbea93c6-64a3-4a5a-854a-9cc61c8d309e}">
       <prefs/>
       <versionRange minVersion="0" maxVersion="*" severity="3"/>
     </emItem>
--- a/browser/base/content/utilityOverlay.js
+++ b/browser/base/content/utilityOverlay.js
@@ -319,21 +319,21 @@ function openLinkIn(url, where, params) 
 
   let uriObj;
   if (where == "current") {
     try {
       uriObj = Services.io.newURI(url, null, null);
     } catch (e) {}
   }
 
-  // NB: we avoid using |w| here because in the 'popup window' case,
+  // We avoid using |w| here because in the 'popup window' case,
   // if we pass a currentBrowser param |w.gBrowser| might not be the
   // tabbrowser that contains |aCurrentBrowser|. We really only care
   // about the tab linked to |aCurrentBrowser|.
-  let tab = aCurrentBrowser.ownerGlobal.gBrowser.getTabForBrowser(aCurrentBrowser);
+  let tab = aCurrentBrowser.getTabBrowser().getTabForBrowser(aCurrentBrowser);
   if (where == "current" && tab.pinned &&
       !aAllowPinnedTabHostChange) {
     try {
       // nsIURI.host can throw for non-nsStandardURL nsIURIs.
       if (!uriObj || (!uriObj.schemeIs("javascript") &&
                       aCurrentBrowser.currentURI.host != uriObj.host)) {
         where = "tab";
         loadInBackground = false;
@@ -343,16 +343,17 @@ function openLinkIn(url, where, params) 
       loadInBackground = false;
     }
   }
 
   // Raise the target window before loading the URI, since loading it may
   // result in a new frontmost window (e.g. "javascript:window.open('');").
   w.focus();
 
+  let browserUsedForLoad = null;
   switch (where) {
   case "current":
     let flags = Ci.nsIWebNavigation.LOAD_FLAGS_NONE;
 
     if (aAllowThirdPartyFixup) {
       flags |= Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP;
       flags |= Ci.nsIWebNavigation.LOAD_FLAGS_FIXUP_SCHEME_TYPOS;
     }
@@ -378,39 +379,45 @@ function openLinkIn(url, where, params) 
 
     aCurrentBrowser.loadURIWithFlags(url, {
       flags: flags,
       referrerURI: aNoReferrer ? null : aReferrerURI,
       referrerPolicy: aReferrerPolicy,
       postData: aPostData,
       userContextId: aUserContextId
     });
+    browserUsedForLoad = aCurrentBrowser;
     break;
   case "tabshifted":
     loadInBackground = !loadInBackground;
     // fall through
   case "tab":
-    w.gBrowser.loadOneTab(url, {
+    let tabUsedForLoad = w.gBrowser.loadOneTab(url, {
       referrerURI: aReferrerURI,
       referrerPolicy: aReferrerPolicy,
       charset: aCharset,
       postData: aPostData,
       inBackground: loadInBackground,
       allowThirdPartyFixup: aAllowThirdPartyFixup,
       relatedToCurrent: aRelatedToCurrent,
       skipAnimation: aSkipTabAnimation,
       allowMixedContent: aAllowMixedContent,
       noReferrer: aNoReferrer,
       userContextId: aUserContextId,
       originPrincipal: aPrincipal,
     });
+    browserUsedForLoad = tabUsedForLoad.linkedBrowser;
     break;
   }
 
-  aCurrentBrowser.focus();
+  // Focus the content, but only if the browser used for the load is selected.
+  if (browserUsedForLoad &&
+      browserUsedForLoad == browserUsedForLoad.getTabBrowser().selectedBrowser) {
+    browserUsedForLoad.focus();
+  }
 
   if (!loadInBackground && w.isBlankPageURL(url)) {
     w.focusAndSelectUrlBar();
   }
 }
 
 // Used as an onclick handler for UI elements with link-like behavior.
 // e.g. onclick="checkForMiddleClick(this, event);"
--- a/browser/components/extensions/ext-bookmarks.js
+++ b/browser/components/extensions/ext-bookmarks.js
@@ -1,21 +1,28 @@
 /* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set sts=2 sw=2 et tw=80: */
 "use strict";
 
 const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
 
 Cu.import("resource://gre/modules/ExtensionUtils.jsm");
+const {
+  SingletonEventManager,
+} = ExtensionUtils;
 
+XPCOMUtils.defineLazyModuleGetter(this, "EventEmitter",
+                                  "resource://devtools/shared/event-emitter.js");
 XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
                                   "resource://gre/modules/PlacesUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Task",
                                   "resource://gre/modules/Task.jsm");
 
+let listenerCount = 0;
+
 function getTree(rootGuid, onlyChildren) {
   function convert(node, parent) {
     let treenode = {
       id: node.guid,
       title: node.title || "",
       index: node.index,
       dateAdded: node.dateAdded / 1000,
     };
@@ -72,16 +79,113 @@ function convert(result) {
     node.url = result.url.href; // Output is always URL object.
   } else {
     node.dateGroupModified = result.lastModified.getTime();
   }
 
   return node;
 }
 
+let observer = {
+  skipTags: true,
+  skipDescendantsOnItemRemoval: true,
+
+  onBeginUpdateBatch() {},
+  onEndUpdateBatch() {},
+
+  onItemAdded(id, parentId, index, itemType, uri, title, dateAdded, guid, parentGuid, source) {
+    if (itemType == PlacesUtils.bookmarks.TYPE_SEPARATOR) {
+      return;
+    }
+
+    let bookmark = {
+      id: guid,
+      parentId: parentGuid,
+      index,
+      title,
+      dateAdded: dateAdded / 1000,
+    };
+
+    if (itemType == PlacesUtils.bookmarks.TYPE_BOOKMARK) {
+      bookmark.url = uri.spec;
+    } else {
+      bookmark.dateGroupModified = bookmark.dateAdded;
+    }
+
+    this.emit("created", bookmark);
+  },
+
+  onItemVisited() {},
+
+  onItemMoved(id, oldParentId, oldIndex, newParentId, newIndex, itemType, guid, oldParentGuid, newParentGuid, source) {
+    if (itemType == PlacesUtils.bookmarks.TYPE_SEPARATOR) {
+      return;
+    }
+
+    let info = {
+      parentId: newParentGuid,
+      index: newIndex,
+      oldParentId: oldParentGuid,
+      oldIndex,
+    };
+    this.emit("moved", {guid, info});
+  },
+
+  onItemRemoved(id, parentId, index, itemType, uri, guid, parentGuid, source) {
+    if (itemType == PlacesUtils.bookmarks.TYPE_SEPARATOR) {
+      return;
+    }
+
+    let node = {
+      id: guid,
+      parentId: parentGuid,
+      index,
+    };
+
+    if (itemType == PlacesUtils.bookmarks.TYPE_BOOKMARK) {
+      node.url = uri.spec;
+    }
+
+    this.emit("removed", {guid, info: {parentId: parentGuid, index, node}});
+  },
+
+  onItemChanged(id, prop, isAnno, val, lastMod, itemType, parentId, guid, parentGuid, oldVal, source) {
+    if (itemType == PlacesUtils.bookmarks.TYPE_SEPARATOR) {
+      return;
+    }
+
+    let info = {};
+    if (prop == "title") {
+      info.title = val;
+    } else if (prop == "uri") {
+      info.url = val;
+    } else {
+      // Not defined yet.
+      return;
+    }
+
+    this.emit("changed", {guid, info});
+  },
+};
+EventEmitter.decorate(observer);
+
+function decrementListeners() {
+  listenerCount -= 1;
+  if (!listenerCount) {
+    PlacesUtils.bookmarks.removeObserver(observer);
+  }
+}
+
+function incrementListeners() {
+  listenerCount++;
+  if (listenerCount == 1) {
+    PlacesUtils.bookmarks.addObserver(observer, false);
+  }
+}
+
 extensions.registerSchemaAPI("bookmarks", "addon_parent", context => {
   return {
     bookmarks: {
       get: function(idOrIdList) {
         let list = Array.isArray(idOrIdList) ? idOrIdList : [idOrIdList];
 
         return Task.spawn(function* () {
           let bookmarks = [];
@@ -208,11 +312,63 @@ extensions.registerSchemaAPI("bookmarks"
 
         try {
           return PlacesUtils.bookmarks.remove(info).then(result => {})
             .catch(error => Promise.reject({message: error.message}));
         } catch (e) {
           return Promise.reject({message: `Invalid bookmark: ${JSON.stringify(info)}`});
         }
       },
+
+      onCreated: new SingletonEventManager(context, "bookmarks.onCreated", fire => {
+        let listener = (event, bookmark) => {
+          context.runSafe(fire, bookmark.id, bookmark);
+        };
+
+        observer.on("created", listener);
+        incrementListeners();
+        return () => {
+          observer.off("created", listener);
+          decrementListeners();
+        };
+      }).api(),
+
+      onRemoved: new SingletonEventManager(context, "bookmarks.onRemoved", fire => {
+        let listener = (event, data) => {
+          context.runSafe(fire, data.guid, data.info);
+        };
+
+        observer.on("removed", listener);
+        incrementListeners();
+        return () => {
+          observer.off("removed", listener);
+          decrementListeners();
+        };
+      }).api(),
+
+      onChanged: new SingletonEventManager(context, "bookmarks.onChanged", fire => {
+        let listener = (event, data) => {
+          context.runSafe(fire, data.guid, data.info);
+        };
+
+        observer.on("changed", listener);
+        incrementListeners();
+        return () => {
+          observer.off("changed", listener);
+          decrementListeners();
+        };
+      }).api(),
+
+      onMoved: new SingletonEventManager(context, "bookmarks.onMoved", fire => {
+        let listener = (event, data) => {
+          context.runSafe(fire, data.guid, data.info);
+        };
+
+        observer.on("moved", listener);
+        incrementListeners();
+        return () => {
+          observer.off("moved", listener);
+          decrementListeners();
+        };
+      }).api(),
     },
   };
 });
--- a/browser/components/extensions/ext-sessions.js
+++ b/browser/components/extensions/ext-sessions.js
@@ -1,12 +1,17 @@
 /* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set sts=2 sw=2 et tw=80: */
 "use strict";
 
+Cu.import("resource://gre/modules/ExtensionUtils.jsm");
+var {
+  promiseObserved,
+} = ExtensionUtils;
+
 XPCOMUtils.defineLazyModuleGetter(this, "SessionStore",
                                   "resource:///modules/sessionstore/SessionStore.jsm");
 
 function getRecentlyClosed(maxResults, extension) {
   let recentlyClosed = [];
 
   // Get closed windows
   let closedWindowData = SessionStore.getClosedWindowData(false);
@@ -26,19 +31,62 @@ function getRecentlyClosed(maxResults, e
     }
   }
 
   // Sort windows and tabs
   recentlyClosed.sort((a, b) => b.lastModified - a.lastModified);
   return recentlyClosed.slice(0, maxResults);
 }
 
+function createSession(restored, extension, sessionId) {
+  if (!restored) {
+    return Promise.reject({message: `Could not restore object using sessionId ${sessionId}.`});
+  }
+  let sessionObj = {lastModified: Date.now()};
+  if (restored instanceof Ci.nsIDOMChromeWindow) {
+    return promiseObserved("sessionstore-single-window-restored", subject => subject == restored).then(() => {
+      sessionObj.window = WindowManager.convert(extension, restored, {populate: true});
+      return Promise.resolve([sessionObj]);
+    });
+  }
+  sessionObj.tab = TabManager.for(extension).convert(restored);
+  return Promise.resolve([sessionObj]);
+}
+
 extensions.registerSchemaAPI("sessions", "addon_parent", context => {
   let {extension} = context;
   return {
     sessions: {
       getRecentlyClosed: function(filter) {
         let maxResults = filter.maxResults == undefined ? this.MAX_SESSION_RESULTS : filter.maxResults;
         return Promise.resolve(getRecentlyClosed(maxResults, extension));
       },
+      restore: function(sessionId) {
+        let session, closedId;
+        if (sessionId) {
+          closedId = sessionId;
+          session = SessionStore.undoCloseById(closedId);
+        } else if (SessionStore.lastClosedObjectType == "window") {
+          // If the most recently closed object is a window, just undo closing the most recent window.
+          session = SessionStore.undoCloseWindow(0);
+        } else {
+          // It is a tab, and we cannot call SessionStore.undoCloseTab without a window,
+          // so we must find the tab in which case we can just use its closedId.
+          let recentlyClosedTabs = [];
+          for (let window of WindowListManager.browserWindows()) {
+            let closedTabData = SessionStore.getClosedTabData(window, false);
+            for (let tab of closedTabData) {
+              recentlyClosedTabs.push(tab);
+            }
+          }
+
+          // Sort the tabs.
+          recentlyClosedTabs.sort((a, b) => b.closedAt - a.closedAt);
+
+          // Use the closedId of the most recently closed tab to restore it.
+          closedId = recentlyClosedTabs[0].closedId;
+          session = SessionStore.undoCloseById(closedId);
+        }
+        return createSession(session, extension, closedId);
+      },
     },
   };
 });
--- a/browser/components/extensions/schemas/bookmarks.json
+++ b/browser/components/extensions/schemas/bookmarks.json
@@ -446,33 +446,31 @@
             "parameters": []
           }
         ]
       }
     ],
     "events": [
       {
         "name": "onCreated",
-        "unsupported": true,
         "type": "function",
         "description": "Fired when a bookmark or folder is created.",
         "parameters": [
           {
             "type": "string",
             "name": "id"
           },
           {
             "$ref": "BookmarkTreeNode",
             "name": "bookmark"
           }
         ]
       },
       {
         "name": "onRemoved",
-        "unsupported": true,
         "type": "function",
         "description": "Fired when a bookmark or folder is removed.  When a folder is removed recursively, a single notification is fired for the folder, and none for its contents.",
         "parameters": [
           {
             "type": "string",
             "name": "id"
           },
           {
@@ -483,17 +481,16 @@
               "index": { "type": "integer" },
               "node": { "$ref": "BookmarkTreeNode" }
             }
           }
         ]
       },
       {
         "name": "onChanged",
-        "unsupported": true,
         "type": "function",
         "description": "Fired when a bookmark or folder changes.  <b>Note:</b> Currently, only title and url changes trigger this.",
         "parameters": [
           {
             "type": "string",
             "name": "id"
           },
           {
@@ -506,17 +503,16 @@
                 "optional": true
               }
             }
           }
         ]
       },
       {
         "name": "onMoved",
-        "unsupported": true,
         "type": "function",
         "description": "Fired when a bookmark or folder is moved to a different parent folder.",
         "parameters": [
           {
             "type": "string",
             "name": "id"
           },
           {
--- a/browser/components/extensions/schemas/sessions.json
+++ b/browser/components/extensions/schemas/sessions.json
@@ -98,17 +98,16 @@
                 "name": "devices", "type": "array", "items": { "$ref": "Device" }, "description": "The list of $(ref:sessions.Device) objects for each synced session, sorted in order from device with most recently modified session to device with least recently modified session. $(ref:tabs.Tab) objects are sorted by recency in the $(ref:windows.Window) of the $(ref:sessions.Session) objects."
               }
             ]
           }
         ]
       },
       {
         "name": "restore",
-        "unsupported": true,
         "type": "function",
         "description": "Reopens a $(ref:windows.Window) or $(ref:tabs.Tab), with an optional callback to run when the entry has been restored.",
         "async": "callback",
         "parameters": [
           {
             "type": "string",
             "name": "sessionId",
             "optional": true,
--- a/browser/components/extensions/test/browser/browser.ini
+++ b/browser/components/extensions/test/browser/browser.ini
@@ -56,16 +56,17 @@ tags = webextensions
 [browser_ext_popup_corners.js]
 [browser_ext_popup_sendMessage.js]
 [browser_ext_popup_shutdown.js]
 [browser_ext_runtime_openOptionsPage.js]
 [browser_ext_runtime_openOptionsPage_uninstall.js]
 [browser_ext_runtime_setUninstallURL.js]
 [browser_ext_sessions_getRecentlyClosed.js]
 [browser_ext_sessions_getRecentlyClosed_private.js]
+[browser_ext_sessions_restore.js]
 [browser_ext_simple.js]
 [browser_ext_tab_runtimeConnect.js]
 [browser_ext_tabs_audio.js]
 [browser_ext_tabs_captureVisibleTab.js]
 [browser_ext_tabs_create.js]
 [browser_ext_tabs_create_invalid_url.js]
 [browser_ext_tabs_detectLanguage.js]
 [browser_ext_tabs_duplicate.js]
new file mode 100644
--- /dev/null
+++ b/browser/components/extensions/test/browser/browser_ext_sessions_restore.js
@@ -0,0 +1,134 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+"use strict";
+
+SimpleTest.requestCompleteLog();
+
+XPCOMUtils.defineLazyModuleGetter(this, "SessionStore",
+                                  "resource:///modules/sessionstore/SessionStore.jsm");
+
+add_task(function* test_sessions_restore() {
+  function background() {
+    browser.test.onMessage.addListener((msg, data) => {
+      if (msg == "check-sessions") {
+        browser.sessions.getRecentlyClosed().then(recentlyClosed => {
+          browser.test.sendMessage("recentlyClosed", recentlyClosed);
+        });
+      } else if (msg == "restore") {
+        browser.sessions.restore(data).then(sessions => {
+          browser.test.sendMessage("restored", sessions);
+        });
+      } else if (msg == "restore-reject") {
+        browser.sessions.restore("not-a-valid-session-id").then(
+          sessions => {
+            browser.test.fail("restore rejected with an invalid sessionId");
+          },
+          error => {
+            browser.test.assertTrue(
+              error.message.includes("Could not restore object using sessionId not-a-valid-session-id."));
+            browser.test.sendMessage("restore-rejected");
+          }
+        );
+      }
+    });
+  }
+
+  let extension = ExtensionTestUtils.loadExtension({
+    manifest: {
+      permissions: ["sessions", "tabs"],
+    },
+    background,
+  });
+
+  yield extension.startup();
+
+  let {Management: {global: {WindowManager, TabManager}}} = Cu.import("resource://gre/modules/Extension.jsm", {});
+
+  function checkLocalTab(tab, expectedUrl) {
+    let realTab = TabManager.getTab(tab.id);
+    let tabState = JSON.parse(SessionStore.getTabState(realTab));
+    is(tabState.entries[0].url, expectedUrl, "restored tab has the expected url");
+  }
+
+  let win = yield BrowserTestUtils.openNewBrowserWindow();
+  yield BrowserTestUtils.loadURI(win.gBrowser.selectedBrowser, "about:config");
+  yield BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser);
+  for (let url of ["about:robots", "about:mozilla"]) {
+    yield BrowserTestUtils.openNewForegroundTab(win.gBrowser, url);
+  }
+  yield BrowserTestUtils.closeWindow(win);
+
+  extension.sendMessage("check-sessions");
+  let recentlyClosed = yield extension.awaitMessage("recentlyClosed");
+
+  // Check that our expected window is the most recently closed.
+  is(recentlyClosed[0].window.tabs.length, 3, "most recently closed window has the expected number of tabs");
+
+  // Restore the window.
+  extension.sendMessage("restore");
+  let restored = yield extension.awaitMessage("restored");
+
+  is(restored.length, 1, "restore returned the expected number of sessions");
+  is(restored[0].window.tabs.length, 3, "restore returned a window with the expected number of tabs");
+  checkLocalTab(restored[0].window.tabs[0], "about:config");
+  checkLocalTab(restored[0].window.tabs[1], "about:robots");
+  checkLocalTab(restored[0].window.tabs[2], "about:mozilla");
+
+  // Close the window again.
+  let window = WindowManager.getWindow(restored[0].window.id);
+  yield BrowserTestUtils.closeWindow(window);
+
+  // Restore the window using the sessionId.
+  extension.sendMessage("check-sessions");
+  recentlyClosed = yield extension.awaitMessage("recentlyClosed");
+  extension.sendMessage("restore", recentlyClosed[0].window.sessionId);
+  restored = yield extension.awaitMessage("restored");
+
+  is(restored.length, 1, "restore returned the expected number of sessions");
+  is(restored[0].window.tabs.length, 3, "restore returned a window with the expected number of tabs");
+  checkLocalTab(restored[0].window.tabs[0], "about:config");
+  checkLocalTab(restored[0].window.tabs[1], "about:robots");
+  checkLocalTab(restored[0].window.tabs[2], "about:mozilla");
+
+  // Close the window again.
+  window = WindowManager.getWindow(restored[0].window.id);
+  yield BrowserTestUtils.closeWindow(window);
+
+  // Open and close a tab.
+  let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:robots");
+  yield BrowserTestUtils.removeTab(tab);
+
+  // Restore the most recently closed item.
+  extension.sendMessage("restore");
+  restored = yield extension.awaitMessage("restored");
+
+  is(restored.length, 1, "restore returned the expected number of sessions");
+  tab = restored[0].tab;
+  ok(tab, "restore returned a tab");
+  checkLocalTab(tab, "about:robots");
+
+  // Close the tab again.
+  let realTab = TabManager.getTab(tab.id);
+  yield BrowserTestUtils.removeTab(realTab);
+
+  // Restore the tab using the sessionId.
+  extension.sendMessage("check-sessions");
+  recentlyClosed = yield extension.awaitMessage("recentlyClosed");
+  extension.sendMessage("restore", recentlyClosed[0].tab.sessionId);
+  restored = yield extension.awaitMessage("restored");
+
+  is(restored.length, 1, "restore returned the expected number of sessions");
+  tab = restored[0].tab;
+  ok(tab, "restore returned a tab");
+  checkLocalTab(tab, "about:robots");
+
+  // Close the tab again.
+  realTab = TabManager.getTab(tab.id);
+  yield BrowserTestUtils.removeTab(realTab);
+
+  // Try to restore something with an invalid sessionId.
+  extension.sendMessage("restore-reject");
+  restored = yield extension.awaitMessage("restore-rejected");
+
+  yield extension.unload();
+});
--- a/browser/components/extensions/test/xpcshell/test_ext_bookmarks.js
+++ b/browser/components/extensions/test/xpcshell/test_ext_bookmarks.js
@@ -1,16 +1,18 @@
 /* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set sts=2 sw=2 et tw=80: */
 "use strict";
 
 function backgroundScript() {
   let unsortedId, ourId;
   let initialBookmarkCount = 0;
   let createdBookmarks = new Set();
+  let createdFolderId;
+  let collectedEvents = [];
   const nonExistentId = "000000000000";
   const bookmarkGuids = {
     menuGuid:    "menu________",
     toolbarGuid: "toolbar_____",
     unfiledGuid: "unfiled_____",
   };
 
   function checkOurBookmark(bookmark) {
@@ -32,16 +34,83 @@ function backgroundScript() {
       browser.test.assertEq(expected.parentId, bookmark.parentId, "Bookmark has the expected parentId");
     }
   }
 
   function expectedError() {
     browser.test.fail("Did not get expected error");
   }
 
+  function checkOnCreated(id, parentId, index, title, url, dateAdded) {
+    let createdData = collectedEvents.pop();
+    browser.test.assertEq("onCreated", createdData.event, "onCreated was the last event received");
+    browser.test.assertEq(id, createdData.id, "onCreated event received the expected id");
+    let bookmark = createdData.bookmark;
+    browser.test.assertEq(id, bookmark.id, "onCreated event received the expected bookmark id");
+    browser.test.assertEq(parentId, bookmark.parentId, "onCreated event received the expected bookmark parentId");
+    browser.test.assertEq(index, bookmark.index, "onCreated event received the expected bookmark index");
+    browser.test.assertEq(title, bookmark.title, "onCreated event received the expected bookmark title");
+    browser.test.assertEq(url, bookmark.url, "onCreated event received the expected bookmark url");
+    browser.test.assertEq(dateAdded, bookmark.dateAdded, "onCreated event received the expected bookmark dateAdded");
+  }
+
+  function checkOnChanged(id, url, title) {
+    // If both url and title are changed, then url is fired last.
+    let changedData = collectedEvents.pop();
+    browser.test.assertEq("onChanged", changedData.event, "onChanged was the last event received");
+    browser.test.assertEq(id, changedData.id, "onChanged event received the expected id");
+    browser.test.assertEq(url, changedData.info.url, "onChanged event received the expected url");
+    // title is fired first.
+    changedData = collectedEvents.pop();
+    browser.test.assertEq("onChanged", changedData.event, "onChanged was the last event received");
+    browser.test.assertEq(id, changedData.id, "onChanged event received the expected id");
+    browser.test.assertEq(title, changedData.info.title, "onChanged event received the expected title");
+  }
+
+  function checkOnMoved(id, parentId, oldParentId, index, oldIndex) {
+    let movedData = collectedEvents.pop();
+    browser.test.assertEq("onMoved", movedData.event, "onMoved was the last event received");
+    browser.test.assertEq(id, movedData.id, "onMoved event received the expected id");
+    let info = movedData.info;
+    browser.test.assertEq(parentId, info.parentId, "onMoved event received the expected parentId");
+    browser.test.assertEq(oldParentId, info.oldParentId, "onMoved event received the expected oldParentId");
+    browser.test.assertEq(index, info.index, "onMoved event received the expected index");
+    browser.test.assertEq(oldIndex, info.oldIndex, "onMoved event received the expected oldIndex");
+  }
+
+  function checkOnRemoved(id, parentId, index, url) {
+    let removedData = collectedEvents.pop();
+    browser.test.assertEq("onRemoved", removedData.event, "onRemoved was the last event received");
+    browser.test.assertEq(id, removedData.id, "onRemoved event received the expected id");
+    let info = removedData.info;
+    browser.test.assertEq(parentId, removedData.info.parentId, "onRemoved event received the expected parentId");
+    browser.test.assertEq(index, removedData.info.index, "onRemoved event received the expected index");
+    let node = info.node;
+    browser.test.assertEq(id, node.id, "onRemoved event received the expected node id");
+    browser.test.assertEq(parentId, node.parentId, "onRemoved event received the expected node parentId");
+    browser.test.assertEq(index, node.index, "onRemoved event received the expected node index");
+    browser.test.assertEq(url, node.url, "onRemoved event received the expected node url");
+  }
+
+  browser.bookmarks.onChanged.addListener((id, info) => {
+    collectedEvents.push({event: "onChanged", id, info});
+  });
+
+  browser.bookmarks.onCreated.addListener((id, bookmark) => {
+    collectedEvents.push({event: "onCreated", id, bookmark});
+  });
+
+  browser.bookmarks.onMoved.addListener((id, info) => {
+    collectedEvents.push({event: "onMoved", id, info});
+  });
+
+  browser.bookmarks.onRemoved.addListener((id, info) => {
+    collectedEvents.push({event: "onRemoved", id, info});
+  });
+
   browser.bookmarks.get(["not-a-bookmark-guid"]).then(expectedError, error => {
     browser.test.assertTrue(
       error.message.includes("Invalid value for property 'guid': not-a-bookmark-guid"),
       "Expected error thrown when trying to get a bookmark using an invalid guid"
     );
 
     return browser.bookmarks.get([nonExistentId]).then(expectedError, error => {
       browser.test.assertTrue(
@@ -52,16 +121,18 @@ function backgroundScript() {
   }).then(() => {
     return browser.bookmarks.search({});
   }).then(results => {
     initialBookmarkCount = results.length;
     return browser.bookmarks.create({title: "test bookmark", url: "http://example.org"});
   }).then(result => {
     ourId = result.id;
     checkOurBookmark(result);
+    browser.test.assertEq(1, collectedEvents.length, "1 expected event received");
+    checkOnCreated(ourId, bookmarkGuids.unfiledGuid, 0, "test bookmark", "http://example.org/", result.dateAdded);
 
     return browser.bookmarks.get(ourId);
   }).then(results => {
     browser.test.assertEq(results.length, 1);
     checkOurBookmark(results[0]);
 
     unsortedId = results[0].parentId;
     return browser.bookmarks.get(unsortedId);
@@ -91,16 +162,19 @@ function backgroundScript() {
 
       return browser.bookmarks.update(ourId, {title: "new test title", url: "http://example.com/"});
     });
   }).then(result => {
     browser.test.assertEq("new test title", result.title, "Updated bookmark has the expected title");
     browser.test.assertEq("http://example.com/", result.url, "Updated bookmark has the expected URL");
     browser.test.assertEq(ourId, result.id, "Updated bookmark has the expected id");
 
+    browser.test.assertEq(2, collectedEvents.length, "2 expected events received");
+    checkOnChanged(ourId, "http://example.com/", "new test title");
+
     return Promise.resolve().then(() => {
       return browser.bookmarks.update(ourId, {url: "this is not a valid url"});
     }).then(expectedError, error => {
       browser.test.assertTrue(
         error.message.includes("Invalid bookmark:"),
         "Expected error thrown when trying update with an invalid url"
       );
       return browser.bookmarks.getTree();
@@ -124,58 +198,78 @@ function backgroundScript() {
           "Expected error thrown when trying to create a bookmark with an invalid parentId"
       );
     });
   }).then(() => {
     return browser.bookmarks.remove(ourId);
   }).then(result => {
     browser.test.assertEq(undefined, result, "Removing a bookmark returns undefined");
 
+    browser.test.assertEq(1, collectedEvents.length, "1 expected events received");
+    checkOnRemoved(ourId, bookmarkGuids.unfiledGuid, 0, "http://example.com/");
+
     return browser.bookmarks.get(ourId).then(expectedError, error => {
       browser.test.assertTrue(
         error.message.includes("Bookmark not found"),
         "Expected error thrown when trying to get a removed bookmark"
       );
     });
   }).then(() => {
     return browser.bookmarks.remove(nonExistentId).then(expectedError, error => {
       browser.test.assertTrue(
         error.message.includes("No bookmarks found for the provided GUID"),
         "Expected error thrown when trying removed a non-existent bookmark"
       );
     });
   }).then(() => {
     // test bookmarks.search
     return Promise.all([
-      browser.bookmarks.create({title: "MØzillä", url: "http://møzîllä.örg"}),
-      browser.bookmarks.create({title: "Example", url: "http://example.org"}),
+      browser.bookmarks.create({title: "MØzillä", url: "http://møzîllä.örg/"}),
+      browser.bookmarks.create({title: "Example", url: "http://example.org/"}),
       browser.bookmarks.create({title: "Mozilla Folder"}),
-      browser.bookmarks.create({title: "EFF", url: "http://eff.org"}),
-      browser.bookmarks.create({title: "Menu Item", url: "http://menu.org", parentId: bookmarkGuids.menuGuid}),
-      browser.bookmarks.create({title: "Toolbar Item", url: "http://toolbar.org", parentId: bookmarkGuids.toolbarGuid}),
+      browser.bookmarks.create({title: "EFF", url: "http://eff.org/"}),
+      browser.bookmarks.create({title: "Menu Item", url: "http://menu.org/", parentId: bookmarkGuids.menuGuid}),
+      browser.bookmarks.create({title: "Toolbar Item", url: "http://toolbar.org/", parentId: bookmarkGuids.toolbarGuid}),
     ]);
   }).then(results => {
+    browser.test.assertEq(6, collectedEvents.length, "6 expected events received");
+    checkOnCreated(results[5].id, bookmarkGuids.toolbarGuid, 0, "Toolbar Item", "http://toolbar.org/", results[5].dateAdded);
+    checkOnCreated(results[4].id, bookmarkGuids.menuGuid, 0, "Menu Item", "http://menu.org/", results[4].dateAdded);
+    checkOnCreated(results[3].id, bookmarkGuids.unfiledGuid, 0, "EFF", "http://eff.org/", results[3].dateAdded);
+    checkOnCreated(results[2].id, bookmarkGuids.unfiledGuid, 0, "Mozilla Folder", undefined, results[2].dateAdded);
+    checkOnCreated(results[1].id, bookmarkGuids.unfiledGuid, 0, "Example", "http://example.org/", results[1].dateAdded);
+    checkOnCreated(results[0].id, bookmarkGuids.unfiledGuid, 0, "MØzillä", "http://møzîllä.örg/", results[0].dateAdded);
+
     for (let result of results) {
       if (result.title !== "Mozilla Folder") {
         createdBookmarks.add(result.id);
       }
     }
-    let createdFolderId = results[2].id;
+    let folderResult = results[2];
+    createdFolderId = folderResult.id;
     return Promise.all([
-      browser.bookmarks.create({title: "Mozilla", url: "http://allizom.org", parentId: createdFolderId}),
-      browser.bookmarks.create({title: "Mozilla Corporation", url: "http://allizom.com", parentId: createdFolderId}),
-      browser.bookmarks.create({title: "Firefox", url: "http://allizom.org/firefox", parentId: createdFolderId}),
+      browser.bookmarks.create({title: "Mozilla", url: "http://allizom.org/", parentId: createdFolderId}),
+      browser.bookmarks.create({title: "Mozilla Corporation", url: "http://allizom.com/", parentId: createdFolderId}),
+      browser.bookmarks.create({title: "Firefox", url: "http://allizom.org/firefox/", parentId: createdFolderId}),
     ]).then(results => {
+      browser.test.assertEq(3, collectedEvents.length, "3 expected events received");
+      checkOnCreated(results[2].id, createdFolderId, 0, "Firefox", "http://allizom.org/firefox/", results[2].dateAdded);
+      checkOnCreated(results[1].id, createdFolderId, 0, "Mozilla Corporation", "http://allizom.com/", results[1].dateAdded);
+      checkOnCreated(results[0].id, createdFolderId, 0, "Mozilla", "http://allizom.org/", results[0].dateAdded);
+
       return browser.bookmarks.create({
         title: "About Mozilla",
-        url: "http://allizom.org/about",
+        url: "http://allizom.org/about/",
         parentId: createdFolderId,
         index: 1,
       });
-    }).then(() => {
+    }).then(result => {
+      browser.test.assertEq(1, collectedEvents.length, "1 expected events received");
+      checkOnCreated(result.id, createdFolderId, 1, "About Mozilla", "http://allizom.org/about/", result.dateAdded);
+
       // returns all items on empty object
       return browser.bookmarks.search({});
     }).then(results => {
       browser.test.assertTrue(results.length >= 9, "At least as many bookmarks as added were returned by search({})");
 
       return Promise.resolve().then(() => {
         return browser.bookmarks.remove(createdFolderId);
       }).then(expectedError, error => {
@@ -370,30 +464,43 @@ function backgroundScript() {
     let corporationBookmark = results[0][0];
     let childCount = results[1].length;
 
     browser.test.assertEq(2, corporationBookmark.index, "Bookmark has the expected index");
 
     return browser.bookmarks.move(corporationBookmark.id, {index: 0}).then(result => {
       browser.test.assertEq(0, result.index, "Bookmark has the expected index");
 
+      browser.test.assertEq(1, collectedEvents.length, "1 expected events received");
+      checkOnMoved(corporationBookmark.id, createdFolderId, createdFolderId, 0, 2);
+
       return browser.bookmarks.move(corporationBookmark.id, {parentId: bookmarkGuids.menuGuid});
     }).then(result => {
       browser.test.assertEq(bookmarkGuids.menuGuid, result.parentId, "Bookmark has the expected parent");
       browser.test.assertEq(childCount, result.index, "Bookmark has the expected index");
 
-      return browser.bookmarks.move(corporationBookmark.id, {index: 1});
+      browser.test.assertEq(1, collectedEvents.length, "1 expected events received");
+      checkOnMoved(corporationBookmark.id, bookmarkGuids.menuGuid, createdFolderId, 1, 0);
+
+      return browser.bookmarks.move(corporationBookmark.id, {index: 0});
     }).then(result => {
       browser.test.assertEq(bookmarkGuids.menuGuid, result.parentId, "Bookmark has the expected parent");
-      browser.test.assertEq(1, result.index, "Bookmark has the expected index");
+      browser.test.assertEq(0, result.index, "Bookmark has the expected index");
+
+      browser.test.assertEq(1, collectedEvents.length, "1 expected events received");
+      checkOnMoved(corporationBookmark.id, bookmarkGuids.menuGuid, bookmarkGuids.menuGuid, 0, 1);
 
       return browser.bookmarks.move(corporationBookmark.id, {parentId: bookmarkGuids.toolbarGuid, index: 1});
     }).then(result => {
       browser.test.assertEq(bookmarkGuids.toolbarGuid, result.parentId, "Bookmark has the expected parent");
       browser.test.assertEq(1, result.index, "Bookmark has the expected index");
+
+      browser.test.assertEq(1, collectedEvents.length, "1 expected events received");
+      checkOnMoved(corporationBookmark.id, bookmarkGuids.toolbarGuid, bookmarkGuids.menuGuid, 1, 0);
+
       createdBookmarks.add(corporationBookmark.id);
     });
   }).then(() => {
     return browser.bookmarks.getRecent(4);
   }).then(results => {
     browser.test.assertEq(4, results.length, "Expected number of results returned by getRecent");
     let prevDate = results[0].dateAdded;
     for (let bookmark of results) {
@@ -410,29 +517,39 @@ function backgroundScript() {
 
     return browser.bookmarks.search({});
   }).then(results => {
     let startBookmarkCount = results.length;
 
     return browser.bookmarks.search({title: "Mozilla Folder"}).then(result => {
       return browser.bookmarks.removeTree(result[0].id);
     }).then(() => {
+      browser.test.assertEq(1, collectedEvents.length, "1 expected events received");
+      checkOnRemoved(createdFolderId, bookmarkGuids.unfiledGuid, 1);
+
       return browser.bookmarks.search({}).then(results => {
         browser.test.assertEq(
           startBookmarkCount - 4,
           results.length,
           "Expected number of results returned after removeTree");
       });
     });
   }).then(() => {
     return browser.bookmarks.create({title: "Empty Folder"});
   }).then(result => {
     let emptyFolderId = result.id;
+
+    browser.test.assertEq(1, collectedEvents.length, "1 expected events received");
+    checkOnCreated(emptyFolderId, bookmarkGuids.unfiledGuid, 3, "Empty Folder", undefined, result.dateAdded);
+
     browser.test.assertEq("Empty Folder", result.title, "Folder has the expected title");
     return browser.bookmarks.remove(emptyFolderId).then(() => {
+      browser.test.assertEq(1, collectedEvents.length, "1 expected events received");
+      checkOnRemoved(emptyFolderId, bookmarkGuids.unfiledGuid, 3);
+
       return browser.bookmarks.get(emptyFolderId).then(expectedError, error => {
         browser.test.assertTrue(
           error.message.includes("Bookmark not found"),
           "Expected error thrown when trying to get a removed folder"
         );
       });
     });
   }).then(() => {
@@ -451,19 +568,22 @@ function backgroundScript() {
         "Expected error thrown when calling move with a non-existent bookmark"
       );
     });
   }).then(() => {
     // remove all created bookmarks
     let promises = Array.from(createdBookmarks, guid => browser.bookmarks.remove(guid));
     return Promise.all(promises);
   }).then(() => {
+    browser.test.assertEq(createdBookmarks.size, collectedEvents.length, "expected number of events received");
+
     return browser.bookmarks.search({});
   }).then(results => {
     browser.test.assertEq(initialBookmarkCount, results.length, "All created bookmarks have been removed");
+
     return browser.test.notifyPass("bookmarks");
   }).catch(error => {
     browser.test.fail(`Error: ${String(error)} :: ${error.stack}`);
     browser.test.notifyFail("bookmarks");
   });
 }
 
 let extensionData = {
--- a/browser/components/search/test/browser_oneOffContextMenu.js
+++ b/browser/components/search/test/browser_oneOffContextMenu.js
@@ -65,16 +65,22 @@ function* doTest() {
   });
   yield promise;
 
   // Click the Search in New Tab menu item.
   promise = BrowserTestUtils.waitForNewTab(gBrowser);
   EventUtils.synthesizeMouseAtCenter(searchInNewTabMenuItem, {});
   let tab = yield promise;
 
+  // By default the search will open in the background and the popup will stay open:
+  promise = promiseEvent(searchPopup, "popuphidden");
+  info("Closing search panel");
+  EventUtils.synthesizeKey("VK_ESCAPE", {});
+  yield promise;
+
   // Check the loaded tab.
   Assert.equal(tab.linkedBrowser.currentURI.spec,
                "http://mochi.test:8888/browser/browser/components/search/test/",
                "Expected search tab should have loaded");
 
   yield BrowserTestUtils.removeTab(tab);
 
   // Move the cursor out of the panel area to avoid messing with other tests.
new file mode 100644
--- /dev/null
+++ b/browser/extensions/formautofill/content/FormAutofillParent.jsm
@@ -0,0 +1,173 @@
+/* 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/. */
+
+/*
+ * Implements a service used to access storage and communicate with content.
+ *
+ * A "fields" array is used to communicate with FormAutofillContent. Each item
+ * represents a single input field in the content page as well as its
+ * @autocomplete properties. The schema is as below. Please refer to
+ * FormAutofillContent.jsm for more details.
+ *
+ * [
+ *   {
+ *     section,
+ *     addressType,
+ *     contactType,
+ *     fieldName,
+ *     value,
+ *     index
+ *   },
+ *   {
+ *     // ...
+ *   }
+ * ]
+ */
+
+/* exported FormAutofillParent */
+
+"use strict";
+
+const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
+
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+
+XPCOMUtils.defineLazyModuleGetter(this, "OS",
+                                  "resource://gre/modules/osfile.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "ProfileStorage",
+                                  "resource://formautofill/ProfileStorage.jsm");
+
+const PROFILE_JSON_FILE_NAME = "autofill-profiles.json";
+
+let FormAutofillParent = {
+  _profileStore: null,
+
+  /**
+   * Initializes ProfileStorage and registers the message handler.
+   */
+  init: function() {
+    let storePath =
+      OS.Path.join(OS.Constants.Path.profileDir, PROFILE_JSON_FILE_NAME);
+
+    this._profileStore = new ProfileStorage(storePath);
+    this._profileStore.initialize();
+
+    let mm = Cc["@mozilla.org/globalmessagemanager;1"]
+               .getService(Ci.nsIMessageListenerManager);
+    mm.addMessageListener("FormAutofill:PopulateFieldValues", this);
+  },
+
+  /**
+   * Handles the message coming from FormAutofillContent.
+   *
+   * @param   {string} message.name The name of the message.
+   * @param   {object} message.data The data of the message.
+   * @param   {nsIFrameMessageManager} message.target Caller's message manager.
+   */
+  receiveMessage: function({name, data, target}) {
+    switch (name) {
+      case "FormAutofill:PopulateFieldValues":
+        this._populateFieldValues(data, target);
+        break;
+    }
+  },
+
+  /**
+   * Returns the instance of ProfileStorage. To avoid syncing issues, anyone
+   * who needs to access the profile should request the instance by this instead
+   * of creating a new one.
+   *
+   * @returns {ProfileStorage}
+   */
+  getProfileStore: function() {
+    return this._profileStore;
+  },
+
+  /**
+   * Uninitializes FormAutofillParent. This is for testing only.
+   *
+   * @private
+   */
+  _uninit: function() {
+    if (this._profileStore) {
+      this._profileStore._saveImmediately();
+      this._profileStore = null;
+    }
+
+    let mm = Cc["@mozilla.org/globalmessagemanager;1"]
+               .getService(Ci.nsIMessageListenerManager);
+    mm.removeMessageListener("FormAutofill:PopulateFieldValues", this);
+  },
+
+  /**
+   * Populates the field values and notifies content to fill in. Exception will
+   * be thrown if there's no matching profile.
+   *
+   * @private
+   * @param  {string} data.guid
+   *         Indicates which profile to populate
+   * @param  {Fields} data.fields
+   *         The "fields" array collected from content.
+   * @param  {nsIFrameMessageManager} target
+   *         Content's message manager.
+   */
+  _populateFieldValues({guid, fields}, target) {
+    this._profileStore.notifyUsed(guid);
+    this._fillInFields(this._profileStore.get(guid), fields);
+    target.sendAsyncMessage("FormAutofill:fillForm", {fields});
+  },
+
+  /**
+   * Transforms a word with hyphen into camel case.
+   * (e.g. transforms "address-type" into "addressType".)
+   *
+   * @private
+   * @param   {string} str The original string with hyphen.
+   * @returns {string} The camel-cased output string.
+   */
+  _camelCase(str) {
+    return str.toLowerCase().replace(/-([a-z])/g, s => s[1].toUpperCase());
+  },
+
+  /**
+   * Get the corresponding value from the specified profile according to a valid
+   * @autocomplete field name.
+   *
+   * Note that the field name doesn't need to match the property name defined in
+   * Profile object. This method can transform the raw data to fulfill it. (e.g.
+   * inputting "country-name" as "fieldName" will get a full name transformed
+   * from the country code that is recorded in "country" field.)
+   *
+   * @private
+   * @param   {Profile} profile   The specified profile.
+   * @param   {string}  fieldName A valid @autocomplete field name.
+   * @returns {string}  The corresponding value. Returns "undefined" if there's
+   *                    no matching field.
+   */
+  _getDataByFieldName(profile, fieldName) {
+    let key = this._camelCase(fieldName);
+
+    // TODO: Transform the raw profile data to fulfill "fieldName" here.
+
+    return profile[key];
+  },
+
+  /**
+   * Fills in the "fields" array by the specified profile.
+   *
+   * @private
+   * @param   {Profile} profile The specified profile to fill in.
+   * @param   {Fields}  fields  The "fields" array collected from content.
+   */
+  _fillInFields(profile, fields) {
+    for (let field of fields) {
+      let value = this._getDataByFieldName(profile, field.fieldName);
+      if (value !== undefined) {
+        field.value = value;
+      }
+    }
+  },
+};
+
+this.EXPORTED_SYMBOLS = ["FormAutofillParent"];
--- a/browser/extensions/formautofill/test/unit/head.js
+++ b/browser/extensions/formautofill/test/unit/head.js
@@ -7,16 +7,26 @@
 "use strict";
 
 const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://testing-common/MockDocument.jsm");
 
+// Redirect the path of the resouce in addon to the exact file path.
+let defineLazyModuleGetter = XPCOMUtils.defineLazyModuleGetter;
+XPCOMUtils.defineLazyModuleGetter = function() {
+  let result = /^resource\:\/\/formautofill\/(.+)$/.exec(arguments[2]);
+  if (result) {
+    arguments[2] = Services.io.newFileURI(do_get_file(result[1])).spec;
+  }
+  return defineLazyModuleGetter.apply(this, arguments);
+};
+
 // Load the module by Service newFileURI API for running extension's XPCShell test
 function importAutofillModule(module) {
   return Cu.import(Services.io.newFileURI(do_get_file(module)).spec);
 }
 
 XPCOMUtils.defineLazyModuleGetter(this, "DownloadPaths",
                                   "resource://gre/modules/DownloadPaths.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "FileUtils",
new file mode 100644
--- /dev/null
+++ b/browser/extensions/formautofill/test/unit/test_populateFieldValues.js
@@ -0,0 +1,106 @@
+/*
+ * Test for populating field values in Form Autofill Parent.
+ */
+
+/* global FormAutofillParent */
+
+"use strict";
+
+importAutofillModule("FormAutofillParent.jsm");
+
+do_get_profile();
+
+const TEST_FIELDS = [
+  {"section": "", "addressType": "shipping", "contactType": "", "fieldName": "organization"},
+  {"section": "", "addressType": "shipping", "contactType": "", "fieldName": "street-address"},
+  {"section": "", "addressType": "shipping", "contactType": "", "fieldName": "address-level2"},
+  {"section": "", "addressType": "shipping", "contactType": "", "fieldName": "address-level1"},
+  {"section": "", "addressType": "shipping", "contactType": "", "fieldName": "postal-code"},
+  {"section": "", "addressType": "shipping", "contactType": "", "fieldName": "country"},
+  {"section": "", "addressType": "shipping", "contactType": "", "fieldName": "tel"},
+  {"section": "", "addressType": "shipping", "contactType": "", "fieldName": "email"},
+];
+
+const TEST_GUID = "test-guid";
+
+const TEST_PROFILE = {
+  guid: TEST_GUID,
+  organization: "World Wide Web Consortium",
+  streetAddress: "32 Vassar Street\nMIT Room 32-G524",
+  addressLevel2: "Cambridge",
+  addressLevel1: "MA",
+  postalCode: "02139",
+  country: "US",
+  tel: "+1 617 253 5702",
+  email: "timbl@w3.org",
+};
+
+function camelCase(str) {
+  return str.toLowerCase().replace(/-([a-z])/g, s => s[1].toUpperCase());
+}
+
+add_task(function* test_populateFieldValues() {
+  FormAutofillParent.init();
+
+  let store = FormAutofillParent.getProfileStore();
+  do_check_neq(store, null);
+
+  store.get = function(guid) {
+    do_check_eq(guid, TEST_GUID);
+    return store._clone(TEST_PROFILE);
+  };
+
+  let notifyUsedCalledCount = 0;
+  store.notifyUsed = function(guid) {
+    do_check_eq(guid, TEST_GUID);
+    notifyUsedCalledCount++;
+  };
+
+  yield new Promise((resolve) => {
+    FormAutofillParent.receiveMessage({
+      name: "FormAutofill:PopulateFieldValues",
+      data: {
+        guid: TEST_GUID,
+        fields: TEST_FIELDS,
+      },
+      target: {
+        sendAsyncMessage: function(name, data) {
+          do_check_eq(name, "FormAutofill:fillForm");
+
+          let fields = data.fields;
+          do_check_eq(fields.length, TEST_FIELDS.length);
+
+          for (let i = 0; i < fields.length; i++) {
+            do_check_eq(fields[i].fieldName, TEST_FIELDS[i].fieldName);
+            do_check_eq(fields[i].value,
+              TEST_PROFILE[camelCase(fields[i].fieldName)]);
+          }
+
+          resolve();
+        },
+      },
+    });
+  });
+
+  do_check_eq(notifyUsedCalledCount, 1);
+
+  FormAutofillParent._uninit();
+  do_check_null(FormAutofillParent.getProfileStore());
+});
+
+add_task(function* test_populateFieldValues_with_invalid_guid() {
+  FormAutofillParent.init();
+
+  Assert.throws(() => {
+    FormAutofillParent.receiveMessage({
+      name: "FormAutofill:PopulateFieldValues",
+      data: {
+        guid: "invalid-guid",
+        fields: TEST_FIELDS,
+      },
+      target: {},
+    });
+  }, /No matching profile\./);
+
+  FormAutofillParent._uninit();
+});
--- a/browser/extensions/formautofill/test/unit/xpcshell.ini
+++ b/browser/extensions/formautofill/test/unit/xpcshell.ini
@@ -1,10 +1,12 @@
 [DEFAULT]
 head = head.js
 tail =
 support-files =
   ../../content/FormAutofillContent.jsm
+  ../../content/FormAutofillParent.jsm
   ../../content/ProfileStorage.jsm
 
 [test_autofillFormFields.js]
 [test_collectFormFields.js]
+[test_populateFieldValues.js]
 [test_profileStorage.js]
--- a/browser/installer/allowed-dupes.mn
+++ b/browser/installer/allowed-dupes.mn
@@ -215,8 +215,12 @@ modules/commonjs/sdk/ui/button/view/even
 modules/commonjs/sdk/ui/state/events.js
 plugin-container.app/Contents/PkgInfo
 res/table-remove-column-active.gif
 res/table-remove-column-hover.gif
 res/table-remove-column.gif
 res/table-remove-row-active.gif
 res/table-remove-row-hover.gif
 res/table-remove-row.gif
+# Aurora branding
+browser/chrome/browser/content/browser/defaultthemes/devedition.icon.png
+browser/chrome/browser/content/branding/icon64.png
+browser/chrome/devtools/content/framework/dev-edition-promo/dev-edition-logo.png
--- a/config/recurse.mk
+++ b/config/recurse.mk
@@ -167,14 +167,14 @@ endif
 ifdef MOZ_LDAP_XPCOM
 ldap/target: config/external/nss/target mozglue/build/target
 toolkit/library/target: ldap/target
 endif
 ifeq ($(MOZ_REPLACE_MALLOC_LINKAGE),dummy library)
 mozglue/build/target memory/replace/logalloc/replay/target: memory/replace/dummy/target
 endif
 endif
-ifeq (,$(MOZ_SYSTEM_NSS)$(MOZ_FOLD_LIBS))
+ifeq (,$(MOZ_SYSTEM_NSPR)$(MOZ_SYSTEM_NSS)$(MOZ_FOLD_LIBS))
 config/external/nss/target: config/external/nspr/pr/target config/external/nspr/ds/target config/external/nspr/libc/target
 endif
 # Most things are built during compile (target/host), but some things happen during export
 # Those need to depend on config/export for system wrappers.
 $(addprefix build/unix/stdc++compat/,target host) build/clang-plugin/target: config/export
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -916,16 +916,25 @@ endif
 ifdef MOZ_CARGO_SUPPORTS_FROZEN
 cargo_build_flags += --frozen
 endif
 
 cargo_build_flags += --manifest-path $(CARGO_FILE)
 cargo_build_flags += --target=$(RUST_TARGET)
 cargo_build_flags += --verbose
 
+# Enable color output if original stdout was a TTY and color settings
+# aren't already present. This essentially restores the default behavior
+# of cargo when running via `mach`.
+ifdef MACH_STDOUT_ISATTY
+ifeq (,$(findstring --color,$(cargo_build_flags)))
+cargo_build_flags += --color=always
+endif
+endif
+
 # Assume any system libraries rustc links against are already in the target's LIBS.
 #
 # We need to run cargo unconditionally, because cargo is the only thing that
 # has full visibility into how changes in Rust sources might affect the final
 # build.
 force-cargo-build:
 	$(REPORT_BUILD)
 	env CARGO_TARGET_DIR=. RUSTC=$(RUSTC) $(CARGO) build $(cargo_build_flags) --
--- a/devtools/client/shared/components/reps/grip-array.js
+++ b/devtools/client/shared/components/reps/grip-array.js
@@ -25,70 +25,83 @@ define(function (require, exports, modul
 
     propTypes: {
       object: React.PropTypes.object.isRequired,
       mode: React.PropTypes.string,
       provider: React.PropTypes.object,
     },
 
     getLength: function (grip) {
-      return grip.preview ? grip.preview.length : 0;
+      if (!grip.preview) {
+        return 0;
+      }
+
+      return grip.preview.length || grip.preview.childNodesLength || 0;
     },
 
     getTitle: function (object, context) {
       let objectLink = this.props.objectLink || span;
       if (this.props.mode != "tiny") {
         return objectLink({
           object: object
         }, object.class + " ");
       }
       return "";
     },
 
+    getPreviewItems: function (grip) {
+      if (!grip.preview) {
+        return null;
+      }
+
+      return grip.preview.items || grip.preview.childNodes || null;
+    },
+
     arrayIterator: function (grip, max) {
       let items = [];
+      const gripLength = this.getLength(grip);
 
-      if (!grip.preview || !grip.preview.length) {
+      if (!gripLength) {
         return items;
       }
 
-      let array = grip.preview.items;
-      if (!array) {
+      const previewItems = this.getPreviewItems(grip);
+      if (!previewItems) {
         return items;
       }
 
       let delim;
-      // number of grip.preview.items is limited to 10, but we may have more
-      // items in grip-array
-      let delimMax = grip.preview.length > array.length ?
-        array.length : array.length - 1;
+      // number of grip preview items is limited to 10, but we may have more
+      // items in grip-array.
+      let delimMax = gripLength > previewItems.length ?
+        previewItems.length : previewItems.length - 1;
       let provider = this.props.provider;
 
-      for (let i = 0; i < array.length && i < max; i++) {
+      for (let i = 0; i < previewItems.length && i < max; i++) {
         try {
-          let itemGrip = array[i];
+          let itemGrip = previewItems[i];
           let value = provider ? provider.getValue(itemGrip) : itemGrip;
 
           delim = (i == delimMax ? "" : ", ");
 
           items.push(GripArrayItem(Object.assign({}, this.props, {
             object: value,
             delim: delim
           })));
         } catch (exc) {
           items.push(GripArrayItem(Object.assign({}, this.props, {
             object: exc,
             delim: delim
           })));
         }
       }
-      if (array.length > max || grip.preview.length > array.length) {
+      if (previewItems.length > max || gripLength > previewItems.length) {
         let objectLink = this.props.objectLink || span;
-        let leftItemNum = grip.preview.length - max > 0 ?
-          grip.preview.length - max : grip.preview.length - array.length;
+        let leftItemNum = gripLength - max > 0 ?
+          gripLength - max : gripLength - previewItems.length;
         items.push(Caption({
           object: objectLink({
             object: this.props.object
           }, leftItemNum + " more…")
         }));
       }
 
       return items;
@@ -165,17 +178,21 @@ define(function (require, exports, modul
     }
   }));
 
   function supportsObject(grip, type) {
     if (!isGrip(grip)) {
       return false;
     }
 
-    return (grip.preview && grip.preview.kind == "ArrayLike");
+    return (grip.preview && (
+        grip.preview.kind == "ArrayLike" ||
+        type === "DocumentFragment"
+      )
+    );
   }
 
   // Exports from this module
   exports.GripArray = {
     rep: GripArray,
     supportsObject: supportsObject
   };
 });
--- a/devtools/client/shared/components/test/mochitest/test_reps_grip-array.html
+++ b/devtools/client/shared/components/test/mochitest/test_reps_grip-array.html
@@ -32,16 +32,17 @@ window.onload = Task.async(function* () 
     // Test property iterator
     yield testMaxProps();
     yield testMoreThanShortMaxProps();
     yield testMoreThanLongMaxProps();
     yield testRecursiveArray();
     yield testPreviewLimit();
     yield testNamedNodeMap();
     yield testNodeList();
+    yield testDocumentFragment();
   } catch(e) {
     ok(false, "Got an error: " + DevToolsUtils.safeErrorString(e));
   } finally {
     SimpleTest.finish();
   }
 
   function testBasic() {
     // Test array: `[]`
@@ -267,16 +268,48 @@ window.onload = Task.async(function* () 
         mode: "long",
         expectedOutput: defaultOutput,
       }
     ];
 
     testRepRenderModes(modeTests, testName, componentUnderTest, getGripStub(testName));
   }
 
+  function testDocumentFragment() {
+    const testName = "testDocumentFragment";
+
+    const defaultOutput = "DocumentFragment [ li#li-0.list-element, " +
+      "li#li-1.list-element, li#li-2.list-element, 2 more… ]";
+
+    const longOutput = "DocumentFragment [ " +
+      "li#li-0.list-element, li#li-1.list-element, li#li-2.list-element, " +
+      "li#li-3.list-element, li#li-4.list-element ]";
+
+    const modeTests = [
+      {
+        mode: undefined,
+        expectedOutput: defaultOutput,
+      },
+      {
+        mode: "tiny",
+        expectedOutput: `[5]`,
+      },
+      {
+        mode: "short",
+        expectedOutput: defaultOutput,
+      },
+      {
+        mode: "long",
+        expectedOutput: longOutput,
+      }
+    ];
+
+    testRepRenderModes(modeTests, testName, componentUnderTest, getGripStub(testName));
+  }
+
   function getGripStub(functionName) {
     switch (functionName) {
       case "testBasic":
         return {
           "type": "object",
           "class": "Array",
           "actor": "server1.conn0.obj35",
           "extensible": true,
@@ -407,77 +440,78 @@ window.onload = Task.async(function* () 
                   "kind": "ArrayLike",
                   "length": 1
                 }
               }
             ]
           }
         };
 
-        case "testNamedNodeMap":
-          return {
-            "type": "object",
-            "class": "NamedNodeMap",
-            "actor": "server1.conn3.obj42",
-            "extensible": true,
-            "frozen": false,
-            "sealed": false,
-            "ownPropertyLength": 6,
-            "preview": {
-              "kind": "ArrayLike",
-              "length": 3,
-              "items": [
-                {
-                  "type": "object",
-                  "class": "Attr",
-                  "actor": "server1.conn3.obj43",
-                  "extensible": true,
-                  "frozen": false,
-                  "sealed": false,
-                  "ownPropertyLength": 0,
-                  "preview": {
-                    "kind": "DOMNode",
-                    "nodeType": 2,
-                    "nodeName": "class",
-                    "value": "myclass"
-                  }
-                },
-                {
-                  "type": "object",
-                  "class": "Attr",
-                  "actor": "server1.conn3.obj44",
-                  "extensible": true,
-                  "frozen": false,
-                  "sealed": false,
-                  "ownPropertyLength": 0,
-                  "preview": {
-                    "kind": "DOMNode",
-                    "nodeType": 2,
-                    "nodeName": "cellpadding",
-                    "value": "7"
-                  }
-                },
-                {
-                  "type": "object",
-                  "class": "Attr",
-                  "actor": "server1.conn3.obj44",
-                  "extensible": true,
-                  "frozen": false,
-                  "sealed": false,
-                  "ownPropertyLength": 0,
-                  "preview": {
-                    "kind": "DOMNode",
-                    "nodeType": 2,
-                    "nodeName": "border",
-                    "value": "3"
-                  }
+      case "testNamedNodeMap":
+        return {
+          "type": "object",
+          "class": "NamedNodeMap",
+          "actor": "server1.conn3.obj42",
+          "extensible": true,
+          "frozen": false,
+          "sealed": false,
+          "ownPropertyLength": 6,
+          "preview": {
+            "kind": "ArrayLike",
+            "length": 3,
+            "items": [
+              {
+                "type": "object",
+                "class": "Attr",
+                "actor": "server1.conn3.obj43",
+                "extensible": true,
+                "frozen": false,
+                "sealed": false,
+                "ownPropertyLength": 0,
+                "preview": {
+                  "kind": "DOMNode",
+                  "nodeType": 2,
+                  "nodeName": "class",
+                  "value": "myclass"
                 }
-              ]
-            }
-          };
+              },
+              {
+                "type": "object",
+                "class": "Attr",
+                "actor": "server1.conn3.obj44",
+                "extensible": true,
+                "frozen": false,
+                "sealed": false,
+                "ownPropertyLength": 0,
+                "preview": {
+                  "kind": "DOMNode",
+                  "nodeType": 2,
+                  "nodeName": "cellpadding",
+                  "value": "7"
+                }
+              },
+              {
+                "type": "object",
+                "class": "Attr",
+                "actor": "server1.conn3.obj44",
+                "extensible": true,
+                "frozen": false,
+                "sealed": false,
+                "ownPropertyLength": 0,
+                "preview": {
+                  "kind": "DOMNode",
+                  "nodeType": 2,
+                  "nodeName": "border",
+                  "value": "3"
+                }
+              }
+            ]
+          }
+        };
+
       case "testNodeList":
         return {
           "type": "object",
           "actor": "server1.conn1.child1/obj51",
           "class": "NodeList",
           "extensible": true,
           "frozen": false,
           "sealed": false,
@@ -544,15 +578,130 @@ window.onload = Task.async(function* () 
                     "type": "button"
                   },
                   "attributesLength": 3
                 }
               }
             ]
           }
         };
+
+      case "testDocumentFragment":
+        return {
+          "type": "object",
+          "actor": "server1.conn1.child1/obj45",
+          "class": "DocumentFragment",
+          "extensible": true,
+          "frozen": false,
+          "sealed": false,
+          "ownPropertyLength": 0,
+          "preview": {
+            "kind": "DOMNode",
+            "nodeType": 11,
+            "nodeName": "#document-fragment",
+            "childNodesLength": 5,
+            "childNodes": [
+              {
+                "type": "object",
+                "actor": "server1.conn1.child1/obj46",
+                "class": "HTMLLIElement",
+                "extensible": true,
+                "frozen": false,
+                "sealed": false,
+                "ownPropertyLength": 0,
+                "preview": {
+                  "kind": "DOMNode",
+                  "nodeType": 1,
+                  "nodeName": "li",
+                  "attributes": {
+                    "id": "li-0",
+                    "class": "list-element"
+                  },
+                  "attributesLength": 2
+                }
+              },
+              {
+                "type": "object",
+                "actor": "server1.conn1.child1/obj47",
+                "class": "HTMLLIElement",
+                "extensible": true,
+                "frozen": false,
+                "sealed": false,
+                "ownPropertyLength": 0,
+                "preview": {
+                  "kind": "DOMNode",
+                  "nodeType": 1,
+                  "nodeName": "li",
+                  "attributes": {
+                    "id": "li-1",
+                    "class": "list-element"
+                  },
+                  "attributesLength": 2
+                }
+              },
+              {
+                "type": "object",
+                "actor": "server1.conn1.child1/obj48",
+                "class": "HTMLLIElement",
+                "extensible": true,
+                "frozen": false,
+                "sealed": false,
+                "ownPropertyLength": 0,
+                "preview": {
+                  "kind": "DOMNode",
+                  "nodeType": 1,
+                  "nodeName": "li",
+                  "attributes": {
+                    "id": "li-2",
+                    "class": "list-element"
+                  },
+                  "attributesLength": 2
+                }
+              },
+              {
+                "type": "object",
+                "actor": "server1.conn1.child1/obj49",
+                "class": "HTMLLIElement",
+                "extensible": true,
+                "frozen": false,
+                "sealed": false,
+                "ownPropertyLength": 0,
+                "preview": {
+                  "kind": "DOMNode",
+                  "nodeType": 1,
+                  "nodeName": "li",
+                  "attributes": {
+                    "id": "li-3",
+                    "class": "list-element"
+                  },
+                  "attributesLength": 2
+                }
+              },
+              {
+                "type": "object",
+                "actor": "server1.conn1.child1/obj50",
+                "class": "HTMLLIElement",
+                "extensible": true,
+                "frozen": false,
+                "sealed": false,
+                "ownPropertyLength": 0,
+                "preview": {
+                  "kind": "DOMNode",
+                  "nodeType": 1,
+                  "nodeName": "li",
+                  "attributes": {
+                    "id": "li-4",
+                    "class": "list-element"
+                  },
+                  "attributesLength": 2
+                }
+              }
+            ]
+          }
+        };
     }
+    return null;
   }
 });
 </script>
 </pre>
 </body>
 </html>
--- a/dom/base/nsRange.cpp
+++ b/dom/base/nsRange.cpp
@@ -25,16 +25,17 @@
 #include "nsContentUtils.h"
 #include "nsGenericDOMDataNode.h"
 #include "nsTextFrame.h"
 #include "nsFontFaceList.h"
 #include "mozilla/dom/DocumentFragment.h"
 #include "mozilla/dom/DocumentType.h"
 #include "mozilla/dom/RangeBinding.h"
 #include "mozilla/dom/DOMRect.h"
+#include "mozilla/dom/DOMStringList.h"
 #include "mozilla/dom/ShadowRoot.h"
 #include "mozilla/dom/Selection.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/Likely.h"
 #include "nsCSSFrameConstructor.h"
 #include "nsStyleStruct.h"
 #include "nsStyleStructInlines.h"
 #include "nsComputedDOMStyle.h"
@@ -2892,54 +2893,78 @@ GetTextFrameForContent(nsIContent* aCont
     if (frame && frame->GetType() == nsGkAtoms::textFrame) {
       return static_cast<nsTextFrame*>(frame);
     }
   }
   return nullptr;
 }
 
 static nsresult GetPartialTextRect(nsLayoutUtils::RectCallback* aCallback,
+                                   mozilla::dom::DOMStringList* aTextList,
                                    nsIContent* aContent, int32_t aStartOffset,
                                    int32_t aEndOffset, bool aClampToEdge,
                                    bool aFlushLayout)
 {
   nsTextFrame* textFrame = GetTextFrameForContent(aContent, aFlushLayout);
   if (textFrame) {
+    // If we'll need it later, collect the full content text now.
+    nsAutoString textContent;
+    if (aTextList) {
+      mozilla::ErrorResult err; // ignored
+      aContent->GetTextContent(textContent, err);
+    }
+
     nsIFrame* relativeTo = nsLayoutUtils::GetContainingBlockForClientRect(textFrame);
     for (nsTextFrame* f = textFrame; f; f = static_cast<nsTextFrame*>(f->GetNextContinuation())) {
       int32_t fstart = f->GetContentOffset(), fend = f->GetContentEnd();
       if (fend <= aStartOffset || fstart >= aEndOffset)
         continue;
 
+      // Calculate the text content offsets we'll need if text is requested.
+      int32_t textContentStart = fstart;
+      int32_t textContentEnd = fend;
+
       // overlapping with the offset we want
       f->EnsureTextRun(nsTextFrame::eInflated);
       NS_ENSURE_TRUE(f->GetTextRun(nsTextFrame::eInflated), NS_ERROR_OUT_OF_MEMORY);
       bool rtl = f->GetTextRun(nsTextFrame::eInflated)->IsRightToLeft();
       nsRect r = f->GetRectRelativeToSelf();
       if (fstart < aStartOffset) {
         // aStartOffset is within this frame
         ExtractRectFromOffset(f, aStartOffset, &r, rtl, aClampToEdge);
+        textContentStart = aStartOffset;
       }
       if (fend > aEndOffset) {
         // aEndOffset is in the middle of this frame
         ExtractRectFromOffset(f, aEndOffset, &r, !rtl, aClampToEdge);
+        textContentEnd = aEndOffset;
       }
       r = nsLayoutUtils::TransformFrameRectToAncestor(f, r, relativeTo);
       aCallback->AddRect(r);
+
+      // Finally capture the text, if requested.
+      if (aTextList) {
+        const nsAString& textSubstring =
+          Substring(textContent,
+                    textContentStart,
+                    (textContentEnd - textContentStart));
+        aTextList->Add(textSubstring);
+      }
     }
   }
   return NS_OK;
 }
 
 /* static */ void
-nsRange::CollectClientRects(nsLayoutUtils::RectCallback* aCollector,
-                            nsRange* aRange,
-                            nsINode* aStartParent, int32_t aStartOffset,
-                            nsINode* aEndParent, int32_t aEndOffset,
-                            bool aClampToEdge, bool aFlushLayout)
+nsRange::CollectClientRectsAndText(nsLayoutUtils::RectCallback* aCollector,
+                                   mozilla::dom::DOMStringList* aTextList,
+                                   nsRange* aRange,
+                                   nsINode* aStartParent, int32_t aStartOffset,
+                                   nsINode* aEndParent, int32_t aEndOffset,
+                                   bool aClampToEdge, bool aFlushLayout)
 {
   // Hold strong pointers across the flush
   nsCOMPtr<nsINode> startContainer = aStartParent;
   nsCOMPtr<nsINode> endContainer = aEndParent;
 
   // Flush out layout so our frames are up to date.
   if (!aStartParent->IsInUncomposedDoc()) {
     return;
@@ -2987,30 +3012,31 @@ nsRange::CollectClientRects(nsLayoutUtil
     iter.Next();
     nsCOMPtr<nsIContent> content = do_QueryInterface(node);
     if (!content)
       continue;
     if (content->IsNodeOfType(nsINode::eTEXT)) {
        if (node == startContainer) {
          int32_t offset = startContainer == endContainer ?
            aEndOffset : content->GetText()->GetLength();
-         GetPartialTextRect(aCollector, content, aStartOffset, offset,
+         GetPartialTextRect(aCollector, aTextList, content, aStartOffset, offset,
                             aClampToEdge, aFlushLayout);
          continue;
        } else if (node == endContainer) {
-         GetPartialTextRect(aCollector, content, 0, aEndOffset,
+         GetPartialTextRect(aCollector, aTextList, content, 0, aEndOffset,
                             aClampToEdge, aFlushLayout);
          continue;
        }
     }
 
     nsIFrame* frame = content->GetPrimaryFrame();
     if (frame) {
-      nsLayoutUtils::GetAllInFlowRects(frame,
+      nsLayoutUtils::GetAllInFlowRectsAndTexts(frame,
         nsLayoutUtils::GetContainingBlockForClientRect(frame), aCollector,
+        aTextList,
         nsLayoutUtils::RECTS_ACCOUNT_FOR_TRANSFORMS);
     }
   } while (!iter.IsDone());
 }
 
 NS_IMETHODIMP
 nsRange::GetBoundingClientRect(nsIDOMClientRect** aResult)
 {
@@ -3022,18 +3048,18 @@ already_AddRefed<DOMRect>
 nsRange::GetBoundingClientRect(bool aClampToEdge, bool aFlushLayout)
 {
   RefPtr<DOMRect> rect = new DOMRect(ToSupports(this));
   if (!mStartParent) {
     return rect.forget();
   }
 
   nsLayoutUtils::RectAccumulator accumulator;
-  CollectClientRects(&accumulator, this, mStartParent, mStartOffset, 
-    mEndParent, mEndOffset, aClampToEdge, aFlushLayout);
+  CollectClientRectsAndText(&accumulator, nullptr, this, mStartParent,
+    mStartOffset, mEndParent, mEndOffset, aClampToEdge, aFlushLayout);
 
   nsRect r = accumulator.mResultRect.IsEmpty() ? accumulator.mFirstRect : 
     accumulator.mResultRect;
   rect->SetLayoutRect(r);
   return rect.forget();
 }
 
 NS_IMETHODIMP
@@ -3050,21 +3076,39 @@ nsRange::GetClientRects(bool aClampToEdg
     return nullptr;
   }
 
   RefPtr<DOMRectList> rectList =
     new DOMRectList(static_cast<nsIDOMRange*>(this));
 
   nsLayoutUtils::RectListBuilder builder(rectList);
 
-  CollectClientRects(&builder, this, mStartParent, mStartOffset, 
-    mEndParent, mEndOffset, aClampToEdge, aFlushLayout);
+  CollectClientRectsAndText(&builder, nullptr, this, mStartParent,
+    mStartOffset, mEndParent, mEndOffset, aClampToEdge, aFlushLayout);
   return rectList.forget();
 }
 
+void
+nsRange::GetClientRectsAndTexts(
+  mozilla::dom::ClientRectsAndTexts& aResult,
+  ErrorResult& aErr)
+{
+  if (!mStartParent) {
+    return;
+  }
+
+  aResult.mRectList = new DOMRectList(static_cast<nsIDOMRange*>(this));
+  aResult.mTextList = new DOMStringList();
+
+  nsLayoutUtils::RectListBuilder builder(aResult.mRectList);
+
+  CollectClientRectsAndText(&builder, aResult.mTextList, this,
+    mStartParent, mStartOffset, mEndParent, mEndOffset, true, true);
+}
+
 NS_IMETHODIMP
 nsRange::GetUsedFontFaces(nsIDOMFontFaceList** aResult)
 {
   *aResult = nullptr;
 
   NS_ENSURE_TRUE(mStartParent, NS_ERROR_UNEXPECTED);
 
   nsCOMPtr<nsINode> startContainer = do_QueryInterface(mStartParent);
--- a/dom/base/nsRange.h
+++ b/dom/base/nsRange.h
@@ -20,16 +20,17 @@
 #include "prmon.h"
 #include "nsStubMutationObserver.h"
 #include "nsWrapperCache.h"
 #include "mozilla/Attributes.h"
 
 namespace mozilla {
 class ErrorResult;
 namespace dom {
+struct ClientRectsAndTexts;
 class DocumentFragment;
 class DOMRect;
 class DOMRectList;
 class Selection;
 } // namespace dom
 } // namespace mozilla
 
 class nsRange final : public nsIDOMRange,
@@ -207,16 +208,19 @@ public:
   void SetStart(nsINode& aNode, uint32_t aOffset, ErrorResult& aErr);
   void SetStartAfter(nsINode& aNode, ErrorResult& aErr);
   void SetStartBefore(nsINode& aNode, ErrorResult& aErr);
   void SurroundContents(nsINode& aNode, ErrorResult& aErr);
   already_AddRefed<DOMRect> GetBoundingClientRect(bool aClampToEdge = true,
                                                   bool aFlushLayout = true);
   already_AddRefed<DOMRectList> GetClientRects(bool aClampToEdge = true,
                                                bool aFlushLayout = true);
+  void GetClientRectsAndTexts(
+    mozilla::dom::ClientRectsAndTexts& aResult,
+    ErrorResult& aErr);
   static void GetInnerTextNoFlush(mozilla::dom::DOMString& aValue,
                                   mozilla::ErrorResult& aError,
                                   nsIContent* aStartParent,
                                   uint32_t aStartOffset,
                                   nsIContent* aEndParent,
                                   uint32_t aEndOffset);
 
   nsINode* GetParentObject() const { return mOwner; }
@@ -258,21 +262,26 @@ public:
    * where aNode is a descendant of a range's common ancestor node).
    * If a nsRange starts in (aNode, aEndOffset) or if it ends in
    * (aNode, aStartOffset) then it is non-overlapping and the result is false
    * for that nsRange.  Collapsed ranges always counts as non-overlapping.
    */
   static bool IsNodeSelected(nsINode* aNode, uint32_t aStartOffset,
                              uint32_t aEndOffset);
 
-  static void CollectClientRects(nsLayoutUtils::RectCallback* aCollector,
-                                 nsRange* aRange,
-                                 nsINode* aStartParent, int32_t aStartOffset,
-                                 nsINode* aEndParent, int32_t aEndOffset,
-                                 bool aClampToEdge, bool aFlushLayout);
+  /**
+   * This helper function gets rects and correlated text for the given range.
+   * @param aTextList optional where nullptr = don't retrieve text
+   */
+  static void CollectClientRectsAndText(nsLayoutUtils::RectCallback* aCollector,
+                                        mozilla::dom::DOMStringList* aTextList,
+                                        nsRange* aRange,
+                                        nsINode* aStartParent, int32_t aStartOffset,
+                                        nsINode* aEndParent, int32_t aEndOffset,
+                                        bool aClampToEdge, bool aFlushLayout);
 
   /**
    * Scan this range for -moz-user-select:none nodes and split it up into
    * multiple ranges to exclude those nodes.  The resulting ranges are put
    * in aOutRanges.  If no -moz-user-select:none node is found in the range
    * then |this| is unmodified and is the only range in aOutRanges.
    * Otherwise, |this| will be modified so that it ends before the first
    * -moz-user-select:none node and additional ranges may also be created.
--- a/dom/base/test/chrome/chrome.ini
+++ b/dom/base/test/chrome/chrome.ini
@@ -63,12 +63,13 @@ support-files = ../file_bug357450.js
 [test_bug1209621.xul]
 [test_cpows.xul]
 [test_registerElement_content.xul]
 [test_registerElement_ep.xul]
 [test_domparsing.xul]
 [test_fileconstructor.xul]
 [test_fileconstructor_tempfile.xul]
 [test_nsITextInputProcessor.xul]
+[test_range_getClientRectsAndTexts.html]
 [test_title.xul]
 [test_windowroot.xul]
 [test_swapFrameLoaders.xul]
 [test_groupedSHistory.xul]
new file mode 100644
--- /dev/null
+++ b/dom/base/test/chrome/test_range_getClientRectsAndTexts.html
@@ -0,0 +1,60 @@
+<html>
+<head>
+<meta charset="utf-8">
+<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+<script>
+'use strict';
+
+SimpleTest.waitForExplicitFinish();
+
+function runTests()
+{
+  let range = document.createRange();
+
+  let attempts = [
+    {startNode: "one", start:0, endNode:"one", end:0, textList:[], message:"Empty rect"},
+    {startNode: "one", start:2, endNode:"one", end:6, textList:["l on"], message:"Single line"},
+    {startNode: "implicit", start:6, endNode:"implicit", end:12, textList:["it\nbre"], message:"Implicit break"},
+    {startNode: "two.a", start:1, endNode:"two.b", end:2, textList:["wo", "", "li"], message:"Two lines"},
+    {startNode: "embed.a", start:7, endNode:"embed.b", end:2, textList:["th ", "simple nested", " ", "te"], message:"Simple nested"},
+    {startNode: "deep.a", start:2, endNode:"deep.b", end:2, textList:["ne with ", "complex, more deeply nested", " ", "te"], message:"Complex nested"},
+    {startNode: "image.a", start:7, endNode:"image.b", end:2, textList:["th inline ", "", " ", "im"], message:"Inline image"},
+  ];
+
+  for (let attempt of attempts) {
+    range.setStart(document.getElementById(attempt.startNode).childNodes[0], attempt.start);
+    range.setEnd(document.getElementById(attempt.endNode).childNodes[0], attempt.end);
+
+    let result = range.getClientRectsAndTexts();
+
+    is(result.textList.length, attempt.textList.length, attempt.message + " range has expected number of texts.");
+    let i = 0;
+    for (let text of result.textList) {
+      is(text, attempt.textList[i], attempt.message + " matched text index " + i + ".");
+      i++;
+    }
+  }
+
+  SimpleTest.finish();
+}
+</script>
+</head>
+<body onLoad="runTests()">
+
+<div id="one">All on one line</div>
+
+<div id="implicit">Implicit
+break in one line</div>
+
+<div id="two.a">Two<br/
+><span id="two.b">lines</span></div>
+
+<div id="embed.a">Line with <span>simple nested</span> <span id="embed.b">text</span></div>
+
+<div id="deep.a">Line with <span>complex, <span>more <span>deeply <span>nested</span></span></span></span> <span id="deep.b">text</span></div>
+
+<div id="image.a">Line with inline <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAIAAAAC64paAAAAG0lEQVR42mP8z0A%2BYKJA76jmUc2jmkc1U0EzACKcASfOgGoMAAAAAElFTkSuQmCC" width="20" height="20"/> <span id="image.b">image</span></div>
+
+</body>
+</html>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/base/test/file_receiveMessage.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <script>
+    window.onmessage = event => {
+      document.body.textContent = `${event.origin}|${event.data}`;
+    };
+  </script>
+</head>
+
+<body></body>
+</html>
+
--- a/dom/base/test/mochitest.ini
+++ b/dom/base/test/mochitest.ini
@@ -736,16 +736,18 @@ skip-if = toolkit == 'android' #CLICK_TO
 tags = audiochannel
 skip-if = toolkit == 'android' # Plugins don't work on Android
 [test_pluginMutedBeforePlay.html]
 tags = audiochannel
 skip-if = toolkit == 'android' # Plugins don't work on Android
 [test_postMessage_solidus.html]
 [test_postMessages.html]
 support-files = worker_postMessages.js
+[test_postMessage_originAttributes.html]
+support-files = file_receiveMessage.html
 [test_processing_instruction_update_stylesheet.xhtml]
 [test_progress_events_for_gzip_data.html]
 [test_range_bounds.html]
 skip-if = toolkit == 'android'
 [test_reentrant_flush.html]
 skip-if = toolkit == 'android'
 [test_referrer_redirect.html]
 [test_root_iframe.html]
new file mode 100644
--- /dev/null
+++ b/dom/base/test/test_postMessage_originAttributes.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <title>Test window.postMessages from system principal to window with non-default originAttributes</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+
+<body>
+<iframe id="target-iframe"></iframe>
+<script type="application/javascript">
+add_task(function*() {
+  let iframe = document.querySelector("#target-iframe");
+
+  let win = SpecialPowers.wrap(iframe).contentWindow;
+  let docShell = win.QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor)
+                    .getInterface(SpecialPowers.Ci.nsIDocShell);
+
+  // Add private browsing ID to docShell origin and load document.
+  docShell.setOriginAttributes({privateBrowsingId: 1});
+
+  yield new Promise(resolve => {
+    iframe.addEventListener("load", resolve, true);
+
+    iframe.src = SimpleTest.getTestFileURL("file_receiveMessage.html");
+  });
+
+  // Set up console monitor to wait for warning.
+  const expectedMessage = (
+    'Attempting to post a message to window with url ' +
+    '"http://mochi.test:8888/tests/dom/base/test/file_receiveMessage.html" ' +
+    'and origin "http://mochi.test:8888^privateBrowsingId=1" from a system ' +
+    'principal scope with mismatched origin "[System Principal]".');
+
+  let consolePromise = new Promise(resolve => {
+    SimpleTest.monitorConsole(resolve, [e => e.message == expectedMessage]);
+  });
+
+  // Post to the content window via SpecialPowers' system principal scope.
+  win.postMessage("Hello. o/", "http://mochi.test:8888");
+  yield new Promise(resolve => setTimeout(resolve, 0));
+
+  SimpleTest.endMonitorConsole();
+  yield consolePromise;
+
+  // Check that the window received and handled the message.
+  is(win.document.body.textContent, "|Hello. o/",
+     "Content window received the expected message");
+});
+</script>
+</body>
+</html>
+
--- a/dom/gamepad/Gamepad.h
+++ b/dom/gamepad/Gamepad.h
@@ -28,24 +28,16 @@ const int kStandardGamepadAxes = 4;
 const int kButtonLeftTrigger = 6;
 const int kButtonRightTrigger = 7;
 
 const int kLeftStickXAxis = 0;
 const int kLeftStickYAxis = 1;
 const int kRightStickXAxis = 2;
 const int kRightStickYAxis = 3;
 
-// Standard channel is used for managing gamepads that
-// are from GamepadPlatformService. VR channel
-// is for gamepads that are from VRManagerChild.
-enum class GamepadServiceType : uint16_t {
-  Standard,
-  VR,
-  NumGamepadServiceType
-};
 
 class Gamepad final : public nsISupports,
                       public nsWrapperCache
 {
 public:
   Gamepad(nsISupports* aParent,
           const nsAString& aID, uint32_t aIndex,
           GamepadMappingType aMapping,
--- a/dom/gamepad/GamepadManager.cpp
+++ b/dom/gamepad/GamepadManager.cpp
@@ -585,17 +585,18 @@ GamepadManager::SetWindowHasSeenGamepad(
 }
 
 void
 GamepadManager::Update(const GamepadChangeEvent& aEvent)
 {
   if (aEvent.type() == GamepadChangeEvent::TGamepadAdded) {
     const GamepadAdded& a = aEvent.get_GamepadAdded();
     AddGamepad(a.index(), a.id(),
-               a.mapping(), a.service_type(),
+               static_cast<GamepadMappingType>(a.mapping()),
+               a.service_type(),
                a.num_buttons(), a.num_axes());
     return;
   }
   if (aEvent.type() == GamepadChangeEvent::TGamepadRemoved) {
     const GamepadRemoved& a = aEvent.get_GamepadRemoved();
     RemoveGamepad(a.index(), a.service_type());
     return;
   }
--- a/dom/gamepad/GamepadManager.h
+++ b/dom/gamepad/GamepadManager.h
@@ -6,16 +6,17 @@
 
 #ifndef mozilla_dom_GamepadManager_h_
 #define mozilla_dom_GamepadManager_h_
 
 #include "nsIIPCBackgroundChildCreateCallback.h"
 #include "nsIObserver.h"
 // Needed for GamepadMappingType
 #include "mozilla/dom/GamepadBinding.h"
+#include "mozilla/dom/GamepadServiceType.h"
 
 class nsGlobalWindow;
 
 namespace mozilla {
 namespace gfx {
 class VRManagerChild;
 } // namespace gfx
 namespace dom {
--- a/dom/gamepad/GamepadPlatformService.cpp
+++ b/dom/gamepad/GamepadPlatformService.cpp
@@ -90,17 +90,17 @@ GamepadPlatformService::AddGamepad(const
 {
   // This method is called by monitor thread populated in
   // platform-dependent backends
   MOZ_ASSERT(XRE_IsParentProcess());
   MOZ_ASSERT(!NS_IsMainThread());
 
   uint32_t index = ++mGamepadIndex;
   GamepadAdded a(NS_ConvertUTF8toUTF16(nsDependentCString(aID)), index,
-                 aMapping, GamepadServiceType::Standard, aNumButtons, aNumAxes);
+                 static_cast<uint32_t>(aMapping), GamepadServiceType::Standard, aNumButtons, aNumAxes);
   NotifyGamepadChange<GamepadAdded>(a);
   return index;
 }
 
 void
 GamepadPlatformService::RemoveGamepad(uint32_t aIndex)
 {
   // This method is called by monitor thread populated in
--- a/dom/gamepad/GamepadServiceTest.cpp
+++ b/dom/gamepad/GamepadServiceTest.cpp
@@ -117,20 +117,18 @@ GamepadServiceTest::AddGamepad(const nsA
                                uint32_t aNumButtons,
                                uint32_t aNumAxes,
                                ErrorResult& aRv)
 {
   if (mShuttingDown) {
     return nullptr;
   }
 
-  // Because GamepadServiceTest::AddGamepad() is opened for Web API,
-  // we need to convert aMapping from uint32_t to GamepadMappingType here.
   GamepadAdded a(nsString(aID), 0,
-                 static_cast<GamepadMappingType>(aMapping),
+                 aMapping,
                  GamepadServiceType::Standard,
                  aNumButtons, aNumAxes);
   GamepadChangeEvent e(a);
   nsCOMPtr<nsIGlobalObject> go = do_QueryInterface(mWindow);
 
   RefPtr<Promise> p = Promise::Create(go, aRv);
   if (aRv.Failed()) {
     return nullptr;
--- a/dom/gamepad/ipc/GamepadEventTypes.ipdlh
+++ b/dom/gamepad/ipc/GamepadEventTypes.ipdlh
@@ -1,23 +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/. */
 
-using mozilla::dom::GamepadMappingType from "mozilla/dom/GamepadMessageUtils.h";
 using mozilla::dom::GamepadServiceType from "mozilla/dom/GamepadMessageUtils.h";
 
 
 namespace mozilla {
 namespace dom {
 
 struct GamepadAdded {
   nsString id;
   uint32_t index;
-  GamepadMappingType mapping;
+  // Ideally, mapping should be a GamepadMappingType
+  // But, we have dependency problems in non MOZ_GAMEPAD
+  // platforms. Therefore, we make it as an uint32_t here.
+  uint32_t mapping;
   GamepadServiceType service_type;
   uint32_t num_buttons;
   uint32_t num_axes;
 };
 
 struct GamepadRemoved {
   uint32_t index;
   GamepadServiceType service_type;
--- a/dom/gamepad/ipc/GamepadMessageUtils.h
+++ b/dom/gamepad/ipc/GamepadMessageUtils.h
@@ -1,24 +1,18 @@
 
 #ifndef mozilla_dom_gamepad_GamepadMessageUtils_h
 #define mozilla_dom_gamepad_GamepadMessageUtils_h
 
 #include "ipc/IPCMessageUtils.h"
-#include "mozilla/dom/Gamepad.h"
+#include "mozilla/dom/GamepadServiceType.h"
 
 namespace IPC {
 
 template<>
-struct ParamTraits<mozilla::dom::GamepadMappingType> :
-  public ContiguousEnumSerializer<mozilla::dom::GamepadMappingType,
-                                  mozilla::dom::GamepadMappingType(mozilla::dom::GamepadMappingType::_empty),
-                                  mozilla::dom::GamepadMappingType(mozilla::dom::GamepadMappingType::EndGuard_)> {};
-
-template<>
 struct ParamTraits<mozilla::dom::GamepadServiceType> :
   public ContiguousEnumSerializer<mozilla::dom::GamepadServiceType,
                                   mozilla::dom::GamepadServiceType(0),
                                   mozilla::dom::GamepadServiceType(
                                   mozilla::dom::GamepadServiceType::NumGamepadServiceType)> {};
 } // namespace IPC
 
 #endif // mozilla_dom_gamepad_GamepadMessageUtils_h
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/gamepad/ipc/GamepadServiceType.h
@@ -0,0 +1,20 @@
+
+#ifndef mozilla_dom_GamepadServiceType_h_
+#define mozilla_dom_GamepadServiceType_h_
+
+namespace mozilla{
+namespace dom{
+
+// Standard channel is used for managing gamepads that
+// are from GamepadPlatformService. VR channel
+// is for gamepads that are from VRManagerChild.
+enum class GamepadServiceType : uint16_t {
+  Standard,
+  VR,
+  NumGamepadServiceType
+};
+
+}// namespace dom
+}// namespace mozilla
+
+#endif // mozilla_dom_GamepadServiceType_h_
\ No newline at end of file
--- a/dom/gamepad/ipc/GamepadTestChannelParent.cpp
+++ b/dom/gamepad/ipc/GamepadTestChannelParent.cpp
@@ -18,17 +18,17 @@ GamepadTestChannelParent::RecvGamepadTes
   RefPtr<GamepadPlatformService>  service =
     GamepadPlatformService::GetParentService();
   MOZ_ASSERT(service);
   if (aEvent.type() == GamepadChangeEvent::TGamepadAdded) {
     const GamepadAdded& a = aEvent.get_GamepadAdded();
     nsCString gamepadID;
     LossyCopyUTF16toASCII(a.id(), gamepadID);
     uint32_t index = service->AddGamepad(gamepadID.get(),
-                                         a.mapping(),
+                                         static_cast<GamepadMappingType>(a.mapping()),
                                          a.num_buttons(),
                                          a.num_axes());
     if (!mShuttingdown) {
       Unused << SendReplyGamepadIndex(aID, index);
     }
     return true;
   }
   if (aEvent.type() == GamepadChangeEvent::TGamepadRemoved) {
--- a/dom/gamepad/moz.build
+++ b/dom/gamepad/moz.build
@@ -5,27 +5,31 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 IPDL_SOURCES += [
     'ipc/GamepadEventTypes.ipdlh',
     'ipc/PGamepadEventChannel.ipdl',
     'ipc/PGamepadTestChannel.ipdl'
 ]
 
+EXPORTS.mozilla.dom += [
+    'ipc/GamepadMessageUtils.h',
+    'ipc/GamepadServiceType.h'
+]
+
 if CONFIG['MOZ_GAMEPAD']:
     EXPORTS.mozilla.dom += [
         'Gamepad.h',
         'GamepadButton.h',
         'GamepadManager.h',
         'GamepadMonitoring.h',
         'GamepadPlatformService.h',
         'GamepadServiceTest.h',
         'ipc/GamepadEventChannelChild.h',
         'ipc/GamepadEventChannelParent.h',
-        'ipc/GamepadMessageUtils.h',
         'ipc/GamepadTestChannelChild.h',
         'ipc/GamepadTestChannelParent.h'
         ]
 
     UNIFIED_SOURCES = [
         'Gamepad.cpp',
         'GamepadButton.cpp',
         'GamepadManager.cpp',
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -2408,18 +2408,19 @@ TabChild::RecvSetDocShellIsActive(const 
     if (aIsActive) {
       ProcessHangMonitor::ClearForcePaint();
     }
   });
 
   // We send the current layer observer epoch to the compositor so that
   // TabParent knows whether a layer update notification corresponds to the
   // latest SetDocShellIsActive request that was made.
-  ClientLayerManager *manager = mPuppetWidget->GetLayerManager()->AsClientLayerManager();
-  manager->SetLayerObserverEpoch(aLayerObserverEpoch);
+  if (ClientLayerManager* clm = mPuppetWidget->GetLayerManager()->AsClientLayerManager()) {
+    clm->SetLayerObserverEpoch(aLayerObserverEpoch);
+  }
 
   // docshell is consider prerendered only if not active yet
   mIsPrerendered &= !aIsActive;
   nsCOMPtr<nsIDocShell> docShell = do_GetInterface(WebNavigation());
   if (docShell) {
     bool wasActive;
     docShell->GetIsActive(&wasActive);
     if (aIsActive && wasActive) {
@@ -2583,44 +2584,50 @@ TabChild::InitRenderingState(const Textu
     // Pushing layers transactions directly to a separate
     // compositor context.
     PCompositorBridgeChild* compositorChild = CompositorBridgeChild::Get();
     if (!compositorChild) {
       NS_WARNING("failed to get CompositorBridgeChild instance");
       PRenderFrameChild::Send__delete__(remoteFrame);
       return false;
     }
-    nsTArray<LayersBackend> backends;
-    backends.AppendElement(mTextureFactoryIdentifier.mParentBackend);
-    bool success;
-    PLayerTransactionChild* shadowManager =
-        compositorChild->SendPLayerTransactionConstructor(backends,
-                                                          aLayersId, &mTextureFactoryIdentifier, &success);
-    if (!success) {
-      NS_WARNING("failed to properly allocate layer transaction");
-      PRenderFrameChild::Send__delete__(remoteFrame);
-      return false;
-    }
-
-    if (!shadowManager) {
-      NS_WARNING("failed to construct LayersChild");
-      // This results in |remoteFrame| being deleted.
-      PRenderFrameChild::Send__delete__(remoteFrame);
-      return false;
-    }
 
     ShadowLayerForwarder* lf =
         mPuppetWidget->GetLayerManager(
-            shadowManager, mTextureFactoryIdentifier.mParentBackend)
+            nullptr, mTextureFactoryIdentifier.mParentBackend)
                 ->AsShadowForwarder();
-    MOZ_ASSERT(lf && lf->HasShadowManager(),
-               "PuppetWidget should have shadow manager");
-    lf->IdentifyTextureHost(mTextureFactoryIdentifier);
-    ImageBridgeChild::IdentifyCompositorTextureHost(mTextureFactoryIdentifier);
-    gfx::VRManagerChild::IdentifyTextureHost(mTextureFactoryIdentifier);
+    // As long as we are creating a ClientLayerManager for the puppet widget,
+    // lf must be non-null here.
+    MOZ_ASSERT(lf);
+
+    if (lf) {
+      nsTArray<LayersBackend> backends;
+      backends.AppendElement(mTextureFactoryIdentifier.mParentBackend);
+      bool success;
+      PLayerTransactionChild* shadowManager =
+          compositorChild->SendPLayerTransactionConstructor(backends,
+                                                            aLayersId, &mTextureFactoryIdentifier, &success);
+      if (!success) {
+        NS_WARNING("failed to properly allocate layer transaction");
+        PRenderFrameChild::Send__delete__(remoteFrame);
+        return false;
+      }
+
+      if (!shadowManager) {
+        NS_WARNING("failed to construct LayersChild");
+        // This results in |remoteFrame| being deleted.
+        PRenderFrameChild::Send__delete__(remoteFrame);
+        return false;
+      }
+
+      lf->SetShadowManager(shadowManager);
+      lf->IdentifyTextureHost(mTextureFactoryIdentifier);
+      ImageBridgeChild::IdentifyCompositorTextureHost(mTextureFactoryIdentifier);
+      gfx::VRManagerChild::IdentifyTextureHost(mTextureFactoryIdentifier);
+    }
 
     mRemoteFrame = remoteFrame;
     if (aLayersId != 0) {
       if (!sTabChildren) {
         sTabChildren = new TabChildMap;
       }
       MOZ_ASSERT(!sTabChildren->Get(aLayersId));
       sTabChildren->Put(aLayersId, this);
@@ -2995,16 +3002,17 @@ TabChild::ReinitRendering()
 
 void
 TabChild::CompositorUpdated(const TextureFactoryIdentifier& aNewIdentifier)
 {
   gfxPlatform::GetPlatform()->CompositorUpdated();
 
   RefPtr<LayerManager> lm = mPuppetWidget->GetLayerManager();
   ClientLayerManager* clm = lm->AsClientLayerManager();
+  MOZ_ASSERT(clm);
 
   mTextureFactoryIdentifier = aNewIdentifier;
   clm->UpdateTextureFactoryIdentifier(aNewIdentifier);
   FrameLayerBuilder::InvalidateAllLayers(clm);
 }
 
 NS_IMETHODIMP
 TabChild::OnShowTooltip(int32_t aXCoords, int32_t aYCoords, const char16_t *aTipText,
--- a/dom/media/AudioCaptureStream.cpp
+++ b/dom/media/AudioCaptureStream.cpp
@@ -97,32 +97,36 @@ AudioCaptureStream::ProcessInput(GraphTi
     track->Get<AudioSegment>()->AppendNullData(aTo - aFrom);
   } else {
     // We mix down all the tracks of all inputs, to a stereo track. Everything
     // is {up,down}-mixed to stereo.
     mMixer.StartMixing();
     AudioSegment output;
     for (uint32_t i = 0; i < inputCount; i++) {
       MediaStream* s = mInputs[i]->GetSource();
-      for (StreamTracks::TrackIter track(s->GetStreamTracks(),
-                                         MediaSegment::AUDIO);
-           !track.IsEnded(); track.Next()) {
+      StreamTracks::TrackIter track(s->GetStreamTracks(), MediaSegment::AUDIO);
+      if (track.IsEnded()) {
+        // No tracks for this input. Still we append data to trigger the mixer.
+        AudioSegment toMix;
+        toMix.AppendNullData(aTo - aFrom);
+        toMix.Mix(mMixer, MONO, Graph()->GraphRate());
+      }
+      for (; !track.IsEnded(); track.Next()) {
         AudioSegment* inputSegment = track->Get<AudioSegment>();
         StreamTime inputStart = s->GraphTimeToStreamTimeWithBlocking(aFrom);
         StreamTime inputEnd = s->GraphTimeToStreamTimeWithBlocking(aTo);
-        if (track->IsEnded() && inputSegment->GetDuration() <= inputEnd) {
-          // If the input track has ended and we have consumed all its data it
-          // can be ignored.
-          continue;
-        }
         AudioSegment toMix;
-        toMix.AppendSlice(*inputSegment, inputStart, inputEnd);
-        // Care for streams blocked in the [aTo, aFrom] range.
-        if (inputEnd - inputStart < aTo - aFrom) {
-          toMix.AppendNullData((aTo - aFrom) - (inputEnd - inputStart));
+        if (track->IsEnded() && inputSegment->GetDuration() <= inputStart) {
+          toMix.AppendNullData(aTo - aFrom);
+        } else {
+          toMix.AppendSlice(*inputSegment, inputStart, inputEnd);
+          // Care for streams blocked in the [aTo, aFrom] range.
+          if (inputEnd - inputStart < aTo - aFrom) {
+            toMix.AppendNullData((aTo - aFrom) - (inputEnd - inputStart));
+          }
         }
         toMix.Mix(mMixer, MONO, Graph()->GraphRate());
       }
     }
     // This calls MixerCallback below
     mMixer.FinishMixing();
   }
 
--- a/dom/media/MediaDecoder.cpp
+++ b/dom/media/MediaDecoder.cpp
@@ -1139,24 +1139,22 @@ MediaDecoder::OnSeekResolved(SeekResolve
     fireEnded = aVal.mAtEnd;
     if (aVal.mAtEnd) {
       ChangeState(PLAY_STATE_ENDED);
     }
     mLogicallySeeking = false;
   }
 
   // Ensure logical position is updated after seek.
-  UpdateLogicalPositionInternal(aVal.mEventVisibility);
+  UpdateLogicalPositionInternal();
 
-  if (aVal.mEventVisibility != MediaDecoderEventVisibility::Suppressed) {
-    mOwner->SeekCompleted();
-    AsyncResolveSeekDOMPromiseIfExists();
-    if (fireEnded) {
-      mOwner->PlaybackEnded();
-    }
+  mOwner->SeekCompleted();
+  AsyncResolveSeekDOMPromiseIfExists();
+  if (fireEnded) {
+    mOwner->PlaybackEnded();
   }
 }
 
 void
 MediaDecoder::OnSeekRejected()
 {
   MOZ_ASSERT(NS_IsMainThread());
   mSeekRequest.Complete();
@@ -1188,17 +1186,17 @@ MediaDecoder::ChangeState(PlayState aSta
   if (mPlayState == PLAY_STATE_PLAYING) {
     ConstructMediaTracks();
   } else if (IsEnded()) {
     RemoveMediaTracks();
   }
 }
 
 void
-MediaDecoder::UpdateLogicalPositionInternal(MediaDecoderEventVisibility aEventVisibility)
+MediaDecoder::UpdateLogicalPositionInternal()
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(!IsShutdown());
 
   double currentPosition = static_cast<double>(CurrentPosition()) / static_cast<double>(USECS_PER_S);
   if (mPlayState == PLAY_STATE_ENDED) {
     currentPosition = std::max(currentPosition, mDuration);
   }
@@ -1206,18 +1204,17 @@ MediaDecoder::UpdateLogicalPositionInter
   mLogicalPosition = currentPosition;
 
   // Invalidate the frame so any video data is displayed.
   // Do this before the timeupdate event so that if that
   // event runs JavaScript that queries the media size, the
   // frame has reflowed and the size updated beforehand.
   Invalidate();
 
-  if (logicalPositionChanged &&
-      aEventVisibility != MediaDecoderEventVisibility::Suppressed) {
+  if (logicalPositionChanged) {
     FireTimeUpdate();
   }
 }
 
 void
 MediaDecoder::DurationChanged()
 {
   MOZ_ASSERT(NS_IsMainThread());
--- a/dom/media/MediaDecoder.h
+++ b/dom/media/MediaDecoder.h
@@ -54,20 +54,17 @@ enum class MediaEventType : int8_t;
 #ifdef GetCurrentTime
 #undef GetCurrentTime
 #endif
 
 class MediaDecoder : public AbstractMediaDecoder
 {
 public:
   struct SeekResolveValue {
-    SeekResolveValue(bool aAtEnd, MediaDecoderEventVisibility aEventVisibility)
-      : mAtEnd(aAtEnd), mEventVisibility(aEventVisibility) {}
     bool mAtEnd;
-    MediaDecoderEventVisibility mEventVisibility;
   };
 
   // Used to register with MediaResource to receive notifications which will
   // be forwarded to MediaDecoder.
   class ResourceCallback : public MediaResourceCallback {
     // Throttle calls to MediaDecoder::NotifyDataArrived()
     // to be at most once per 500ms.
     static const uint32_t sDelay = 500;
@@ -397,26 +394,26 @@ private:
     // seeking to prevent wild changes to the progress notification.
     MOZ_ASSERT(NS_IsMainThread());
     mIgnoreProgressData = mLogicallySeeking;
   }
 
   // Seeking has started. Inform the element on the main thread.
   void SeekingStarted();
 
-  void UpdateLogicalPositionInternal(MediaDecoderEventVisibility aEventVisibility);
+  void UpdateLogicalPositionInternal();
   void UpdateLogicalPosition()
   {
     MOZ_ASSERT(NS_IsMainThread());
     MOZ_ASSERT(!IsShutdown());
     // Per spec, offical position remains stable during pause and seek.
     if (mPlayState == PLAY_STATE_PAUSED || IsSeeking()) {
       return;
     }
-    UpdateLogicalPositionInternal(MediaDecoderEventVisibility::Observable);
+    UpdateLogicalPositionInternal();
   }
 
   // Find the end of the cached data starting at the current decoder
   // position.
   int64_t GetDownloadPosition();
 
   // Notifies the element that decoding has failed.
   void DecodeError(const MediaResult& aError);
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -195,33 +195,39 @@ public:
   // Event handlers for various events.
   virtual void HandleCDMProxyReady() {}
   virtual void HandleAudioDecoded(MediaData* aAudio) {}
   virtual void HandleVideoDecoded(MediaData* aVideo, TimeStamp aDecodeStart) {}
   virtual void HandleEndOfStream() {}
   virtual void HandleWaitingForData() {}
   virtual void HandleAudioCaptured() {}
 
-  virtual RefPtr<MediaDecoder::SeekPromise> HandleSeek(SeekTarget aTarget) = 0;
+  virtual RefPtr<MediaDecoder::SeekPromise> HandleSeek(SeekTarget aTarget);
 
   virtual RefPtr<ShutdownPromise> HandleShutdown();
 
   virtual void HandleVideoSuspendTimeout() = 0;
 
   virtual void HandleResumeVideoDecoding();
 
   virtual void HandlePlayStateChanged(MediaDecoder::PlayState aPlayState) {}
 
   virtual void DumpDebugInfo() {}
 
 private:
   template <class S, typename R, typename... As>
   auto ReturnTypeHelper(R(S::*)(As...)) -> R;
 
 protected:
+  enum class EventVisibility : int8_t
+  {
+    Observable,
+    Suppressed
+  };
+
   using Master = MediaDecoderStateMachine;
   explicit StateObject(Master* aPtr) : mMaster(aPtr) {}
   TaskQueue* OwnerThread() const { return mMaster->mTaskQueue; }
   MediaResource* Resource() const { return mMaster->mResource; }
   MediaDecoderReaderWrapper* Reader() const { return mMaster->mReader; }
   const MediaInfo& Info() const { return mMaster->Info(); }
   bool IsExpectingMoreData() const
   {
@@ -389,49 +395,55 @@ public:
 private:
   SeekJob mPendingSeek;
 };
 
 /**
  * Purpose: release decoder resources to save memory and hardware resources.
  *
  * Transition to:
- *   DECODING_FIRSTFRAME when play state changes to PLAYING.
- *   SEEKING if any seek request.
+ *   SEEKING if any seek request or play state changes to PLAYING.
  */
 class MediaDecoderStateMachine::DormantState
   : public MediaDecoderStateMachine::StateObject
 {
 public:
   explicit DormantState(Master* aPtr) : StateObject(aPtr) {}
 
-  void Enter(SeekJob aPendingSeek)
+  void Enter()
   {
-    mPendingSeek = Move(aPendingSeek);
     if (mMaster->IsPlaying()) {
       mMaster->StopPlayback();
     }
+
+    // Calculate the position to seek to when exiting dormant.
+    auto t = mMaster->mMediaSink->IsStarted()
+      ? mMaster->GetClock()
+      : mMaster->GetMediaTime();
+    mPendingSeek.mTarget = SeekTarget(t, SeekTarget::Accurate);
+    // SeekJob asserts |mTarget.IsValid() == !mPromise.IsEmpty()| so we
+    // need to create the promise even it is not used at all.
+    RefPtr<MediaDecoder::SeekPromise> x = mPendingSeek.mPromise.Ensure(__func__);
+
     mMaster->Reset();
     mMaster->mReader->ReleaseResources();
   }
 
   void Exit() override
   {
     // mPendingSeek is either moved when exiting dormant or
     // should be rejected here before transition to SHUTDOWN.
     mPendingSeek.RejectIfExists(__func__);
   }
 
   State GetState() const override
   {
     return DECODER_STATE_DORMANT;
   }
 
-  RefPtr<MediaDecoder::SeekPromise> HandleSeek(SeekTarget aTarget) override;
-
   void HandleVideoSuspendTimeout() override
   {
     // Do nothing since we've released decoders in Enter().
   }
 
   void HandleResumeVideoDecoding() override
   {
     // Do nothing since we won't resume decoding until exiting dormant.
@@ -576,18 +588,16 @@ public:
 
   void HandleVideoDecoded(MediaData* aVideo, TimeStamp aDecodeStart) override
   {
     mMaster->Push(aVideo, MediaData::VIDEO_DATA);
     MaybeStopPrerolling();
     CheckSlowDecoding(aDecodeStart);
   }
 
-  RefPtr<MediaDecoder::SeekPromise> HandleSeek(SeekTarget aTarget) override;
-
   void HandleEndOfStream() override;
 
   void HandleWaitingForData() override
   {
     MaybeStopPrerolling();
   }
 
   void HandleAudioCaptured() override
@@ -681,26 +691,17 @@ private:
       mIsPrerolling = false;
       // Check if we can start playback.
       mMaster->ScheduleStateMachine();
     }
   }
 
   void EnterDormant()
   {
-    auto t = mMaster->mMediaSink->IsStarted()
-      ? mMaster->GetClock()
-      : mMaster->GetMediaTime();
-    SeekJob seekJob;
-    seekJob.mTarget = SeekTarget(t, SeekTarget::Accurate,
-                                 MediaDecoderEventVisibility::Suppressed);
-    // SeekJob asserts |mTarget.IsValid() == !mPromise.IsEmpty()| so we
-    // need to create the promise even it is not used at all.
-    RefPtr<MediaDecoder::SeekPromise> unused = seekJob.mPromise.Ensure(__func__);
-    SetState<DormantState>(Move(seekJob));
+    SetState<DormantState>();
   }
 
   void StartDormantTimer()
   {
     auto timeout = MediaPrefs::DormantOnPauseTimeout();
     if (timeout < 0) {
       // Disabled when timeout is negative.
       return;
@@ -748,17 +749,18 @@ private:
  *   DECODING otherwise.
  */
 class MediaDecoderStateMachine::SeekingState
   : public MediaDecoderStateMachine::StateObject
 {
 public:
   explicit SeekingState(Master* aPtr) : StateObject(aPtr) {}
 
-  RefPtr<MediaDecoder::SeekPromise> Enter(SeekJob aSeekJob)
+  RefPtr<MediaDecoder::SeekPromise> Enter(SeekJob aSeekJob,
+                                          EventVisibility aVisibility)
   {
     mSeekJob = Move(aSeekJob);
 
     // Always switch off the blank decoder otherwise we might become visible
     // in the middle of seeking and won't have a valid video frame to show
     // when seek is done.
     if (mMaster->mVideoDecodeSuspended) {
       mMaster->mVideoDecodeSuspended = false;
@@ -791,18 +793,17 @@ public:
 
     // mSeekJob.mTarget.mTime might be different from
     // mSeekTask->GetSeekTarget().mTime because the seek task might clamp the
     // seek target to [0, duration]. We want to update the playback position to
     // the clamped value.
     mMaster->UpdatePlaybackPositionInternal(
       mSeekTask->GetSeekTarget().GetTime().ToMicroseconds());
 
-    if (mSeekJob.mTarget.mEventVisibility ==
-        MediaDecoderEventVisibility::Observable) {
+    if (aVisibility == EventVisibility::Observable) {
       mMaster->mOnPlaybackEvent.Notify(MediaEventType::SeekStarted);
     }
 
     // Reset our state machine and decoding pipeline before seeking.
     if (mSeekTask->NeedToResetMDSM()) {
       if (mSeekJob.mTarget.IsVideoOnly()) {
         mMaster->Reset(TrackInfo::kVideoTrack);
       } else {
@@ -843,18 +844,16 @@ public:
     MOZ_ASSERT(false);
   }
 
   void HandleVideoDecoded(MediaData* aVideo, TimeStamp aDecodeStart) override
   {
     MOZ_ASSERT(false);
   }
 
-  RefPtr<MediaDecoder::SeekPromise> HandleSeek(SeekTarget aTarget) override;
-
   void HandleVideoSuspendTimeout() override
   {
     // Do nothing since we want a valid video frame to show when seek is done.
   }
 
   void HandleResumeVideoDecoding() override
   {
     // We set mVideoDecodeSuspended to false in Enter().
@@ -962,18 +961,16 @@ public:
     // This might be the sample we need to exit buffering.
     // Schedule Step() to check it.
     mMaster->Push(aVideo, MediaData::VIDEO_DATA);
     mMaster->ScheduleStateMachine();
   }
 
   void HandleEndOfStream() override;
 
-  RefPtr<MediaDecoder::SeekPromise> HandleSeek(SeekTarget aTarget) override;
-
   void HandleVideoSuspendTimeout() override
   {
     if (mMaster->HasVideo()) {
       mMaster->mVideoDecodeSuspended = true;
       mMaster->mOnPlaybackEvent.Notify(MediaEventType::EnterVideoSuspend);
       Reader()->SetVideoBlankDecode(true);
     }
   }
@@ -1054,18 +1051,16 @@ public:
     }
   }
 
   State GetState() const override
   {
     return DECODER_STATE_COMPLETED;
   }
 
-  RefPtr<MediaDecoder::SeekPromise> HandleSeek(SeekTarget aTarget) override;
-
   void HandleAudioCaptured() override
   {
     // MediaSink is changed. Schedule Step() to check if we can start playback.
     mMaster->ScheduleStateMachine();
   }
 
   void HandleVideoSuspendTimeout() override
   {
@@ -1129,16 +1124,26 @@ public:
   }
 
   void HandleResumeVideoDecoding() override
   {
     MOZ_DIAGNOSTIC_ASSERT(false, "Already shutting down.");
   }
 };
 
+RefPtr<MediaDecoder::SeekPromise>
+MediaDecoderStateMachine::
+StateObject::HandleSeek(SeekTarget aTarget)
+{
+  SLOG("Changed state to SEEKING (to %lld)", aTarget.GetTime().ToMicroseconds());
+  SeekJob seekJob;
+  seekJob.mTarget = aTarget;
+  return SetState<SeekingState>(Move(seekJob), EventVisibility::Observable);
+}
+
 RefPtr<ShutdownPromise>
 MediaDecoderStateMachine::
 StateObject::HandleShutdown()
 {
   return SetState<ShutdownState>();
 }
 
 static void
@@ -1199,20 +1204,19 @@ StateObject::HandleResumeVideoDecoding()
   SeekJob seekJob;
 
   const SeekTarget::Type type = mMaster->HasAudio()
                                 ? SeekTarget::Type::Accurate
                                 : SeekTarget::Type::PrevSyncPoint;
 
   seekJob.mTarget = SeekTarget(mMaster->GetMediaTime(),
                                type,
-                               MediaDecoderEventVisibility::Suppressed,
                                true /* aVideoOnly */);
 
-  SetState<SeekingState>(Move(seekJob))->Then(
+  SetState<SeekingState>(Move(seekJob), EventVisibility::Suppressed)->Then(
     AbstractThread::MainThread(), __func__,
     [start, info, hw](){ ReportRecoveryTelemetry(start, info, hw); },
     [](){});
 }
 
 void
 MediaDecoderStateMachine::
 DecodeMetadataState::OnMetadataRead(MetadataHolder* aMetadata)
@@ -1271,35 +1275,25 @@ DecodeMetadataState::OnMetadataRead(Meta
     // Metadata parsing was successful but we're still waiting for CDM caps
     // to become available so that we can build the correct decryptor/decoder.
     SetState<WaitForCDMState>();
   } else {
     SetState<DecodingFirstFrameState>(SeekJob{});
   }
 }
 
-RefPtr<MediaDecoder::SeekPromise>
-MediaDecoderStateMachine::
-DormantState::HandleSeek(SeekTarget aTarget)
-{
-  // Exit dormant when the user wants to seek.
-  mPendingSeek.RejectIfExists(__func__);
-  SeekJob seekJob;
-  seekJob.mTarget = aTarget;
-  return SetState<SeekingState>(Move(seekJob));
-}
-
 void
 MediaDecoderStateMachine::
 DormantState::HandlePlayStateChanged(MediaDecoder::PlayState aPlayState)
 {
   if (aPlayState == MediaDecoder::PLAY_STATE_PLAYING) {
     // Exit dormant when the user wants to play.
     MOZ_ASSERT(!Info().IsEncrypted() || mMaster->mCDMProxy);
-    SetState<DecodingFirstFrameState>(Move(mPendingSeek));
+    MOZ_ASSERT(mMaster->mSentFirstFrameLoadedEvent);
+    SetState<SeekingState>(Move(mPendingSeek), EventVisibility::Suppressed);
   }
 }
 
 void
 MediaDecoderStateMachine::
 WaitForCDMState::HandleCDMProxyReady()
 {
   SetState<DecodingFirstFrameState>(Move(mPendingSeek));
@@ -1308,17 +1302,17 @@ WaitForCDMState::HandleCDMProxyReady()
 void
 MediaDecoderStateMachine::
 DecodingFirstFrameState::Enter(SeekJob aPendingSeek)
 {
   // Handle pending seek.
   if (aPendingSeek.Exists() &&
       (mMaster->mSentFirstFrameLoadedEvent ||
        Reader()->ForceZeroStartTime())) {
-    SetState<SeekingState>(Move(aPendingSeek));
+    SetState<SeekingState>(Move(aPendingSeek), EventVisibility::Observable);
     return;
   }
 
   // Transition to DECODING if we've decoded first frames.
   if (mMaster->mSentFirstFrameLoadedEvent) {
     SetState<DecodingState>();
     return;
   }
@@ -1345,37 +1339,34 @@ DecodingFirstFrameState::HandleSeek(Seek
     mPendingSeek.mTarget = aTarget;
     return mPendingSeek.mPromise.Ensure(__func__);
   }
 
   // Since ForceZeroStartTime() is true, we should've transitioned to SEEKING
   // in Enter() if there is any pending seek.
   MOZ_ASSERT(!mPendingSeek.Exists());
 
-  SLOG("Changed state to SEEKING (to %lld)", aTarget.GetTime().ToMicroseconds());
-  SeekJob seekJob;
-  seekJob.mTarget = aTarget;
-  return SetState<SeekingState>(Move(seekJob));
+  return StateObject::HandleSeek(aTarget);
 }
 
 void
 MediaDecoderStateMachine::
 DecodingFirstFrameState::MaybeFinishDecodeFirstFrame()
 {
   MOZ_ASSERT(!mMaster->mSentFirstFrameLoadedEvent);
 
   if ((mMaster->IsAudioDecoding() && mMaster->AudioQueue().GetSize() == 0) ||
       (mMaster->IsVideoDecoding() && mMaster->VideoQueue().GetSize() == 0)) {
     return;
   }
 
   mMaster->FinishDecodeFirstFrame();
 
   if (mPendingSeek.Exists()) {
-    SetState<SeekingState>(Move(mPendingSeek));
+    SetState<SeekingState>(Move(mPendingSeek), EventVisibility::Observable);
   } else {
     SetState<DecodingState>();
   }
 }
 
 void
 MediaDecoderStateMachine::
 DecodingState::Enter()
@@ -1405,26 +1396,16 @@ DecodingState::Enter()
   mMaster->ScheduleStateMachine();
 
   // Will enter dormant when playback is paused for a while.
   if (mMaster->mPlayState == MediaDecoder::PLAY_STATE_PAUSED) {
     StartDormantTimer();
   }
 }
 
-RefPtr<MediaDecoder::SeekPromise>
-MediaDecoderStateMachine::
-DecodingState::HandleSeek(SeekTarget aTarget)
-{
-  SLOG("Changed state to SEEKING (to %lld)", aTarget.GetTime().ToMicroseconds());
-  SeekJob seekJob;
-  seekJob.mTarget = aTarget;
-  return SetState<SeekingState>(Move(seekJob));
-}
-
 void
 MediaDecoderStateMachine::
 DecodingState::HandleEndOfStream()
 {
   if (mMaster->CheckIfDecodeComplete()) {
     SetState<CompletedState>();
   } else {
     MaybeStopPrerolling();
@@ -1460,26 +1441,16 @@ DecodingState::MaybeStartBuffering()
       (mMaster->OutOfDecodedAudio() && Reader()->IsWaitingAudioData()) ||
       (mMaster->OutOfDecodedVideo() && Reader()->IsWaitingVideoData());
   }
   if (shouldBuffer) {
     SetState<BufferingState>();
   }
 }
 
-RefPtr<MediaDecoder::SeekPromise>
-MediaDecoderStateMachine::
-SeekingState::HandleSeek(SeekTarget aTarget)
-{
-  SLOG("Changed state to SEEKING (to %lld)", aTarget.GetTime().ToMicroseconds());
-  SeekJob seekJob;
-  seekJob.mTarget = aTarget;
-  return SetState<SeekingState>(Move(seekJob));
-}
-
 void
 MediaDecoderStateMachine::
 SeekingState::SeekCompleted()
 {
   int64_t seekTime = mSeekTask->GetSeekTarget().GetTime().ToMicroseconds();
   int64_t newCurrentTime = seekTime;
 
   // Setup timestamp state.
@@ -1607,36 +1578,16 @@ BufferingState::HandleEndOfStream()
   if (mMaster->CheckIfDecodeComplete()) {
     SetState<CompletedState>();
   } else {
     // Check if we can exit buffering.
     mMaster->ScheduleStateMachine();
   }
 }
 
-RefPtr<MediaDecoder::SeekPromise>
-MediaDecoderStateMachine::
-BufferingState::HandleSeek(SeekTarget aTarget)
-{
-  SLOG("Changed state to SEEKING (to %lld)", aTarget.GetTime().ToMicroseconds());
-  SeekJob seekJob;
-  seekJob.mTarget = aTarget;
-  return SetState<SeekingState>(Move(seekJob));
-}
-
-RefPtr<MediaDecoder::SeekPromise>
-MediaDecoderStateMachine::
-CompletedState::HandleSeek(SeekTarget aTarget)
-{
-  SLOG("Changed state to SEEKING (to %lld)", aTarget.GetTime().ToMicroseconds());
-  SeekJob seekJob;
-  seekJob.mTarget = aTarget;
-  return SetState<SeekingState>(Move(seekJob));
-}
-
 RefPtr<ShutdownPromise>
 MediaDecoderStateMachine::
 ShutdownState::Enter()
 {
   auto master = mMaster;
 
   master->mIsShutdown = true;
   master->mDelayedScheduler.Reset();
--- a/dom/media/SeekJob.cpp
+++ b/dom/media/SeekJob.cpp
@@ -36,17 +36,18 @@ SeekJob& SeekJob::operator=(SeekJob&& aO
 bool SeekJob::Exists() const
 {
   MOZ_ASSERT(mTarget.IsValid() == !mPromise.IsEmpty());
   return mTarget.IsValid();
 }
 
 void SeekJob::Resolve(bool aAtEnd, const char* aCallSite)
 {
-  MediaDecoder::SeekResolveValue val(aAtEnd, mTarget.mEventVisibility);
+  MediaDecoder::SeekResolveValue val;
+  val.mAtEnd = aAtEnd;
   mPromise.Resolve(val, aCallSite);
   mTarget.Reset();
 }
 
 void SeekJob::RejectIfExists(const char* aCallSite)
 {
   mTarget.Reset();
   mPromise.RejectIfExists(true, aCallSite);
--- a/dom/media/SeekTarget.h
+++ b/dom/media/SeekTarget.h
@@ -22,47 +22,39 @@ enum class MediaDecoderEventVisibility :
 struct SeekTarget {
   enum Type {
     Invalid,
     PrevSyncPoint,
     Accurate,
     NextFrame,
   };
   SeekTarget()
-    : mEventVisibility(MediaDecoderEventVisibility::Observable)
-    , mTime(media::TimeUnit::Invalid())
+    : mTime(media::TimeUnit::Invalid())
     , mType(SeekTarget::Invalid)
     , mVideoOnly(false)
   {
   }
   SeekTarget(int64_t aTimeUsecs,
              Type aType,
-             MediaDecoderEventVisibility aEventVisibility =
-               MediaDecoderEventVisibility::Observable,
              bool aVideoOnly = false)
-    : mEventVisibility(aEventVisibility)
-    , mTime(media::TimeUnit::FromMicroseconds(aTimeUsecs))
+    : mTime(media::TimeUnit::FromMicroseconds(aTimeUsecs))
     , mType(aType)
     , mVideoOnly(aVideoOnly)
   {
   }
   SeekTarget(const media::TimeUnit& aTime,
              Type aType,
-             MediaDecoderEventVisibility aEventVisibility =
-               MediaDecoderEventVisibility::Observable,
              bool aVideoOnly = false)
-    : mEventVisibility(aEventVisibility)
-    , mTime(aTime)
+    : mTime(aTime)
     , mType(aType)
     , mVideoOnly(aVideoOnly)
   {
   }
   SeekTarget(const SeekTarget& aOther)
-    : mEventVisibility(aOther.mEventVisibility)
-    , mTime(aOther.mTime)
+    : mTime(aOther.mTime)
     , mType(aOther.mType)
     , mVideoOnly(aOther.mVideoOnly)
   {
   }
   bool IsValid() const {
     return mType != SeekTarget::Invalid;
   }
   void Reset() {
@@ -92,18 +84,16 @@ struct SeekTarget {
   }
   bool IsNextFrame() const {
     return mType == SeekTarget::Type::NextFrame;
   }
   bool IsVideoOnly() const {
     return mVideoOnly;
   }
 
-  MediaDecoderEventVisibility mEventVisibility;
-
 private:
   // Seek target time.
   media::TimeUnit mTime;
   // Whether we should seek "Fast", or "Accurate".
   // "Fast" seeks to the seek point preceding mTime, whereas
   // "Accurate" seeks as close as possible to mTime.
   Type mType;
   bool mVideoOnly;
--- a/dom/media/test/external/external_media_harness/testcase.py
+++ b/dom/media/test/external/external_media_harness/testcase.py
@@ -6,25 +6,25 @@ import re
 import os
 import time
 
 from marionette import BrowserMobProxyTestCaseMixin, MarionetteTestCase, Marionette
 from marionette_driver import Wait
 from marionette_driver.errors import TimeoutException
 from marionette.marionette_test import SkipTest
 
-from firefox_puppeteer.testcases import BaseFirefoxTestCase
+from firefox_puppeteer import PuppeteerMixin
 from external_media_tests.utils import (timestamp_now, verbose_until)
 from external_media_tests.media_utils.video_puppeteer import (
     VideoException,
     VideoPuppeteer
 )
 
 
-class MediaTestCase(BaseFirefoxTestCase, MarionetteTestCase):
+class MediaTestCase(PuppeteerMixin, MarionetteTestCase):
 
     """
     Necessary methods for MSE playback
 
     :param video_urls: Urls you are going to play as part of the tests.
     """
 
     def __init__(self, *args, **kwargs):
--- a/dom/media/test/external/requirements.txt
+++ b/dom/media/test/external/requirements.txt
@@ -12,9 +12,9 @@ moznetwork==0.27
 mozprocess==0.23
 mozprofile==0.28
 mozrunner==6.12
 moztest==0.7
 mozversion==1.4
 wptserve==1.3.0
 marionette-client==3.1.0
 marionette-driver==2.0.0
-firefox-puppeteer >= 52.0.0, <53.0.0
+firefox-puppeteer >= 52.1.0, <53.0.0
--- a/dom/webidl/Range.webidl
+++ b/dom/webidl/Range.webidl
@@ -81,8 +81,18 @@ partial interface Range {
   DocumentFragment createContextualFragment(DOMString fragment);
 };
 
 // http://dvcs.w3.org/hg/csswg/raw-file/tip/cssom-view/Overview.html#extensions-to-the-range-interface
 partial interface Range {
   DOMRectList? getClientRects();
   DOMRect getBoundingClientRect();
 };
+
+dictionary ClientRectsAndTexts {
+  required DOMRectList rectList;
+  required DOMStringList textList;
+};
+
+partial interface Range {
+  [ChromeOnly, Throws]
+  ClientRectsAndTexts getClientRectsAndTexts();
+};
--- a/editor/libeditor/EditorBase.cpp
+++ b/editor/libeditor/EditorBase.cpp
@@ -1995,36 +1995,41 @@ EditorBase::RestorePreservedSelection(Se
 
 void
 EditorBase::StopPreservingSelection()
 {
   mRangeUpdater.DropSelectionState(mSavedSel);
   mSavedSel.MakeEmpty();
 }
 
-void
+bool
 EditorBase::EnsureComposition(WidgetCompositionEvent* aCompositionEvent)
 {
   if (mComposition) {
-    return;
+    return true;
   }
   // The compositionstart event must cause creating new TextComposition
   // instance at being dispatched by IMEStateManager.
   mComposition = IMEStateManager::GetTextCompositionFor(aCompositionEvent);
   if (!mComposition) {
-    MOZ_CRASH("IMEStateManager doesn't return proper composition");
+    // However, TextComposition may be committed before the composition
+    // event comes here.
+    return false;
   }
   mComposition->StartHandlingComposition(this);
+  return true;
 }
 
 nsresult
 EditorBase::BeginIMEComposition(WidgetCompositionEvent* aCompositionEvent)
 {
   MOZ_ASSERT(!mComposition, "There is composition already");
-  EnsureComposition(aCompositionEvent);
+  if (!EnsureComposition(aCompositionEvent)) {
+    return NS_OK;
+  }
   if (mPhonetic) {
     mPhonetic->Truncate(0);
   }
   return NS_OK;
 }
 
 void
 EditorBase::EndIMEComposition()
--- a/editor/libeditor/EditorBase.h
+++ b/editor/libeditor/EditorBase.h
@@ -436,18 +436,24 @@ protected:
     // or not.
     return !IsPasswordEditor() && !IsReadonly() && !IsDisabled() &&
            !ShouldSkipSpellCheck();
   }
 
   /**
    * EnsureComposition() should be called by composition event handlers.  This
    * tries to get the composition for the event and set it to mComposition.
+   * However, this may fail because the composition may be committed before
+   * the event comes to the editor.
+   *
+   * @return            true if there is a composition.  Otherwise, for example,
+   *                    a composition event handler in web contents moved focus
+   *                    for committing the composition, returns false.
    */
-  void EnsureComposition(WidgetCompositionEvent* aCompositionEvent);
+  bool EnsureComposition(WidgetCompositionEvent* aCompositionEvent);
 
   nsresult GetSelection(SelectionType aSelectionType,
                         nsISelection** aSelection);
 
 public:
   /**
    * All editor operations which alter the doc should be prefaced
    * with a call to StartOperation, naming the action and direction.
--- a/editor/libeditor/TextEditor.cpp
+++ b/editor/libeditor/TextEditor.cpp
@@ -839,17 +839,19 @@ TextEditor::UpdateIMEComposition(nsIDOME
   MOZ_ASSERT(aDOMTextEvent, "aDOMTextEvent must not be nullptr");
 
   WidgetCompositionEvent* compositionChangeEvent =
     aDOMTextEvent->WidgetEventPtr()->AsCompositionEvent();
   NS_ENSURE_TRUE(compositionChangeEvent, NS_ERROR_INVALID_ARG);
   MOZ_ASSERT(compositionChangeEvent->mMessage == eCompositionChange,
              "The internal event should be eCompositionChange");
 
-  EnsureComposition(compositionChangeEvent);
+  if (!EnsureComposition(compositionChangeEvent)) {
+    return NS_OK;
+  }
 
   nsCOMPtr<nsIPresShell> ps = GetPresShell();
   NS_ENSURE_TRUE(ps, NS_ERROR_NOT_INITIALIZED);
 
   RefPtr<Selection> selection = GetSelection();
   NS_ENSURE_STATE(selection);
 
   // NOTE: TextComposition should receive selection change notification before
--- a/editor/libeditor/tests/mochitest.ini
+++ b/editor/libeditor/tests/mochitest.ini
@@ -195,16 +195,17 @@ subsuite = clipboard
 skip-if = toolkit == 'android' # bug 1299578
 [test_bug1153237.html]
 [test_bug1154791.html]
 skip-if = os == 'android'
 [test_bug1162952.html]
 [test_bug1181130-1.html]
 [test_bug1181130-2.html]
 [test_bug1186799.html]
+[test_bug1230473.html]
 [test_bug1247483.html]
 subsuite = clipboard
 skip-if = toolkit == 'android'
 [test_bug1248128.html]
 [test_bug1250010.html]
 [test_bug1257363.html]
 [test_bug1248185.html]
 [test_bug1258085.html]
new file mode 100644
--- /dev/null
+++ b/editor/libeditor/tests/test_bug1230473.html
@@ -0,0 +1,124 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1230473
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for Bug 1230473</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1230473">Mozilla Bug 1230473</a>
+<input id="input">
+<textarea id="textarea"></textarea>
+<div id="div" contenteditable></div>
+<script type="application/javascript">
+/** Test for Bug 1230473 **/
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(()=>{
+  function runTest(aEditor) {
+    function committer() {
+      aEditor.blur();
+      aEditor.focus();
+    }
+    function isNSEditableElement() {
+      return aEditor.tagName.toLowerCase() == "input" || aEditor.tagName.toLowerCase() == "textarea";
+    }
+    function value() {
+      return isNSEditableElement() ? aEditor.value : aEditor.textContent;
+    }
+    function isComposing() {
+      return isNSEditableElement() ?  SpecialPowers.wrap(aEditor)
+                                                   .QueryInterface(SpecialPowers.Ci.nsIDOMNSEditableElement)
+                                                   .editor
+                                                   .QueryInterface(SpecialPowers.Ci.nsIEditorIMESupport)
+                                                   .composing :
+                                      SpecialPowers.wrap(window)
+                                                   .QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor)
+                                                   .getInterface(SpecialPowers.Ci.nsIWebNavigation)
+                                                   .QueryInterface(SpecialPowers.Ci.nsIDocShell)
+                                                   .editor
+                                                   .QueryInterface(SpecialPowers.Ci.nsIEditorIMESupport)
+                                                   .composing;
+    }
+    function clear() {
+      if (isNSEditableElement()) {
+        aEditor.value = "";
+      } else {
+        aEditor.textContent = "";
+      }
+    }
+
+    clear();
+
+    // Committing at compositionstart
+    aEditor.focus();
+    aEditor.addEventListener("compositionstart", committer, true);
+    synthesizeCompositionChange({ composition: { string: "a", clauses: [{length: 1, attr: COMPOSITION_ATTR_RAW_CLAUSE }] },
+                                  caret: { start: 1, length: 0 }});
+    aEditor.removeEventListener("compositionstart", committer, true);
+    ok(!isComposing(), "composition in " + aEditor.id + " should be committed by compositionstart event handler");
+    is(value(), "", "composition in " + aEditor.id + " shouldn't insert any text since it's committed at compositionstart");
+    clear();
+
+    // Committing at first compositionupdate
+    aEditor.focus();
+    aEditor.addEventListener("compositionupdate", committer, true);
+    synthesizeCompositionChange({ composition: { string: "a", clauses: [{length: 1, attr: COMPOSITION_ATTR_RAW_CLAUSE }] },
+                                  caret: { start: 1, length: 0 }});
+    aEditor.removeEventListener("compositionupdate", committer, true);
+    ok(!isComposing(), "composition in " + aEditor.id + " should be committed by compositionupdate event handler");
+    is(value(), "", "composition in " + aEditor.id + " shouldn't have inserted any text since it's committed at first compositionupdate");
+    clear();
+
+    // Committing at first text (eCompositionChange)
+    aEditor.focus();
+    aEditor.addEventListener("text", committer, true);
+    synthesizeCompositionChange({ composition: { string: "a", clauses: [{length: 1, attr: COMPOSITION_ATTR_RAW_CLAUSE }] },
+                                  caret: { start: 1, length: 0 }});
+    aEditor.removeEventListener("text", committer, true);
+    ok(!isComposing(), "composition in " + aEditor.id + " should be committed by text event handler");
+    is(value(), "", "composition in " + aEditor.id + " should have inserted any text since it's committed at first text");
+    clear();
+
+    // Committing at second compositionupdate
+    aEditor.focus();
+    synthesizeComposition({ type: "compositionstart" });
+    synthesizeCompositionChange({ composition: { string: "a", clauses: [{length: 1, attr: COMPOSITION_ATTR_RAW_CLAUSE }] },
+                                  caret: { start: 1, length: 0 }});
+    ok(isComposing(), "composition should be in " + aEditor.id + " before dispatching second compositionupdate");
+    is(value(), "a", "composition in " + aEditor.id + " should be 'a' before dispatching second compositionupdate");
+    aEditor.addEventListener("compositionupdate", committer, true);
+    synthesizeCompositionChange({ composition: { string: "ab", clauses: [{length: 2, attr: COMPOSITION_ATTR_RAW_CLAUSE }] },
+                                  caret: { start: 2, length: 0 }});
+    aEditor.removeEventListener("compositionupdate", committer, true);
+    ok(!isComposing(), "composition in " + aEditor.id + " should be committed by compositionupdate event handler");
+    todo_is(value(), "a", "composition in " + aEditor.id + " shouldn't have been modified since it's committed at second compositionupdate");
+    clear();
+
+    // Committing at second text (eCompositionChange)
+    aEditor.focus();
+    synthesizeComposition({ type: "compositionstart" });
+    synthesizeCompositionChange({ composition: { string: "a", clauses: [{length: 1, attr: COMPOSITION_ATTR_RAW_CLAUSE }] },
+                                  caret: { start: 1, length: 0 }});
+    ok(isComposing(), "composition should be in " + aEditor.id + " before dispatching second text");
+    is(value(), "a", "composition in " + aEditor.id + " should be 'a' before dispatching second text");
+    aEditor.addEventListener("text", committer, true);
+    synthesizeCompositionChange({ composition: { string: "ab", clauses: [{length: 2, attr: COMPOSITION_ATTR_RAW_CLAUSE }] },
+                                  caret: { start: 2, length: 0 }});
+    aEditor.removeEventListener("text", committer, true);
+    ok(!isComposing(), "composition in " + aEditor.id + " should be committed by text event handler");
+    todo_is(value(), "a", "composition in " + aEditor.id + " shouldn't have been modified since it's committed at second text");
+    clear();
+  }
+  runTest(document.getElementById("input"));
+  runTest(document.getElementById("textarea"));
+  runTest(document.getElementById("div"));
+  SimpleTest.finish();
+});
+</script>
+</body>
+</html>
--- a/gfx/ipc/GPUProcessManager.cpp
+++ b/gfx/ipc/GPUProcessManager.cpp
@@ -419,17 +419,17 @@ GPUProcessManager::DestroyProcess()
   if (mVsyncBridge) {
     mVsyncBridge->Close();
     mVsyncBridge = nullptr;
   }
 }
 
 RefPtr<CompositorSession>
 GPUProcessManager::CreateTopLevelCompositor(nsBaseWidget* aWidget,
-                                            ClientLayerManager* aLayerManager,
+                                            LayerManager* aLayerManager,
                                             CSSToLayoutDeviceScale aScale,
                                             bool aUseAPZ,
                                             bool aUseExternalSurfaceSize,
                                             const gfx::IntSize& aSurfaceSize)
 {
   uint64_t layerTreeId = AllocateLayerTreeId();
 
   EnsureGPUReady();
@@ -460,17 +460,17 @@ GPUProcessManager::CreateTopLevelComposi
     aScale,
     aUseAPZ,
     aUseExternalSurfaceSize,
     aSurfaceSize);
 }
 
 RefPtr<CompositorSession>
 GPUProcessManager::CreateRemoteSession(nsBaseWidget* aWidget,
-                                       ClientLayerManager* aLayerManager,
+                                       LayerManager* aLayerManager,
                                        const uint64_t& aRootLayerTreeId,
                                        CSSToLayoutDeviceScale aScale,
                                        bool aUseAPZ,
                                        bool aUseExternalSurfaceSize,
                                        const gfx::IntSize& aSurfaceSize)
 {
 #ifdef MOZ_WIDGET_SUPPORTS_OOP_COMPOSITING
   ipc::Endpoint<PCompositorBridgeParent> parentPipe;
--- a/gfx/ipc/GPUProcessManager.h
+++ b/gfx/ipc/GPUProcessManager.h
@@ -20,17 +20,16 @@
 #include "nsThreadUtils.h"
 class nsBaseWidget;
 
 
 namespace mozilla {
 namespace layers {
 class IAPZCTreeManager;
 class CompositorSession;
-class ClientLayerManager;
 class CompositorUpdateObserver;
 class PCompositorBridgeChild;
 class PImageBridgeChild;
 class RemoteCompositorSession;
 } // namespace layers
 namespace widget {
 class CompositorWidget;
 } // namespace widget
@@ -52,20 +51,20 @@ class VsyncIOThreadHolder;
 
 // The GPUProcessManager is a singleton responsible for creating GPU-bound
 // objects that may live in another process. Currently, it provides access
 // to the compositor via CompositorBridgeParent.
 class GPUProcessManager final : public GPUProcessHost::Listener
 {
   friend class layers::RemoteCompositorSession;
 
-  typedef layers::ClientLayerManager ClientLayerManager;
   typedef layers::CompositorSession CompositorSession;
+  typedef layers::CompositorUpdateObserver CompositorUpdateObserver;
   typedef layers::IAPZCTreeManager IAPZCTreeManager;
-  typedef layers::CompositorUpdateObserver CompositorUpdateObserver;
+  typedef layers::LayerManager LayerManager;
   typedef layers::PCompositorBridgeChild PCompositorBridgeChild;
   typedef layers::PImageBridgeChild PImageBridgeChild;
   typedef layers::RemoteCompositorSession RemoteCompositorSession;
 
 public:
   static void Initialize();
   static void Shutdown();
   static GPUProcessManager* Get();
@@ -77,17 +76,17 @@ public:
 
   // Ensure that GPU-bound methods can be used. If no GPU process is being
   // used, or one is launched and ready, this function returns immediately.
   // Otherwise it blocks until the GPU process has finished launching.
   void EnsureGPUReady();
 
   RefPtr<CompositorSession> CreateTopLevelCompositor(
     nsBaseWidget* aWidget,
-    ClientLayerManager* aLayerManager,
+    LayerManager* aLayerManager,
     CSSToLayoutDeviceScale aScale,
     bool aUseAPZ,
     bool aUseExternalSurfaceSize,
     const gfx::IntSize& aSurfaceSize);
 
   bool CreateContentBridges(
     base::ProcessId aOtherProcess,
     ipc::Endpoint<PCompositorBridgeChild>* aOutCompositor,
@@ -180,17 +179,17 @@ private:
   void EnsureVsyncIOThread();
   void ShutdownVsyncIOThread();
 
   void EnsureImageBridgeChild();
   void EnsureVRManager();
 
   RefPtr<CompositorSession> CreateRemoteSession(
     nsBaseWidget* aWidget,
-    ClientLayerManager* aLayerManager,
+    LayerManager* aLayerManager,
     const uint64_t& aRootLayerTreeId,
     CSSToLayoutDeviceScale aScale,
     bool aUseAPZ,
     bool aUseExternalSurfaceSize,
     const gfx::IntSize& aSurfaceSize);
 
   DISALLOW_COPY_AND_ASSIGN(GPUProcessManager);
 
--- a/gfx/ipc/InProcessCompositorSession.cpp
+++ b/gfx/ipc/InProcessCompositorSession.cpp
@@ -19,17 +19,17 @@ InProcessCompositorSession::InProcessCom
  : CompositorSession(aWidget->AsDelegate(), aChild, aParent->RootLayerTreeId()),
    mCompositorBridgeParent(aParent),
    mCompositorWidget(aWidget)
 {
 }
 
 /* static */ RefPtr<InProcessCompositorSession>
 InProcessCompositorSession::Create(nsIWidget* aWidget,
-                                   ClientLayerManager* aLayerManager,
+                                   LayerManager* aLayerManager,
                                    const uint64_t& aRootLayerTreeId,
                                    CSSToLayoutDeviceScale aScale,
                                    bool aUseAPZ,
                                    bool aUseExternalSurfaceSize,
                                    const gfx::IntSize& aSurfaceSize)
 {
   CompositorWidgetInitData initData;
   aWidget->GetCompositorWidgetInitData(&initData);
--- a/gfx/ipc/InProcessCompositorSession.h
+++ b/gfx/ipc/InProcessCompositorSession.h
@@ -15,17 +15,17 @@ namespace layers {
 
 // A CompositorSession where both the child and parent CompositorBridge reside
 // in the same process.
 class InProcessCompositorSession final : public CompositorSession
 {
 public:
   static RefPtr<InProcessCompositorSession> Create(
     nsIWidget* aWidget,
-    ClientLayerManager* aLayerManager,
+    LayerManager* aLayerManager,
     const uint64_t& aRootLayerTreeId,
     CSSToLayoutDeviceScale aScale,
     bool aUseAPZ,
     bool aUseExternalSurfaceSize,
     const gfx::IntSize& aSurfaceSize);
 
   CompositorBridgeParent* GetInProcessBridge() const override;
   void SetContentController(GeckoContentController* aController) override;
--- a/gfx/layers/ipc/CompositorBridgeChild.cpp
+++ b/gfx/layers/ipc/CompositorBridgeChild.cpp
@@ -69,17 +69,17 @@ static void ShmemAllocated(CompositorBri
     MOZ_PERFORMANCE_WARNING("gfx", "The number of shmem allocations is too damn high!");
   }
 }
 
 static StaticRefPtr<CompositorBridgeChild> sCompositorBridge;
 
 Atomic<int32_t> KnowsCompositor::sSerialCounter(0);
 
-CompositorBridgeChild::CompositorBridgeChild(ClientLayerManager *aLayerManager)
+CompositorBridgeChild::CompositorBridgeChild(LayerManager *aLayerManager)
   : mLayerManager(aLayerManager)
   , mCanSend(false)
   , mFwdTransactionId(0)
   , mMessageLoop(MessageLoop::current())
   , mSectionAllocator(nullptr)
 {
   MOZ_ASSERT(NS_IsMainThread());
 }
@@ -251,17 +251,17 @@ CompositorBridgeChild::InitSameProcess(w
 
   InitIPDL();
   mCompositorBridgeParent->InitSameProcess(aWidget, aLayerTreeId, aUseAPZ);
   return mCompositorBridgeParent;
 }
 
 /* static */ RefPtr<CompositorBridgeChild>
 CompositorBridgeChild::CreateRemote(const uint64_t& aProcessToken,
-                                    ClientLayerManager* aLayerManager,
+                                    LayerManager* aLayerManager,
                                     Endpoint<PCompositorBridgeChild>&& aEndpoint)
 {
   RefPtr<CompositorBridgeChild> child = new CompositorBridgeChild(aLayerManager);
   if (!aEndpoint.Bind(child)) {
     return nullptr;
   }
   child->InitIPDL();
   child->mProcessToken = aProcessToken;
@@ -533,17 +533,18 @@ CompositorBridgeChild::RecvHideAllPlugin
 
 bool
 CompositorBridgeChild::RecvDidComposite(const uint64_t& aId, const uint64_t& aTransactionId,
                                         const TimeStamp& aCompositeStart,
                                         const TimeStamp& aCompositeEnd)
 {
   if (mLayerManager) {
     MOZ_ASSERT(aId == 0);
-    RefPtr<ClientLayerManager> m = mLayerManager;
+    RefPtr<ClientLayerManager> m = mLayerManager->AsClientLayerManager();
+    MOZ_ASSERT(m);
     m->DidComposite(aTransactionId, aCompositeStart, aCompositeEnd);
   } else if (aId != 0) {
     RefPtr<dom::TabChild> child = dom::TabChild::GetFrom(aId);
     if (child) {
       child->DidComposite(aTransactionId, aCompositeStart, aCompositeEnd);
     }
   }
 
--- a/gfx/layers/ipc/CompositorBridgeChild.h
+++ b/gfx/layers/ipc/CompositorBridgeChild.h
@@ -45,17 +45,17 @@ struct FrameMetrics;
 class CompositorBridgeChild final : public PCompositorBridgeChild,
                                     public TextureForwarder
 {
   typedef InfallibleTArray<AsyncParentMessageData> AsyncParentMessageArray;
 
 public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CompositorBridgeChild, override);
 
-  explicit CompositorBridgeChild(ClientLayerManager *aLayerManager);
+  explicit CompositorBridgeChild(LayerManager *aLayerManager);
 
   void Destroy();
 
   /**
    * Lookup the FrameMetrics shared by the compositor process with the
    * associated FrameMetrics::ViewID. The returned FrameMetrics is used
    * in progressive paint calculations.
    */
@@ -64,17 +64,17 @@ public:
   /**
    * Initialize the singleton compositor bridge for a content process.
    */
   static bool InitForContent(Endpoint<PCompositorBridgeChild>&& aEndpoint);
   static bool ReinitForContent(Endpoint<PCompositorBridgeChild>&& aEndpoint);
 
   static RefPtr<CompositorBridgeChild> CreateRemote(
     const uint64_t& aProcessToken,
-    ClientLayerManager* aLayerManager,
+    LayerManager* aLayerManager,
     Endpoint<PCompositorBridgeChild>&& aEndpoint);
 
   /**
    * Initialize the CompositorBridgeChild, create CompositorBridgeParent, and
    * open a same-process connection.
    */
   CompositorBridgeParent* InitSameProcess(
     widget::CompositorWidget* aWidget,
@@ -280,17 +280,17 @@ private:
     // the shared FrameMetrics
     RefPtr<mozilla::ipc::SharedMemoryBasic> mBuffer;
     CrossProcessMutex* mMutex;
     uint64_t mLayersId;
     // Unique ID of the APZC that is sharing the FrameMetrics
     uint32_t mAPZCId;
   };
 
-  RefPtr<ClientLayerManager> mLayerManager;
+  RefPtr<LayerManager> mLayerManager;
   // When not multi-process, hold a reference to the CompositorBridgeParent to keep it
   // alive. This reference should be null in multi-process.
   RefPtr<CompositorBridgeParent> mCompositorBridgeParent;
 
   // The ViewID of the FrameMetrics is used as the key for this hash table.
   // While this should be safe to use since the ViewID is unique
   nsClassHashtable<nsUint64HashKey, SharedFrameMetricsData> mFrameMetricsTable;
 
--- a/gfx/thebes/gfxQuartzNativeDrawing.cpp
+++ b/gfx/thebes/gfxQuartzNativeDrawing.cpp
@@ -19,17 +19,18 @@ gfxQuartzNativeDrawing::gfxQuartzNativeD
 }
 
 CGContextRef
 gfxQuartzNativeDrawing::BeginNativeDrawing()
 {
   NS_ASSERTION(!mCGContext, "BeginNativeDrawing called when drawing already in progress");
 
   DrawTarget *dt = mDrawTarget;
-  if (dt->IsDualDrawTarget() || dt->IsTiledDrawTarget()) {
+  if (dt->IsDualDrawTarget() || dt->IsTiledDrawTarget() ||
+      dt->GetBackendType() != BackendType::SKIA) {
     // We need a DrawTarget that we can get a CGContextRef from:
     Matrix transform = dt->GetTransform();
 
     mNativeRect = transform.TransformBounds(mNativeRect);
     mNativeRect.RoundOut();
     // Quartz theme drawing often adjusts drawing rects, so make
     // sure our surface is big enough for that.
     mNativeRect.Inflate(5);
@@ -44,16 +45,17 @@ gfxQuartzNativeDrawing::BeginNativeDrawi
 
     if (mTempDrawTarget) {
         transform.PostTranslate(-mNativeRect.x, -mNativeRect.y);
         mTempDrawTarget->SetTransform(transform);
     }
     dt = mTempDrawTarget;
   }
   if (dt) {
+    MOZ_ASSERT(dt->GetBackendType() == BackendType::SKIA);
     mCGContext = mBorrowedContext.Init(dt);
     MOZ_ASSERT(mCGContext);
   }
   return mCGContext;
 }
 
 void
 gfxQuartzNativeDrawing::EndNativeDrawing()
--- a/gfx/vr/VRDisplayHost.cpp
+++ b/gfx/vr/VRDisplayHost.cpp
@@ -168,9 +168,21 @@ VRControllerHost::SetIndex(uint32_t aInd
 {
   mIndex = aIndex;
 }
 
 uint32_t
 VRControllerHost::GetIndex()
 {
   return mIndex;
-}
\ No newline at end of file
+}
+
+void
+VRControllerHost::SetButtonPressed(uint64_t aBit)
+{
+  mButtonPressed = aBit;
+}
+
+uint64_t
+VRControllerHost::GetButtonPressed()
+{
+  return mButtonPressed;
+}
--- a/gfx/vr/VRDisplayHost.h
+++ b/gfx/vr/VRDisplayHost.h
@@ -85,22 +85,26 @@ private:
 
 class VRControllerHost {
 public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VRControllerHost)
 
   const VRControllerInfo& GetControllerInfo() const;
   void SetIndex(uint32_t aIndex);
   uint32_t GetIndex();
+  void SetButtonPressed(uint64_t aBit);
+  uint64_t GetButtonPressed();
 
 protected:
   explicit VRControllerHost(VRDeviceType aType);
   virtual ~VRControllerHost();
 
   VRControllerInfo mControllerInfo;
   // The controller index in VRControllerManager.
   uint32_t mIndex;
+  // The current button pressed bit of button mask.
+  uint64_t mButtonPressed;
 };
 
 } // namespace gfx
 } // namespace mozilla
 
 #endif /* GFX_VR_DISPLAY_HOST_H */
--- a/gfx/vr/gfxVR.cpp
+++ b/gfx/vr/gfxVR.cpp
@@ -1,17 +1,20 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include <math.h>
 
 #include "gfxVR.h"
-#include "mozilla/dom/Gamepad.h"
+#ifdef MOZ_GAMEPAD
+#include "mozilla/dom/GamepadEventTypes.h"
+#include "mozilla/dom/GamepadBinding.h"
+#endif
 
 #ifndef M_PI
 # define M_PI 3.14159265358979323846
 #endif
 
 using namespace mozilla;
 using namespace mozilla::gfx;
 
@@ -60,18 +63,17 @@ VRFieldOfView::ConstructProjectionMatrix
 
 /* static */ uint32_t
 VRControllerManager::AllocateControllerID()
 {
   return ++sControllerBase;
 }
 
 void
-VRControllerManager::AddGamepad(const char* aID,
-                                dom::GamepadMappingType aMapping,
+VRControllerManager::AddGamepad(const char* aID, uint32_t aMapping,
                                 uint32_t aNumButtons, uint32_t aNumAxes)
 {
   dom::GamepadAdded a(NS_ConvertUTF8toUTF16(nsDependentCString(aID)), mControllerCount,
                      aMapping, dom::GamepadServiceType::VR, aNumButtons,
                      aNumAxes);
 
   VRManager* vm = VRManager::Get();
   MOZ_ASSERT(vm);
--- a/gfx/vr/gfxVR.h
+++ b/gfx/vr/gfxVR.h
@@ -10,17 +10,16 @@
 #include "nsString.h"
 #include "nsCOMPtr.h"
 #include "mozilla/RefPtr.h"
 #include "mozilla/gfx/2D.h"
 #include "mozilla/Atomics.h"
 #include "mozilla/EnumeratedArray.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/TypedEnumBits.h"
-#include "mozilla/dom/GamepadBinding.h"
 
 namespace mozilla {
 namespace layers {
 class PTextureParent;
 }
 namespace gfx {
 class VRLayerParent;
 class VRDisplayHost;
@@ -211,24 +210,24 @@ protected:
   virtual ~VRDisplayManager() { }
 };
 
 struct VRControllerInfo
 {
   VRDeviceType GetType() const { return mType; }
   uint32_t GetControllerID() const { return mControllerID; }
   const nsCString& GetControllerName() const { return mControllerName; }
-  dom::GamepadMappingType GetMappingType() const { return mMappingType; }
+  uint32_t GetMappingType() const { return mMappingType; }
   uint32_t GetNumButtons() const { return mNumButtons; }
   uint32_t GetNumAxes() const { return mNumAxes; }
 
   uint32_t mControllerID;
   VRDeviceType mType;
   nsCString mControllerName;
-  dom::GamepadMappingType mMappingType;
+  uint32_t mMappingType;
   uint32_t mNumButtons;
   uint32_t mNumAxes;
 
   bool operator==(const VRControllerInfo& other) const {
   return mType == other.mType &&
          mControllerID == other.mControllerID &&
          mControllerName == other.mControllerName &&
          mMappingType == other.mMappingType &&
@@ -248,17 +247,17 @@ public:
   static uint32_t AllocateControllerID();
   virtual bool Init() = 0;
   virtual void Destroy() = 0;
   virtual void HandleInput() = 0;
   virtual void GetControllers(nsTArray<RefPtr<VRControllerHost>>& aControllerResult) = 0;
   virtual void ScanForDevices() = 0;
   void NewButtonEvent(uint32_t aIndex, uint32_t aButton, bool aPressed);
   void NewAxisMove(uint32_t aIndex, uint32_t aAxis, double aValue);
-  void AddGamepad(const char* aID, dom::GamepadMappingType aMapping,
+  void AddGamepad(const char* aID, uint32_t aMapping,
                   uint32_t aNumButtons, uint32_t aNumAxes);
   void RemoveGamepad(uint32_t aIndex);
 
 protected:
   VRControllerManager() : mInstalled(false), mControllerCount(0) {}
   virtual ~VRControllerManager() {}
 
   bool mInstalled;
--- a/gfx/vr/gfxVROpenVR.cpp
+++ b/gfx/vr/gfxVROpenVR.cpp
@@ -19,17 +19,21 @@
 #include "TextureD3D11.h"
 #endif // XP_WIN
 
 #include "gfxVROpenVR.h"
 
 #include "nsServiceManagerUtils.h"
 #include "nsIScreenManager.h"
 #include "openvr/openvr.h"
-#include "mozilla/dom/Gamepad.h"
+
+#ifdef MOZ_GAMEPAD
+#include "mozilla/dom/GamepadEventTypes.h"
+#include "mozilla/dom/GamepadBinding.h"
+#endif
 
 #ifndef M_PI
 # define M_PI 3.14159265358979323846
 #endif
 
 using namespace mozilla;
 using namespace mozilla::gfx;
 using namespace mozilla::gfx::impl;
@@ -480,17 +484,21 @@ VRDisplayManagerOpenVR::GetHMDs(nsTArray
   }
 }
 
 VRControllerOpenVR::VRControllerOpenVR()
   : VRControllerHost(VRDeviceType::OpenVR)
 {
   MOZ_COUNT_CTOR_INHERITED(VRControllerOpenVR, VRControllerHost);
   mControllerInfo.mControllerName.AssignLiteral("OpenVR HMD");
-  mControllerInfo.mMappingType = dom::GamepadMappingType::_empty;
+#ifdef MOZ_GAMEPAD
+  mControllerInfo.mMappingType = static_cast<uint32_t>(dom::GamepadMappingType::_empty);
+#else
+  mControllerInfo.mMappingType = 0;
+#endif
   mControllerInfo.mNumButtons = gNumOpenVRButtonMask;
   mControllerInfo.mNumAxes = gNumOpenVRAxis;
 }
 
 VRControllerOpenVR::~VRControllerOpenVR()
 {
   MOZ_COUNT_DTOR_INHERITED(VRControllerOpenVR, VRControllerHost);
 }
@@ -578,19 +586,17 @@ VRControllerManagerOpenVR::HandleInput()
   // Process OpenVR controller state
   for (uint32_t i = 0; i < mOpenVRController.Length(); ++i) {
     controller = mOpenVRController[i];
 
     MOZ_ASSERT(mVRSystem->GetTrackedDeviceClass(controller->GetTrackedIndex())
                == vr::TrackedDeviceClass_Controller);
 
     if (mVRSystem->GetControllerState(controller->GetTrackedIndex(), &state)) {
-      if (state.ulButtonPressed) {
-        HandleButtonPress(controller->GetIndex(), state.ulButtonPressed);
-      }
+      HandleButtonPress(controller->GetIndex(), state.ulButtonPressed);
 
       axis = static_cast<uint32_t>(VRControllerAxisType::TrackpadXAxis);
       HandleAxisMove(controller->GetIndex(), axis,
                      state.rAxis[gOpenVRAxes[axis]].x);
 
       axis = static_cast<uint32_t>(VRControllerAxisType::TrackpadYAxis);
       HandleAxisMove(controller->GetIndex(), axis,
                      state.rAxis[gOpenVRAxes[axis]].y);
@@ -602,21 +608,36 @@ VRControllerManagerOpenVR::HandleInput()
   }
 }
 
 void
 VRControllerManagerOpenVR::HandleButtonPress(uint32_t aControllerIdx,
                                              uint64_t aButtonPressed)
 {
   uint64_t buttonMask = 0;
+  RefPtr<impl::VRControllerOpenVR> controller;
+  controller = mOpenVRController[aControllerIdx];
+  uint64_t diff = (controller->GetButtonPressed() ^ aButtonPressed);
+
+  if (!diff) {
+    return;
+  }
 
   for (uint32_t i = 0; i < gNumOpenVRButtonMask; ++i) {
     buttonMask = gOpenVRButtonMask[i];
-    NewButtonEvent(aControllerIdx, i, aButtonPressed & buttonMask);
+
+    if (diff & buttonMask) {
+      // diff & aButtonPressed would be true while a new button press
+      // event, otherwise it is an old press event and needs to notify
+      // the button has been released.
+      NewButtonEvent(aControllerIdx, i, diff & aButtonPressed);
+    }
   }
+
+  controller->SetButtonPressed(aButtonPressed);
 }
 
 void
 VRControllerManagerOpenVR::HandleAxisMove(uint32_t aControllerIdx, uint32_t aAxis,
                                           float aValue)
 {
   if (aValue != 0.0f) {
     NewAxisMove(aControllerIdx, aAxis, aValue);
@@ -660,14 +681,17 @@ VRControllerManagerOpenVR::ScanForDevice
       continue;
     }
 
     RefPtr<VRControllerOpenVR> openVRController = new VRControllerOpenVR();
     openVRController->SetIndex(mControllerCount);
     openVRController->SetTrackedIndex(trackedDevice);
     mOpenVRController.AppendElement(openVRController);
 
+// Only in MOZ_GAMEPAD platform, We add gamepads.
+#ifdef MOZ_GAMEPAD
     // Not already present, add it.
-    AddGamepad("OpenVR Gamepad", GamepadMappingType::_empty,
+    AddGamepad("OpenVR Gamepad", static_cast<uint32_t>(GamepadMappingType::_empty),
                gNumOpenVRButtonMask, gNumOpenVRAxis);
     ++mControllerCount;
+#endif
   }
 }
\ No newline at end of file
--- a/gfx/vr/ipc/VRManagerChild.cpp
+++ b/gfx/vr/ipc/VRManagerChild.cpp
@@ -10,20 +10,23 @@
 #include "VRDisplayClient.h"
 #include "nsGlobalWindow.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/layers/CompositorThread.h" // for CompositorThread
 #include "mozilla/dom/Navigator.h"
 #include "mozilla/dom/VREventObserver.h"
 #include "mozilla/dom/WindowBinding.h" // for FrameRequestCallback
 #include "mozilla/dom/ContentChild.h"
-#include "mozilla/dom/GamepadManager.h"
 #include "mozilla/layers/TextureClient.h"
 #include "nsContentUtils.h"
 
+#ifdef MOZ_GAMEPAD
+#include "mozilla/dom/GamepadManager.h"
+#endif
+
 using layers::TextureClient;
 
 namespace {
 const nsTArray<RefPtr<dom::VREventObserver>>::index_type kNoIndex =
   nsTArray<RefPtr<dom::VREventObserver> >::NoIndex;
 } // namespace
 
 namespace mozilla {
@@ -465,22 +468,24 @@ VRManagerChild::RecvNotifyVRVSync(const 
   }
 
   return true;
 }
 
 bool
 VRManagerChild::RecvGamepadUpdate(const GamepadChangeEvent& aGamepadEvent)
 {
+#ifdef MOZ_GAMEPAD
   // VRManagerChild could be at other processes, but GamepadManager
   // only exists at the content process or the parent process
   // in non-e10s mode.
   if (mGamepadManager) {
       mGamepadManager->Update(aGamepadEvent);
   }
+#endif
 
   return true;
 }
 
 void
 VRManagerChild::RunFrameRequestCallbacks()
 {
   TimeStamp nowTime = TimeStamp::Now();
--- a/ipc/mscom/MainThreadHandoff.cpp
+++ b/ipc/mscom/MainThreadHandoff.cpp
@@ -251,20 +251,28 @@ MainThreadHandoff::FixArrayElements(ICal
     // ICallFrame::GetParam is not able to coerce the param into a VARIANT.
     // That's ok, we can try to do it ourselves.
     CALLFRAMEPARAMINFO paramInfo;
     hr = aFrame->GetParamInfo(aArrayData.mArrayParamIndex, &paramInfo);
     if (FAILED(hr)) {
       return hr;
     }
     PVOID stackBase = aFrame->GetStackLocation();
-    // We dereference because we need to obtain the value of a parameter
-    // from a stack offset. This pointer is the base of the array.
-    arrayPtr = *reinterpret_cast<PVOID*>(reinterpret_cast<PBYTE>(stackBase) +
-                                         paramInfo.stackOffset);
+    if (aArrayData.mFlag == ArrayData::Flag::eAllocatedByServer) {
+      // In order for the server to allocate the array's buffer and store it in
+      // an outparam, the parameter must be typed as Type***. Since the base
+      // of the array is Type*, we must dereference twice.
+      arrayPtr = **reinterpret_cast<PVOID**>(reinterpret_cast<PBYTE>(stackBase) +
+                                             paramInfo.stackOffset);
+    } else {
+      // We dereference because we need to obtain the value of a parameter
+      // from a stack offset. This pointer is the base of the array.
+      arrayPtr = *reinterpret_cast<PVOID*>(reinterpret_cast<PBYTE>(stackBase) +
+                                           paramInfo.stackOffset);
+    }
   } else if (FAILED(hr)) {
     return hr;
   } else {
     arrayPtr = ResolveArrayPtr(paramVal);
   }
 
   MOZ_ASSERT(arrayPtr);
   if (!arrayPtr) {
--- a/ipc/mscom/Registration.h
+++ b/ipc/mscom/Registration.h
@@ -76,47 +76,59 @@ UniquePtr<RegisteredProxy> RegisterTypel
  * The COM interceptor uses type library information to build its interface
  * proxies. Unfortunately type libraries do not encode size_is and length_is
  * annotations that have been specified in IDL. This structure allows us to
  * explicitly declare such relationships so that the COM interceptor may
  * be made aware of them.
  */
 struct ArrayData
 {
+  enum class Flag
+  {
+    eNone = 0,
+    eAllocatedByServer = 1 // This implies an extra level of indirection
+  };
+
   ArrayData(REFIID aIid, ULONG aMethodIndex, ULONG aArrayParamIndex,
             VARTYPE aArrayParamType, REFIID aArrayParamIid,
-            ULONG aLengthParamIndex)
+            ULONG aLengthParamIndex, Flag aFlag = Flag::eNone)
     : mIid(aIid)
     , mMethodIndex(aMethodIndex)
     , mArrayParamIndex(aArrayParamIndex)
     , mArrayParamType(aArrayParamType)
     , mArrayParamIid(aArrayParamIid)
     , mLengthParamIndex(aLengthParamIndex)
+    , mFlag(aFlag)
   {
   }
+
   ArrayData(const ArrayData& aOther)
   {
     *this = aOther;
   }
+
   ArrayData& operator=(const ArrayData& aOther)
   {
     mIid = aOther.mIid;
     mMethodIndex = aOther.mMethodIndex;
     mArrayParamIndex = aOther.mArrayParamIndex;
     mArrayParamType = aOther.mArrayParamType;
     mArrayParamIid = aOther.mArrayParamIid;
     mLengthParamIndex = aOther.mLengthParamIndex;
+    mFlag = aOther.mFlag;
     return *this;
   }
+
   IID     mIid;
   ULONG   mMethodIndex;
   ULONG   mArrayParamIndex;
   VARTYPE mArrayParamType;
   IID     mArrayParamIid;
   ULONG   mLengthParamIndex;
+  Flag    mFlag;
 };
 
 void RegisterArrayData(const ArrayData* aArrayData, size_t aLength);
 
 template <size_t N>
 inline void
 RegisterArrayData(const ArrayData (&aData)[N])
 {
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -92,16 +92,22 @@ uint8_t gImageLayerUserData;
  */
 uint8_t gLayerManagerUserData;
 /**
  * The address of gMaskLayerUserData is used as the user
  * data key for mask layers managed by FrameLayerBuilder.
  * The user data is a MaskLayerUserData.
  */
 uint8_t gMaskLayerUserData;
+/**
+ * The address of gCSSMaskLayerUserData is used as the user
+ * data key for mask layers of css masking managed by FrameLayerBuilder.
+ * The user data is a CSSMaskLayerUserData.
+ */
+uint8_t gCSSMaskLayerUserData;
 
 // a global cache of image containers used for mask layers
 static MaskLayerImageCache* gMaskLayerImageCache = nullptr;
 
 static inline MaskLayerImageCache* GetMaskLayerImageCache()
 {
   if (!gMaskLayerImageCache) {
     gMaskLayerImageCache = new MaskLayerImageCache();
@@ -1247,17 +1253,19 @@ protected:
    * a layer doesn't exist.
    *
    * Since mask layers can exist either on the layer directly, or as a side-
    * attachment to FrameMetrics (for ancestor scrollframe clips), we key the
    * recycle operation on both the originating layer and the mask layer's
    * index in the layer, if any.
    */
   struct MaskLayerKey;
-  already_AddRefed<ImageLayer> CreateOrRecycleMaskImageLayerFor(const MaskLayerKey& aKey);
+  already_AddRefed<ImageLayer>
+  CreateOrRecycleMaskImageLayerFor(const MaskLayerKey& aKey,
+                                   mozilla::function<void(Layer* aLayer)> aSetUserData);
   /**
    * Grabs all PaintedLayers and ColorLayers from the ContainerLayer and makes them
    * available for recycling.
    */
   void CollectOldLayers();
   /**
    * If aItem used to belong to a PaintedLayer, invalidates the area of
    * aItem in that layer. If aNewLayer is a PaintedLayer, invalidates the area of
@@ -1340,16 +1348,22 @@ protected:
    * add it to |aLayer|'s ancestor mask layers, returning an index into
    * the array of ancestor mask layers. Returns an empty Maybe if
    * |aClip| does not have rounded corners, or if no mask layer could
    * be created.
    */
   Maybe<size_t> SetupMaskLayerForScrolledClip(Layer* aLayer,
                                               const DisplayItemClip& aClip);
 
+  /*
+   * Create/find a mask layer with suitable size for aMaskItem to paint
+   * css-positioned-masking onto.
+   */
+  void SetupMaskLayerForCSSMask(Layer* aLayer, nsDisplayMask* aMaskItem);
+
   already_AddRefed<Layer> CreateMaskLayer(
     Layer *aLayer, const DisplayItemClip& aClip,
     const Maybe<size_t>& aForAncestorMaskLayer,
     uint32_t aRoundedRectClipCount = UINT32_MAX);
 
   bool ChooseAnimatedGeometryRoot(const nsDisplayList& aList,
                                   AnimatedGeometryRoot **aAnimatedGeometryRoot);
 
@@ -1499,16 +1513,36 @@ public:
  */
 struct MaskLayerUserData : public LayerUserData
 {
   MaskLayerUserData()
     : mScaleX(-1.0f)
     , mScaleY(-1.0f)
     , mAppUnitsPerDevPixel(-1)
   { }
+  MaskLayerUserData(const DisplayItemClip& aClip,
+                    uint32_t aRoundedRectClipCount,
+                    int32_t aAppUnitsPerDevPixel,
+                    const ContainerLayerParameters& aParams)
+    : mScaleX(aParams.mXScale)
+    , mScaleY(aParams.mYScale)
+    , mOffset(aParams.mOffset)
+    , mAppUnitsPerDevPixel(aAppUnitsPerDevPixel)
+  {
+    aClip.AppendRoundedRects(&mRoundedClipRects, aRoundedRectClipCount);
+  }
+
+  void operator=(MaskLayerUserData&& aOther)
+  {
+    mScaleX = aOther.mScaleX;
+    mScaleY = aOther.mScaleY;
+    mOffset = aOther.mOffset;
+    mAppUnitsPerDevPixel = aOther.mAppUnitsPerDevPixel;
+    mRoundedClipRects.SwapElements(aOther.mRoundedClipRects);
+  }
 
   bool
   operator== (const MaskLayerUserData& aOther) const
   {
     return mRoundedClipRects == aOther.mRoundedClipRects &&
            mScaleX == aOther.mScaleX &&
            mScaleY == aOther.mScaleY &&
            mOffset == aOther.mOffset &&
@@ -1522,39 +1556,139 @@ struct MaskLayerUserData : public LayerU
   nsTArray<DisplayItemClip::RoundedRect> mRoundedClipRects;
   // scale from the masked layer which is applied to the mask
   float mScaleX, mScaleY;
   // The ContainerLayerParameters offset which is applied to the mask's transform.
   nsIntPoint mOffset;
   int32_t mAppUnitsPerDevPixel;
 };
 
+/*
+ * User data for layers which will be used as masks for css positioned mask.
+ */
+struct CSSMaskLayerUserData : public LayerUserData
+{
+  CSSMaskLayerUserData()
+    : mImageLayers(nsStyleImageLayers::LayerType::Mask)
+  { }
+
+  CSSMaskLayerUserData(nsIFrame* aFrame, const nsRect& aBound)
+    : mImageLayers(aFrame->StyleSVGReset()->mMask),
+      mContentRect(aFrame->GetContentRectRelativeToSelf()),
+      mPaddingRect(aFrame->GetPaddingRectRelativeToSelf()),
+      mBorderRect(aFrame->GetRectRelativeToSelf()),
+      mMarginRect(aFrame->GetMarginRectRelativeToSelf()),
+      mBounds(aBound)
+  {
+    Hash(aFrame);
+  }
+
+  CSSMaskLayerUserData& operator=(const CSSMaskLayerUserData& aOther)
+  {
+    mImageLayers = aOther.mImageLayers;
+
+    mContentRect = aOther.mContentRect;
+    mPaddingRect = aOther.mPaddingRect;
+    mBorderRect = aOther.mBorderRect;
+    mMarginRect = aOther.mMarginRect;
+
+    mBounds = aOther.mBounds;
+
+    mHash = aOther.mHash;
+
+    return *this;
+  }
+
+  bool
+  operator==(const CSSMaskLayerUserData& aOther) const
+  {
+    if (mHash != aOther.mHash) {
+      return false;
+    }
+
+    if (mImageLayers.mLayers != aOther.mImageLayers.mLayers) {
+      return false;
+    }
+
+    if (!mContentRect.IsEqualEdges(aOther.mContentRect) ||
+        !mPaddingRect.IsEqualEdges(aOther.mPaddingRect) ||
+        !mBorderRect.IsEqualEdges(aOther.mBorderRect) ||
+        !mMarginRect.IsEqualEdges(aOther.mMarginRect)) {
+      return false;
+    }
+
+    if (!mBounds.IsEqualEdges(aOther.mBounds)) {
+      return false;
+    }
+
+    return true;
+  }
+
+private:
+  void Hash(nsIFrame* aFrame)
+  {
+    uint32_t hash = 0;
+
+    const nsStyleImageLayers& imageLayers = aFrame->StyleSVGReset()->mMask;
+    for (uint32_t i = 0; i < imageLayers.mLayers.Length(); i++) {
+      const nsStyleImageLayers::Layer& newLayer = imageLayers.mLayers[i];
+      hash = AddToHash(hash, HashBytes(&newLayer, sizeof(newLayer)));
+    }
+
+    hash = AddToHash(hash, HashBytes(&mContentRect, sizeof(mContentRect)));
+    hash = AddToHash(hash, HashBytes(&mPaddingRect, sizeof(mPaddingRect)));
+    hash = AddToHash(hash, HashBytes(&mBorderRect, sizeof(mBorderRect)));
+    hash = AddToHash(hash, HashBytes(&mMarginRect, sizeof(mMarginRect)));
+
+    hash = AddToHash(hash, HashBytes(&mBounds, sizeof(mBounds)));
+
+    mHash = hash;
+  }
+
+  nsStyleImageLayers mImageLayers;
+
+  nsRect mContentRect;
+  nsRect mPaddingRect;
+  nsRect mBorderRect;
+  nsRect mMarginRect;
+
+  nsRect mBounds;
+
+  uint32_t mHash;
+};
+
+/*
+ * A helper object to create a draw target for painting mask and create a
+ * image container to hold the drawing result. The caller can then bind this
+ * image container with a image mask layer via ImageLayer::SetContainer.
+ */
 class MaskImageData
 {
 public:
   MaskImageData(const gfx::IntSize& aSize, LayerManager* aLayerManager)
     : mTextureClientLocked(false)
     , mSize(aSize)
     , mLayerManager(aLayerManager)
   {
+    MOZ_ASSERT(!mSize.IsEmpty());
+    MOZ_ASSERT(mLayerManager);
   }
 
   ~MaskImageData()
   {
     if (mTextureClientLocked) {
       MOZ_ASSERT(mTextureClient);
       // Clear DrawTarget before Unlock.
       mDrawTarget = nullptr;
       mTextureClient->Unlock();
     }
   }
 
   gfx::DrawTarget* CreateDrawTarget()
   {
-    MOZ_ASSERT(mLayerManager);
     if (mDrawTarget) {
       return mDrawTarget;
     }
 
     if (mLayerManager->GetBackendType() == LayersBackend::LAYERS_BASIC) {
       mDrawTarget = mLayerManager->CreateOptimalMaskDrawTarget(mSize);
       return mDrawTarget;
     }
@@ -1580,16 +1714,30 @@ public:
     if (!mTextureClientLocked) {
       return nullptr;
     }
 
     mDrawTarget = mTextureClient->BorrowDrawTarget();
     return mDrawTarget;
   }
 
+  already_AddRefed<ImageContainer> CreateImageAndImageContainer()
+  {
+    RefPtr<ImageContainer> container = mLayerManager->CreateImageContainer();
+    RefPtr<Image> image = CreateImage();
+
+    if (!image) {
+      return nullptr;
+    }
+    container->SetCurrentImageInTransaction(image);
+
+    return container.forget();
+  }
+
+private:
   already_AddRefed<Image> CreateImage()
   {
     if (mLayerManager->GetBackendType() == LayersBackend::LAYERS_BASIC &&
         mDrawTarget) {
       RefPtr<SourceSurface> surface = mDrawTarget->Snapshot();
       RefPtr<SourceSurfaceImage> image = new SourceSurfaceImage(mSize, surface);
       // Disallow BIGIMAGE (splitting into multiple textures) for mask
       // layer images
@@ -1599,20 +1747,20 @@ public:
 
     if (mLayerManager->GetBackendType() == LayersBackend::LAYERS_CLIENT &&
         mTextureClient &&
         mDrawTarget) {
       RefPtr<TextureWrapperImage> image =
           new TextureWrapperImage(mTextureClient, gfx::IntRect(gfx::IntPoint(0, 0), mSize));
       return image.forget();
     }
+
     return nullptr;
   }
 
-private:
   bool mTextureClientLocked;
   gfx::IntSize mSize;
   LayerManager* mLayerManager;
   RefPtr<gfx::DrawTarget> mDrawTarget;
   RefPtr<TextureClient> mTextureClient;
 };
 
 /**
@@ -2102,29 +2250,30 @@ ContainerState::CreateOrRecycleImageLaye
 
     // Remove other layer types we might have stored for this PaintedLayer
     data->mColorLayer = nullptr;
   }
   return layer.forget();
 }
 
 already_AddRefed<ImageLayer>
-ContainerState::CreateOrRecycleMaskImageLayerFor(const MaskLayerKey& aKey)
+ContainerState::CreateOrRecycleMaskImageLayerFor(const MaskLayerKey& aKey,
+                                                 mozilla::function<void(Layer* aLayer)> aSetUserData)
 {
   RefPtr<ImageLayer> result = mRecycledMaskImageLayers.Get(aKey);
   if (result) {
     mRecycledMaskImageLayers.Remove(aKey);
     aKey.mLayer->ClearExtraDumpInfo();
     // XXX if we use clip on mask layers, null it out here
   } else {
     // Create a new layer
     result = mManager->CreateImageLayer();
     if (!result)
       return nullptr;
-    result->SetUserData(&gMaskLayerUserData, new MaskLayerUserData());
+    aSetUserData(result);
   }
 
   return result.forget();
 }
 
 static const double SUBPIXEL_OFFSET_EPSILON = 0.02;
 
 /**
@@ -3740,16 +3889,90 @@ ContainerState::SetupMaskLayerForScrolle
       aLayer->AddAncestorMaskLayer(maskLayer);
       return maskLayerIndex;
     }
     // Fall through to |return Nothing()|.
   }
   return Nothing();
 }
 
+void
+ContainerState::SetupMaskLayerForCSSMask(Layer* aLayer,
+                                         nsDisplayMask* aMaskItem)
+{
+  MOZ_ASSERT(mManager->IsCompositingCheap());
+
+  RefPtr<ImageLayer> maskLayer =
+    CreateOrRecycleMaskImageLayerFor(MaskLayerKey(aLayer, Nothing()),
+      [](Layer* aMaskLayer)
+      {
+        aMaskLayer->SetUserData(&gCSSMaskLayerUserData,
+                                new CSSMaskLayerUserData());
+      }
+    );
+
+  CSSMaskLayerUserData* oldUserData =
+    static_cast<CSSMaskLayerUserData*>(maskLayer->GetUserData(&gCSSMaskLayerUserData));
+
+  bool snap;
+  nsRect bounds = aMaskItem->GetBounds(mBuilder, &snap);
+  CSSMaskLayerUserData newUserData(aMaskItem->Frame(), bounds);
+  if (*oldUserData == newUserData) {
+    aLayer->SetMaskLayer(maskLayer);
+    return;
+  }
+
+  const nsIFrame* frame = aMaskItem->Frame();
+  int32_t A2D = frame->PresContext()->AppUnitsPerDevPixel();
+  Rect devBounds = NSRectToRect(bounds, A2D);
+  uint32_t maxSize = mManager->GetMaxTextureSize();
+  gfx::Size surfaceSize(std::min<gfx::Float>(devBounds.Width(), maxSize),
+                        std::min<gfx::Float>(devBounds.Height(), maxSize));
+  IntSize surfaceSizeInt(NSToIntCeil(surfaceSize.width),
+                         NSToIntCeil(surfaceSize.height));
+
+  if (surfaceSizeInt.IsEmpty()) {
+    return;
+  }
+
+  MaskImageData imageData(surfaceSizeInt, mManager);
+  RefPtr<DrawTarget> dt = imageData.CreateDrawTarget();
+  if (!dt || !dt->IsValid()) {
+    NS_WARNING("Could not create DrawTarget for mask layer.");
+    return;
+  }
+
+  RefPtr<gfxContext> maskCtx = gfxContext::CreateOrNull(dt);
+  gfxPoint offset = nsLayoutUtils::PointToGfxPoint(bounds.TopLeft(), A2D);
+  maskCtx->SetMatrix(gfxMatrix::Translation(-offset));
+
+  if (!aMaskItem->PaintMask(mBuilder, maskCtx)) {
+    // Mostly because of mask resource is not ready.
+    return;
+  }
+
+  // Setup mask layer offset.
+  Matrix4x4 matrix;
+  matrix.PreTranslate(offset.x, offset.y, 0);
+  matrix.PreTranslate(mParameters.mOffset.x, mParameters.mOffset.y, 0);
+  matrix.PreScale(mParameters.mXScale, mParameters.mYScale, 1.0);
+
+  maskLayer->SetBaseTransform(matrix);
+
+  RefPtr<ImageContainer> imgContainer =
+    imageData.CreateImageAndImageContainer();
+  if (!imgContainer) {
+    return;
+  }
+  maskLayer->SetContainer(imgContainer);
+
+  *oldUserData = newUserData;
+  aLayer->SetMaskLayer(maskLayer);
+}
+
 /*
  * Iterate through the non-clip items in aList and its descendants.
  * For each item we compute the effective clip rect. Each item is assigned
  * to a layer. We invalidate the areas in PaintedLayers where an item
  * has moved from one PaintedLayer to another. Also,
  * aState->mInvalidPaintedContent is invalidated in every PaintedLayer.
  * We set the clip rect for items that generated their own layer, and
  * create a mask layer to do any rounded rect clipping.
@@ -4143,16 +4366,19 @@ ContainerState::ProcessDisplayItems(nsDi
           ownLayer->SetClipRect(Some(layerClipRect));
 
           // rounded rectangle clipping using mask layers
           // (must be done after visible rect is set on layer)
           if (layerClip.GetRoundedRectCount() > 0) {
             SetupMaskLayer(ownLayer, layerClip);
           }
         }
+      } else if (item->GetType() == nsDisplayItem::TYPE_MASK) {
+        nsDisplayMask* maskItem = static_cast<nsDisplayMask*>(item);
+        SetupMaskLayerForCSSMask(ownLayer, maskItem);
       }
 
       ContainerLayer* oldContainer = ownLayer->GetParent();
       if (oldContainer && oldContainer != mContainerLayer) {
         oldContainer->RemoveChild(ownLayer);
       }
       NS_ASSERTION(FindIndexOfLayerIn(mNewChildLayers, ownLayer) < 0,
                    "Layer already in list???");
@@ -6021,28 +6247,37 @@ ContainerState::SetupMaskLayer(Layer *aL
 }
 
 already_AddRefed<Layer>
 ContainerState::CreateMaskLayer(Layer *aLayer,
                                const DisplayItemClip& aClip,
                                const Maybe<size_t>& aForAncestorMaskLayer,
                                uint32_t aRoundedRectClipCount)
 {
+  // aLayer will never be the container layer created by an nsDisplayMask
+  // because nsDisplayMask propagates the DisplayItemClip to its contents
+  // and is not clipped itself.
+  // This assertion will fail if that ever stops being the case.
+  MOZ_ASSERT(!aLayer->GetUserData(&gCSSMaskLayerUserData),
+             "A layer contains round clips should not have css-mask on it.");
+
   // check if we can re-use the mask layer
   MaskLayerKey recycleKey(aLayer, aForAncestorMaskLayer);
-  RefPtr<ImageLayer> maskLayer = CreateOrRecycleMaskImageLayerFor(recycleKey);
+  RefPtr<ImageLayer> maskLayer =
+    CreateOrRecycleMaskImageLayerFor(recycleKey,
+      [](Layer* aMaskLayer)
+      {
+        aMaskLayer->SetUserData(&gMaskLayerUserData,
+                                new MaskLayerUserData());
+      }
+    );
   MaskLayerUserData* userData = GetMaskLayerUserData(maskLayer);
 
-  MaskLayerUserData newData;
-  aClip.AppendRoundedRects(&newData.mRoundedClipRects, aRoundedRectClipCount);
-  newData.mScaleX = mParameters.mXScale;
-  newData.mScaleY = mParameters.mYScale;
-  newData.mOffset = mParameters.mOffset;
-  newData.mAppUnitsPerDevPixel = mContainerFrame->PresContext()->AppUnitsPerDevPixel();
-
+  int32_t A2D = mContainerFrame->PresContext()->AppUnitsPerDevPixel();
+  MaskLayerUserData newData(aClip, aRoundedRectClipCount, A2D, mParameters);
   if (*userData == newData) {
     return maskLayer.forget();
   }
 
   // calculate a more precise bounding rect
   gfx::Rect boundingRect = CalculateBounds(newData.mRoundedClipRects,
                                            newData.mAppUnitsPerDevPixel);
   boundingRect.Scale(mParameters.mXScale, mParameters.mYScale);
@@ -6109,39 +6344,34 @@ ContainerState::CreateMaskLayer(Layer *a
     // paint the clipping rects with alpha to create the mask
     aClip.FillIntersectionOfRoundedRectClips(context,
                                              Color(1.f, 1.f, 1.f, 1.f),
                                              newData.mAppUnitsPerDevPixel,
                                              0,
                                              aRoundedRectClipCount);
 
     // build the image and container
-    container = aLayer->Manager()->CreateImageContainer();
+    MOZ_ASSERT(aLayer->Manager() == mManager);
+    container = imageData.CreateImageAndImageContainer();
     NS_ASSERTION(container, "Could not create image container for mask layer.");
 
-    RefPtr<Image> image = imageData.CreateImage();
-    if (!image) {
+    if (!container) {
       return nullptr;
     }
-    container->SetCurrentImageInTransaction(image);
 
     GetMaskLayerImageCache()->PutImage(newKey.forget(), container);
   }
 
   maskLayer->SetContainer(container);
 
   maskTransform.Invert();
   Matrix4x4 matrix = Matrix4x4::From2D(maskTransform);
   matrix.PreTranslate(mParameters.mOffset.x, mParameters.mOffset.y, 0);
   maskLayer->SetBaseTransform(matrix);
 
   // save the details of the clip in user data
-  userData->mScaleX = newData.mScaleX;
-  userData->mScaleY = newData.mScaleY;
-  userData->mOffset = newData.mOffset;
-  userData->mAppUnitsPerDevPixel = newData.mAppUnitsPerDevPixel;
-  userData->mRoundedClipRects.SwapElements(newData.mRoundedClipRects);
+  *userData = Move(newData);
   userData->mImageKey.Reset(lookupKey);
 
   return maskLayer.forget();
 }
 
 } // namespace mozilla
--- a/layout/base/FrameLayerBuilder.h
+++ b/layout/base/FrameLayerBuilder.h
@@ -19,16 +19,17 @@
 #include "Layers.h"
 #include "LayerUserData.h"
 
 class nsDisplayListBuilder;
 class nsDisplayList;
 class nsDisplayItem;
 class gfxContext;
 class nsDisplayItemGeometry;
+class nsDisplayMask;
 
 namespace mozilla {
 class DisplayItemScrollClip;
 namespace layers {
 class ContainerLayer;
 class LayerManager;
 class BasicLayerManager;
 class PaintedLayer;
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -7047,24 +7047,85 @@ nsDisplayMask::BuildLayer(nsDisplayListB
 
   RefPtr<ContainerLayer> container = aManager->GetLayerBuilder()->
     BuildContainerLayerFor(aBuilder, aManager, mFrame, this, &mList,
                            aContainerParameters, nullptr);
 
   return container.forget();
 }
 
+bool
+nsDisplayMask::PaintMask(nsDisplayListBuilder* aBuilder,
+                         gfxContext* aMaskContext)
+{
+  MOZ_ASSERT(aMaskContext->GetDrawTarget()->GetFormat() == SurfaceFormat::A8);
+
+  nsRect borderArea = nsRect(ToReferenceFrame(), mFrame->GetSize());
+  nsSVGIntegrationUtils::PaintFramesParams params(*aMaskContext,
+                                                  mFrame,  mVisibleRect,
+                                                  borderArea, aBuilder,
+                                                  nullptr,
+                                                  mHandleOpacity);
+  ComputeMaskGeometry(params);
+  image::DrawResult result = nsSVGIntegrationUtils::PaintMask(params);
+
+  nsDisplayMaskGeometry::UpdateDrawResult(this, result);
+  return (result == image::DrawResult::SUCCESS) ? true : false;
+}
+
 LayerState
 nsDisplayMask::GetLayerState(nsDisplayListBuilder* aBuilder,
                              LayerManager* aManager,
                              const ContainerLayerParameters& aParameters)
 {
+  if (ShouldPaintOnMaskLayer(aManager)) {
+    return RequiredLayerStateForChildren(aBuilder, aManager, aParameters,
+                                         mList, GetAnimatedGeometryRoot());
+  }
+
   return LAYER_SVG_EFFECTS;
 }
 
+bool nsDisplayMask::ShouldPaintOnMaskLayer(LayerManager* aManager)
+{
+  if (!aManager->IsCompositingCheap()) {
+    return false;
+  }
+
+  nsSVGIntegrationUtils::MaskUsage maskUsage;
+  nsSVGIntegrationUtils::DetermineMaskUsage(mFrame, mHandleOpacity, maskUsage);
+
+  if (!maskUsage.shouldGenerateMaskLayer ||
+      maskUsage.opacity != 1.0 || maskUsage.shouldApplyClipPath ||
+      maskUsage.shouldApplyBasicShape ||
+      maskUsage.shouldGenerateClipMaskLayer) {
+    return false;
+  }
+
+  if (!nsSVGIntegrationUtils::IsMaskResourceReady(mFrame)) {
+    return false;
+  }
+
+  // XXX temporary disable drawing SVG mask onto mask layer before bug 1313877
+  // been fixed.
+  nsIFrame* firstFrame =
+    nsLayoutUtils::FirstContinuationOrIBSplitSibling(mFrame);
+  nsSVGEffects::EffectProperties effectProperties =
+    nsSVGEffects::GetEffectProperties(firstFrame);
+  nsTArray<nsSVGMaskFrame *> maskFrames = effectProperties.GetMaskFrames();
+  for (size_t i = 0; i < maskFrames.Length() ; i++) {
+    nsSVGMaskFrame *maskFrame = maskFrames[i];
+    if (maskFrame) {
+      return false; // Found SVG mask.
+    }
+  }
+
+  return true;
+}
+
 bool nsDisplayMask::ComputeVisibility(nsDisplayListBuilder* aBuilder,
                                       nsRegion* aVisibleRegion)
 {
   // Our children may be made translucent or arbitrarily deformed so we should
   // not allow them to subtract area from aVisibleRegion.
   nsRegion childrenVisible(mVisibleRect);
   nsRect r = mVisibleRect.Intersect(mList.GetBounds(aBuilder));
   mList.ComputeVisibilityForSublist(aBuilder, &childrenVisible, r);
@@ -7108,16 +7169,18 @@ nsDisplayMask::ComputeInvalidationRegion
   }
 }
 
 void
 nsDisplayMask::PaintAsLayer(nsDisplayListBuilder* aBuilder,
                             nsRenderingContext* aCtx,
                             LayerManager* aManager)
 {
+  MOZ_ASSERT(!ShouldPaintOnMaskLayer(aManager));
+
   nsRect borderArea = nsRect(ToReferenceFrame(), mFrame->GetSize());
   nsSVGIntegrationUtils::PaintFramesParams params(*aCtx->ThebesContext(),
                                                   mFrame,  mVisibleRect,
                                                   borderArea, aBuilder,
                                                   aManager,
                                                   mHandleOpacity);
 
   // Clip the drawing target by mVisibleRect, which contains the visible
--- a/layout/base/nsDisplayList.h
+++ b/layout/base/nsDisplayList.h
@@ -3873,16 +3873,19 @@ protected:
 };
 
 /**
  * A display item to paint a stacking context with mask and clip effects
  * set by the stacking context root frame's style.
  */
 class nsDisplayMask : public nsDisplaySVGEffects {
 public:
+  typedef mozilla::layers::ImageLayer ImageLayer;
+  typedef class mozilla::gfx::DrawTarget DrawTarget;
+
   nsDisplayMask(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
                 nsDisplayList* aList, bool aHandleOpacity,
                 const DisplayItemScrollClip* aScrollClip);
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplayMask();
 #endif
 
   NS_DISPLAY_DECL_NAME("Mask", TYPE_MASK)
@@ -3908,21 +3911,30 @@ public:
 #ifdef MOZ_DUMP_PAINTING
   void PrintEffects(nsACString& aTo);
 #endif
 
   void PaintAsLayer(nsDisplayListBuilder* aBuilder,
                     nsRenderingContext* aCtx,
                     LayerManager* aManager);
 
+  /*
+   * Paint mask onto aMaskContext in mFrame's coordinate space.
+   */
+  bool PaintMask(nsDisplayListBuilder* aBuilder, gfxContext* aMaskContext);
+
   const nsTArray<nsRect>& GetDestRects()
   {
     return mDestRects;
   }
 private:
+  // According to mask property and the capability of aManager, determine
+  // whether paint mask onto a dedicate mask layer.
+  bool ShouldPaintOnMaskLayer(LayerManager* aManager);
+
   nsTArray<nsRect> mDestRects;
 };
 
 /**
  * A display item to paint a stacking context with filter effects set by the
  * stacking context root frame's style.
  */
 class nsDisplayFilter : public nsDisplaySVGEffects {
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -65,16 +65,17 @@
 #include "mozilla/dom/HTMLCanvasElement.h"
 #include "nsICanvasRenderingContextInternal.h"
 #include "gfxPlatform.h"
 #include <algorithm>
 #include <limits>
 #include "mozilla/dom/HTMLVideoElement.h"
 #include "mozilla/dom/HTMLImageElement.h"
 #include "mozilla/dom/DOMRect.h"
+#include "mozilla/dom/DOMStringList.h"
 #include "mozilla/dom/KeyframeEffectReadOnly.h"
 #include "mozilla/layers/APZCCallbackHelper.h"
 #include "imgIRequest.h"
 #include "nsIImageLoadingContent.h"
 #include "nsCOMPtr.h"
 #include "nsCSSProps.h"
 #include "nsListControlFrame.h"
 #include "mozilla/dom/Element.h"
@@ -3933,24 +3934,53 @@ struct BoxToRect : public nsLayoutUtils:
       r = nsLayoutUtils::TransformFrameRectToAncestor(outer, r, mRelativeTo);
     } else {
       r += outer->GetOffsetTo(mRelativeTo);
     }
     mCallback->AddRect(r);
   }
 };
 
+struct BoxToRectAndText : public BoxToRect {
+  mozilla::dom::DOMStringList* mTextList;
+
+  BoxToRectAndText(nsIFrame* aRelativeTo, nsLayoutUtils::RectCallback* aCallback,
+                   mozilla::dom::DOMStringList* aTextList, uint32_t aFlags)
+    : BoxToRect(aRelativeTo, aCallback, aFlags), mTextList(aTextList) {}
+
+  virtual void AddBox(nsIFrame* aFrame) override {
+    BoxToRect::AddBox(aFrame);
+    if (mTextList) {
+      nsIContent* content = aFrame->GetContent();
+      nsAutoString textContent;
+      mozilla::ErrorResult err; // ignored
+      content->GetTextContent(textContent, err);
+      mTextList->Add(textContent);
+    }
+  }
+};
+
 void
 nsLayoutUtils::GetAllInFlowRects(nsIFrame* aFrame, nsIFrame* aRelativeTo,
                                  RectCallback* aCallback, uint32_t aFlags)
 {
   BoxToRect converter(aRelativeTo, aCallback, aFlags);
   GetAllInFlowBoxes(aFrame, &converter);
 }
 
+void
+nsLayoutUtils::GetAllInFlowRectsAndTexts(nsIFrame* aFrame, nsIFrame* aRelativeTo,
+                                         RectCallback* aCallback,
+                                         mozilla::dom::DOMStringList* aTextList,
+                                         uint32_t aFlags)
+{
+  BoxToRectAndText converter(aRelativeTo, aCallback, aTextList, aFlags);
+  GetAllInFlowBoxes(aFrame, &converter);
+}
+
 nsLayoutUtils::RectAccumulator::RectAccumulator() : mSeenFirstRect(false) {}
 
 void nsLayoutUtils::RectAccumulator::AddRect(const nsRect& aRect) {
   mResultRect.UnionRect(mResultRect, aRect);
   if (!mSeenFirstRect) {
     mSeenFirstRect = true;
     mFirstRect = aRect;
   }
@@ -8864,17 +8894,17 @@ nsLayoutUtils::GetSelectionBoundingRect(
       nsIFrame* relativeTo = GetContainingBlockForClientRect(frame);
       res = TransformFrameRectToAncestor(frame, res, relativeTo);
     }
   } else {
     int32_t rangeCount = aSel->RangeCount();
     RectAccumulator accumulator;
     for (int32_t idx = 0; idx < rangeCount; ++idx) {
       nsRange* range = aSel->GetRangeAt(idx);
-      nsRange::CollectClientRects(&accumulator, range,
+      nsRange::CollectClientRectsAndText(&accumulator, nullptr, range,
                                   range->GetStartParent(), range->StartOffset(),
                                   range->GetEndParent(), range->EndOffset(),
                                   true, false);
     }
     res = accumulator.mResultRect.IsEmpty() ? accumulator.mFirstRect :
       accumulator.mResultRect;
   }
 
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -1193,16 +1193,21 @@ public:
    * and SVG transforms) are taken into account.
    * If aFlags includes one of RECTS_USE_CONTENT_BOX, RECTS_USE_PADDING_BOX,
    * or RECTS_USE_MARGIN_BOX, the corresponding type of box is used.
    * Otherwise (by default), the border box is used.
    */
   static void GetAllInFlowRects(nsIFrame* aFrame, nsIFrame* aRelativeTo,
                                 RectCallback* aCallback, uint32_t aFlags = 0);
 
+  static void GetAllInFlowRectsAndTexts(nsIFrame* aFrame, nsIFrame* aRelativeTo,
+                                        RectCallback* aCallback,
+                                        mozilla::dom::DOMStringList* aTextList,
+                                        uint32_t aFlags = 0);
+
   /**
    * Computes the union of all rects returned by GetAllInFlowRects. If
    * the union is empty, returns the first rect.
    * If aFlags includes RECTS_ACCOUNT_FOR_TRANSFORMS, then when converting
    * the boxes into aRelativeTo coordinates, transforms (including CSS
    * and SVG transforms) are taken into account.
    * If aFlags includes one of RECTS_USE_CONTENT_BOX, RECTS_USE_PADDING_BOX,
    * or RECTS_USE_MARGIN_BOX, the corresponding type of box is used.
--- a/layout/generic/nsSelection.cpp
+++ b/layout/generic/nsSelection.cpp
@@ -5881,17 +5881,17 @@ bool
 Selection::ContainsPoint(const nsPoint& aPoint)
 {
   if (IsCollapsed()) {
     return false;
   }
   PointInRectChecker checker(aPoint);
   for (uint32_t i = 0; i < RangeCount(); i++) {
     nsRange* range = GetRangeAt(i);
-    nsRange::CollectClientRects(&checker, range,
+    nsRange::CollectClientRectsAndText(&checker, nullptr, range,
                                 range->GetStartParent(), range->StartOffset(),
                                 range->GetEndParent(), range->EndOffset(),
                                 true, false);
     if (checker.MatchFound()) {
       return true;
     }
   }
   return false;
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -2616,16 +2616,51 @@ nsStyleImageLayers::HasLayerWithImage() 
         !mLayers[i].mImage.IsEmpty()) {
       return true;
     }
   }
 
   return false;
 }
 
+nsStyleImageLayers&
+nsStyleImageLayers::operator=(const nsStyleImageLayers& aOther)
+{
+  mAttachmentCount = aOther.mAttachmentCount;
+  mClipCount = aOther.mClipCount;
+  mOriginCount = aOther.mOriginCount;
+  mRepeatCount = aOther.mRepeatCount;
+  mPositionXCount = aOther.mPositionXCount;
+  mPositionYCount = aOther.mPositionYCount;
+  mImageCount = aOther.mImageCount;
+  mSizeCount = aOther.mSizeCount;
+  mMaskModeCount = aOther.mMaskModeCount;
+  mBlendModeCount = aOther.mBlendModeCount;
+  mCompositeCount = aOther.mCompositeCount;
+  mLayers = aOther.mLayers;
+
+  uint32_t count = mLayers.Length();
+  if (count != aOther.mLayers.Length()) {
+    NS_WARNING("truncating counts due to out-of-memory");
+    mAttachmentCount = std::max(mAttachmentCount, count);
+    mClipCount = std::max(mClipCount, count);
+    mOriginCount = std::max(mOriginCount, count);
+    mRepeatCount = std::max(mRepeatCount, count);
+    mPositionXCount = std::max(mPositionXCount, count);
+    mPositionYCount = std::max(mPositionYCount, count);
+    mImageCount = std::max(mImageCount, count);
+    mSizeCount = std::max(mSizeCount, count);
+    mMaskModeCount = std::max(mMaskModeCount, count);
+    mBlendModeCount = std::max(mBlendModeCount, count);
+    mCompositeCount = std::max(mCompositeCount, count);
+  }
+
+  return *this;
+}
+
 bool
 nsStyleImageLayers::IsInitialPositionForLayerType(Position aPosition, LayerType aType)
 {
   if (aPosition.mXPosition.mPercent == 0.0f &&
       aPosition.mXPosition.mLength == 0 &&
       aPosition.mXPosition.mHasPercent &&
       aPosition.mYPosition.mPercent == 0.0f &&
       aPosition.mYPosition.mLength == 0 &&
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -887,16 +887,17 @@ struct nsStyleImageLayers {
       mLayers[i].ResolveImage(aContext);
     }
   }
 
   nsChangeHint CalcDifference(const nsStyleImageLayers& aNewLayers,
                               nsStyleImageLayers::LayerType aType) const;
 
   bool HasLayerWithImage() const;
+  nsStyleImageLayers& operator=(const nsStyleImageLayers& aOther);
 
   static const nsCSSPropertyID kBackgroundLayerTable[];
   static const nsCSSPropertyID kMaskLayerTable[];
 
   #define NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT(var_, layers_) \
     for (uint32_t var_ = (layers_).mImageCount; var_-- != 0; )
   #define NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT_WITH_RANGE(var_, layers_, start_, count_) \
     NS_ASSERTION((int32_t)(start_) >= 0 && (uint32_t)(start_) < (layers_).mImageCount, "Invalid layer start!"); \
--- a/layout/svg/nsSVGIntegrationUtils.cpp
+++ b/layout/svg/nsSVGIntegrationUtils.cpp
@@ -410,114 +410,81 @@ private:
   LayerManager* mLayerManager;
   nsPoint mOffset;
 };
 
 /**
  * Returns true if any of the masks is an image mask (and not an SVG mask).
  */
 static bool
-HasNonSVGMask(const nsTArray<nsSVGMaskFrame *>& aMaskFrames)
+HasNonSVGMask(const nsTArray<nsSVGMaskFrame*>& aMaskFrames)
 {
   for (size_t i = 0; i < aMaskFrames.Length() ; i++) {
     nsSVGMaskFrame *maskFrame = aMaskFrames[i];
     if (!maskFrame) {
       return true;
     }
   }
 
   return false;
 }
 
 typedef nsSVGIntegrationUtils::PaintFramesParams PaintFramesParams;
 
+/**
+ * Paint css-positioned-mask onto a given target(aMaskDT).
+ */
 static DrawResult
-GenerateMaskSurface(const PaintFramesParams& aParams,
-                    float aOpacity, nsStyleContext* aSC,
-                    const nsTArray<nsSVGMaskFrame *>& aMaskFrames,
-                    const nsPoint& aOffsetToUserSpace,
-                    Matrix& aOutMaskTransform,
-                    RefPtr<SourceSurface>& aOutMaskSurface,
-                    bool& aOpacityApplied)
+PaintMaskSurface(const PaintFramesParams& aParams,
+                 DrawTarget* aMaskDT, float aOpacity, nsStyleContext* aSC,
+                 const nsTArray<nsSVGMaskFrame*>& aMaskFrames,
+                 const gfxMatrix& aMaskSurfaceMatrix,
+                 const nsPoint& aOffsetToUserSpace)
 {
+  MOZ_ASSERT(aMaskFrames.Length() > 0);
+  MOZ_ASSERT(aMaskDT->GetFormat() == SurfaceFormat::A8);
+
   const nsStyleSVGReset *svgReset = aSC->StyleSVGReset();
-  MOZ_ASSERT(aMaskFrames.Length() > 0);
-
   gfxMatrix cssPxToDevPxMatrix =
     nsSVGIntegrationUtils::GetCSSPxToDevPxMatrix(aParams.frame);
 
-  gfxContext& ctx = aParams.ctx;
-
-  // There is only one SVG mask.
-  if (((aMaskFrames.Length() == 1) && aMaskFrames[0])) {
-    aOpacityApplied = true;
-    aOutMaskSurface =
-      aMaskFrames[0]->GetMaskForMaskedFrame(&ctx, aParams.frame,
-                                            cssPxToDevPxMatrix, aOpacity,
-                                            &aOutMaskTransform,
-                                            svgReset->mMask.mLayers[0].mMaskMode);
-    return DrawResult::SUCCESS;
-  }
-
-  const IntRect& maskSurfaceRect = aParams.maskRect;
-  if (maskSurfaceRect.IsEmpty()) {
-    return DrawResult::SUCCESS;
-  }
-
-  RefPtr<DrawTarget> maskDT =
-      ctx.GetDrawTarget()->CreateSimilarDrawTarget(maskSurfaceRect.Size(),
-                                                   SurfaceFormat::A8);
-  if (!maskDT || !maskDT->IsValid()) {
-    return DrawResult::TEMPORARY_ERROR;
-  }
-
-  RefPtr<gfxContext> maskContext = gfxContext::CreateOrNull(maskDT);
-  MOZ_ASSERT(maskContext);
-
   nsPresContext* presContext = aParams.frame->PresContext();
   gfxPoint devPixelOffsetToUserSpace =
     nsLayoutUtils::PointToGfxPoint(aOffsetToUserSpace,
                                    presContext->AppUnitsPerDevPixel());
 
-  // Set ctx's matrix on maskContext, offset by the maskSurfaceRect's position.
-  // This makes sure that we combine the masks in device space.
-  gfxMatrix maskSurfaceMatrix =
-    ctx.CurrentMatrix() * gfxMatrix::Translation(-maskSurfaceRect.TopLeft());
-  maskContext->SetMatrix(maskSurfaceMatrix);
-
-  // Set aAppliedOpacity as true only if all mask layers are svg mask.
-  // In this case, we will apply opacity into the final mask surface, so the
-  // caller does not need to apply it again.
-  aOpacityApplied = !HasNonSVGMask(aMaskFrames);
+  RefPtr<gfxContext> maskContext = gfxContext::CreateOrNull(aMaskDT);
+  MOZ_ASSERT(maskContext);
+  maskContext->SetMatrix(aMaskSurfaceMatrix);
 
   // Multiple SVG masks interleave with image mask. Paint each layer onto
-  // maskDT one at a time.
+  // aMaskDT one at a time.
   for (int i = aMaskFrames.Length() - 1; i >= 0 ; i--) {
     nsSVGMaskFrame *maskFrame = aMaskFrames[i];
 
     CompositionOp compositionOp = (i == int(aMaskFrames.Length() - 1))
       ? CompositionOp::OP_OVER
       : nsCSSRendering::GetGFXCompositeMode(svgReset->mMask.mLayers[i].mComposite);
 
     // maskFrame != nullptr means we get a SVG mask.
     // maskFrame == nullptr means we get an image mask.
     if (maskFrame) {
       Matrix svgMaskMatrix;
       RefPtr<SourceSurface> svgMask =
         maskFrame->GetMaskForMaskedFrame(maskContext, aParams.frame,
                                          cssPxToDevPxMatrix,
-                                         aOpacityApplied ? aOpacity : 1.0,
+                                         aOpacity,
                                          &svgMaskMatrix,
                                          svgReset->mMask.mLayers[i].mMaskMode);
       if (svgMask) {
         gfxContextMatrixAutoSaveRestore matRestore(maskContext);
 
         maskContext->Multiply(ThebesMatrix(svgMaskMatrix));
         Rect drawRect = IntRectToRect(IntRect(IntPoint(0, 0), svgMask->GetSize()));
-        maskDT->MaskSurface(ColorPattern(Color(0.0, 0.0, 0.0, 1.0)), svgMask,
+        aMaskDT->MaskSurface(ColorPattern(Color(0.0, 0.0, 0.0, 1.0)), svgMask,
                             drawRect.TopLeft(),
                             DrawOptions(1.0, compositionOp));
       }
     } else {
       gfxContextMatrixAutoSaveRestore matRestore(maskContext);
 
       maskContext->Multiply(gfxMatrix::Translation(-devPixelOffsetToUserSpace));
       nsRenderingContext rc(maskContext);
@@ -534,33 +501,93 @@ GenerateMaskSurface(const PaintFramesPar
         nsCSSRendering::PaintBackgroundWithSC(params, aSC,
                                               *aParams.frame->StyleBorder());
       if (result != DrawResult::SUCCESS) {
         return result;
       }
     }
   }
 
+  return DrawResult::SUCCESS;
+}
+
+static DrawResult
+CreateAndPaintMaskSurface(const PaintFramesParams& aParams,
+                          float aOpacity, nsStyleContext* aSC,
+                          const nsTArray<nsSVGMaskFrame*>& aMaskFrames,
+                          const nsPoint& aOffsetToUserSpace,
+                          Matrix& aOutMaskTransform,
+                          RefPtr<SourceSurface>& aOutMaskSurface,
+                          bool& aOpacityApplied)
+{
+  const nsStyleSVGReset *svgReset = aSC->StyleSVGReset();
+  MOZ_ASSERT(aMaskFrames.Length() > 0);
+
+  gfxContext& ctx = aParams.ctx;
+
+  // There is only one SVG mask.
+  if (((aMaskFrames.Length() == 1) && aMaskFrames[0])) {
+    gfxMatrix cssPxToDevPxMatrix =
+    nsSVGIntegrationUtils::GetCSSPxToDevPxMatrix(aParams.frame);
+
+    aOpacityApplied = true;
+    aOutMaskSurface =
+      aMaskFrames[0]->GetMaskForMaskedFrame(&ctx, aParams.frame,
+                                            cssPxToDevPxMatrix, aOpacity,
+                                            &aOutMaskTransform,
+                                            svgReset->mMask.mLayers[0].mMaskMode);
+    return DrawResult::SUCCESS;
+  }
+
+  const IntRect& maskSurfaceRect = aParams.maskRect;
+  if (maskSurfaceRect.IsEmpty()) {
+    return DrawResult::SUCCESS;
+  }
+
+  RefPtr<DrawTarget> maskDT =
+      ctx.GetDrawTarget()->CreateSimilarDrawTarget(maskSurfaceRect.Size(),
+                                                   SurfaceFormat::A8);
+  if (!maskDT || !maskDT->IsValid()) {
+    return DrawResult::TEMPORARY_ERROR;
+  }
+
+  // Set aAppliedOpacity as true only if all mask layers are svg mask.
+  // In this case, we will apply opacity into the final mask surface, so the
+  // caller does not need to apply it again.
+  aOpacityApplied = !HasNonSVGMask(aMaskFrames);
+
+  // Set context's matrix on maskContext, offset by the maskSurfaceRect's
+  // position. This makes sure that we combine the masks in device space.
+  gfxMatrix maskSurfaceMatrix =
+    ctx.CurrentMatrix() * gfxMatrix::Translation(-aParams.maskRect.TopLeft());
+
+  DrawResult result = PaintMaskSurface(aParams, maskDT,
+                                       aOpacityApplied ? aOpacity : 1.0,
+                                       aSC, aMaskFrames, maskSurfaceMatrix,
+                                       aOffsetToUserSpace);
+  if (result != DrawResult::SUCCESS) {
+    return result;
+  }
+
   aOutMaskTransform = ToMatrix(maskSurfaceMatrix);
   if (!aOutMaskTransform.Invert()) {
     return DrawResult::SUCCESS;
   }
 
   aOutMaskSurface = maskDT->Snapshot();
   return DrawResult::SUCCESS;
 }
 
 static float
-ComputeOpacity(const PaintFramesParams& aParams)
+ComputeOpacity(nsIFrame* aFrame, bool aHandleOpacity)
 {
-  nsIFrame* frame = aParams.frame;
-  float opacity = frame->StyleEffects()->mOpacity;
+  float opacity = aFrame->StyleEffects()->mOpacity;
 
   if (opacity != 1.0f &&
-      (nsSVGUtils::CanOptimizeOpacity(frame) || !aParams.handleOpacity)) {
+      (nsSVGUtils::CanOptimizeOpacity(aFrame) || !aHandleOpacity)) {
     return 1.0f;
   }
 
   return opacity;
 }
 
 static bool
 ValidateSVGFrame(nsIFrame* aFrame)
@@ -653,16 +680,146 @@ SetupContextMatrix(nsIFrame* aFrame, con
     nsRect clipRect =
       aParams.frame->GetVisualOverflowRectRelativeToSelf() + toUserSpace;
     context.Clip(NSRectToSnappedRect(clipRect,
                                   aFrame->PresContext()->AppUnitsPerDevPixel(),
                                   *context.GetDrawTarget()));
   }
 }
 
+void
+nsSVGIntegrationUtils::DetermineMaskUsage(nsIFrame* aFrame,
+                                          bool aHandleOpacity,
+                                          MaskUsage& aUsage)
+{
+  aUsage.opacity = ComputeOpacity(aFrame, aHandleOpacity);
+
+  nsIFrame* firstFrame =
+    nsLayoutUtils::FirstContinuationOrIBSplitSibling(aFrame);
+
+  nsSVGEffects::EffectProperties effectProperties =
+    nsSVGEffects::GetEffectProperties(firstFrame);
+  const nsStyleSVGReset *svgReset = firstFrame->StyleSVGReset();
+
+  nsTArray<nsSVGMaskFrame*> maskFrames = effectProperties.GetMaskFrames();
+
+#ifdef MOZ_ENABLE_MASK_AS_SHORTHAND
+  // For a HTML doc:
+  //   According to css-masking spec, always create a mask surface when we
+  //   have any item in maskFrame even if all of those items are
+  //   non-resolvable <mask-sources> or <images>, we still need to create a
+  //   transparent black mask layer under this condition.
+  // For a SVG doc:
+  //   SVG 1.1 say that  if we fail to resolve a mask, we should draw the
+  //   object unmasked.
+  aUsage.shouldGenerateMaskLayer =
+    (aFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT)
+      ? maskFrames.Length() == 1 && maskFrames[0]
+      : maskFrames.Length() > 0;
+#else
+  // Since we do not support image mask so far, we should treat any
+  // unresolvable mask as no mask. Otherwise, any object with a valid image
+  // mask, e.g. url("xxx.png"), will become invisible just because we can not
+  // handle image mask correctly. (See bug 1294171)
+  aUsage.shouldGenerateMaskLayer = maskFrames.Length() == 1 && maskFrames[0];
+#endif
+
+  bool isOK = effectProperties.HasNoFilterOrHasValidFilter();
+  nsSVGClipPathFrame *clipPathFrame = effectProperties.GetClipPathFrame(&isOK);
+  MOZ_ASSERT_IF(clipPathFrame,
+                svgReset->mClipPath.GetType() == StyleShapeSourceType::URL);
+
+  switch (svgReset->mClipPath.GetType()) {
+    case StyleShapeSourceType::URL:
+      if (clipPathFrame) {
+        if (clipPathFrame->IsTrivial()) {
+          aUsage.shouldApplyClipPath = true;
+        } else {
+          aUsage.shouldGenerateClipMaskLayer = true;
+        }
+      }
+      break;
+    case StyleShapeSourceType::Shape:
+    case StyleShapeSourceType::Box:
+      aUsage.shouldApplyBasicShape = true;
+      break;
+    case StyleShapeSourceType::None:
+      MOZ_ASSERT(!aUsage.shouldGenerateClipMaskLayer &&
+                 !aUsage.shouldApplyClipPath && !aUsage.shouldApplyBasicShape);
+      break;
+    default:
+      MOZ_ASSERT_UNREACHABLE("Unsupported clip-path type.");
+      break;
+  }
+}
+
+bool
+nsSVGIntegrationUtils::IsMaskResourceReady(nsIFrame* aFrame)
+{
+  nsIFrame* firstFrame =
+    nsLayoutUtils::FirstContinuationOrIBSplitSibling(aFrame);
+  nsSVGEffects::EffectProperties effectProperties =
+    nsSVGEffects::GetEffectProperties(firstFrame);
+  nsTArray<nsSVGMaskFrame*> maskFrames = effectProperties.GetMaskFrames();
+  const nsStyleSVGReset* svgReset = firstFrame->StyleSVGReset();
+
+  for (uint32_t i = 0; i < maskFrames.Length(); i++) {
+    // Refers to a valid SVG mask.
+    if (maskFrames[i]) {
+      continue;
+    }
+
+    // Refers to an external resource, which is not ready yet.
+    if (!svgReset->mMask.mLayers[i].mImage.IsComplete()) {
+      return false;
+    }
+  }
+
+  // Either all mask resources are ready, or no mask resource is needed.
+  return true;
+}
+
+DrawResult
+nsSVGIntegrationUtils::PaintMask(const PaintFramesParams& aParams)
+{
+  MaskUsage maskUsage;
+  DetermineMaskUsage(aParams.frame, aParams.handleOpacity, maskUsage);
+  MOZ_ASSERT(maskUsage.shouldGenerateMaskLayer);
+
+  nsIFrame* frame = aParams.frame;
+  if (!ValidateSVGFrame(frame)) {
+    return DrawResult::SUCCESS;
+  }
+
+  if (maskUsage.opacity == 0.0f) {
+    return DrawResult::SUCCESS;
+  }
+
+  gfxContext& ctx = aParams.ctx;
+
+  gfxContextMatrixAutoSaveRestore matSR(&ctx);
+
+  nsIFrame* firstFrame =
+    nsLayoutUtils::FirstContinuationOrIBSplitSibling(frame);
+  nsSVGEffects::EffectProperties effectProperties =
+    nsSVGEffects::GetEffectProperties(firstFrame);
+  nsTArray<nsSVGMaskFrame *> maskFrames = effectProperties.GetMaskFrames();
+  bool opacityApplied = !HasNonSVGMask(maskFrames);
+
+  nsPoint offsetToBoundingBox;
+  nsPoint offsetToUserSpace;
+  SetupContextMatrix(frame, aParams, offsetToBoundingBox,
+                     offsetToUserSpace, false);
+
+  return PaintMaskSurface(aParams, ctx.GetDrawTarget(),
+                            opacityApplied ? maskUsage.opacity : 1.0,
+                            firstFrame->StyleContext(), maskFrames,
+                            ctx.CurrentMatrix(), offsetToUserSpace);
+}
+
 DrawResult
 nsSVGIntegrationUtils::PaintMaskAndClipPath(const PaintFramesParams& aParams)
 {
   MOZ_ASSERT(UsingMaskOrClipPathForFrame(aParams.frame),
              "Should not use this method when no mask or clipPath effect"
              "on this frame");
 
   /* SVG defines the following rendering model:
@@ -679,119 +836,75 @@ nsSVGIntegrationUtils::PaintMaskAndClipP
    * + Merge opacity and masking if both used together.
    */
   nsIFrame* frame = aParams.frame;
   DrawResult result = DrawResult::SUCCESS;
   if (!ValidateSVGFrame(frame)) {
     return result;
   }
 
-  float opacity = ComputeOpacity(aParams);
-  if (opacity == 0.0f) {
+  MaskUsage maskUsage;
+  DetermineMaskUsage(aParams.frame, aParams.handleOpacity, maskUsage);
+
+  if (maskUsage.opacity == 0.0f) {
     return DrawResult::SUCCESS;
   }
 
   gfxContext& context = aParams.ctx;
   gfxContextMatrixAutoSaveRestore matrixAutoSaveRestore(&context);
 
   /* Properties are added lazily and may have been removed by a restyle,
      so make sure all applicable ones are set again. */
   nsIFrame* firstFrame =
     nsLayoutUtils::FirstContinuationOrIBSplitSibling(frame);
   nsSVGEffects::EffectProperties effectProperties =
     nsSVGEffects::GetEffectProperties(firstFrame);
 
-  gfxMatrix cssPxToDevPxMatrix = GetCSSPxToDevPxMatrix(frame);
-  const nsStyleSVGReset *svgReset = firstFrame->StyleSVGReset();
-  nsTArray<nsSVGMaskFrame *> maskFrames = effectProperties.GetMaskFrames();
-
-#ifdef MOZ_ENABLE_MASK_AS_SHORTHAND
-  // For a HTML doc:
-  //   According to css-masking spec, always create a mask surface when we
-  //   have any item in maskFrame even if all of those items are
-  //   non-resolvable <mask-sources> or <images>, we still need to create a
-  //   transparent black mask layer under this condition.
-  // For a SVG doc:
-  //   SVG 1.1 say that  if we fail to resolve a mask, we should draw the
-  //   object unmasked.
-  bool hasSVGLayout = (frame->GetStateBits() & NS_FRAME_SVG_LAYOUT);
-  bool shouldGenerateMaskLayer = hasSVGLayout
-                                 ? maskFrames.Length() == 1 && maskFrames[0]
-                                 : maskFrames.Length() > 0;
-#else
-  // Since we do not support image mask so far, we should treat any
-  // unresolvable mask as no mask. Otherwise, any object with a valid image
-  // mask, e.g. url("xxx.png"), will become invisible just because we can not
-  // handle image mask correctly. (See bug 1294171)
-  bool shouldGenerateMaskLayer = maskFrames.Length() == 1 && maskFrames[0];
-#endif
-
   bool isOK = effectProperties.HasNoFilterOrHasValidFilter();
   nsSVGClipPathFrame *clipPathFrame = effectProperties.GetClipPathFrame(&isOK);
-  MOZ_ASSERT_IF(clipPathFrame,
-                svgReset->mClipPath.GetType() == StyleShapeSourceType::URL);
 
-  bool shouldGenerateClipMaskLayer = false;
-  bool shouldApplyClipPath = false;
-  bool shouldApplyBasicShape = false;
-  switch (svgReset->mClipPath.GetType()) {
-    case StyleShapeSourceType::URL:
-      if (clipPathFrame) {
-        if (clipPathFrame->IsTrivial()) {
-          shouldApplyClipPath = true;
-        } else {
-          shouldGenerateClipMaskLayer = true;
-        }
-      }
-      break;
-    case StyleShapeSourceType::Shape:
-    case StyleShapeSourceType::Box:
-      shouldApplyBasicShape = true;
-      break;
-    case StyleShapeSourceType::None:
-      break;
-    default:
-      MOZ_ASSERT_UNREACHABLE("Unsupported clip-path type.");
-      break;
-  }
+  gfxMatrix cssPxToDevPxMatrix = GetCSSPxToDevPxMatrix(frame);
+  nsTArray<nsSVGMaskFrame*> maskFrames = effectProperties.GetMaskFrames();
 
   nsPoint offsetToBoundingBox;
   nsPoint offsetToUserSpace;
 
-  bool shouldGenerateMask = (opacity != 1.0f || shouldGenerateClipMaskLayer ||
-                             shouldGenerateMaskLayer);
+  bool shouldGenerateMask = (maskUsage.opacity != 1.0f ||
+                             maskUsage.shouldGenerateClipMaskLayer ||
+                             maskUsage.shouldGenerateMaskLayer);
 
   /* Check if we need to do additional operations on this child's
    * rendering, which necessitates rendering into another surface. */
   if (shouldGenerateMask) {
     gfxContextMatrixAutoSaveRestore matSR;
 
     Matrix maskTransform;
     RefPtr<SourceSurface> maskSurface;
     bool opacityApplied = false;
 
-    if (shouldGenerateMaskLayer) {
+    if (maskUsage.shouldGenerateMaskLayer) {
       matSR.SetContext(&context);
 
       // For css-mask, we want to generate a mask for each continuation frame,
       // so we setup context matrix by the position of the current frame,
       // instead of the first continuation frame.
       SetupContextMatrix(frame, aParams, offsetToBoundingBox,
                          offsetToUserSpace, false);
-      result = GenerateMaskSurface(aParams, opacity,
-                                  firstFrame->StyleContext(),
-                                  maskFrames, offsetToUserSpace,
-                                  maskTransform, maskSurface, opacityApplied);
+      result = CreateAndPaintMaskSurface(aParams, maskUsage.opacity,
+                                         firstFrame->StyleContext(),
+                                         maskFrames, offsetToUserSpace,
+                                         maskTransform, maskSurface,
+                                         opacityApplied);
       if (!maskSurface) {
         // Entire surface is clipped out.
         return result;
       }
     }
 
-    if (shouldGenerateClipMaskLayer) {
+    if (maskUsage.shouldGenerateClipMaskLayer) {
       matSR.Restore();
       matSR.SetContext(&context);
 
       SetupContextMatrix(firstFrame, aParams, offsetToBoundingBox,
                          offsetToUserSpace, false);
       Matrix clippedMaskTransform;
       RefPtr<SourceSurface> clipMaskSurface =
         clipPathFrame->GetClipMask(context, frame, cssPxToDevPxMatrix,
@@ -804,62 +917,66 @@ nsSVGIntegrationUtils::PaintMaskAndClipP
       } else {
         // Either entire surface is clipped out, or gfx buffer allocation
         // failure in nsSVGClipPathFrame::GetClipMask.
         return result;
       }
     }
 
     // opacity != 1.0f.
-    if (!shouldGenerateClipMaskLayer && !shouldGenerateMaskLayer) {
-      MOZ_ASSERT(opacity != 1.0f);
+    if (!maskUsage.shouldGenerateClipMaskLayer &&
+        !maskUsage.shouldGenerateMaskLayer) {
+      MOZ_ASSERT(maskUsage.opacity != 1.0f);
 
       matSR.SetContext(&context);
       SetupContextMatrix(firstFrame, aParams, offsetToBoundingBox,
                          offsetToUserSpace, false);
     }
 
     if (aParams.layerManager->GetRoot()->GetContentFlags() & Layer::CONTENT_COMPONENT_ALPHA) {
       context.PushGroupAndCopyBackground(gfxContentType::COLOR_ALPHA,
-                                         opacityApplied ?  1.0 : opacity,
+                                         opacityApplied
+                                           ? 1.0
+                                           : maskUsage.opacity,
                                          maskSurface, maskTransform);
     } else {
       context.PushGroupForBlendBack(gfxContentType::COLOR_ALPHA,
-                                    opacityApplied ?  1.0 : opacity,
+                                    opacityApplied ? 1.0 : maskUsage.opacity,
                                     maskSurface, maskTransform);
     }
   }
 
   /* If this frame has only a trivial clipPath, set up cairo's clipping now so
    * we can just do normal painting and get it clipped appropriately.
    */
-  if (shouldApplyClipPath || shouldApplyBasicShape) {
+  if (maskUsage.shouldApplyClipPath || maskUsage.shouldApplyBasicShape) {
     gfxContextMatrixAutoSaveRestore matSR(&context);
 
     SetupContextMatrix(firstFrame, aParams, offsetToBoundingBox,
                        offsetToUserSpace, false);
 
-    MOZ_ASSERT(!shouldApplyClipPath || !shouldApplyBasicShape);
-    if (shouldApplyClipPath) {
+    MOZ_ASSERT(!maskUsage.shouldApplyClipPath ||
+               !maskUsage.shouldApplyBasicShape);
+    if (maskUsage.shouldApplyClipPath) {
       clipPathFrame->ApplyClipPath(context, frame, cssPxToDevPxMatrix);
     } else {
       nsCSSClipPathInstance::ApplyBasicShapeClip(context, frame);
     }
   }
 
   /* Paint the child */
   context.SetMatrix(matrixAutoSaveRestore.Matrix());
   BasicLayerManager* basic = aParams.layerManager->AsBasicLayerManager();
   RefPtr<gfxContext> oldCtx = basic->GetTarget();
   basic->SetTarget(&context);
   aParams.layerManager->EndTransaction(FrameLayerBuilder::DrawPaintedLayer,
                                        aParams.builder);
   basic->SetTarget(oldCtx);
 
-  if (shouldApplyClipPath || shouldApplyBasicShape) {
+  if (maskUsage.shouldApplyClipPath || maskUsage.shouldApplyBasicShape) {
     context.PopClip();
   }
 
   if (shouldGenerateMask) {
     context.PopGroupAndBlend();
   }
 
   return result;
@@ -873,17 +990,17 @@ nsSVGIntegrationUtils::PaintFilter(const
   MOZ_ASSERT(aParams.frame->StyleEffects()->HasFilters(),
              "Should not use this method when no filter effect on this frame");
 
   nsIFrame* frame = aParams.frame;
   if (!ValidateSVGFrame(frame)) {
     return DrawResult::SUCCESS;
   }
 
-  float opacity = ComputeOpacity(aParams);
+  float opacity = ComputeOpacity(frame, aParams.handleOpacity);
   if (opacity == 0.0f) {
     return DrawResult::SUCCESS;
   }
 
   /* Properties are added lazily and may have been removed by a restyle,
      so make sure all applicable ones are set again. */
   nsIFrame* firstFrame =
     nsLayoutUtils::FirstContinuationOrIBSplitSibling(frame);
--- a/layout/svg/nsSVGIntegrationUtils.h
+++ b/layout/svg/nsSVGIntegrationUtils.h
@@ -156,16 +156,45 @@ public:
 
   /**
    * Paint non-SVG frame with mask, clipPath and opacity effect.
    */
   static DrawResult
   PaintMaskAndClipPath(const PaintFramesParams& aParams);
 
   /**
+   * Paint mask of non-SVG frame onto a given context, aParams.ctx.
+   * aParams.ctx must contain an A8 surface.
+   */
+  static DrawResult
+  PaintMask(const PaintFramesParams& aParams);
+
+  struct MaskUsage {
+    bool shouldGenerateMaskLayer;
+    bool shouldGenerateClipMaskLayer;
+    bool shouldApplyClipPath;
+    bool shouldApplyBasicShape;
+    float opacity;
+
+    MaskUsage()
+      : shouldGenerateMaskLayer(false), shouldGenerateClipMaskLayer(false),
+        shouldApplyClipPath(false), shouldApplyBasicShape(false), opacity(0.0)
+    { }
+  };
+
+  static void
+  DetermineMaskUsage(nsIFrame* aFrame, bool aHandleOpacity, MaskUsage& aUsage);
+
+  /**
+   * Return true if all the mask resource of aFrame are ready.
+   */
+  static bool
+  IsMaskResourceReady(nsIFrame* aFrame);
+
+  /**
    * Paint non-SVG frame with filter and opacity effect.
    */
   static DrawResult
   PaintFilter(const PaintFramesParams& aParams);
 
   /**
    * SVG frames expect to paint in SVG user units, which are equal to CSS px
    * units. This method provides a transform matrix to multiply onto a
--- a/mobile/android/installer/allowed-dupes.mn
+++ b/mobile/android/installer/allowed-dupes.mn
@@ -112,8 +112,10 @@ modules/devtools/shared/Console.jsm
 modules/devtools/shared/Loader.jsm
 modules/devtools/shared/apps/Simulator.jsm
 res/table-remove-column-active.gif
 res/table-remove-column-hover.gif
 res/table-remove-column.gif
 res/table-remove-row-active.gif
 res/table-remove-row-hover.gif
 res/table-remove-row.gif
+modules/commonjs/index.js
+chrome/toolkit/content/global/XPCNativeWrapper.js
--- a/netwerk/protocol/http/AlternateServices.cpp
+++ b/netwerk/protocol/http/AlternateServices.cpp
@@ -537,16 +537,17 @@ public:
 
   nsresult Start()
   {
     LOG(("WellKnownChecker::Start %p\n", this));
     nsCOMPtr<nsILoadInfo> loadInfo = new LoadInfo(nsContentUtils::GetSystemPrincipal(),
                                                   nullptr, nullptr,
                                                   nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
                                                   nsIContentPolicy::TYPE_OTHER);
+    loadInfo->SetOriginAttributes(mCI->GetOriginAttributes());
 
     RefPtr<nsHttpChannel> chan = new nsHttpChannel();
     nsresult rv;
 
     mTransactionAlternate = new TransactionObserver(chan, this);
     RefPtr<nsHttpConnectionInfo> newCI = mCI->Clone();
     rv = MakeChannel(chan, mTransactionAlternate, newCI, mURI, mCaps, loadInfo);
     if (NS_FAILED(rv)) {
--- a/other-licenses/ia2/ia2_api_all.idl
+++ b/other-licenses/ia2/ia2_api_all.idl
@@ -5441,16 +5441,17 @@ cpp_quote("")
 ]
 
 library IAccessible2Lib
 {
     importlib ("stdole2.tlb");
     importlib ("oleacc.dll");
     interface IAccessible2;
     interface IAccessible2_2;
+    interface IAccessible2_3;
     interface IAccessibleAction;
     interface IAccessibleApplication;
     interface IAccessibleComponent;
     interface IAccessibleDocument;
     interface IAccessibleEditableText;
     interface IAccessibleHyperlink;
     interface IAccessibleHypertext;
     interface IAccessibleHypertext2;
--- a/python/mach/mach/main.py
+++ b/python/mach/mach/main.py
@@ -325,26 +325,35 @@ To see more help for a specific command,
         orig_stdin = sys.stdin
         orig_stdout = sys.stdout
         orig_stderr = sys.stderr
 
         sys.stdin = stdin
         sys.stdout = stdout
         sys.stderr = stderr
 
+        orig_env = dict(os.environ)
+
         try:
             if stdin.encoding is None:
                 sys.stdin = codecs.getreader('utf-8')(stdin)
 
             if stdout.encoding is None:
                 sys.stdout = codecs.getwriter('utf-8')(stdout)
 
             if stderr.encoding is None:
                 sys.stderr = codecs.getwriter('utf-8')(stderr)
 
+            # Allow invoked processes (which may not have a handle on the
+            # original stdout file descriptor) to know if the original stdout
+            # is a TTY. This provides a mechanism to allow said processes to
+            # enable emitting code codes, for example.
+            if os.isatty(orig_stdout.fileno()):
+                os.environ[b'MACH_STDOUT_ISATTY'] = b'1'
+
             return self._run(argv)
         except KeyboardInterrupt:
             print('mach interrupted by signal or user action. Stopping.')
             return 1
 
         except Exception as e:
             # _run swallows exceptions in invoked handlers and converts them to
             # a proper exit code. So, the only scenario where we should get an
@@ -357,16 +366,19 @@ To see more help for a specific command,
             exc_type, exc_value, exc_tb = sys.exc_info()
             stack = traceback.extract_tb(exc_tb)
 
             self._print_exception(sys.stdout, exc_type, exc_value, stack)
 
             return 1
 
         finally:
+            os.environ.clear()
+            os.environ.update(orig_env)
+
             sys.stdin = orig_stdin
             sys.stdout = orig_stdout
             sys.stderr = orig_stderr
 
     def _run(self, argv):
         # Load settings as early as possible so things in dispatcher.py
         # can use them.
         for provider in Registrar.settings_providers:
--- a/python/mozlint/mozlint/roller.py
+++ b/python/mozlint/mozlint/roller.py
@@ -1,16 +1,17 @@
 # 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/.
 
 from __future__ import unicode_literals
 
 import os
 import signal
+import sys
 import traceback
 from collections import defaultdict
 from Queue import Empty
 from multiprocessing import (
     Manager,
     Pool,
     cpu_count,
 )
@@ -57,16 +58,18 @@ def _run_linters(queue, paths, **lintarg
 def _run_worker(*args, **lintargs):
     try:
         return _run_linters(*args, **lintargs)
     except Exception:
         # multiprocessing seems to munge worker exceptions, print
         # it here so it isn't lost.
         traceback.print_exc()
         raise
+    finally:
+        sys.stdout.flush()
 
 
 class LintRoller(object):
     """Registers and runs linters.
 
     :param root: Path to which relative paths will be joined. If
                  unspecified, root will either be determined from
                  version control or cwd.
--- a/security/certverifier/NSSCertDBTrustDomain.cpp
+++ b/security/certverifier/NSSCertDBTrustDomain.cpp
@@ -553,17 +553,17 @@ NSSCertDBTrustDomain::CheckRevocation(En
     SECItem ocspRequestItem = {
       siBuffer,
       ocspRequest,
       static_cast<unsigned int>(ocspRequestLength)
     };
     // Owned by arena
     SECItem* responseSECItem = nullptr;
     Result tempRV =
-      DoOCSPRequest(arena, url, &ocspRequestItem,
+      DoOCSPRequest(arena, url, mFirstPartyDomain, &ocspRequestItem,
                     OCSPFetchingTypeToTimeoutTime(mOCSPFetching),
                     mOCSPGetConfig == CertVerifier::ocspGetEnabled,
                     responseSECItem);
     MOZ_ASSERT((tempRV != Success) || responseSECItem);
     if (tempRV != Success) {
       rv = tempRV;
     } else if (response.Init(responseSECItem->data, responseSECItem->len)
                  != Success) {
--- a/security/certverifier/OCSPRequestor.cpp
+++ b/security/certverifier/OCSPRequestor.cpp
@@ -69,18 +69,18 @@ AppendEscapedBase64Item(const SECItem* e
   base64Request.ReplaceSubstring("/", "%2F");
   base64Request.ReplaceSubstring("=", "%3D");
   path.Append(base64Request);
   return NS_OK;
 }
 
 Result
 DoOCSPRequest(const UniquePLArenaPool& arena, const char* url,
-              const SECItem* encodedRequest, PRIntervalTime timeout,
-              bool useGET,
+              const char* firstPartyDomain, const SECItem* encodedRequest,
+              PRIntervalTime timeout, bool useGET,
       /*out*/ SECItem*& encodedResponse)
 {
   MOZ_ASSERT(arena.get());
   MOZ_ASSERT(url);
   MOZ_ASSERT(encodedRequest);
   MOZ_ASSERT(encodedRequest->data);
   if (!arena.get() || !url || !encodedRequest || !encodedRequest->data) {
     return Result::FATAL_ERROR_INVALID_ARGS;
@@ -168,17 +168,18 @@ DoOCSPRequest(const UniquePLArenaPool& a
     nsresult nsrv = AppendEscapedBase64Item(encodedRequest, path);
     if (NS_WARN_IF(NS_FAILED(nsrv))) {
       return Result::FATAL_ERROR_LIBRARY_FAILURE;
     }
   }
 
   nsNSSHttpRequestSession* requestSessionPtr;
   rv = nsNSSHttpInterface::createFcn(serverSession.get(), "http", path.get(),
-                                     method.get(), timeout, &requestSessionPtr);
+                                     method.get(), firstPartyDomain, timeout,
+                                     &requestSessionPtr);
   if (rv != Success) {
     return rv;
   }
 
   UniqueHTTPRequestSession requestSession(requestSessionPtr);
 
   if (!useGET) {
     rv = nsNSSHttpInterface::setPostDataFcn(
--- a/security/certverifier/OCSPRequestor.h
+++ b/security/certverifier/OCSPRequestor.h
@@ -9,15 +9,16 @@
 
 #include "CertVerifier.h"
 #include "secmodt.h"
 
 namespace mozilla { namespace psm {
 
 // The memory returned via |encodedResponse| is owned by the given arena.
 Result DoOCSPRequest(const UniquePLArenaPool& arena, const char* url,
+                     const char* firstPartyDomain,
                      const SECItem* encodedRequest, PRIntervalTime timeout,
                      bool useGET,
              /*out*/ SECItem*& encodedResponse);
 
 } } // namespace mozilla::psm
 
 #endif // OCSPRequestor_h
--- a/security/manager/locales/en-US/chrome/pipnss/pipnss.properties
+++ b/security/manager/locales/en-US/chrome/pipnss/pipnss.properties
@@ -167,17 +167,16 @@ CertDumpKeyCompromise=Key Compromise
 CertDumpCACompromise=CA Compromise
 CertDumpAffiliationChanged=Affiliation Changed
 CertDumpSuperseded=Superseded
 CertDumpCessation=Cessation of Operation
 CertDumpHold=Certificate Hold
 CertDumpOCSPResponder=OCSP
 CertDumpCAIssuers=CA Issuers
 CertDumpCPSPointer=Certification Practice Statement pointer
-CertDumpPolicyOidEV=Extended Validation (EV) SSL Server Certificate
 CertDumpUserNotice=User Notice
 CertDumpLogotype=Logotype
 CertDumpECPublicKey=Elliptic Curve Public Key
 CertDumpECDSAWithSHA1=X9.62 ECDSA Signature with SHA1
 CertDumpECprime192v1=ANSI X9.62 elliptic curve prime192v1 (aka secp192r1, NIST P-192)
 CertDumpECprime192v2=ANSI X9.62 elliptic curve prime192v2
 CertDumpECprime192v3=ANSI X9.62 elliptic curve prime192v3
 CertDumpECprime239v1=ANSI X9.62 elliptic curve prime239v1
--- a/security/manager/pki/nsNSSDialogs.cpp
+++ b/security/manager/pki/nsNSSDialogs.cpp
@@ -265,48 +265,46 @@ nsNSSDialogs::ChooseCertificate(nsIInter
     if (NS_FAILED(rv)) {
       return rv;
     }
   }
 
   return NS_OK;
 }
 
-NS_IMETHODIMP 
-nsNSSDialogs::SetPKCS12FilePassword(nsIInterfaceRequestor *ctx, 
-                                    nsAString &_password,
-                                    bool *_retval)
+NS_IMETHODIMP
+nsNSSDialogs::SetPKCS12FilePassword(nsIInterfaceRequestor* ctx,
+                            /*out*/ nsAString& password,
+                            /*out*/ bool* confirmedPassword)
 {
-  nsresult rv;
-  *_retval = true;
+  // |ctx| is allowed to be null.
+  NS_ENSURE_ARG(confirmedPassword);
+
   // Get the parent window for the dialog
   nsCOMPtr<mozIDOMWindowProxy> parent = do_GetInterface(ctx);
-  nsCOMPtr<nsIDialogParamBlock> block =
-           do_CreateInstance(NS_DIALOGPARAMBLOCK_CONTRACTID);
-  if (!block) return NS_ERROR_FAILURE;
-  // open up the window
-  rv = nsNSSDialogHelper::openDialog(parent,
+  nsCOMPtr<nsIWritablePropertyBag2> retVals = new nsHashPropertyBag();
+  nsresult rv =
+    nsNSSDialogHelper::openDialog(parent,
                                   "chrome://pippki/content/setp12password.xul",
-                                  block);
-  if (NS_FAILED(rv)) return rv;
-  // see if user canceled
-  int32_t status;
-  rv = block->GetInt(1, &status);
-  if (NS_FAILED(rv)) return rv;
-  *_retval = (status == 0) ? false : true;
-  if (*_retval) {
-    // retrieve the password
-    char16_t *pw;
-    rv = block->GetString(2, &pw);
-    if (NS_SUCCEEDED(rv)) {
-      _password = pw;
-      free(pw);
-    }
+                                  retVals);
+  if (NS_FAILED(rv)) {
+    return rv;
   }
-  return rv;
+
+  rv = retVals->GetPropertyAsBool(NS_LITERAL_STRING("confirmedPassword"),
+                                  confirmedPassword);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+
+  if (!*confirmedPassword) {
+    return NS_OK;
+  }
+
+  return retVals->GetPropertyAsAString(NS_LITERAL_STRING("password"), password);
 }
 
 NS_IMETHODIMP
 nsNSSDialogs::GetPKCS12FilePassword(nsIInterfaceRequestor* ctx,
                                     nsAString& _password,
                                     bool* _retval)
 {
   *_retval = false;
rename from security/manager/pki/resources/content/password.js
rename to security/manager/pki/resources/content/changepassword.js
--- a/security/manager/pki/resources/content/password.js
+++ b/security/manager/pki/resources/content/changepassword.js
@@ -119,25 +119,16 @@ function process()
   if (params) {
     // Return value 0 means "canceled"
     params.SetInt(1, 0);
   }
 
   checkPasswords();
 }
 
-function onP12Load(disableOkButton)
-{
-  document.documentElement.getButton("accept").disabled = disableOkButton;
-  pw1 = document.getElementById("pw1");
-  params = window.arguments[0].QueryInterface(nsIDialogParamBlock);
-  // Select first password field
-  document.getElementById('pw1').focus();
-}
-
 function setPassword()
 {
   var pk11db = Components.classes[nsPK11TokenDB].getService(nsIPK11TokenDB);
   var token = pk11db.findTokenByName(tokenName);
 
   var oldpwbox = document.getElementById("oldpw");
   var initpw = oldpwbox.getAttribute("inited");
   var bundle = document.getElementById("pippki_bundle");
@@ -201,26 +192,16 @@ function setPassword()
     // Return value 1 means "successfully executed ok"
     params.SetInt(1, 1);
   }
 
   // Terminate dialog
   return success;
 }
 
-function setP12Password()
-{
-  // grab what was entered
-  params.SetString(2, pw1.value);
-  // Return value
-  params.SetInt(1, 1);
-  // Terminate dialog
-  return true;
-}
-
 function setPasswordStrength()
 {
   // We weigh the quality of the password by checking the number of:
   //  - Characters
   //  - Numbers
   //  - Non-alphanumeric chars
   //  - Upper and lower case characters
 
--- a/security/manager/pki/resources/content/changepassword.xul
+++ b/security/manager/pki/resources/content/changepassword.xul
@@ -10,17 +10,18 @@
 <dialog id="set_password" title="&setPassword.title;"
   xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"      
   buttons="accept,cancel"
   ondialogaccept="return setPassword();"
   onload="onLoad();">
 
 <stringbundle id="pippki_bundle" src="chrome://pippki/locale/pippki.properties"/>
 
-<script type="application/javascript" src="chrome://pippki/content/password.js"/>
+<script type="application/javascript"
+        src="chrome://pippki/content/changepassword.js"/>
 
 <hbox align="center">
   <label value="&setPassword.tokenName.label;: "/>
   <label id="tokenName" />
   <menulist id="tokenMenu" oncommand="onMenuChange()">
      <menupopup/>
   </menulist>
 </hbox>
new file mode 100644
--- /dev/null
+++ b/security/manager/pki/resources/content/setp12password.js
@@ -0,0 +1,128 @@
+/* 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 strict";
+
+/**
+ * @file Implements the functionality of setp12password.xul: a dialog that lets
+ *       the user confirm the password to set on a PKCS #12 file.
+ * @argument {nsISupports} window.arguments[0]
+ *           Object to set the return values of calling the dialog on, queryable
+ *           to the underlying type of SetP12PasswordReturnValues.
+ */
+
+/**
+ * @typedef SetP12PasswordReturnValues
+ * @type nsIWritablePropertyBag2
+ * @property {Boolean} confirmedPassword
+ *           Set to true if the user entered two matching passwords and
+ *           confirmed the dialog.
+ * @property {String} password
+ *           The password the user entered. Undefined value if
+ *           |confirmedPassword| is not true.
+ */
+
+const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
+
+/**
+ * onload() handler.
+ */
+function onLoad() {
+  // Ensure the first password textbox has focus.
+  document.getElementById("pw1").focus();
+}
+
+/**
+ * ondialogaccept() handler.
+ *
+ * @returns {Boolean} true to make the dialog close, false otherwise.
+ */
+function onDialogAccept() {
+  let password = document.getElementById("pw1").value;
+
+  let retVals = window.arguments[0].QueryInterface(Ci.nsIWritablePropertyBag2);
+  retVals.setPropertyAsBool("confirmedPassword", true);
+  retVals.setPropertyAsAString("password", password);
+  return true;
+}
+
+/**
+ * ondialogcancel() handler.
+ *
+ * @returns {Boolean} true to make the dialog close, false otherwise.
+ */
+function onDialogCancel() {
+  let retVals = window.arguments[0].QueryInterface(Ci.nsIWritablePropertyBag2);
+  retVals.setPropertyAsBool("confirmedPassword", false);
+  return true;
+}
+
+/**
+ * Calculates the strength of the given password, suitable for use in updating
+ * a progress bar that represents said strength.
+ *
+ * The strength of the password is calculated by checking the number of:
+ *   - Characters
+ *   - Numbers
+ *   - Non-alphanumeric chars
+ *   - Upper case characters
+ *
+ * @param {String} password
+ *        The password to calculate the strength of.
+ * @returns {Number}
+ *          The strength of the password in the range [0, 100].
+ */
+function getPasswordStrength(password) {
+  let lengthStrength = password.length;
+  if (lengthStrength > 5) {
+    lengthStrength = 5;
+  }
+
+  let nonNumericChars = password.replace(/[0-9]/g, "");
+  let numericStrength = password.length - nonNumericChars.length;
+  if (numericStrength > 3) {
+    numericStrength = 3;
+  }
+
+  let nonSymbolChars = password.replace(/\W/g, "");
+  let symbolStrength = password.length - nonSymbolChars.length;
+  if (symbolStrength > 3) {
+    symbolStrength = 3;
+  }
+
+  let nonUpperAlphaChars = password.replace(/[A-Z]/g, "");
+  let upperAlphaStrength = password.length - nonUpperAlphaChars.length;
+  if (upperAlphaStrength > 3) {
+    upperAlphaStrength = 3;
+  }
+
+  let strength = (lengthStrength * 10) - 20 + (numericStrength * 10) +
+                 (symbolStrength * 15) + (upperAlphaStrength * 10);
+  if (strength < 0) {
+    strength = 0;
+  }
+  if (strength > 100) {
+    strength = 100;
+  }
+
+  return strength;
+}
+
+/**
+ * oninput() handler for both password textboxes.
+ *
+ * @param {Boolean} recalculatePasswordStrength
+ *                  Whether to recalculate the strength of the first password.
+ */
+function onPasswordInput(recalculatePasswordStrength) {
+  let pw1 = document.getElementById("pw1").value;
+
+  if (recalculatePasswordStrength) {
+    document.getElementById("pwmeter").value = getPasswordStrength(pw1);
+  }
+
+  // Disable the accept button if the two passwords don't match, and enable it
+  // if the passwords do match.
+  let pw2 = document.getElementById("pw2").value;
+  document.documentElement.getButton("accept").disabled = (pw1 != pw2);
+}
--- a/security/manager/pki/resources/content/setp12password.xul
+++ b/security/manager/pki/resources/content/setp12password.xul
@@ -2,50 +2,50 @@
 <!-- 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/. -->
 
 <?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
 
 <!DOCTYPE dialog SYSTEM "chrome://pippki/locale/pippki.dtd">
 
-<dialog id="setp12password" title="&pkcs12.setpassword.title;"
-  xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"      
-  style="width: 48em;"
-  buttons="accept,cancel"
-  ondialogaccept="return setP12Password();"
-  onload="onP12Load(true);">
+<dialog id="setp12password"
+        title="&pkcs12.setpassword.title;"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        style="width: 48em;"
+        buttons="accept,cancel"
+        ondialogaccept="return onDialogAccept();"
+        ondialogcancel="return onDialogCancel();"
+        onload="onLoad();">
 
-  <script type="application/javascript" src="chrome://pippki/content/password.js"/>
+  <script type="application/javascript"
+          src="chrome://pippki/content/setp12password.js"/>
 
   <description>&pkcs12.setpassword.message;</description>
   <separator />
   <grid>
     <columns> <column/> <column/> </columns>
     <rows>
       <row>
-        <label value="&pkcs12.setpassword.label1;"/> 
-        <textbox id="pw1" type="password" 
-                 oninput="setPasswordStrength(); checkPasswords();"/> 
+        <label value="&pkcs12.setpassword.label1;"/>
+        <textbox id="pw1" type="password" oninput="onPasswordInput(true);"/>
       </row>
       <row>
-        <label value="&pkcs12.setpassword.label2;"/> 
-        <textbox id="pw2" type="password" 
-                 oninput="checkPasswords();"/>  
+        <label value="&pkcs12.setpassword.label2;"/>
+        <textbox id="pw2" type="password" oninput="onPasswordInput(false);"/>
       </row>
     </rows>
   </grid>
   <separator/>
   <description>&pkcs12.setpassword.reminder;</description>
   <separator/>
   <label value="&setPassword.meter.label;"/>
   <grid style="margin: 4px;">
     <rows> <row/> </rows>
     <columns>
       <column style="margin: 5px;">
-        <progressmeter flex="1" id="pwmeter" mode="determined" value="0%"
+        <progressmeter flex="1" id="pwmeter" mode="determined" value="0"
                        orient="horizontal"
-                       style="width: 20em; foreground-color: red"/> 
+                       style="width: 20em; foreground-color: red"/>
       </column>
     </columns>
   </grid>
-  
 </dialog>
--- a/security/manager/pki/resources/jar.mn
+++ b/security/manager/pki/resources/jar.mn
@@ -1,42 +1,43 @@
 # 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/.
 
 pippki.jar:
 % content pippki %content/pippki/
-    content/pippki/changepassword.xul        (content/changepassword.xul)
-    content/pippki/password.js               (content/password.js)
-    content/pippki/resetpassword.xul         (content/resetpassword.xul)
-    content/pippki/resetpassword.js          (content/resetpassword.js)
-    content/pippki/downloadcert.js           (content/downloadcert.js)
-    content/pippki/downloadcert.xul          (content/downloadcert.xul)
-    content/pippki/certManager.js            (content/certManager.js)
-    content/pippki/certManager.xul           (content/certManager.xul)
     content/pippki/CAOverlay.xul             (content/CAOverlay.xul)
-    content/pippki/WebSitesOverlay.xul       (content/WebSitesOverlay.xul)
-    content/pippki/OthersOverlay.xul         (content/OthersOverlay.xul)
     content/pippki/MineOverlay.xul           (content/MineOverlay.xul)
     content/pippki/OrphanOverlay.xul         (content/OrphanOverlay.xul)
-    content/pippki/viewCertDetails.xul       (content/viewCertDetails.xul)
-    content/pippki/editcacert.xul            (content/editcacert.xul)
-    content/pippki/editcacert.js             (content/editcacert.js)
-*   content/pippki/exceptionDialog.xul       (content/exceptionDialog.xul)
-    content/pippki/exceptionDialog.js        (content/exceptionDialog.js)
-    content/pippki/deletecert.xul            (content/deletecert.xul)
-    content/pippki/deletecert.js             (content/deletecert.js)
-    content/pippki/setp12password.xul        (content/setp12password.xul)
-    content/pippki/pippki.js                 (content/pippki.js)
-    content/pippki/clientauthask.xul	     (content/clientauthask.xul)
-    content/pippki/clientauthask.js          (content/clientauthask.js)
+    content/pippki/OthersOverlay.xul         (content/OthersOverlay.xul)
+    content/pippki/WebSitesOverlay.xul       (content/WebSitesOverlay.xul)
+    content/pippki/certDump.xul              (content/certDump.xul)
+    content/pippki/certManager.js            (content/certManager.js)
+    content/pippki/certManager.xul           (content/certManager.xul)
+    content/pippki/certViewer.js             (content/certViewer.js)
     content/pippki/certViewer.xul            (content/certViewer.xul)
-    content/pippki/certViewer.js             (content/certViewer.js)
-    content/pippki/certDump.xul              (content/certDump.xul)
-    content/pippki/device_manager.xul        (content/device_manager.xul)
-    content/pippki/device_manager.js         (content/device_manager.js)
-    content/pippki/load_device.xul           (content/load_device.xul)
+    content/pippki/changepassword.js         (content/changepassword.js)
+    content/pippki/changepassword.xul        (content/changepassword.xul)
+    content/pippki/choosetoken.js            (content/choosetoken.js)
     content/pippki/choosetoken.xul           (content/choosetoken.xul)
-    content/pippki/choosetoken.js            (content/choosetoken.js)
-    content/pippki/createCertInfo.xul        (content/createCertInfo.xul)
+    content/pippki/clientauthask.js          (content/clientauthask.js)
+    content/pippki/clientauthask.xul         (content/clientauthask.xul)
     content/pippki/createCertInfo.js         (content/createCertInfo.js)
+    content/pippki/createCertInfo.xul        (content/createCertInfo.xul)
+    content/pippki/deletecert.js             (content/deletecert.js)
+    content/pippki/deletecert.xul            (content/deletecert.xul)
+    content/pippki/device_manager.js         (content/device_manager.js)
+    content/pippki/device_manager.xul        (content/device_manager.xul)
+    content/pippki/downloadcert.js           (content/downloadcert.js)
+    content/pippki/downloadcert.xul          (content/downloadcert.xul)
+    content/pippki/editcacert.js             (content/editcacert.js)
+    content/pippki/editcacert.xul            (content/editcacert.xul)
+    content/pippki/exceptionDialog.js        (content/exceptionDialog.js)
+*   content/pippki/exceptionDialog.xul       (content/exceptionDialog.xul)
+    content/pippki/load_device.xul           (content/load_device.xul)
+    content/pippki/pippki.js                 (content/pippki.js)
+    content/pippki/protectedAuth.js          (content/protectedAuth.js)
     content/pippki/protectedAuth.xul         (content/protectedAuth.xul)
-    content/pippki/protectedAuth.js          (content/protectedAuth.js)
+    content/pippki/resetpassword.js          (content/resetpassword.js)
+    content/pippki/resetpassword.xul         (content/resetpassword.xul)
+    content/pippki/setp12password.js         (content/setp12password.js)
+    content/pippki/setp12password.xul        (content/setp12password.xul)
+    content/pippki/viewCertDetails.xul       (content/viewCertDetails.xul)
--- a/security/manager/ssl/SSLServerCertVerification.cpp
+++ b/security/manager/ssl/SSLServerCertVerification.cpp
@@ -99,35 +99,40 @@
 #include "BRNameMatchingPolicy.h"
 #include "CertVerifier.h"
 #include "CryptoTask.h"
 #include "ExtendedValidation.h"
 #include "NSSCertDBTrustDomain.h"
 #include "PSMRunnable.h"
 #include "RootCertificateTelemetryUtils.h"
 #include "ScopedNSSTypes.h"
+#include "SharedCertVerifier.h"
 #include "SharedSSLState.h"
+#include "TransportSecurityInfo.h" // For RememberCertErrorsTable
 #include "cert.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/Casting.h"
 #include "mozilla/Mutex.h"
+#include "mozilla/RefPtr.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/UniquePtr.h"
+#include "mozilla/Unused.h"
 #include "mozilla/net/DNS.h"
-#include "mozilla/Unused.h"
 #include "nsComponentManagerUtils.h"
 #include "nsContentUtils.h"
 #include "nsIBadCertListener2.h"
 #include "nsICertOverrideService.h"
 #include "nsISiteSecurityService.h"
 #include "nsISocketProvider.h"
 #include "nsIThreadPool.h"
+#include "nsNSSCertificate.h"
 #include "nsNSSComponent.h"
 #include "nsNSSIOLayer.h"
 #include "nsNSSShutDown.h"
+#include "nsSSLStatus.h"
 #include "nsServiceManagerUtils.h"
 #include "nsURLHelper.h"
 #include "nsXPCOMCIDInternal.h"
 #include "pkix/pkix.h"
 #include "pkix/pkixnss.h"
 #include "secerr.h"
 #include "secoidt.h"
 #include "secport.h"
@@ -1364,63 +1369,47 @@ AuthCertificate(CertVerifier& certVerifi
                           pinningTelemetryInfo.rootBucket);
   }
 
   if (pinningTelemetryInfo.accumulateResult) {
     Telemetry::Accumulate(pinningTelemetryInfo.certPinningResultHistogram,
                           pinningTelemetryInfo.certPinningResultBucket);
   }
 
-  RefPtr<nsSSLStatus> status(infoObject->SSLStatus());
-  RefPtr<nsNSSCertificate> nsc;
-
-  if (!status || !status->HasServerCert()) {
-    if (rv == Success) {
-      nsc = nsNSSCertificate::Create(cert.get(), &evOidPolicy);
-    } else {
-      nsc = nsNSSCertificate::Create(cert.get());
-    }
-  }
-
   if (rv == Success) {
+    // Certificate verification succeeded. Delete any potential record of
+    // certificate error bits.
+    RememberCertErrorsTable::GetInstance().RememberCertHasError(infoObject,
+                                                                nullptr,
+                                                                SECSuccess);
     GatherSuccessfulValidationTelemetry(certList);
     GatherCertificateTransparencyTelemetry(certList,
                                            certificateTransparencyInfo);
 
     // The connection may get terminated, for example, if the server requires
     // a client cert. Let's provide a minimal SSLStatus
     // to the caller that contains at least the cert and its status.
+    RefPtr<nsSSLStatus> status(infoObject->SSLStatus());
     if (!status) {
       status = new nsSSLStatus();
       infoObject->SetSSLStatus(status);
     }
 
-    if (rv == Success) {
-      // Certificate verification succeeded delete any potential record
-      // of certificate error bits.
-      RememberCertErrorsTable::GetInstance().RememberCertHasError(infoObject,
-                                                                  nullptr,
-                                                                  SECSuccess);
-    } else {
-      // Certificate verification failed, update the status' bits.
-      RememberCertErrorsTable::GetInstance().LookupCertErrorBits(
-        infoObject, status);
-    }
-
-    if (status && !status->HasServerCert()) {
-      nsNSSCertificate::EVStatus evStatus;
-      if (evOidPolicy == SEC_OID_UNKNOWN || rv != Success) {
-        evStatus = nsNSSCertificate::ev_status_invalid;
+    if (!status->HasServerCert()) {
+      EVStatus evStatus;
+      if (evOidPolicy == SEC_OID_UNKNOWN) {
+        evStatus = EVStatus::NotEV;
       } else {
-        evStatus = nsNSSCertificate::ev_status_valid;
+        evStatus = EVStatus::EV;
       }
 
+      RefPtr<nsNSSCertificate> nsc = nsNSSCertificate::Create(cert.get());
       status->SetServerCert(nsc, evStatus);
       MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
-             ("AuthCertificate setting NEW cert %p\n", nsc.get()));
+              ("AuthCertificate setting NEW cert %p", nsc.get()));
     }
 
     status->SetCertificateTransparencyInfo(certificateTransparencyInfo);
   }
 
   if (rv != Success) {
     // Certificate validation failed; store the peer certificate chain on
     // infoObject so it can be used for error reporting.
--- a/security/manager/ssl/StaticHPKPins.h
+++ b/security/manager/ssl/StaticHPKPins.h
@@ -1159,9 +1159,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 = 463;
 
 static const int32_t kUnknownId = -1;
 
-static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1487082357536000);
+static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1487168364572000);
--- a/security/manager/ssl/TransportSecurityInfo.cpp
+++ b/security/manager/ssl/TransportSecurityInfo.cpp
@@ -1051,17 +1051,17 @@ TransportSecurityInfo::SetStatusErrorBit
                                           uint32_t collected_errors)
 {
   MutexAutoLock lock(mMutex);
 
   if (!mSSLStatus) {
     mSSLStatus = new nsSSLStatus();
   }
 
-  mSSLStatus->SetServerCert(cert, nsNSSCertificate::ev_status_invalid);
+  mSSLStatus->SetServerCert(cert, EVStatus::NotEV);
 
   mSSLStatus->mHaveCertErrorBits = true;
   mSSLStatus->mIsDomainMismatch = 
     collected_errors & nsICertOverrideService::ERROR_MISMATCH;
   mSSLStatus->mIsNotValidAtThisTime = 
     collected_errors & nsICertOverrideService::ERROR_TIME;
   mSSLStatus->mIsUntrusted = 
     collected_errors & nsICertOverrideService::ERROR_UNTRUSTED;
--- a/security/manager/ssl/nsNSSCallbacks.cpp
+++ b/security/manager/ssl/nsNSSCallbacks.cpp
@@ -1,39 +1,42 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  *
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsNSSCallbacks.h"
 
+#include "PSMRunnable.h"
+#include "ScopedNSSTypes.h"
+#include "SharedCertVerifier.h"
+#include "SharedSSLState.h"
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/Casting.h"
+#include "mozilla/RefPtr.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/Unused.h"
 #include "nsContentUtils.h"
 #include "nsICertOverrideService.h"
 #include "nsIHttpChannelInternal.h"
 #include "nsIPrompt.h"
 #include "nsISupportsPriority.h"
 #include "nsITokenDialogs.h"
 #include "nsIUploadChannel.h"
 #include "nsIWebProgressListener.h"
-#include "nsNetUtil.h"
+#include "nsNSSCertificate.h"
 #include "nsNSSComponent.h"
 #include "nsNSSIOLayer.h"
+#include "nsNetUtil.h"
 #include "nsProtectedAuthThread.h"
 #include "nsProxyRelease.h"
 #include "pkix/pkixtypes.h"
-#include "PSMRunnable.h"
-#include "ScopedNSSTypes.h"
-#include "SharedSSLState.h"
 #include "ssl.h"
 #include "sslproto.h"
 
 using namespace mozilla;
 using namespace mozilla::psm;
 
 extern LazyLogModule gPIPNSSLog;
 
@@ -106,16 +109,28 @@ nsHTTPDownloadEvent::Run()
   // high priority to accommodate real time OCSP transactions.
   nsCOMPtr<nsISupportsPriority> priorityChannel = do_QueryInterface(chan);
   if (priorityChannel)
     priorityChannel->AdjustPriority(nsISupportsPriority::PRIORITY_HIGHEST);
 
   chan->SetLoadFlags(nsIRequest::LOAD_ANONYMOUS |
                      nsIChannel::LOAD_BYPASS_SERVICE_WORKER);
 
+  if (!mRequestSession->mFirstPartyDomain.IsEmpty()) {
+    NeckoOriginAttributes attrs;
+    attrs.mFirstPartyDomain =
+      NS_ConvertUTF8toUTF16(mRequestSession->mFirstPartyDomain);
+
+    nsCOMPtr<nsILoadInfo> loadInfo = chan->GetLoadInfo();
+    if (loadInfo) {
+      rv = loadInfo->SetOriginAttributes(attrs);
+      NS_ENSURE_SUCCESS(rv, rv);
+    }
+  }
+
   // Create a loadgroup for this new channel.  This way if the channel
   // is redirected, we'll have a way to cancel the resulting channel.
   nsCOMPtr<nsILoadGroup> lg = do_CreateInstance(NS_LOADGROUP_CONTRACTID);
   chan->SetLoadGroup(lg);
 
   if (mRequestSession->mHasPostData)
   {
     nsCOMPtr<nsIInputStream> uploadStream;
@@ -210,16 +225,17 @@ nsNSSHttpServerSession::createSessionFcn
   return Success;
 }
 
 mozilla::pkix::Result
 nsNSSHttpRequestSession::createFcn(const nsNSSHttpServerSession* session,
                                    const char* http_protocol_variant,
                                    const char* path_and_query_string,
                                    const char* http_request_method,
+                                   const char* first_party_domain,
                                    const PRIntervalTime timeout,
                            /*out*/ nsNSSHttpRequestSession** pRequest)
 {
   if (!session || !http_protocol_variant || !path_and_query_string ||
       !http_request_method || !pRequest) {
     return Result::FATAL_ERROR_INVALID_ARGS;
   }
 
@@ -239,16 +255,18 @@ nsNSSHttpRequestSession::createFcn(const
 
   rs->mURL.Assign(http_protocol_variant);
   rs->mURL.AppendLiteral("://");
   rs->mURL.Append(session->mHost);
   rs->mURL.Append(':');
   rs->mURL.AppendInt(session->mPort);
   rs->mURL.Append(path_and_query_string);
 
+  rs->mFirstPartyDomain.Assign(first_party_domain);
+
   rs->mRequestMethod = http_request_method;
 
   *pRequest = rs;
   return Success;
 }
 
 mozilla::pkix::Result
 nsNSSHttpRequestSession::setPostDataFcn(const char* http_data,
@@ -1078,16 +1096,99 @@ AccumulateCipherSuite(Telemetry::ID prob
     default:
       value = 0;
       break;
   }
   MOZ_ASSERT(value != 0);
   Telemetry::Accumulate(probe, value);
 }
 
+// In the case of session resumption, the AuthCertificate hook has been bypassed
+// (because we've previously successfully connected to our peer). That being the
+// case, we unfortunately don't know if the peer's server certificate verified
+// as extended validation or not. To address this, we attempt to build a
+// verified EV certificate chain here using as much of the original context as
+// possible (e.g. stapled OCSP responses, SCTs, the hostname, the first party
+// domain, etc.). Note that because we are on the socket thread, this must not
+// cause any network requests, hence the use of FLAG_LOCAL_ONLY.
+static void
+DetermineEVStatusAndSetNewCert(RefPtr<nsSSLStatus> sslStatus, PRFileDesc* fd,
+                               nsNSSSocketInfo* infoObject)
+{
+  MOZ_ASSERT(sslStatus);
+  MOZ_ASSERT(fd);
+  MOZ_ASSERT(infoObject);
+
+  if (!sslStatus || !fd || !infoObject) {
+    return;
+  }
+
+  UniqueCERTCertificate cert(SSL_PeerCertificate(fd));
+  MOZ_ASSERT(cert, "SSL_PeerCertificate failed in TLS handshake callback?");
+  if (!cert) {
+    return;
+  }
+
+  RefPtr<SharedCertVerifier> certVerifier(GetDefaultCertVerifier());
+  MOZ_ASSERT(certVerifier,
+             "Certificate verifier uninitialized in TLS handshake callback?");
+  if (!certVerifier) {
+    return;
+  }
+
+  // We don't own these pointers.
+  const SECItemArray* stapledOCSPResponses = SSL_PeerStapledOCSPResponses(fd);
+  const SECItem* stapledOCSPResponse = nullptr;
+  // we currently only support single stapled responses
+  if (stapledOCSPResponses && stapledOCSPResponses->len == 1) {
+    stapledOCSPResponse = &stapledOCSPResponses->items[0];
+  }
+  const SECItem* sctsFromTLSExtension = SSL_PeerSignedCertTimestamps(fd);
+  if (sctsFromTLSExtension && sctsFromTLSExtension->len == 0) {
+    // SSL_PeerSignedCertTimestamps returns null on error and empty item
+    // when no extension was returned by the server. We always use null when
+    // no extension was received (for whatever reason), ignoring errors.
+    sctsFromTLSExtension = nullptr;
+  }
+
+  int flags = mozilla::psm::CertVerifier::FLAG_LOCAL_ONLY |
+              mozilla::psm::CertVerifier::FLAG_MUST_BE_EV;
+  if (!infoObject->SharedState().IsOCSPStaplingEnabled() ||
+      !infoObject->SharedState().IsOCSPMustStapleEnabled()) {
+    flags |= CertVerifier::FLAG_TLS_IGNORE_STATUS_REQUEST;
+  }
+
+  SECOidTag evOidPolicy;
+  UniqueCERTCertList unusedBuiltChain;
+  const bool saveIntermediates = false;
+  mozilla::pkix::Result rv = certVerifier->VerifySSLServerCert(
+    cert,
+    stapledOCSPResponse,
+    sctsFromTLSExtension,
+    mozilla::pkix::Now(),
+    infoObject,
+    infoObject->GetHostNameRaw(),
+    unusedBuiltChain,
+    saveIntermediates,
+    flags,
+    infoObject->GetFirstPartyDomainRaw(),
+    &evOidPolicy);
+
+  RefPtr<nsNSSCertificate> nssc(nsNSSCertificate::Create(cert.get()));
+  if (rv == Success && evOidPolicy != SEC_OID_UNKNOWN) {
+    MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
+            ("HandshakeCallback using NEW cert %p (is EV)", nssc.get()));
+    sslStatus->SetServerCert(nssc, EVStatus::EV);
+  } else {
+    MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
+            ("HandshakeCallback using NEW cert %p (is not EV)", nssc.get()));
+    sslStatus->SetServerCert(nssc, EVStatus::NotEV);
+  }
+}
+
 void HandshakeCallback(PRFileDesc* fd, void* client_data) {
   nsNSSShutDownPreventionLock locker;
   SECStatus rv;
 
   nsNSSSocketInfo* infoObject = (nsNSSSocketInfo*) fd->higher->secret;
 
   // Do the bookkeeping that needs to be done after the
   // server's ServerHello...ServerHelloDone have been processed, but that doesn't
@@ -1231,21 +1332,17 @@ void HandshakeCallback(PRFileDesc* fd, v
       }
     }
   }
 
   if (status->HasServerCert()) {
     MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
            ("HandshakeCallback KEEPING existing cert\n"));
   } else {
-    UniqueCERTCertificate serverCert(SSL_PeerCertificate(fd));
-    RefPtr<nsNSSCertificate> nssc(nsNSSCertificate::Create(serverCert.get()));
-    MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
-           ("HandshakeCallback using NEW cert %p\n", nssc.get()));
-    status->SetServerCert(nssc, nsNSSCertificate::ev_status_unknown);
+    DetermineEVStatusAndSetNewCert(status, fd, infoObject);
   }
 
   bool domainMismatch;
   bool untrusted;
   bool notValidAtThisTime;
   // These all return NS_OK, so don't even bother checking the return values.
   Unused << status->GetIsDomainMismatch(&domainMismatch);
   Unused << status->GetIsUntrusted(&untrusted);
--- a/security/manager/ssl/nsNSSCallbacks.h
+++ b/security/manager/ssl/nsNSSCallbacks.h
@@ -94,16 +94,17 @@ protected:
 
 public:
   typedef mozilla::pkix::Result Result;
 
   static Result createFcn(const nsNSSHttpServerSession* session,
                           const char* httpProtocolVariant,
                           const char* pathAndQueryString,
                           const char* httpRequestMethod,
+                          const char* firstPartyDomain,
                           const PRIntervalTime timeout,
                   /*out*/ nsNSSHttpRequestSession** pRequest);
 
   Result setPostDataFcn(const char* httpData,
                         const uint32_t httpDataLen,
                         const char* httpContentType);
 
   Result trySendAndReceiveFcn(PRPollDesc** pPollDesc,
@@ -118,16 +119,18 @@ public:
 
   nsCString mURL;
   nsCString mRequestMethod;
 
   bool mHasPostData;
   nsCString mPostData;
   nsCString mPostContentType;
 
+  nsCString mFirstPartyDomain;
+
   PRIntervalTime mTimeoutInterval;
 
   RefPtr<nsHTTPListener> mListener;
 
 protected:
   nsNSSHttpRequestSession();
   ~nsNSSHttpRequestSession();
 
@@ -151,23 +154,24 @@ public:
   {
     return nsNSSHttpServerSession::createSessionFcn(host, portnum, pSession);
   }
 
   static Result createFcn(const nsNSSHttpServerSession* session,
                           const char* httpProtocolVariant,
                           const char* pathAndQueryString,
                           const char* httpRequestMethod,
+                          const char* firstPartyDomain,
                           const PRIntervalTime timeout,
                   /*out*/ nsNSSHttpRequestSession** pRequest)
   {
     return nsNSSHttpRequestSession::createFcn(session, httpProtocolVariant,
                                               pathAndQueryString,
-                                              httpRequestMethod, timeout,
-                                              pRequest);
+                                              httpRequestMethod, firstPartyDomain,
+                                              timeout, pRequest);
   }
 
   static Result setPostDataFcn(nsNSSHttpRequestSession* request,
                                const char* httpData,
                                const uint32_t httpDataLen,
                                const char* httpContentType)
   {
     return request->setPostDataFcn(httpData, httpDataLen, httpContentType);
--- a/security/manager/ssl/nsNSSCertHelper.cpp
+++ b/security/manager/ssl/nsNSSCertHelper.cpp
@@ -1228,17 +1228,16 @@ ProcessUserNotice(SECItem* derNotice, ns
   }
 
   return NS_OK;
 }
 
 static nsresult
 ProcessCertificatePolicies(SECItem  *extData, 
 			   nsAString &text,
-                           SECOidTag ev_oid_tag, // SEC_OID_UNKNOWN means: not EV
 			   nsINSSComponent *nssComponent)
 {
   CERTPolicyInfo **policyInfos, *policyInfo;
   CERTPolicyQualifier **policyQualifiers, *policyQualifier;
   nsAutoString local;
   nsresult rv = NS_OK;
 
   UniqueCERTCertificatePolicies policies(
@@ -1255,36 +1254,20 @@ ProcessCertificatePolicies(SECItem  *ext
       nssComponent->GetPIPNSSBundleString("CertDumpVerisignNotices", local);
       text.Append(local);
       break;
     default:
       GetDefaultOIDFormat(&policyInfo->policyID, nssComponent, local, '.');
       text.Append(local);
     }
 
-    bool needColon = true;
-    if (ev_oid_tag != SEC_OID_UNKNOWN) {
-      // This is an EV cert. Let's see if this oid is the EV oid,
-      // because we want to display the EV information string
-      // next to the correct OID.
-
-      if (policyInfo->oid == ev_oid_tag) {
-        text.Append(':');
-        text.AppendLiteral(SEPARATOR);
-        needColon = false;
-        nssComponent->GetPIPNSSBundleString("CertDumpPolicyOidEV", local);
-        text.Append(local);
-      }
-    }
-
     if (policyInfo->policyQualifiers) {
       /* Add all qualifiers on separate lines, indented */
       policyQualifiers = policyInfo->policyQualifiers;
-      if (needColon)
-        text.Append(':');
+      text.Append(':');
       text.AppendLiteral(SEPARATOR);
       while (*policyQualifiers) {
 	text.AppendLiteral("  ");
 	policyQualifier = *policyQualifiers++;
 	switch(policyQualifier->oid) {
 	case SEC_OID_PKIX_CPS_POINTER_QUALIFIER:
 	  nssComponent->GetPIPNSSBundleString("CertDumpCPSPointer", local);
 	  text.Append(local);
@@ -1495,17 +1478,16 @@ ProcessMSCAVersion(SECItem  *extData,
 
   text.AppendASCII(buf);
   return NS_OK;
 }
 
 static nsresult
 ProcessExtensionData(SECOidTag oidTag, SECItem *extData, 
                      nsAString &text, 
-                     SECOidTag ev_oid_tag, // SEC_OID_UNKNOWN means: not EV
                      nsINSSComponent *nssComponent)
 {
   nsresult rv;
   switch (oidTag) {
   case SEC_OID_X509_KEY_USAGE:
     rv = ProcessKeyUsageExtension(extData, text, nssComponent);
     break;
   case SEC_OID_X509_BASIC_CONSTRAINTS:
@@ -1520,17 +1502,17 @@ ProcessExtensionData(SECOidTag oidTag, S
     break;
   case SEC_OID_X509_SUBJECT_KEY_ID:
     rv = ProcessSubjectKeyId(extData, text, nssComponent);
     break;
   case SEC_OID_X509_AUTH_KEY_ID:
     rv = ProcessAuthKeyId(extData, text, nssComponent);
     break;
   case SEC_OID_X509_CERTIFICATE_POLICIES:
-    rv = ProcessCertificatePolicies(extData, text, ev_oid_tag, nssComponent);
+    rv = ProcessCertificatePolicies(extData, text, nssComponent);
     break;
   case SEC_OID_X509_CRL_DIST_POINTS:
     rv = ProcessCrlDistPoints(extData, text, nssComponent);
     break;
   case SEC_OID_X509_AUTH_INFO_ACCESS:
     rv = ProcessAuthInfoAccess(extData, text, nssComponent);
     break;
   default:
@@ -1545,17 +1527,16 @@ ProcessExtensionData(SECOidTag oidTag, S
     rv = ProcessRawBytes(nssComponent, extData, text);
     break; 
   }
   return rv;
 }
 
 static nsresult
 ProcessSingleExtension(CERTCertExtension *extension,
-                       SECOidTag ev_oid_tag, // SEC_OID_UNKNOWN means: not EV
                        nsINSSComponent *nssComponent,
                        nsIASN1PrintableItem **retExtension)
 {
   nsAutoString text, extvalue;
   GetOIDText(&extension->id, nssComponent, text);
   nsCOMPtr<nsIASN1PrintableItem>extensionItem = new nsNSSASN1PrintableItem();
 
   extensionItem->SetDisplayName(text);
@@ -1567,17 +1548,17 @@ ProcessSingleExtension(CERTCertExtension
     } else {
       nssComponent->GetPIPNSSBundleString("CertDumpNonCritical", text);
     }
   } else {
     nssComponent->GetPIPNSSBundleString("CertDumpNonCritical", text);
   }
   text.AppendLiteral(SEPARATOR);
   nsresult rv = ProcessExtensionData(oidTag, &extension->value, extvalue, 
-                                     ev_oid_tag, nssComponent);
+                                     nssComponent);
   if (NS_FAILED(rv)) {
     extvalue.Truncate();
     rv = ProcessRawBytes(nssComponent, &extension->value, extvalue, false);
   }
   text.Append(extvalue);
 
   extensionItem->SetDisplayValue(text);
   extensionItem.forget(retExtension);
@@ -1763,32 +1744,30 @@ ProcessSubjectPublicKeyInfo(CERTSubjectP
   parentSequence->GetASN1Objects(getter_AddRefs(asn1Objects));
   asn1Objects->AppendElement(spkiSequence, false);
   return NS_OK;
 }
 
 static nsresult
 ProcessExtensions(CERTCertExtension **extensions, 
                   nsIASN1Sequence *parentSequence,
-                  SECOidTag ev_oid_tag, // SEC_OID_UNKNOWN means: not EV
                   nsINSSComponent *nssComponent)
 {
   nsCOMPtr<nsIASN1Sequence> extensionSequence = new nsNSSASN1Sequence;
 
   nsString text;
   nssComponent->GetPIPNSSBundleString("CertDumpExtensions", text);
   extensionSequence->SetDisplayName(text);
   int32_t i;
   nsresult rv;
   nsCOMPtr<nsIASN1PrintableItem> newExtension;
   nsCOMPtr<nsIMutableArray> asn1Objects;
   extensionSequence->GetASN1Objects(getter_AddRefs(asn1Objects));
   for (i=0; extensions[i] != nullptr; i++) {
     rv = ProcessSingleExtension(extensions[i], 
-                                ev_oid_tag,
                                 nssComponent,
                                 getter_AddRefs(newExtension));
     if (NS_FAILED(rv))
       return rv;
 
     asn1Objects->AppendElement(newExtension, false);
   }
   parentSequence->GetASN1Objects(getter_AddRefs(asn1Objects));
@@ -1961,29 +1940,17 @@ nsNSSCertificate::CreateTBSCertificateAS
 
     printableItem->SetDisplayValue(text);
     nssComponent->GetPIPNSSBundleString("CertDumpSubjectUniqueID", text);
     printableItem->SetDisplayName(text);
     asn1Objects->AppendElement(printableItem, false);
 
   }
   if (mCert->extensions) {
-    SECOidTag ev_oid_tag = SEC_OID_UNKNOWN;
-
-    bool validEV;
-    rv = hasValidEVOidTag(ev_oid_tag, validEV);
-    if (NS_FAILED(rv)) {
-      return rv;
-    }
-
-    if (!validEV) {
-      ev_oid_tag = SEC_OID_UNKNOWN;
-    }
-
-    rv = ProcessExtensions(mCert->extensions, sequence, ev_oid_tag, nssComponent);
+    rv = ProcessExtensions(mCert->extensions, sequence, nssComponent);
     if (NS_FAILED(rv))
       return rv;
   }
   sequence.forget(retSequence);
   return NS_OK;
 }
 
 nsresult
--- a/security/manager/ssl/nsNSSCertificate.cpp
+++ b/security/manager/ssl/nsNSSCertificate.cpp
@@ -65,24 +65,24 @@ extern LazyLogModule gPIPNSSLog;
 NS_IMPL_ISUPPORTS(nsNSSCertificate,
                   nsIX509Cert,
                   nsISerializable,
                   nsIClassInfo)
 
 static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
 
 /*static*/ nsNSSCertificate*
-nsNSSCertificate::Create(CERTCertificate* cert, SECOidTag* evOidPolicy)
+nsNSSCertificate::Create(CERTCertificate* cert)
 {
   if (GeckoProcessType_Default != XRE_GetProcessType()) {
     NS_ERROR("Trying to initialize nsNSSCertificate in a non-chrome process!");
     return nullptr;
   }
   if (cert)
-    return new nsNSSCertificate(cert, evOidPolicy);
+    return new nsNSSCertificate(cert);
   else
     return new nsNSSCertificate();
 }
 
 nsNSSCertificate*
 nsNSSCertificate::ConstructFromDER(char* certDER, int derLen)
 {
   // On non-chrome process prevent instantiation
@@ -117,51 +117,39 @@ nsNSSCertificate::InitFromDER(char* cert
   {
     aCert->dbhandle = CERT_GetDefaultCertDB();
   }
 
   mCert.reset(aCert);
   return true;
 }
 
-nsNSSCertificate::nsNSSCertificate(CERTCertificate* cert,
-                                   SECOidTag* evOidPolicy)
+nsNSSCertificate::nsNSSCertificate(CERTCertificate* cert)
   : mCert(nullptr)
   , mPermDelete(false)
   , mCertType(CERT_TYPE_NOT_YET_INITIALIZED)
-  , mCachedEVStatus(ev_status_unknown)
 {
 #if defined(DEBUG)
   if (GeckoProcessType_Default != XRE_GetProcessType())
     NS_ERROR("Trying to initialize nsNSSCertificate in a non-chrome process!");
 #endif
 
   nsNSSShutDownPreventionLock locker;
   if (isAlreadyShutDown())
     return;
 
   if (cert) {
     mCert.reset(CERT_DupCertificate(cert));
-    if (evOidPolicy) {
-      if (*evOidPolicy == SEC_OID_UNKNOWN) {
-        mCachedEVStatus =  ev_status_invalid;
-      }
-      else {
-        mCachedEVStatus = ev_status_valid;
-      }
-      mCachedEVOidTag = *evOidPolicy;
-    }
   }
 }
 
-nsNSSCertificate::nsNSSCertificate() :
-  mCert(nullptr),
-  mPermDelete(false),
-  mCertType(CERT_TYPE_NOT_YET_INITIALIZED),
-  mCachedEVStatus(ev_status_unknown)
+nsNSSCertificate::nsNSSCertificate()
+  : mCert(nullptr)
+  , mPermDelete(false)
+  , mCertType(CERT_TYPE_NOT_YET_INITIALIZED)
 {
   if (GeckoProcessType_Default != XRE_GetProcessType())
     NS_ERROR("Trying to initialize nsNSSCertificate in a non-chrome process!");
 }
 
 nsNSSCertificate::~nsNSSCertificate()
 {
   nsNSSShutDownPreventionLock locker;
@@ -1129,95 +1117,16 @@ nsNSSCertificate::Equals(nsIX509Cert* ot
   NS_ENSURE_ARG(other);
   NS_ENSURE_ARG(result);
 
   UniqueCERTCertificate cert(other->GetCert());
   *result = (mCert.get() == cert.get());
   return NS_OK;
 }
 
-nsresult
-nsNSSCertificate::hasValidEVOidTag(SECOidTag& resultOidTag, bool& validEV)
-{
-  nsNSSShutDownPreventionLock locker;
-  if (isAlreadyShutDown()) {
-    return NS_ERROR_NOT_AVAILABLE;
-  }
-
-  RefPtr<mozilla::psm::SharedCertVerifier>
-    certVerifier(mozilla::psm::GetDefaultCertVerifier());
-  NS_ENSURE_TRUE(certVerifier, NS_ERROR_UNEXPECTED);
-
-  validEV = false;
-  resultOidTag = SEC_OID_UNKNOWN;
-
-  uint32_t flags = mozilla::psm::CertVerifier::FLAG_LOCAL_ONLY |
-    mozilla::psm::CertVerifier::FLAG_MUST_BE_EV;
-  UniqueCERTCertList unusedBuiltChain;
-  mozilla::pkix::Result result = certVerifier->VerifyCert(mCert.get(),
-    certificateUsageSSLServer, mozilla::pkix::Now(),
-    nullptr /* XXX pinarg */,
-    nullptr /* hostname */,
-    unusedBuiltChain,
-    flags,
-    nullptr /* stapledOCSPResponse */,
-    nullptr /* sctsFromTLSExtension */,
-    nullptr /* firstPartyDomain */,
-    &resultOidTag);
-
-  if (result != mozilla::pkix::Success) {
-    resultOidTag = SEC_OID_UNKNOWN;
-  }
-  if (resultOidTag != SEC_OID_UNKNOWN) {
-    validEV = true;
-  }
-  return NS_OK;
-}
-
-nsresult
-nsNSSCertificate::getValidEVOidTag(SECOidTag& resultOidTag, bool& validEV)
-{
-  if (mCachedEVStatus != ev_status_unknown) {
-    validEV = (mCachedEVStatus == ev_status_valid);
-    if (validEV) {
-      resultOidTag = mCachedEVOidTag;
-    }
-    return NS_OK;
-  }
-
-  nsresult rv = hasValidEVOidTag(resultOidTag, validEV);
-  if (NS_SUCCEEDED(rv)) {
-    if (validEV) {
-      mCachedEVOidTag = resultOidTag;
-    }
-    mCachedEVStatus = validEV ? ev_status_valid : ev_status_invalid;
-  }
-  return rv;
-}
-
-nsresult
-nsNSSCertificate::GetIsExtendedValidation(bool* aIsEV)
-{
-  nsNSSShutDownPreventionLock locker;
-  if (isAlreadyShutDown()) {
-    return NS_ERROR_NOT_AVAILABLE;
-  }
-
-  NS_ENSURE_ARG(aIsEV);
-  *aIsEV = false;
-
-  if (mCachedEVStatus != ev_status_unknown) {
-    *aIsEV = (mCachedEVStatus == ev_status_valid);
-    return NS_OK;
-  }
-
-  SECOidTag oid_tag;
-  return getValidEVOidTag(oid_tag, *aIsEV);
-}
-
 namespace mozilla {
 
 // TODO(bug 1036065): It seems like we only construct CERTCertLists for the
 // purpose of constructing nsNSSCertLists, so maybe we should change this
 // function to output an nsNSSCertList instead.
 SECStatus
 ConstructCERTCertListFromReversedDERArray(
   const mozilla::pkix::DERArray& certArray,
@@ -1623,46 +1532,39 @@ nsNSSCertListEnumerator::GetNext(nsISupp
   return NS_OK;
 }
 
 // NB: This serialization must match that of nsNSSCertificateFakeTransport.
 NS_IMETHODIMP
 nsNSSCertificate::Write(nsIObjectOutputStream* aStream)
 {
   NS_ENSURE_STATE(mCert);
-  nsresult rv = aStream->Write32(static_cast<uint32_t>(mCachedEVStatus));
+  // This field used to be the cached EV status, but it is no longer necessary.
+  nsresult rv = aStream->Write32(0);
   if (NS_FAILED(rv)) {
     return rv;
   }
   rv = aStream->Write32(mCert->derCert.len);
   if (NS_FAILED(rv)) {
     return rv;
   }
   return aStream->WriteByteArray(mCert->derCert.data, mCert->derCert.len);
 }
 
 NS_IMETHODIMP
 nsNSSCertificate::Read(nsIObjectInputStream* aStream)
 {
   NS_ENSURE_STATE(!mCert);
 
-  uint32_t cachedEVStatus;
-  nsresult rv = aStream->Read32(&cachedEVStatus);
+  // This field is no longer used.
+  uint32_t unusedCachedEVStatus;
+  nsresult rv = aStream->Read32(&unusedCachedEVStatus);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  if (cachedEVStatus == static_cast<uint32_t>(ev_status_unknown)) {
-    mCachedEVStatus = ev_status_unknown;
-  } else if (cachedEVStatus == static_cast<uint32_t>(ev_status_valid)) {
-    mCachedEVStatus = ev_status_valid;
-  } else if (cachedEVStatus == static_cast<uint32_t>(ev_status_invalid)) {
-    mCachedEVStatus = ev_status_invalid;
-  } else {
-    return NS_ERROR_UNEXPECTED;
-  }
 
   uint32_t len;
   rv = aStream->Read32(&len);
   if (NS_FAILED(rv)) {
     return rv;
   }
 
   nsXPIDLCString str;
--- a/security/manager/ssl/nsNSSCertificate.h
+++ b/security/manager/ssl/nsNSSCertificate.h
@@ -32,28 +32,20 @@ class nsNSSCertificate final : public ns
 public:
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIX509CERT
   NS_DECL_NSISERIALIZABLE
   NS_DECL_NSICLASSINFO
 
   friend class nsNSSCertificateFakeTransport;
 
-  explicit nsNSSCertificate(CERTCertificate* cert, SECOidTag* evOidPolicy = nullptr);
+  explicit nsNSSCertificate(CERTCertificate* cert);
   nsNSSCertificate();
-  static nsNSSCertificate* Create(CERTCertificate*cert = nullptr,
-                                  SECOidTag* evOidPolicy = nullptr);
+  static nsNSSCertificate* Create(CERTCertificate* cert = nullptr);
   static nsNSSCertificate* ConstructFromDER(char* certDER, int derLen);
-  nsresult GetIsExtendedValidation(bool* aIsEV);
-
-  enum EVStatus {
-    ev_status_invalid = 0,
-    ev_status_valid = 1,
-    ev_status_unknown = 2
-  };
 
   // This is a separate static method so nsNSSComponent can use it during NSS
   // initialization. Other code should probably not use it.
   static nsresult GetDbKey(const mozilla::UniqueCERTCertificate& cert,
                            nsACString& aDbKey);
 
 private:
   virtual ~nsNSSCertificate();
@@ -65,21 +57,16 @@ private:
   nsresult CreateTBSCertificateASN1Struct(nsIASN1Sequence** retSequence,
                                           nsINSSComponent* nssComponent);
   nsresult GetSortableDate(PRTime aTime, nsAString& _aSortableDate);
   virtual void virtualDestroyNSSReference() override;
   void destructorSafeDestroyNSSReference();
   bool InitFromDER(char* certDER, int derLen);  // return false on failure
 
   nsresult GetCertificateHash(nsAString& aFingerprint, SECOidTag aHashAlg);
-
-  EVStatus mCachedEVStatus;
-  SECOidTag mCachedEVOidTag;
-  nsresult hasValidEVOidTag(SECOidTag& resultOidTag, bool& validEV);
-  nsresult getValidEVOidTag(SECOidTag& resultOidTag, bool& validEV);
 };
 
 namespace mozilla {
 
 SECStatus ConstructCERTCertListFromReversedDERArray(
             const mozilla::pkix::DERArray& certArray,
             /*out*/ mozilla::UniqueCERTCertList& certList);
 
--- a/security/manager/ssl/nsNSSCertificateFakeTransport.cpp
+++ b/security/manager/ssl/nsNSSCertificateFakeTransport.cpp
@@ -213,40 +213,39 @@ nsNSSCertificateFakeTransport::GetSha256
 // NB: This serialization must match that of nsNSSCertificate.
 NS_IMETHODIMP
 nsNSSCertificateFakeTransport::Write(nsIObjectOutputStream* aStream)
 {
   // On a non-chrome process we don't have mCert because we lack
   // nsNSSComponent. nsNSSCertificateFakeTransport object is used only to
   // carry the certificate serialization.
 
-  // This serialization has to match that of nsNSSCertificate,
-  // so write a fake cached EV Status.
-  uint32_t status = static_cast<uint32_t>(nsNSSCertificate::ev_status_unknown);
-  nsresult rv = aStream->Write32(status);
+  // This serialization has to match that of nsNSSCertificate, so include this
+  // now-unused field.
+  nsresult rv = aStream->Write32(0);
   if (NS_FAILED(rv)) {
     return rv;
   }
 
   rv = aStream->Write32(mCertSerialization->len);
   if (NS_FAILED(rv)) {
     return rv;
   }
 
   return aStream->WriteByteArray(mCertSerialization->data,
                                  mCertSerialization->len);
 }
 
 NS_IMETHODIMP
 nsNSSCertificateFakeTransport::Read(nsIObjectInputStream* aStream)
 {
-  // This serialization has to match that of nsNSSCertificate,
-  // so read the cachedEVStatus but don't actually use it.
-  uint32_t cachedEVStatus;
-  nsresult rv = aStream->Read32(&cachedEVStatus);
+  // This serialization has to match that of nsNSSCertificate, so read the (now
+  // unused) cachedEVStatus.
+  uint32_t unusedCachedEVStatus;
+  nsresult rv = aStream->Read32(&unusedCachedEVStatus);
   if (NS_FAILED(rv)) {
     return rv;
   }
 
   uint32_t len;
   rv = aStream->Read32(&len);
   if (NS_FAILED(rv)) {
     return rv;
--- a/security/manager/ssl/nsSSLStatus.cpp
+++ b/security/manager/ssl/nsSSLStatus.cpp
@@ -1,20 +1,20 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  *
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/Casting.h"
 #include "nsSSLStatus.h"
-#include "plstr.h"
 #include "nsIClassInfoImpl.h"
 #include "nsIObjectOutputStream.h"
 #include "nsIObjectInputStream.h"
+#include "nsNSSCertificate.h"
 #include "SignedCertificateTimestamp.h"
 #include "ssl.h"
 
 NS_IMETHODIMP
 nsSSLStatus::GetServerCert(nsIX509Cert** aServerCert)
 {
   NS_ENSURE_ARG_POINTER(aServerCert);
 
@@ -312,34 +312,23 @@ nsSSLStatus::nsSSLStatus()
 
 NS_IMPL_ISUPPORTS(nsSSLStatus, nsISSLStatus, nsISerializable, nsIClassInfo)
 
 nsSSLStatus::~nsSSLStatus()
 {
 }
 
 void
-nsSSLStatus::SetServerCert(nsNSSCertificate* aServerCert,
-                           nsNSSCertificate::EVStatus aEVStatus)
+nsSSLStatus::SetServerCert(nsNSSCertificate* aServerCert, EVStatus aEVStatus)
 {
-  mServerCert = aServerCert;
+  MOZ_ASSERT(aServerCert);
 
-  if (aEVStatus != nsNSSCertificate::ev_status_unknown) {
-    mIsEV = (aEVStatus == nsNSSCertificate::ev_status_valid);
-    mHasIsEVStatus = true;
-    return;
-  }
-
-  if (aServerCert) {
-    nsresult rv = aServerCert->GetIsExtendedValidation(&mIsEV);
-    if (NS_FAILED(rv)) {
-      return;
-    }
-    mHasIsEVStatus = true;
-  }
+  mServerCert = aServerCert;
+  mIsEV = (aEVStatus == EVStatus::EV);
+  mHasIsEVStatus = true;
 }
 
 void
 nsSSLStatus::SetCertificateTransparencyInfo(
   const mozilla::psm::CertificateTransparencyInfo& info)
 {
   using mozilla::ct::SignedCertificateTimestamp;
 
--- a/security/manager/ssl/nsSSLStatus.h
+++ b/security/manager/ssl/nsSSLStatus.h
@@ -9,35 +9,40 @@
 
 #include "CertVerifier.h" // For CertificateTransparencyInfo
 #include "nsISSLStatus.h"
 #include "nsCOMPtr.h"
 #include "nsXPIDLString.h"
 #include "nsIX509Cert.h"
 #include "nsISerializable.h"
 #include "nsIClassInfo.h"
-#include "nsNSSCertificate.h" // For EVStatus
+
+class nsNSSCertificate;
+
+enum class EVStatus {
+  NotEV = 0,
+  EV = 1,
+};
 
 class nsSSLStatus final
   : public nsISSLStatus
   , public nsISerializable
   , public nsIClassInfo
 {
 protected:
   virtual ~nsSSLStatus();
 public:
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSISSLSTATUS
   NS_DECL_NSISERIALIZABLE
   NS_DECL_NSICLASSINFO
 
   nsSSLStatus();
 
-  void SetServerCert(nsNSSCertificate* aServerCert,
-                     nsNSSCertificate::EVStatus aEVStatus);
+  void SetServerCert(nsNSSCertificate* aServerCert, EVStatus aEVStatus);
 
   bool HasServerCert() {
     return mServerCert != nullptr;
   }
 
   void SetCertificateTransparencyInfo(
     const mozilla::psm::CertificateTransparencyInfo& info);
 
--- a/security/manager/ssl/nsSTSPreloadList.errors
+++ b/security/manager/ssl/nsSTSPreloadList.errors
@@ -134,41 +134,40 @@ alessandro.pw: did not receive HSTS head
 alethearose.com: did not receive HSTS header
 alexandre.sh: did not receive HSTS header
 alexhaydock.co.uk: [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 121"  data: no]
 alexisabarca.com: did not receive HSTS header
 alexismeza.com: could not connect to host
 alexismeza.com.mx: could not connect to host
 alexismeza.dk: could not connect to host
 alfredxing.com: did not receive HSTS header
-aljaspod.net: could not connect to host
 alkami.com: did not receive HSTS header
 all-subtitles.com: did not receive HSTS header
 allforyou.at: could not connect to host
 allinnote.com: could not connect to host
 allstarswithus.com: could not connect to host
 alpha.irccloud.com: could not connect to host
 alphabit-secure.com: could not connect to host
 alphabuild.io: did not receive HSTS header
 alphalabs.xyz: could not connect to host
-altesses.eu: could not connect to host
+alterbaum.net: did not receive HSTS header
 altfire.ca: could not connect to host
 altmv.com: max-age too low: 7776000
 amaforums.org: could not connect to host
 american-truck-simulator.de: could not connect to host
 american-truck-simulator.net: could not connect to host
 americanworkwear.nl: did not receive HSTS header
 ameza.co.uk: could not connect to host
 amigogeek.net: could not connect to host
 amilx.com: could not connect to host
 amilx.org: could not connect to host
 amitube.com: could not connect to host
 amri.nl: did not receive HSTS header
 anakros.me: did not receive HSTS header
-analytic-s.ml: did not receive HSTS header
+analytic-s.ml: could not connect to host
 anarchistischegroepnijmegen.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 121"  data: no]
 anassiriphotography.com: could not connect to host
 ancientkarma.com: could not connect to host
 andere-gedanken.net: max-age too low: 10
 andreasbreitenlohner.de: did not receive HSTS header
 andreasolsson.se: could not connect to host
 andreigec.net: did not receive HSTS header
 andrewmichaud.beer: could not connect to host
@@ -220,25 +219,26 @@ appreciationkards.com: could not connect
 approlys.fr: did not receive HSTS header
 apps-for-fishing.com: could not connect to host
 appseccalifornia.org: did not receive HSTS header
 arabdigitalexpression.org: did not receive HSTS header
 aradulconteaza.ro: could not connect to host
 aran.me.uk: did not receive HSTS header
 arboineuropa.nl: did not receive HSTS header
 arboworks.com: could not connect to host
-arbu.eu: max-age too low: 2419200
+arbu.eu: could not connect to host
 arlen.se: could not connect to host
 armory.consulting: could not connect to host
 armory.supplies: could not connect to host
 armytricka.cz: did not receive HSTS header
+arnetdigital.eu: did not receive HSTS header
 arrayify.com: could not connect to host
 ars-design.net: could not connect to host
 ars.toscana.it: max-age too low: 0
-artistnetwork.nl: could not connect to host
+artistnetwork.nl: did not receive HSTS header
 arturkohut.com: could not connect to host
 asasuou.pw: could not connect to host
 asc16.com: could not connect to host
 asdpress.cn: could not connect to host
 asmui.ml: could not connect to host
 asrob.eu: could not connect to host
 ass.org.au: did not receive HSTS header
 assdecoeur.org: could not connect to host
@@ -261,16 +261,17 @@ auditmatrix.com: did not receive HSTS he
 aujapan.ru: could not connect to host
 aurainfosec.com.au: could not connect to host
 ausnah.me: could not connect to host
 auszeit.bio: did not receive HSTS header
 auth.mail.ru: did not receive HSTS header
 authentication.io: could not connect to host
 auto-serwis.zgorzelec.pl: did not receive HSTS header
 auto4trade.nl: could not connect to host
+autojuhos.sk: did not receive HSTS header
 autokovrik-diskont.ru: did not receive HSTS header
 automacity.com: could not connect to host
 autotsum.com: could not connect to host
 autumnwindsagility.com: could not connect to host
 auverbox.ovh: did not receive HSTS header
 av.de: did not receive HSTS header
 avec-ou-sans-ordonnance.fr: could not connect to host
 avinet.com: max-age too low: 0
@@ -302,16 +303,17 @@ bassh.net: did not receive HSTS header
 baumstark.ca: did not receive HSTS header
 bazarstupava.sk: did not receive HSTS header
 bcbsmagentprofile.com: could not connect to host
 bccx.com: could not connect to host
 bckp.de: could not connect to host
 bcm.com.au: max-age too low: 0
 bcnx.de: max-age too low: 0
 bcsytv.com: could not connect to host
+bcvps.com: could not connect to host
 be.search.yahoo.com: did not receive HSTS header
 beach-inspector.com: did not receive HSTS header
 beachi.es: could not connect to host
 beaglewatch.com: did not receive HSTS header
 beastowner.com: did not receive HSTS header
 beavers.io: could not connect to host
 bebesurdoue.com: could not connect to host
 bedeta.de: could not connect to host
@@ -330,27 +332,29 @@ benny003.de: did not receive HSTS header
 benzkosmetik.de: could not connect to host
 bermytraq.bm: [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 121"  data: no]
 berrymark.be: max-age too low: 0
 besixdouze.world: could not connect to host
 betafive.net: could not connect to host
 betnet.fr: could not connect to host
 betplanning.it: did not receive HSTS header
 bets.de: did not receive HSTS header
+betterlifemakers.com: could not connect to host
 bettween.com: did not receive HSTS header
 betz.ro: did not receive HSTS header
 bevapehappy.com: did not receive HSTS header
 bezorg.ninja: could not connect to host
 bf.am: max-age too low: 0
 bgcparkstad.nl: did not receive HSTS header
 bgmn.net: could not connect to host
 bi.search.yahoo.com: did not receive HSTS header
 bidon.ca: did not receive HSTS header
 bieberium.de: did not receive HSTS header
 bienenblog.cc: could not connect to host
+big-black.de: did not receive HSTS header
 bigbrownpromotions.com.au: did not receive HSTS header
 bigdinosaur.org: did not receive HSTS header
 bigshinylock.minazo.net: could not connect to host
 bildiri.ci: did not receive HSTS header
 bildschirmflackern.de: did not receive HSTS header
 billin.net: could not connect to host
 billkiss.com: max-age too low: 300
 billninja.com: could not connect to host
@@ -385,16 +389,17 @@ black-armada.pl: could not connect to ho
 blackburn.link: did not receive HSTS header
 blackdragoninc.org: could not connect to host
 blacklane.com: did not receive HSTS header
 blackly.uk: could not connect to host
 blackpayment.ru: could not connect to host
 blackunicorn.wtf: could not connect to host
 blantik.net: could not connect to host
 blaudev.es: could not connect to host
+blauwwit.be: did not receive HSTS header
 blenheimchalcot.com: did not receive HSTS header
 blha303.com.au: could not connect to host
 blindsexdate.nl: could not connect to host
 blog.cyveillance.com: did not receive HSTS header
 blog.lookout.com: did not receive HSTS header
 blubbablasen.de: could not connect to host
 blucas.org: did not receive HSTS header
 blueliv.com: did not receive HSTS header
@@ -417,17 +422,16 @@ boomerang.com: could not connect to host
 boosterlearnpro.com: did not receive HSTS header
 bootjp.me: did not receive HSTS header
 boringsecurity.net: could not connect to host
 boris.one: did not receive HSTS header
 botox.bz: did not receive HSTS header
 bouwbedrijfpurmerend.nl: did not receive HSTS header
 bowlroll.net: max-age too low: 0
 boxcryptor.com: did not receive HSTS header
-bqtoolbox.com: could not connect to host
 br3in.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 121"  data: no]
 braineet.com: did not receive HSTS header
 brainfork.ml: could not connect to host
 braintreegateway.com: did not receive HSTS header
 braintreepayments.com: did not receive HSTS header
 brainvation.de: did not receive HSTS header
 bran.cc: could not connect to host
 branchtrack.com: did not receive HSTS header
@@ -485,16 +489,17 @@ caconnect.org: could not connect to host
 cadao.me: did not receive HSTS header
 cadusilva.com: did not receive HSTS header
 cafe-scientifique.org.ec: could not connect to host
 caim.cz: did not receive HSTS header
 cajapopcorn.com: did not receive HSTS header
 cake.care: could not connect to host
 calgaryconstructionjobs.com: could not connect to host
 calix.com: max-age too low: 0
+call.me: did not receive HSTS header
 calltrackingreports.com: could not connect to host
 calvin.me: max-age too low: 2592000
 calvin.my: could not connect to host
 calvinallen.net: could not connect to host
 calyxinstitute.org: [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 121"  data: no]
 canadiangamblingchoice.com: did not receive HSTS header
 cancelmyprofile.com: did not receive HSTS header
 candicontrols.com: did not receive HSTS header
@@ -623,16 +628,17 @@ cmplainpalais.ch: did not receive HSTS h
 cmsbattle.com: could not connect to host
 cmscafe.ru: did not receive HSTS header
 cn.search.yahoo.com: did not receive HSTS header
 co50.com: did not receive HSTS header
 cocaine-import.agency: could not connect to host
 codabix.com: did not receive HSTS header
 codabix.de: could not connect to host
 codabix.net: could not connect to host
+code.fm: could not connect to host
 code.google.com: did not receive HSTS header (error ignored - included regardless)
 codeco.pw: could not connect to host
 codeforce.io: did not receive HSTS header
 codepult.com: could not connect to host
 codepx.com: did not receive HSTS header
 codewiththepros.org: could not connect to host
 codiva.io: max-age too low: 2592000
 coffeeetc.co.uk: did not receive HSTS header
@@ -652,16 +658,17 @@ comicspines.com: could not connect to ho
 compalytics.com: could not connect to host
 comparejewelleryprices.co.uk: could not connect to host
 completionist.audio: could not connect to host
 computeremergency.com.au: did not receive HSTS header
 concord-group.co.jp: did not receive HSTS header
 condesaelectronics.com: max-age too low: 0
 confirm365.com: could not connect to host
 conformal.com: could not connect to host
+connectingconcepts.com: could not connect to host
 conrad-kostecki.de: did not receive HSTS header
 consciousandglamorous.com: could not connect to host
 console.python.org: did not receive HSTS header
 constructionjobs.com: did not receive HSTS header
 content-api-dev.azurewebsites.net: could not connect to host
 continuumgaming.com: could not connect to host
 controlcenter.gigahost.dk: did not receive HSTS header
 convert.zone: did not receive HSTS header
@@ -681,16 +688,17 @@ corruption-mc.net: could not connect to 
 corruption-rsps.net: could not connect to host
 corruption-server.net: could not connect to host
 count.sh: could not connect to host
 couragewhispers.ca: did not receive HSTS header
 coursdeprogrammation.com: could not connect to host
 coursella.com: did not receive HSTS header
 covenantbank.net: could not connect to host
 coverduck.ru: could not connect to host
+cqchome.com: could not connect to host
 cr.search.yahoo.com: did not receive HSTS header
 cracking.org: did not receive HSTS header
 craftbeerbarn.co.uk: could not connect to host
 craftedge.xyz: could not connect to host
 crate.io: did not receive HSTS header
 cravelyrics.com: did not receive HSTS header
 crazycen.com: did not receive HSTS header
 crazyhotseeds.com: did not receive HSTS header
@@ -724,16 +732,17 @@ csgoelemental.com: could not connect to 
 csgokings.eu: could not connect to host
 csohack.tk: could not connect to host
 cspbuilder.info: could not connect to host
 ct.search.yahoo.com: did not receive HSTS header
 cthulhuden.com: could not connect to host
 cubeserver.eu: could not connect to host
 cubewano.com: could not connect to host
 cujanovic.com: did not receive HSTS header
+cumshots-video.ru: could not connect to host
 cupidmentor.com: did not receive HSTS header
 curroapp.com: could not connect to host
 custe.rs: could not connect to host
 cuvva.insure: did not receive HSTS header
 cyanogenmod.xxx: could not connect to host
 cyberpunk.ca: could not connect to host
 cybershambles.com: could not connect to host
 cycleluxembourg.lu: did not receive HSTS header
@@ -775,17 +784,17 @@ datenreiter.tk: could not connect to hos
 datewon.net: did not receive HSTS header
 david-schiffmann.de: did not receive HSTS header
 davidhunter.scot: did not receive HSTS header
 davidreinhardt.de: could not connect to host
 davidscherzer.at: could not connect to host
 daylightcompany.com: did not receive HSTS header
 db.gy: did not receive HSTS header
 dbx.ovh: did not receive HSTS header
-dc585.info: could not connect to host
+dc585.info: did not receive HSTS header
 dccode.gov: could not connect to host
 dcurt.is: did not receive HSTS header
 ddatsh.com: did not receive HSTS header
 dden.ca: could not connect to host
 debank.tv: did not receive HSTS header
 debtkit.co.uk: did not receive HSTS header
 decafu.co: could not connect to host
 decibelios.li: could not connect to host
@@ -793,16 +802,17 @@ deco.me: could not connect to host
 dedicatutiempo.es: could not connect to host
 deepcovelabs.net: could not connect to host
 degroetenvanrosaline.nl: did not receive HSTS header
 deight.co: could not connect to host
 dekasan.ru: could not connect to host
 deliverance.co.uk: could not connect to host
 deltaconcepts.de: did not receive HSTS header
 deltanet-production.de: did not receive HSTS header
+delvj.org: could not connect to host
 demilitarized.ninja: could not connect to host
 democracychronicles.com: did not receive HSTS header
 denh.am: did not receive HSTS header
 denisjean.fr: could not connect to host
 dennisdoes.net: did not receive HSTS header
 dentaldomain.org: did not receive HSTS header
 dentaldomain.ph: did not receive HSTS header
 depijl-mz.nl: did not receive HSTS header
@@ -812,16 +822,17 @@ derevtsov.com: did not receive HSTS head
 derwolfe.net: did not receive HSTS header
 desiccantpackets.com: did not receive HSTS header
 despora.de: did not receive HSTS header
 destinationbijoux.fr: could not connect to host
 detector.exposed: could not connect to host
 deux.solutions: could not connect to host
 deuxsol.com: could not connect to host
 deuxsolutions.com: could not connect to host
+devcu.net: did not receive HSTS header
 devh.de: did not receive HSTS header
 devincrow.me: could not connect to host
 devinfo.net: did not receive HSTS header
 devtub.com: did not receive HSTS header
 devuan.org: did not receive HSTS header
 diablotine.rocks: could not connect to host
 diarbag.us: did not receive HSTS header
 diasp.cz: [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 121"  data: no]
@@ -876,31 +887,31 @@ dragonisles.net: could not connect to ho
 dragons-of-highlands.cz: could not connect to host
 dragontrainingmobilezoo.com.au: max-age too low: 0
 draw.uy: could not connect to host
 drbethanybarnes.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 121"  data: no]
 drdevil.ru: could not connect to host
 drdim.ru: could not connect to host
 dreadbyte.com: could not connect to host
 dreamlinehost.com: did not receive HSTS header
-dredgepress.com: did not receive HSTS header
 drishti.guru: could not connect to host
 drive.google.com: did not receive HSTS header (error ignored - included regardless)
 driving-lessons.co.uk: did not receive HSTS header
 droidboss.com: could not connect to host
 dropcam.com: did not receive HSTS header
 drtroyhendrickson.com: could not connect to host
 drumbandesperanto.nl: could not connect to host
 dshiv.io: could not connect to host
 dubrovskiy.net: could not connect to host
 dubrovskiy.pro: could not connect to host
 duesee.org: could not connect to host
 duria.de: max-age too low: 3600
 dustri.org: did not receive HSTS header
 dwhd.org: [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 121"  data: no]
+dworzak.ch: could not connect to host
 dycontrol.de: could not connect to host
 dylanscott.com.au: did not receive HSTS header
 dymersion.com: did not receive HSTS header
 dynamize.solutions: could not connect to host
 dzimejl.sk: did not receive HSTS header
 dzlibs.io: could not connect to host
 e-aut.net: could not connect to host
 e-deca2.org: did not receive HSTS header
@@ -945,17 +956,16 @@ electricianforum.co.uk: could not connec
 electromc.com: could not connect to host
 elemprendedor.com.ve: could not connect to host
 elenag.ga: could not connect to host
 elenoon.ir: did not receive HSTS header
 elgacien.de: could not connect to host
 elimdengelen.com: did not receive HSTS header
 elisabeth-kostecki.de: did not receive HSTS header
 elisabethkostecki.de: did not receive HSTS header
-elite-porno.ru: could not connect to host
 elitefishtank.com: could not connect to host
 elnutricionista.es: did not receive HSTS header
 elpo.xyz: could not connect to host
 elsamakhin.com: could not connect to host
 elsitar.com: could not connect to host
 email.lookout.com: could not connect to host
 emeldi-commerce.com: max-age too low: 0
 emjainteractive.com: did not receive HSTS header
@@ -986,32 +996,31 @@ epanurse.com: could not connect to host
 ephry.com: could not connect to host
 epoxate.com: did not receive HSTS header
 eq8.net.au: could not connect to host
 equate.net.au: max-age too low: 3600
 equatetechnologies.com.au: max-age too low: 3600
 equilibre-yoga-jennifer-will.com: could not connect to host
 erawanarifnugroho.com: did not receive HSTS header
 eressea.xyz: could not connect to host
-ericyl.com: did not receive HSTS header
+ericyl.com: could not connect to host
 eromixx.com: did not receive HSTS header
 erotalia.es: could not connect to host
 eroticen.com: did not receive HSTS header
 erotische-aanbiedingen.nl: could not connect to host
 errlytics.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 121"  data: no]
 errolz.com: could not connect to host
 errors.zenpayroll.com: could not connect to host
 ersindemirtas.com: did not receive HSTS header
 esclear.de: did not receive HSTS header
-escotour.com: could not connect to host
+escotour.com: did not receive HSTS header
 esec.rs: did not receive HSTS header
 espra.com: could not connect to host
 essexcosmeticdentists.co.uk: did not receive HSTS header
 essexghosthunters.co.uk: did not receive HSTS header
-estan.cn: did not receive HSTS header
 estilosapeca.com: could not connect to host
 et-buchholz.de: could not connect to host
 etdonline.co.uk: could not connect to host
 eternitylove.us: could not connect to host
 ethack.org: [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 121"  data: no]
 etsysecure.com: could not connect to host
 etula.ga: could not connect to host
 etula.me: did not receive HSTS header
@@ -1021,17 +1030,16 @@ euph.eu: did not receive HSTS header
 euren.se: could not connect to host
 euroshop24.net: could not connect to host
 evantage.org: could not connect to host
 evdenevenakliyatankara.pw: could not connect to host
 everybooks.com: max-age too low: 60
 everylab.org: could not connect to host
 evi.be: did not receive HSTS header
 evin.ml: could not connect to host
-evites.me: could not connect to host
 evomon.com: could not connect to host
 evossd.tk: could not connect to host
 exceltobarcode.com: did not receive HSTS header
 exfiles.cz: did not receive HSTS header
 exgravitus.com: could not connect to host
 exitus.jp: max-age too low: 0
 exno.co: could not connect to host
 expertmile.com: did not receive HSTS header
@@ -1050,17 +1058,16 @@ f-s-u.co.uk: could not connect to host
 f00.ca: did not receive HSTS header
 fabhub.io: could not connect to host
 fabianfischer.de: did not receive HSTS header
 factorable.net: did not receive HSTS header
 factorygw.com: did not receive HSTS header
 fadilus.com: did not receive HSTS header
 faesser.com: did not receive HSTS header
 fail4free.de: did not receive HSTS header
-failproof.be: could not connect to host
 fairlyoddtreasures.com: did not receive HSTS header
 faithwatch.org: could not connect to host
 faizan.net: did not receive HSTS header
 faizan.xyz: could not connect to host
 fakeletters.org: did not receive HSTS header
 falconfrag.com: could not connect to host
 falkena.net: max-age too low: 5184000
 falkp.no: did not receive HSTS header
@@ -1097,17 +1104,17 @@ fightr.co: could not connect to host
 filmipop.com: max-age too low: 0
 finalgear.com: did not receive HSTS header
 finanzkontor.net: could not connect to host
 findtutorsnearme.com: did not receive HSTS header
 fingent.com: did not receive HSTS header
 finiteheap.com: could not connect to host
 firebaseio-demo.com: could not connect to host
 firebaseio.com: could not connect to host (error ignored - included regardless)
-firefall.rocks: did not receive HSTS header
+firefall.rocks: could not connect to host
 firemail.io: could not connect to host
 firstforex.co.uk: did not receive HSTS header
 fish2.me: did not receive HSTS header
 fit4medien.de: did not receive HSTS header
 fitnesswerk.de: could not connect to host
 fivestarsitters.com: did not receive HSTS header
 fixatom.com: did not receive HSTS header
 fixingdns.com: did not receive HSTS header
@@ -1115,17 +1122,16 @@ fj.search.yahoo.com: did not receive HST
 flags.ninja: could not connect to host
 flamewall.net: could not connect to host
 flawcheck.com: did not receive HSTS header
 fliexer.com: did not receive HSTS header
 floless.co.uk: did not receive HSTS header
 florian-lillpopp.de: max-age too low: 10
 florianlillpopp.de: max-age too low: 10
 floridaescapes.co.uk: did not receive HSTS header
-florisvdk.net: did not receive HSTS header
 flouartistique.ch: could not connect to host
 flow.su: could not connect to host
 flowersandclouds.com: could not connect to host
 flushstudios.com: did not receive HSTS header
 fly.moe: could not connect to host
 flyaces.com: did not receive HSTS header
 flyss.net: did not receive HSTS header
 fm83.nl: did not receive HSTS header
@@ -1150,17 +1156,16 @@ fotografosexpertos.com: did not receive 
 fotopasja.info: could not connect to host
 fourchin.net: could not connect to host
 foxdev.io: could not connect to host
 foxelbox.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 121"  data: no]
 foxtrot.pw: could not connect to host
 fr33d0m.link: could not connect to host
 francevpn.xyz: could not connect to host
 frangor.info: did not receive HSTS header
-fransallen.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 121"  data: no]
 franzt.de: could not connect to host
 frasys.io: did not receive HSTS header
 freeflow.tv: could not connect to host
 freekdevries.nl: could not connect to host
 freematthale.net: could not connect to host
 freemedforms.com: did not receive HSTS header
 freesounding.com: could not connect to host
 freesounding.ru: could not connect to host
@@ -1205,16 +1210,17 @@ gallery44.org: did not receive HSTS head
 galoisvpn.xyz: could not connect to host
 game.yt: could not connect to host
 gamecave.de: could not connect to host
 gamechasm.com: could not connect to host
 gamehacks.me: could not connect to host
 gameink.net: max-age too low: 0
 gamenected.com: could not connect to host
 gamenected.de: could not connect to host
+gamepiece.com: could not connect to host
 gamerslair.org: did not receive HSTS header
 gamesdepartment.co.uk: max-age too low: 0
 gamingmedia.eu: could not connect to host
 gampenhof.de: did not receive HSTS header
 gaptek.id: did not receive HSTS header
 gatilagata.com.br: did not receive HSTS header
 gdpventure.com: max-age too low: 0
 gedankenbude.info: did not receive HSTS header
@@ -1233,29 +1239,29 @@ getbooks.co.il: did not receive HSTS hea
 getcarefirst.com: did not receive HSTS header
 getcolor.com: did not receive HSTS header
 getinternet.de: max-age too low: 0
 getlantern.org: did not receive HSTS header
 getlifti.com: did not receive HSTS header
 getlolaccount.com: could not connect to host
 getmassage.com.ng: did not receive HSTS header
 getsello.com: did not receive HSTS header
-getwashdaddy.com: could not connect to host
+getwashdaddy.com: did not receive HSTS header
 gfhgiro.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 121"  data: no]
 gfm.tech: could not connect to host
 gfournier.ca: could not connect to host
 gfwsb.ml: could not connect to host
 gheorghesarcov.ga: could not connect to host
 gheorghesarcov.tk: could not connect to host
 giakki.eu: could not connect to host
 gigacloud.org: did not receive HSTS header
 gilgaz.com: did not receive HSTS header
 gilly.berlin: did not receive HSTS header
 gingali.de: did not receive HSTS header
-gintenreiter-photography.com: could not connect to host
+gintenreiter-photography.com: did not receive HSTS header
 gipsamsfashion.com: could not connect to host
 gistfy.com: could not connect to host
 github.party: could not connect to host
 givemyanswer.com: did not receive HSTS header
 gizzo.sk: could not connect to host
 gjspunk.de: did not receive HSTS header
 gl.search.yahoo.com: did not receive HSTS header
 glass.google.com: did not receive HSTS header (error ignored - included regardless)
@@ -1286,17 +1292,17 @@ gogold-g.com: could not connect to host
 gold24.in: did not receive HSTS header
 goldendata.io: could not connect to host
 golocal-media.de: did not receive HSTS header
 gonzalosanchez.mx: did not receive HSTS header
 goodenough.nz: did not receive HSTS header
 goodwin43.ru: did not receive HSTS header
 google: could not connect to host (error ignored - included regardless)
 googlemail.com: did not receive HSTS header (error ignored - included regardless)
-googleplex.com: did not receive HSTS header (error ignored - included regardless)
+googleplex.com: could not connect to host (error ignored - included regardless)
 gorilla-gym.site: could not connect to host
 goto.google.com: did not receive HSTS header (error ignored - included regardless)
 gottcode.org: did not receive HSTS header
 govillemo.ca: did not receive HSTS header
 gowe.wang: could not connect to host
 gparent.org: did not receive HSTS header
 gpsfix.cz: could not connect to host
 gpstuner.com: did not receive HSTS header
@@ -1376,16 +1382,18 @@ hastherebeenamassshooting.today: could n
 hatoko.net: could not connect to host
 haufschild.de: could not connect to host
 haurumcraft.net: could not connect to host
 haveeruexaminer.com: could not connect to host
 havellab.de: could not connect to host
 haydenhill.us: could not connect to host
 hazcod.com: could not connect to host
 hcie.pl: could not connect to host
+hcs-company.com: could not connect to host
+hcs-company.nl: could not connect to host
 hdm.io: [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 121"  data: no]
 hdsmigrationtool.com: could not connect to host
 hduin.xyz: did not receive HSTS header
 hdwallpapers.net: did not receive HSTS header
 healtious.com: did not receive HSTS header
 heart.ge: did not receive HSTS header
 heartlandrentals.com: did not receive HSTS header
 heftkaufen.de: did not receive HSTS header
@@ -1476,17 +1484,16 @@ ideation-inc.co.jp: did not receive HSTS
 identitylabs.uk: did not receive HSTS header
 idgsupply.com: could not connect to host
 idlekernel.com: could not connect to host
 ie.search.yahoo.com: did not receive HSTS header
 ies-italia.it: did not receive HSTS header
 ies.id.lv: could not connect to host
 ifad.org: did not receive HSTS header
 ifleurs.com: could not connect to host
-ifoss.me: could not connect to host
 ignatisd.gr: did not receive HSTS header
 igule.net: could not connect to host
 ihrlotto.de: could not connect to host
 ihrnationalrat.ch: could not connect to host
 ihsbsd.me: could not connect to host
 ihuanmeng.com: did not receive HSTS header
 ikujii.com: max-age too low: 0
 ikwilguidobellen.nl: did not receive HSTS header
@@ -1502,25 +1509,27 @@ imjiangtao.com: did not receive HSTS hea
 immoprotect.ca: did not receive HSTS header
 immortals-co.com: did not receive HSTS header
 immoverkauf24.at: did not receive HSTS header
 immoverkauf24.de: did not receive HSTS header
 immunicity.info: could not connect to host
 immunicity.press: could not connect to host
 immunicity.top: could not connect to host
 imolug.org: did not receive HSTS header
+imoni-blog.net: could not connect to host
 imouto.my: max-age too low: 5184000
 imperialwebsolutions.com: did not receive HSTS header
 imu.li: did not receive HSTS header
 imusic.dk: could not connect to host
 inb4.us: could not connect to host
 inbox.li: did not receive HSTS header
 inchomatic.com: did not receive HSTS header
 indoorskiassen.nl: did not receive HSTS header
 indust.me: did not receive HSTS header
+indybay.org: could not connect to host
 inertianetworks.com: did not receive HSTS header
 infcof.com: max-age too low: 0
 infinitude.me.uk: could not connect to host
 infinitude.xyz: could not connect to host
 infinitudecloud.com: could not connect to host
 infinitusgaming.eu: could not connect to host
 inflation.ml: could not connect to host
 infogrfx.com: did not receive HSTS header
@@ -1582,16 +1591,17 @@ itechgeek.com: max-age too low: 0
 itfh.eu: could not connect to host
 itos.asia: did not receive HSTS header
 itos.pl: did not receive HSTS header
 its4living.com: could not connect to host
 itsadog.co.uk: did not receive HSTS header
 itsamurai.ru: max-age too low: 2592000
 itsecurityassurance.pw: did not receive HSTS header
 itshost.ru: could not connect to host
+itspawned.com: could not connect to host
 ivi-fertility.com: max-age too low: 0
 ivi.es: max-age too low: 0
 ivk.website: could not connect to host
 iww.mx: could not connect to host
 izdiwho.com: could not connect to host
 izzzorgconcerten.nl: could not connect to host
 ja-publications.com: did not receive HSTS header
 jaba.hosting: did not receive HSTS header
@@ -1606,17 +1616,17 @@ jamesbradach.com: did not receive HSTS h
 jamesburton.london: could not connect to host
 jamesbywater.me: could not connect to host
 jamesbywater.me.uk: could not connect to host
 jamesconroyfinn.com: did not receive HSTS header
 jamesdoell.com: could not connect to host
 jamesdoylephoto.com: did not receive HSTS header
 jamesmorrison.me: did not receive HSTS header
 jamourtney.com: could not connect to host
-jan27.org: could not connect to host
+jan27.org: did not receive HSTS header
 janario.me: could not connect to host
 janbrodda.de: max-age too low: 2592000
 jannyrijneveld.nl: did not receive HSTS header
 janus-engineering.de: did not receive HSTS header
 japlex.com: could not connect to host
 jaqen.ch: could not connect to host
 jaredeberle.org: did not receive HSTS header
 jaroslavtrsek.cz: did not receive HSTS header
@@ -1637,17 +1647,17 @@ jcor.me: could not connect to host
 jctf.io: could not connect to host
 jdh8.org: could not connect to host
 jeff393.com: could not connect to host
 jenjoit.de: could not connect to host
 jensenbanden.no: could not connect to host
 jeremye77.com: could not connect to host
 jesorsenville.com: did not receive HSTS header
 jessicabenedictus.nl: could not connect to host
-jetaprices.com: max-age too low: 0
+jetaprices.com: could not connect to host
 jetsetpay.com: could not connect to host
 jettlarue.com: could not connect to host
 jettshome.org: could not connect to host
 jeugdkans.nl: did not receive HSTS header
 jf.duckdns.org: could not connect to host
 jfmel.com: did not receive HSTS header
 jh-media.eu: could not connect to host
 jhburton.uk: could not connect to host
@@ -1662,17 +1672,16 @@ jmdekker.it: could not connect to host
 joakimalgroy.com: could not connect to host
 jobmedic.com: did not receive HSTS header
 joedavison.me: could not connect to host
 johnbrownphotography.ch: did not receive HSTS header
 johners.me: could not connect to host
 johners.tech: did not receive HSTS header
 johnrom.com: did not receive HSTS header
 jonas-keidel.de: did not receive HSTS header
-jonas-thelemann.de: could not connect to host
 jonasgroth.se: max-age too low: 2592000
 jonathan.ir: could not connect to host
 jonathancarter.org: [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 121"  data: no]
 jonn.me: could not connect to host
 joostbovee.nl: did not receive HSTS header
 joretapo.fr: could not connect to host
 josahrens.me: could not connect to host
 joshstroup.me: could not connect to host
@@ -1697,16 +1706,17 @@ justnaw.co.uk: could not connect to host
 justudin.com: did not receive HSTS header
 juwairen.cn: could not connect to host
 jvoice.net: could not connect to host
 jwilsson.me: could not connect to host
 jxm.in: could not connect to host
 k-dev.de: could not connect to host
 ka-clan.com: could not connect to host
 kabuabc.com: did not receive HSTS header
+kabus.org: could not connect to host
 kadioglumakina.com.tr: did not receive HSTS header
 kahopoon.net: could not connect to host
 kaisers.de: did not receive HSTS header
 kalami.nl: did not receive HSTS header
 kamikano.com: could not connect to host
 kaplatz.is: could not connect to host
 kapucini.si: max-age too low: 0
 karaoketonight.com: could not connect to host
@@ -1715,34 +1725,33 @@ katproxy.online: could not connect to ho
 katproxy.site: could not connect to host
 katproxy.tech: could not connect to host
 kaufkraftkiel.de: could not connect to host
 kausch.at: could not connect to host
 kawaii.io: max-age too low: 2592000
 kawaiiku.com: could not connect to host
 kawaiiku.de: could not connect to host
 kayon.cf: could not connect to host
-kdata.it: could not connect to host
+kdata.it: did not receive HSTS header
 kdm-online.de: did not receive HSTS header
 keeley.gq: could not connect to host
 keeley.ml: could not connect to host
 keeleysam.me: could not connect to host
 keepclean.me: could not connect to host
 kerangalam.com: did not receive HSTS header
 kerksanders.nl: did not receive HSTS header
 kermadec.net: could not connect to host
 kernl.us: did not receive HSTS header
 kevinapease.com: could not connect to host
 keymaster.lookout.com: did not receive HSTS header
 kg-rating.com: did not receive HSTS header
 kgxtech.com: max-age too low: 2592000
 kickass.al: could not connect to host
 kid-dachau.de: did not receive HSTS header
 kiel-media.de: did not receive HSTS header
-kilianvalkhof.com: did not receive HSTS header
 kimpost.org: could not connect to host
 kinderwagen-test24.de: could not connect to host
 kingmanhall.org: could not connect to host
 kini24.ru: did not receive HSTS header
 kinnon.enterprises: could not connect to host
 kinogb.net: max-age too low: 0
 kionetworks.com: did not receive HSTS header
 kirkforcongress.com: could not connect to host
@@ -1762,17 +1771,16 @@ klauwd.com: did not receive HSTS header
 klaxn.org: could not connect to host
 kleertjesvoordelig.nl: could not connect to host
 kleinblogje.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 121"  data: no]
 kleppe.co: could not connect to host
 kletterkater.com: did not receive HSTS header
 klicktojob.de: could not connect to host
 klimat-pro.pl: max-age too low: 0
 kmartin.io: did not receive HSTS header
-knapen.io: could not connect to host
 knccloud.com: did not receive HSTS header
 kodokushi.fr: could not connect to host
 kolaykaydet.com: did not receive HSTS header
 kollabria.com: max-age too low: 0
 komikito.com: could not connect to host
 kompetenzwerft.de: did not receive HSTS header
 kontaxis.network: could not connect to host
 kontorhaus-schlachte.de: could not connect to host
@@ -1836,17 +1844,17 @@ laxatus.com: did not receive HSTS header
 laxiongames.es: could not connect to host
 lbrt.xyz: could not connect to host
 ldarby.me.uk: could not connect to host
 leadership9.com: could not connect to host
 leardev.de: did not receive HSTS header
 learnfrenchfluently.com: did not receive HSTS header
 learningorder.com: could not connect to host
 ledgerscope.net: could not connect to host
-leermotorrijden.nl: could not connect to host
+leermotorrijden.nl: max-age too low: 300
 legarage.org: did not receive HSTS header
 leinir.dk: max-age too low: 86400
 leitner.com.au: did not receive HSTS header
 leiyun.me: did not receive HSTS header
 lellyboi.ml: could not connect to host
 lelongbank.com: did not receive HSTS header
 lemp.io: did not receive HSTS header
 lenovogaming.com: did not receive HSTS header
@@ -1865,20 +1873,22 @@ letustravel.tk: could not connect to hos
 lfullerdesign.com: did not receive HSTS header
 lgiswa.com.au: did not receive HSTS header
 lgrs.com.au: did not receive HSTS header
 lgts.se: could not connect to host
 li.search.yahoo.com: did not receive HSTS header
 liaillustr.at: did not receive HSTS header
 liam-w.com: could not connect to host
 liaoshuma.com: could not connect to host
+libbitcoin.org: could not connect to host
 libertyrp.org: could not connect to host
-libnull.com: could not connect to host
 library.linode.com: did not receive HSTS header
 librechan.net: could not connect to host
+liduan.com: could not connect to host
+liduan.net: could not connect to host
 lifeguard.aecom.com: did not receive HSTS header
 lifeinitsownway.com: did not receive HSTS header
 lifestylehunter.co.uk: did not receive HSTS header
 lifetimemoneymachine.com: did not receive HSTS header
 lightarmory.com: could not connect to host
 lightpaste.com: could not connect to host
 lillpopp.eu: max-age too low: 10
 lilpwny.com: could not connect to host
@@ -1926,17 +1936,16 @@ lowhangingfruitgrabber.com: could not co
 lpak.nl: could not connect to host
 lrhsclubs.com: could not connect to host
 lrhstsa.com: could not connect to host
 ls-a.org: did not receive HSTS header
 lsky.cn: did not receive HSTS header
 lsp-sports.de: did not receive HSTS header
 lt.search.yahoo.com: did not receive HSTS header
 ltbytes.com: could not connect to host
-ltn-tom-morel.fr: could not connect to host
 lu.search.yahoo.com: did not receive HSTS header
 luine.xyz: could not connect to host
 luis-checa.com: could not connect to host
 lukas.im: did not receive HSTS header
 luke.ch: could not connect to host
 lukeng.me: could not connect to host
 lukeng.net: could not connect to host
 lukonet.com: did not receive HSTS header
@@ -1948,37 +1957,40 @@ lusis.fr: did not receive HSTS header
 lusis.net: did not receive HSTS header
 lustrumxi.nl: could not connect to host
 luxus-russen.de: did not receive HSTS header
 luxwatch.com: could not connect to host
 lv.search.yahoo.com: did not receive HSTS header
 lzkill.com: did not receive HSTS header
 m-ali.xyz: did not receive HSTS header
 m.gparent.org: could not connect to host
+m.nu: did not receive HSTS header
 m3-gmbh.de: did not receive HSTS header
 m82labs.com: did not receive HSTS header
 maarten.nyc: did not receive HSTS header
 maartenvandekamp.nl: did not receive HSTS header
 macbolo.com: could not connect to host
 macchaberrycream.com: could not connect to host
 macchedil.com: did not receive HSTS header
 madars.org: did not receive HSTS header
 maddin.ga: could not connect to host
 madebymagnitude.com: did not receive HSTS header
 maderwin.com: did not receive HSTS header
 madusecurity.com: could not connect to host
 mafamane.com: could not connect to host
 mafiareturns.com: max-age too low: 2592000
 magenx.com: did not receive HSTS header
 mahamed91.pw: could not connect to host
+maidofhonorcleaning.net: could not connect to host
 mail-settings.google.com: did not receive HSTS header (error ignored - included regardless)
 mail.google.com: did not receive HSTS header (error ignored - included regardless)
 maildragon.com: could not connect to host
 makeitdynamic.com: could not connect to host
 makerstuff.net: did not receive HSTS header
+makeyourank.com: could not connect to host
 malerversand.de: did not receive HSTS header
 malwre.io: could not connect to host
 mamaison.io: could not connect to host
 mamaxi.org: did not receive HSTS header
 mammothmail.com: could not connect to host
 mammothmail.net: could not connect to host
 mammothmail.org: could not connect to host
 managemynetsuite.com: could not connect to host
@@ -2079,23 +2091,21 @@ midwestwomenworkers.org: did not receive
 mightydicks.io: could not connect to host
 mightydicks.tech: could not connect to host
 mightysounds.cz: max-age too low: 0
 mijcorijneveld.nl: did not receive HSTS header
 mijn-email.org: could not connect to host
 mikaelemilsson.net: did not receive HSTS header
 mikeburns.com: did not receive HSTS header
 mikeg.de: did not receive HSTS header
-mikek.work: did not receive HSTS header
 mikeology.org: could not connect to host
 mikepair.net: did not receive HSTS header
 mikonmaa.fi: could not connect to host
 miku.be: could not connect to host
 miku.hatsune.my: max-age too low: 5184000
-milang.xyz: could not connect to host
 milesgeek.com: did not receive HSTS header
 mindcraft.ga: max-age too low: 7776000
 mindoktor.se: did not receive HSTS header
 minecraftserverz.com: could not connect to host
 minecraftvoter.com: could not connect to host
 minikneet.nl: did not receive HSTS header
 minnesotadata.com: could not connect to host
 minora.io: did not receive HSTS header
@@ -2116,16 +2126,17 @@ mmgazhomeloans.com: did not receive HSTS
 mnemotiv.com: could not connect to host
 mnetworkingsolutions.co.uk: did not receive HSTS header
 mobilekey.co: could not connect to host
 mobilemedics.com: did not receive HSTS header
 mobilethreat.net: could not connect to host
 mobilethreatnetwork.net: could not connect to host
 mocloud.eu: could not connect to host
 modemagazines.co.uk: could not connect to host
+moe4sale.in: could not connect to host
 moebel-nagel.de: did not receive HSTS header
 moelord.org: could not connect to host
 moen.io: did not receive HSTS header
 mogry.net: did not receive HSTS header
 mona.lu: did not receive HSTS header
 monarca.systems: could not connect to host
 monasterialis.eu: could not connect to host
 mondar.io: could not connect to host
@@ -2142,18 +2153,18 @@ moriz.net: could not connect to host
 morningcalculation.com: could not connect to host
 morotech.com.br: max-age too low: 2592000
 morpork.xyz: could not connect to host
 mortgagecentersmo.com: did not receive HSTS header
 mostwuat.com: could not connect to host
 motherbase.io: could not connect to host
 motionpicturesolutions.com: could not connect to host
 motocyklovedily.cz: did not receive HSTS header
-motoryz.com: could not connect to host
-motoryz.nl: could not connect to host
+motoryz.com: max-age too low: 300
+motoryz.nl: max-age too low: 300
 mottvd.com: could not connect to host
 moula.com.au: did not receive HSTS header
 mountainmusicpromotions.com: did not receive HSTS header
 moviesabout.net: could not connect to host
 mozoa.net: did not receive HSTS header
 mp3juices.is: could not connect to host
 mqas.net: could not connect to host
 mrnonz.com: max-age too low: 0
@@ -2181,17 +2192,16 @@ mw.search.yahoo.com: did not receive HST
 my-owncloud.com: could not connect to host
 my.alfresco.com: did not receive HSTS header
 my.swedbank.se: did not receive HSTS header
 mybon.at: could not connect to host
 mycollab.net: could not connect to host
 mycoted.com: did not receive HSTS header
 mydeos.com: could not connect to host
 mydigipass.com: did not receive HSTS header
-mygadgetguardian.lookout.com: could not connect to host
 mygov.scot: did not receive HSTS header
 myiocc.org: could not connect to host
 mykolab.com: did not receive HSTS header
 mykreuzfahrt.de: could not connect to host
 myni.io: could not connect to host
 mypagella.com: could not connect to host
 mypagella.eu: could not connect to host
 mypagella.it: could not connect to host
@@ -2261,26 +2271,28 @@ newtonwarp.com: could not connect to hos
 nextcloud.org: could not connect to host
 nexth.de: could not connect to host
 nexth.net: could not connect to host
 nexth.us: could not connect to host
 nextproject.us: could not connect to host
 ng-security.com: could not connect to host
 ngine.ch: did not receive HSTS header
 nginxnudes.com: could not connect to host
+ngt-service.ru: could not connect to host
 ni.search.yahoo.com: did not receive HSTS header
 nibiisclaim.com: could not connect to host
 nicestresser.fr: could not connect to host
 nicky.io: did not receive HSTS header
-nicolasbettag.me: did not receive HSTS header
+nicolasbettag.me: could not connect to host
 niconiconi.xyz: could not connect to host
 niconode.com: did not receive HSTS header
 nien.chat: could not connect to host
 nightx.uk: could not connect to host
 niho.jp: [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 121"  data: no]
+nikksno.io: could not connect to host
 nikomo.fi: could not connect to host
 ninchisho-online.com: did not receive HSTS header
 ninhs.org: could not connect to host
 nippler.org: did not receive HSTS header
 nippombashi.net: did not receive HSTS header
 nipponcareers.com: did not receive HSTS header
 nkinka.de: did not receive HSTS header
 nmctest.net: could not connect to host
@@ -2319,16 +2331,17 @@ nu3.fr: did not receive HSTS header
 nu3.no: did not receive HSTS header
 nu3.se: did not receive HSTS header
 nufla.de: could not connect to host
 null-sec.ru: could not connect to host
 null.cat: could not connect to host
 null.tips: could not connect to host
 nullpoint.at: did not receive HSTS header
 numericacu.com: did not receive HSTS header
+numero-di-telefono.it: could not connect to host
 nuos.org: could not connect to host
 nutleyeducationalfoundation.org: did not receive HSTS header
 nutleyef.org: did not receive HSTS header
 nutrienti.eu: did not receive HSTS header
 nutritionculture.com: could not connect to host
 nutsandboltsmedia.com: did not receive HSTS header
 nwgh.org: max-age too low: 86400
 nyantec.com: did not receive HSTS header
@@ -2378,17 +2391,17 @@ onlyshopstation.com: did not receive HST
 ononpay.com: did not receive HSTS header
 ontras.com: could not connect to host
 onyxwall.net: could not connect to host
 ookjesprookje.nl: could not connect to host
 ooonja.de: could not connect to host
 oopsmycase.com: could not connect to host
 oost.io: could not connect to host
 open-mx.de: could not connect to host
-open-to-repair.fr: could not connect to host
+open-to-repair.fr: did not receive HSTS header
 opendesk.cc: did not receive HSTS header
 openmind-shop.de: did not receive HSTS header
 opennippon.ru: could not connect to host
 openprovider.nl: did not receive HSTS header
 openquery.com.au: did not receive HSTS header
 openshift.redhat.com: did not receive HSTS header
 opensrd.com: could not connect to host
 openxmpp.com: could not connect to host
@@ -2397,34 +2410,31 @@ oprbox.com: could not connect to host
 opsbears.com: did not receive HSTS header
 optenhoefel.de: could not connect to host
 optometriepunt.nl: did not receive HSTS header
 optumrxhealthstore.com: did not receive HSTS header
 oracaodocredo.com.br: could not connect to host
 orbiosales.com: could not connect to host
 orbitcom.de: max-age too low: 0
 orbograph-hrcm.com: did not receive HSTS header
-ordr.mobi: could not connect to host
 orioncustompcs.com: could not connect to host
 orionfcu.com: did not receive HSTS header
 orleika.ml: could not connect to host
 osaiyuwu.com: could not connect to host
 oshell.me: did not receive HSTS header
 oslfoundation.org: could not connect to host
 ossan-kobe-gourmet.com: did not receive HSTS header
 ossbinaries.com: could not connect to host
 osteammate.com: did not receive HSTS header
-ostr.io: did not receive HSTS header
 otakuworld.de: could not connect to host
 othercode.nl: could not connect to host
 othermedia.cc: [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 121"  data: no]
 otherstuff.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 121"  data: no]
 otichi.com: did not receive HSTS header
 ottospora.nl: could not connect to host
-ouaibe.qc.ca: could not connect to host
 ourbank.com: did not receive HSTS header
 outetc.com: could not connect to host
 outreachbuddy.com: could not connect to host
 outsider.im: could not connect to host
 ouvirmusica.com.br: did not receive HSTS header
 ovenapp.io: did not receive HSTS header
 overclockers.ge: could not connect to host
 oversight.io: could not connect to host
@@ -2441,22 +2451,24 @@ pader-deko.de: [Exception... "Component 
 paestbin.com: could not connect to host
 pagerate.io: did not receive HSTS header
 pagetoimage.com: could not connect to host
 paisaone.com: did not receive HSTS header
 paku.me: could not connect to host
 pamsoft.pl: max-age too low: 0
 panaceallc.net: could not connect to host
 panelomix.net: could not connect to host
+pants-off.xyz: could not connect to host
 pantsu.cat: did not receive HSTS header
 papeda.net: did not receive HSTS header
 papercard.co.uk: did not receive HSTS header
 papierniak.net: could not connect to host
 parent5446.us: could not connect to host
 parentmail.co.uk: did not receive HSTS header
+parithy.net: could not connect to host
 particonpsplus.it: could not connect to host
 partijtjevoordevrijheid.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 121"  data: no]
 partyvan.it: could not connect to host
 partyvan.moe: could not connect to host
 partyvan.nl: could not connect to host
 partyvan.se: could not connect to host
 passumpsicbank.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 121"  data: no]
 passwordbox.com: did not receive HSTS header
@@ -2484,33 +2496,40 @@ pchax.net: did not receive HSTS header
 peissen.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 121"  data: no]
 pekkapikkarainen.fi: could not connect to host
 pekkarik.ru: could not connect to host
 pentagram.me: could not connect to host
 pepperhead.com: could not connect to host
 pepperworldhotshop.de: did not receive HSTS header
 perfectionis.me: could not connect to host
 performous.org: could not connect to host
+perfumista.vn: could not connect to host
 perlwork.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 121"  data: no]
 perplex.nl: did not receive HSTS header
 perroud.pro: max-age too low: 2592000
 personaldatabasen.no: could not connect to host
 personalinjurylist.com: did not receive HSTS header
 perthdevicelab.com: did not receive HSTS header
 pet-nsk.ru: could not connect to host
 petchart.net: could not connect to host
 petja.me: could not connect to host
 petplum.com: did not receive HSTS header
 petrachuk.ru: did not receive HSTS header
 petravdbos.nl: did not receive HSTS header
 petrolplus.ru: did not receive HSTS header
 pettsy.com: could not connect to host
 pewboards.com: could not connect to host
 pgpm.io: could not connect to host
+phenomeno-porto.com: could not connect to host
+phenomeno.nl: could not connect to host
+phenomenoporto.com: could not connect to host
+phenomenoporto.nl: could not connect to host
+phonenumberinfo.co.uk: could not connect to host
 phongmay24h.com: could not connect to host
+phperformances.fr: could not connect to host
 phurl.de: could not connect to host
 pickr.co: could not connect to host
 picotronic.biz: could not connect to host
 picscare.co.uk: did not receive HSTS header
 piligrimname.com: could not connect to host
 pinesandneedles.com: did not receive HSTS header
 pippen.io: could not connect to host
 pir9.com: max-age too low: 2592000
@@ -2524,26 +2543,25 @@ pisidia.de: could not connect to host
 pittonpreschool.com: did not receive HSTS header
 pixel.google.com: did not receive HSTS header (error ignored - included regardless)
 pixelcode.com.au: max-age too low: 0
 pixelhero.co.uk: did not receive HSTS header
 pixi.me: could not connect to host
 pj83.duckdns.org: [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 121"  data: no]
 pk.search.yahoo.com: did not receive HSTS header
 placollection.org: could not connect to host
+plaintech.net.au: could not connect to host
 platform.lookout.com: could not connect to host
 play.google.com: did not receive HSTS header (error ignored - included regardless)
 playkh.com: did not receive HSTS header
 playmaker.io: could not connect to host
 playnation.io: did not receive HSTS header
 plogable.co: could not connect to host
 plothost.com: did not receive HSTS header
 ploup.net: could not connect to host
-pm13.cz: could not connect to host
-pm13.org: could not connect to host
 pmnts.io: could not connect to host
 po.gl: did not receive HSTS header
 poiema.com.sg: did not receive HSTS header
 pol.in.th: could not connect to host
 poleartschool.com: could not connect to host
 polimat.org: could not connect to host
 politically-incorrect.xyz: could not connect to host
 politologos.org: could not connect to host
@@ -2552,16 +2570,17 @@ pompompoes.com: could not connect to hos
 pontokay.com.br: did not receive HSTS header
 pontualcomp.com: max-age too low: 2592000
 poolsandstuff.com: did not receive HSTS header
 poris.web.id: did not receive HSTS header
 portalplatform.net: did not receive HSTS header
 postcodewise.co.uk: did not receive HSTS header
 postscheduler.org: could not connect to host
 posylka.de: did not receive HSTS header
+potatofrom.space: could not connect to host
 poussinooz.fr: could not connect to host
 povitria.net: could not connect to host
 powerplannerapp.com: did not receive HSTS header
 powerxequality.com: could not connect to host
 ppr-truby.ru: could not connect to host
 pr.search.yahoo.com: did not receive HSTS header
 prefontaine.name: could not connect to host
 prego-shop.de: did not receive HSTS header
@@ -2592,17 +2611,16 @@ prowhisky.de: did not receive HSTS heade
 proximato.com: could not connect to host
 proxybay.al: could not connect to host
 proxybay.club: could not connect to host
 proxybay.info: did not receive HSTS header
 prxio.site: did not receive HSTS header
 prytkov.com: did not receive HSTS header
 psw.academy: did not receive HSTS header
 psw.consulting: did not receive HSTS header
-ptm.ro: max-age too low: 0
 ptn.moscow: could not connect to host
 ptonet.com: could not connect to host
 pubkey.is: could not connect to host
 puiterwijk.org: could not connect to host
 pumpgames.net: could not connect to host
 punchr-kamikazee.rhcloud.com: did not receive HSTS header
 purewebmasters.com: could not connect to host
 purplemoon.mobi: did not receive HSTS header
@@ -2616,18 +2634,18 @@ pyplo.org: did not receive HSTS header
 pypt.lt: did not receive HSTS header
 q2.si: could not connect to host
 qingxuan.info: max-age too low: 864000
 qinxi1992.com: did not receive HSTS header
 qiwi.be: did not receive HSTS header
 qorm.co.uk: did not receive HSTS header
 qrara.net: did not receive HSTS header
 qrlending.com: did not receive HSTS header
-qtxh.net: [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 121"  data: no]
 quail.solutions: could not connect to host
+qualityology.com: could not connect to host
 quantacloud.ch: could not connect to host
 quantumcourse.org: did not receive HSTS header
 queercoders.com: did not receive HSTS header
 quemmeliga.com: could not connect to host
 questsandrewards.com: could not connect to host
 quranserver.net: could not connect to host
 qvi.st: did not receive HSTS header
 qwilink.me: did not receive HSTS header
@@ -2638,17 +2656,17 @@ raajheshkannaa.com: could not connect to
 radicaleducation.net: could not connect to host
 radiormi.com: did not receive HSTS header
 rafaelcz.de: could not connect to host
 rainbowbarracuda.com: could not connect to host
 ramonj.nl: could not connect to host
 rankthespot.com: did not receive HSTS header
 rapidresearch.me: could not connect to host
 rapidthunder.io: could not connect to host
-rasing.me: did not receive HSTS header
+rasing.me: could not connect to host
 ratajczak.fr: could not connect to host
 raulfraile.net: could not connect to host
 rawet.se: did not receive HSTS header
 rawstorieslondon.com: could not connect to host
 raydobe.me: could not connect to host
 rc4.io: did not receive HSTS header
 rcafox.com: could not connect to host
 rcpcbd.com: did not receive HSTS header
@@ -2683,16 +2701,17 @@ renteater.com: could not connect to host
 replacemychina.com: did not receive HSTS header
 reprolife.co.uk: max-age too low: 0
 res-rheingau.de: did not receive HSTS header
 res42.com: did not receive HSTS header
 reserve-online.net: did not receive HSTS header
 respice.xyz: could not connect to host
 restchart.com: did not receive HSTS header
 revello.org: did not receive HSTS header
+revensoftware.com: could not connect to host
 reverie.pw: could not connect to host
 reviews.anime.my: could not connect to host
 revtut.net: did not receive HSTS header
 rewardstock.com: max-age too low: 0
 rewrite3.com: could not connect to host
 rgavmf.ru: did not receive HSTS header
 rhapsodhy.hu: could not connect to host
 rhdigital.pro: could not connect to host
@@ -2709,17 +2728,16 @@ ring0.xyz: did not receive HSTS header
 ringh.am: could not connect to host
 ringingliberty.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 121"  data: no]
 rippleunion.com: could not connect to host
 riskmgt.com.au: could not connect to host
 rj.gg: could not connect to host
 rk6.cz: could not connect to host
 rkmantpur.org: did not receive HSTS header
 rme.li: did not receive HSTS header
-rmf.io: could not connect to host
 roan24.pl: did not receive HSTS header
 robertglastra.com: could not connect to host
 robigalia.org: did not receive HSTS header
 robin.info: could not connect to host
 rochman.id: could not connect to host
 rocketmill.co.uk: max-age too low: 0
 rocksberg.net: did not receive HSTS header
 roddis.net: did not receive HSTS header
@@ -2811,23 +2829,23 @@ scooshonline.co.uk: did not receive HSTS
 scotbirchfield.com: did not receive HSTS header
 scrambl.is: could not connect to host
 scrambler.in: could not connect to host
 scrapings.net: could not connect to host
 screenresolution.space: could not connect to host
 scribe.systems: could not connect to host
 script.google.com: did not receive HSTS header (error ignored - included regardless)
 scriptict.nl: could not connect to host
-scrumstack.co.uk: could not connect to host
 sdmoscow.ru: could not connect to host
 sdrobs.com: did not receive HSTS header
 sdsl-speedtest.de: could not connect to host
 search-one.de: did not receive HSTS header
 sebster.com: did not receive HSTS header
 secandtech.com: could not connect to host
+secpatrol.de: could not connect to host
 sectia22.ro: could not connect to host
 secure-games.us: could not connect to host
 secureradio.net: could not connect to host
 securesuisse.ch: could not connect to host
 security.google.com: did not receive HSTS header (error ignored - included regardless)
 securityinet.biz: did not receive HSTS header
 securityinet.net: did not receive HSTS header
 securityinet.org.il: did not receive HSTS header
@@ -2939,20 +2957,21 @@ slix.io: could not connect to host
 slope.haus: could not connect to host
 slovakiana.sk: did not receive HSTS header
 sluitkampzeist.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 121"  data: no]
 slycurity.de: did not receive HSTS header
 smart-mirror.de: did not receive HSTS header
 smart-ov.nl: could not connect to host
 smartcoin.com.br: could not connect to host
 smartofficesandsmarthomes.com: did not receive HSTS header
+smartrak.co.nz: did not receive HSTS header
 smatch.com: did not receive HSTS header
 smet.us: could not connect to host
 smirkingwhorefromhighgarden.pro: could not connect to host
-smith.is: did not receive HSTS header
+smith.is: could not connect to host
 smkn1lengkong.sch.id: did not receive HSTS header
 smksi2.com: max-age too low: 0
 smusg.com: did not receive HSTS header
 snailing.org: could not connect to host
 snapappointments.com: did not receive HSTS header
 snapappts.com: could not connect to host
 snapworks.net: did not receive HSTS header
 sneberger.cz: [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 121"  data: no]
@@ -2967,31 +2986,29 @@ soccergif.com: could not connect to host
 soci.ml: did not receive HSTS header
 socialbillboard.com: could not connect to host
 socialdevelop.biz: did not receive HSTS header
 socialhams.net: did not receive HSTS header
 socialhead.io: could not connect to host
 socialspirit.com.br: did not receive HSTS header
 sockeye.cc: could not connect to host
 socomponents.co.uk: did not receive HSTS header
-sogeek.me: did not receive HSTS header
 solidfuelappliancespares.co.uk: did not receive HSTS header
 solinter.com.br: did not receive HSTS header
 soll-i.ch: did not receive HSTS header
 solsystems.ru: could not connect to host
 someshit.xyz: could not connect to host
 somethingnew.xyz: did not receive HSTS header
 songzhuolun.com: did not receive HSTS header
 sonic.sk: max-age too low: 0
 sotar.us: [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 121"  data: no]
 sotor.de: did not receive HSTS header
 soulboy.io: did not receive HSTS header
-soulema.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 121"  data: no]
+soulema.com: could not connect to host
 soulfulglamour.uk: could not connect to host
-soundhunter.xyz: could not connect to host
 sourcelair.com: did not receive HSTS header
 southside-crew.club: could not connect to host
 southworcestershiregpservices.co.uk: could not connect to host
 souyar.de: could not connect to host
 souyar.net: could not connect to host
 souyar.us: could not connect to host
 sovereignshare.com: could not connect to host
 sown.dyndns.org: could not connect to host
@@ -3003,17 +3020,17 @@ spartantheatre.org: max-age too low: 172
 spauted.com: could not connect to host
 spdysync.com: could not connect to host
 speculor.net: could not connect to host
 speed-mailer.com: could not connect to host
 speedcounter.net: did not receive HSTS header
 speedmann.de: could not connect to host
 speedtest-russia.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 121"  data: no]
 speidel.com.tr: did not receive HSTS header
-spencerbaer.com: could not connect to host
+spencerbaer.com: did not receive HSTS header
 sperohub.io: could not connect to host
 spherenix.org: could not connect to host
 spideroak.com: did not receive HSTS header
 spiegels.nl: could not connect to host
 spilsbury.io: could not connect to host
 spitefultowel.com: could not connect to host
 spongepowered.org: did not receive HSTS header
 sportwette.eu: did not receive HSTS header
@@ -3021,17 +3038,17 @@ spot-events.com: could not connect to ho
 spotlightsrule.ddns.net: could not connect to host
 spreadsheets.google.com: did not receive HSTS header (error ignored - included regardless)
 spreed.me: did not receive HSTS header
 spritchard.photos: max-age too low: 0
 sproutconnections.com: did not receive HSTS header
 sprybear.com: did not receive HSTS header
 square.gs: could not connect to host
 squatldf.org: [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 121"  data: no]
-sqzryang.com: could not connect to host
+sqzryang.com: max-age too low: 604800
 srevilak.net: did not receive HSTS header
 srna.sk: could not connect to host
 srrr.ca: could not connect to host
 ss.wtf: did not receive HSTS header
 ssersay.com: did not receive HSTS header
 ssl.panoramio.com: did not receive HSTS header
 ssl.rip: could not connect to host
 sslhosting.cz: could not connect to host
@@ -3050,17 +3067,17 @@ stefany.eu: could not connect to host
 stephanierxo.com: did not receive HSTS header
 stephenandburns.com: did not receive HSTS header
 stevensononthe.net: did not receive HSTS header
 stewartremodelingadvantage.com: could not connect to host
 stick2bike.de: did not receive HSTS header
 stig.io: did not receive HSTS header
 stigroom.com: could not connect to host
 stirlingpoon.xyz: could not connect to host
-stkbn.com: did not receive HSTS header
+stkbn.com: could not connect to host
 stmbgr.com: could not connect to host
 stn.me.uk: did not receive HSTS header
 stnl.de: could not connect to host
 stocktrade.de: could not connect to host
 stoffe-monster.de: did not receive HSTS header
 stopwoodfin.org: could not connect to host
 storecove.com: did not receive HSTS header
 storeden.com: did not receive HSTS header
@@ -3089,16 +3106,17 @@ subdimension.org: could not connect to h
 subtitle.rip: could not connect to host
 sudo.im: could not connect to host
 sudo.li: did not receive HSTS header
 suite73.org: could not connect to host
 suksit.com: could not connect to host
 sumoatm.com: did not receive HSTS header
 sumoscout.de: did not receive HSTS header
 suncountrymarine.com: did not receive HSTS header
+sunflyer.cn: did not receive HSTS header
 sunshinepress.org: could not connect to host
 superbabysitting.ch: could not connect to host
 supereight.net: did not receive HSTS header
 superiorfloridavacation.com: did not receive HSTS header
 supersalescontest.nl: did not receive HSTS header
 superwally.org: could not connect to host
 suprlink.net: could not connect to host
 supweb.ovh: did not receive HSTS header
@@ -3167,16 +3185,18 @@ techhub.ml: could not connect to host
 techllage.com: could not connect to host
 techloaner.com: could not connect to host
 techmatehq.com: could not connect to host
 technosavvyport.com: did not receive HSTS header
 techpointed.com: could not connect to host
 techvalue.gr: did not receive HSTS header
 tegelsensanitaironline.nl: did not receive HSTS header
 tekshrek.com: max-age too low: 0
+telefonnummer.online: could not connect to host
+telefoonnummerinfo.nl: could not connect to host
 temehu.com: did not receive HSTS header
 tempcraft.net: could not connect to host
 tendertool.nl: could not connect to host
 tenni.xyz: could not connect to host
 tensionup.com: could not connect to host
 terrax.berlin: could not connect to host
 terrax.info: could not connect to host
 testandroid.xyz: could not connect to host
@@ -3218,16 +3238,17 @@ thestack.xyz: could not connect to host
 thestagchorleywood.co.uk: did not receive HSTS header
 thetomharling.com: max-age too low: 86400
 theurbanyoga.com: did not receive HSTS header
 thevintagenews.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 121"  data: no]
 thezonders.com: did not receive HSTS header
 thierfreund.de: could not connect to host
 thierryhayoz.ch: could not connect to host
 thijsalders.nl: max-age too low: 300
+thinkcash.nl: could not connect to host
 thinkcoding.de: could not connect to host
 thinlyveiledcontempt.com: could not connect to host
 thirdpartytrade.com: did not receive HSTS header
 thirty5.net: did not receive HSTS header
 thomaswoo.com: could not connect to host
 thorncreek.net: did not receive HSTS header
 thriveapproach.co.uk: did not receive HSTS header
 thumbtack.com: did not receive HSTS header
@@ -3254,33 +3275,33 @@ tkarstens.de: did not receive HSTS heade
 tlo.hosting: could not connect to host
 tlo.network: could not connect to host
 tls.li: could not connect to host
 tm-solutions.eu: could not connect to host
 tmitchell.io: could not connect to host
 tmprod.com: did not receive HSTS header
 tncnanet.com.br: could not connect to host
 tnrsca.jp: did not receive HSTS header
-toast.al: could not connect to host
 tobiasmathes.com: could not connect to host
 tobiasmathes.name: could not connect to host
 tobiasofficial.at: could not connect to host
 todo.is: did not receive HSTS header
 todobazar.es: could not connect to host
 tokyopopline.com: did not receive HSTS header
 tollmanz.com: did not receive HSTS header
 tomeara.net: could not connect to host
 tomharling.co.uk: max-age too low: 86400
 tomharling.uk: max-age too low: 86400
 tomlankhorst.nl: did not receive HSTS header
 tommsy.com: did not receive HSTS header
 tonburi.jp: [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 121"  data: no]
 tonyfantjr.com: could not connect to host
 toomanypillows.com: could not connect to host
 tooolroc.org: could not connect to host
+tooti.biz: could not connect to host
 topbargains.com.au: did not receive HSTS header
 topmarine.se: could not connect to host
 topnewstoday.org: could not connect to host
 topshelfguild.com: could not connect to host
 topyx.com: did not receive HSTS header
 torahanytime.com: did not receive HSTS header
 torprojects.com: could not connect to host
 tosecure.link: could not connect to host
@@ -3294,25 +3315,26 @@ tpe-edu.com: could not connect to host
 track.plus: could not connect to host
 tracktivity.com.au: did not receive HSTS header
 tradingcentre.com.au: did not receive HSTS header
 tradinghope.com: could not connect to host
 traeningsprojekt.dk: did not receive HSTS header
 translate.googleapis.com: did not receive HSTS header (error ignored - included regardless)
 transportal.sk: did not receive HSTS header
 trendberry.ru: did not receive HSTS header
+trik.es: [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 121"  data: no]
 trinityaffirmations.com: max-age too low: 0
 trinitycore.org: max-age too low: 2592000
 tripdelta.com: did not receive HSTS header
 trixies-wish.nz: could not connect to host
 trusitio.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 121"  data: no]
 trustmeimfancy.com: could not connect to host
 trybind.com: could not connect to host
 ts2.se: did not receive HSTS header
-tsecy.com: could not connect to host
+tsecy.com: did not receive HSTS header
 tsgoc.com: did not receive HSTS header
 tssouthernpower.com: max-age too low: 0
 tuingereedschappen.net: could not connect to host
 tuningblog.eu: did not receive HSTS header
 turnik-67.ru: could not connect to host
 tuturulianda.com: could not connect to host
 tuvalie.com: could not connect to host
 tuxcall.de: could not connect to host
@@ -3365,18 +3387,18 @@ unicooo.com: could not connect to host
 unison.com: could not connect to host
 unitedcyberdevelopment.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 121"  data: no]
 unitel2000.de: could not connect to host
 university4industry.com: did not receive HSTS header
 universogay.com: did not receive HSTS header
 univz.com: could not connect to host
 unknownphenomena.net: could not connect to host
 unravel.ie: did not receive HSTS header
+unsystem.net: could not connect to host
 unterschicht.tv: could not connect to host
-unun.fi: could not connect to host
 unwiredbrain.com: could not connect to host
 uonstaffhub.com: could not connect to host
 uow.ninja: could not connect to host
 upaknship.com: did not receive HSTS header
 upani.net: could not connect to host
 upldr.pw: could not connect to host
 upr.com.ua: could not connect to host
 uprotect.it: could not connect to host
@@ -3408,17 +3430,17 @@ vanestack.com: could not connect to host
 vanetv.com: could not connect to host
 vanitas.xyz: could not connect to host
 vanitynailworkz.com: could not connect to host
 vansieleghem.com: could not connect to host
 vasanth.org: did not receive HSTS header
 vbh2o.com: did not receive HSTS header
 vbulletin-russia.com: could not connect to host
 vbulletinrussia.com: could not connect to host
-vcdove.com: did not receive HSTS header
+vcdove.com: could not connect to host
 vcr.re: could not connect to host
 vdcomp.cz: could not connect to host
 veblen.com: could not connect to host
 vechkasov.ru: did not receive HSTS header
 vemokin.net: did not receive HSTS header
 verifikatorindonesia.com: could not connect to host
 vermontcareergateway.org: could not connect to host
 versia.ru: did not receive HSTS header
@@ -3434,37 +3456,38 @@ vieaw.com: could not connect to host
 viktorsvantesson.net: did not receive HSTS header
 vincentkooijman.at: did not receive HSTS header
 vincentkooijman.nl: did not receive HSTS header
 vintageheartcoffee.com: did not receive HSTS header
 vio.no: did not receive HSTS header
 viperdns.com: could not connect to host
 vipmusic.ga: could not connect to host
 vipnettikasinoklubi.com: could not connect to host
+vispaleistexel.nl: could not connect to host
 vissanum.com: did not receive HSTS header
 vistarait.com: did not receive HSTS header
 viva-french.com: did not receive HSTS header
 vlora.city: could not connect to host
 vm0.eu: did not receive HSTS header
 vmrdev.com: could not connect to host
 voceinveste.com: did not receive HSTS header
 voicesuk.co.uk: did not receive HSTS header
 volcrado.com: could not connect to host
 voliere-info.nl: did not receive HSTS header
 vortexhobbies.com: did not receive HSTS header
 votocek.cz: [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 121"  data: no]
-votockova.cz: [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 121"  data: no]
+votockova.cz: could not connect to host
 vox.vg: did not receive HSTS header
 vpl.me: did not receive HSTS header
 vpn-byen.dk: did not receive HSTS header
 vratny.space: could not connect to host
 vvl.me: did not receive HSTS header
 vxstream-sandbox.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 121"  data: no]
 vyncke.org: max-age too low: 2678400
-vyskocil.eu: did not receive HSTS header
+vyskocil.eu: could not connect to host
 vzk.io: could not connect to host
 w4a.fr: max-age too low: 0
 w4xzr.top: could not connect to host
 w4xzr.xyz: could not connect to host
 wait.jp: could not connect to host
 wait.moe: could not connect to host
 wakapp.de: could not connect to host
 walkeryoung.ca: could not connect to host
@@ -3576,16 +3599,17 @@ womosale.de: could not connect to host
 wonderfall.xyz: could not connect to host
 woording.com: could not connect to host
 woresite.jp: did not receive HSTS header
 workfone.io: did not receive HSTS header
 workwithgo.com: could not connect to host
 wowapi.org: could not connect to host
 wphostingspot.com: did not receive HSTS header
 wpmetadatastandardsproject.org: could not connect to host
+wql.zj.cn: [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 121"  data: no]
 writeapp.me: did not receive HSTS header
 wscales.com: could not connect to host
 wsscompany.com.ve: could not connect to host
 wufu.org: could not connect to host
 wuhengmin.com: did not receive HSTS header
 wurzelzwerg.net: could not connect to host
 www.apollo-auto.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 121"  data: no]
 www.braintreepayments.com: did not receive HSTS header
@@ -3607,17 +3631,16 @@ www.moneybookers.com: did not receive HS
 www.neonisi.com: could not connect to host
 www.paycheckrecords.com: did not receive HSTS header
 www.rme.li: did not receive HSTS header
 www.sandbox.mydigipass.com: could not connect to host
 www.surfeasy.com: did not receive HSTS header
 www.zenpayroll.com: did not receive HSTS header
 www3.info: did not receive HSTS header
 wxukang.cn: could not connect to host
-x.st: could not connect to host
 x2w.io: could not connect to host
 xa.search.yahoo.com: did not receive HSTS header
 xandocs.com: could not connect to host
 xatr0z.org: could not connect to host
 xavierbarroso.com: could not connect to host
 xcoop.me: could not connect to host
 xellos.ga: could not connect to host
 xellos.ml: could not connect to host
@@ -3625,16 +3648,17 @@ xenesisziarovky.sk: could not connect to
 xett.com: did not receive HSTS header
 xf-liam.com: could not connect to host
 xfive.de: did not receive HSTS header
 xiaody.me: could not connect to host
 xiaolvmu.me: could not connect to host
 xiaoxiao.im: did not receive HSTS header
 xisa.it: could not connect to host
 xiyu.moe: could not connect to host
+xmerak.com: could not connect to host
 xmr.my: could not connect to host
 xn--4dbjwf8c.cf: could not connect to host
 xn--4dbjwf8c.ga: could not connect to host
 xn--4dbjwf8c.gq: could not connect to host
 xn--4dbjwf8c.tk: could not connect to host
 xn--79q87uvkclvgd56ahq5a.net: did not receive HSTS header
 xn--7rvz7ku3ppnr.jp: did not receive HSTS header
 xn--9pr52k0p5a.com: did not receive HSTS header
@@ -3695,17 +3719,17 @@ yukontec.com: [Exception... "Component r
 yunzhu.li: did not receive HSTS header
 yunzhu.org: could not connect to host
 yzal.io: could not connect to host
 z33.ch: did not receive HSTS header
 z3liff.com: could not connect to host
 z3liff.net: could not connect to host
 za.search.yahoo.com: did not receive HSTS header
 zadieheimlich.com: did not receive HSTS header
-zamorano.edu: could not connect to host
+zamorano.edu: did not receive HSTS header
 zap.yt: could not connect to host
 zarooba.com: did not receive HSTS header
 zary.me: could not connect to host
 zbasenem.pl: did not receive HSTS header
 zbigniewgalucki.eu: did not receive HSTS header
 zbp.at: did not receive HSTS header
 zebrababy.cn: did not receive HSTS header
 zefu.ca: could not connect to host
@@ -3732,11 +3756,12 @@ zoneminder.com: did not receive HSTS hea
 zoo24.de: did not receive HSTS header
 zoomingin.net: max-age too low: 2592000
 zoznamrealit.sk: did not receive HSTS header
 zqhong.com: could not connect to host
 zrn.in: did not receive HSTS header
 zscales.com: could not connect to host
 ztan.tk: could not connect to host
 zten.org: could not connect to host
+zuolan.me: could not connect to host
 zvncloud.com: did not receive HSTS header
 zwy.me: did not receive HSTS header
 zyf.pw: could not connect to host
--- a/security/manager/ssl/nsSTSPreloadList.inc
+++ b/security/manager/ssl/nsSTSPreloadList.inc
@@ -3,17 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /*****************************************************************************/
 /* This is an automatically generated file. If you're not                    */
 /* nsSiteSecurityService.cpp, you shouldn't be #including it.     */
 /*****************************************************************************/
 
 #include <stdint.h>
-const PRTime gPreloadListExpirationTime = INT64_C(1489501548062000);
+const PRTime gPreloadListExpirationTime = INT64_C(1489587554100000);
 
 static const char kSTSHostTable[] = {
   /* "007sascha.de", true */ '0', '0', '7', 's', 'a', 's', 'c', 'h', 'a', '.', 'd', 'e', '\0',
   /* "00f.net", true */ '0', '0', 'f', '.', 'n', 'e', 't', '\0',
   /* "01electronica.com.ar", true */ '0', '1', 'e', 'l', 'e', 'c', 't', 'r', 'o', 'n', 'i', 'c', 'a', '.', 'c', 'o', 'm', '.', 'a', 'r', '\0',
   /* "01seguridad.com.ar", true */ '0', '1', 's', 'e', 'g', 'u', 'r', 'i', 'd', 'a', 'd', '.', 'c', 'o', 'm', '.', 'a', 'r', '\0',
   /* "050media.nl", true */ '0', '5', '0', 'm', 'e', 'd', 'i', 'a', '.', 'n', 'l', '\0',
   /* "0513c.com", true */ '0', '5', '1', '3', 'c', '.', 'c', 'o', 'm', '\0',
@@ -475,16 +475,17 @@ static const char kSTSHostTable[] = {
   /* "algolia.com", true */ 'a', 'l', 'g', 'o', 'l', 'i', 'a', '.', 'c', 'o', 'm', '\0',
   /* "alicestudio.it", true */ 'a', 'l', 'i', 'c', 'e', 's', 't', 'u', 'd', 'i', 'o', '.', 'i', 't', '\0',
   /* "alienstat.com", true */ 'a', 'l', 'i', 'e', 'n', 's', 't', 'a', 't', '.', 'c', 'o', 'm', '\0',
   /* "alinasmusicstudio.com", true */ 'a', 'l', 'i', 'n', 'a', 's', 'm', 'u', 's', 'i', 'c', 's', 't', 'u', 'd', 'i', 'o', '.', 'c', 'o', 'm', '\0',
   /* "alisonlitchfield.com", true */ 'a', 'l', 'i', 's', 'o', 'n', 'l', 'i', 't', 'c', 'h', 'f', 'i', 'e', 'l', 'd', '.', 'c', 'o', 'm', '\0',
   /* "alittlebitcheeky.com", false */ 'a', 'l', 'i', 't', 't', 'l', 'e', 'b', 'i', 't', 'c', 'h', 'e', 'e', 'k', 'y', '.', 'c', 'o', 'm', '\0',
   /* "aljaspod.com", true */ 'a', 'l', 'j', 'a', 's', 'p', 'o', 'd', '.', 'c', 'o', 'm', '\0',
   /* "aljaspod.hu", true */ 'a', 'l', 'j', 'a', 's', 'p', 'o', 'd', '.', 'h', 'u', '\0',
+  /* "aljaspod.net", true */ 'a', 'l', 'j', 'a', 's', 'p', 'o', 'd', '.', 'n', 'e', 't', '\0',
   /* "alkamitech.com", true */ 'a', 'l', 'k', 'a', 'm', 'i', 't', 'e', 'c', 'h', '.', 'c', 'o', 'm', '\0',
   /* "alkel.info", true */ 'a', 'l', 'k', 'e', 'l', '.', 'i', 'n', 'f', 'o', '\0',
   /* "all-connect.net", true */ 'a', 'l', 'l', '-', 'c', 'o', 'n', 'n', 'e', 'c', 't', '.', 'n', 'e', 't', '\0',
   /* "all.tf", false */ 'a', 'l', 'l', '.', 't', 'f', '\0',
   /* "all4os.com", true */ 'a', 'l', 'l', '4', 'o', 's', '.', 'c', 'o', 'm', '\0',
   /* "allabout.me", true */ 'a', 'l', 'l', 'a', 'b', 'o', 'u', 't', '.', 'm', 'e', '\0',
   /* "allbenjoy.de", true */ 'a', 'l', 'l', 'b', 'e', 'n', 'j', 'o', 'y', '.', 'd', 'e', '\0',
   /* "allcarepharmacy.com", true */ 'a', 'l', 'l', 'c', 'a', 'r', 'e', 'p', 'h', 'a', 'r', 'm', 'a', 'c', 'y', '.', 'c', 'o', 'm', '\0',
@@ -511,18 +512,18 @@ static const char kSTSHostTable[] = {
   /* "alphachat.net", true */ 'a', 'l', 'p', 'h', 'a', 'c', 'h', 'a', 't', '.', 'n', 'e', 't', '\0',
   /* "alphagamers.net", true */ 'a', 'l', 'p', 'h', 'a', 'g', 'a', 'm', 'e', 'r', 's', '.', 'n', 'e', 't', '\0',
   /* "alphassl.de", true */ 'a', 'l', 'p', 'h', 'a', 's', 's', 'l', '.', 'd', 'e', '\0',
   /* "alphatrash.de", true */ 'a', 'l', 'p', 'h', 'a', 't', 'r', 'a', 's', 'h', '.', 'd', 'e', '\0',
   /* "alspolska.pl", true */ 'a', 'l', 's', 'p', 'o', 'l', 's', 'k', 'a', '.', 'p', 'l', '\0',
   /* "alt-three.com", true */ 'a', 'l', 't', '-', 't', 'h', 'r', 'e', 'e', '.', 'c', 'o', 'm', '\0',
   /* "alt.org", true */ 'a', 'l', 't', '.', 'o', 'r', 'g', '\0',
   /* "altedirect.com", true */ 'a', 'l', 't', 'e', 'd', 'i', 'r', 'e', 'c', 't', '.', 'c', 'o', 'm', '\0',
-  /* "alterbaum.net", true */ 'a', 'l', 't', 'e', 'r', 'b', 'a', 'u', 'm', '.', 'n', 'e', 't', '\0',
   /* "alternativet.party", true */ 'a', 'l', 't', 'e', 'r', 'n', 'a', 't', 'i', 'v', 'e', 't', '.', 'p', 'a', 'r', 't', 'y', '\0',
+  /* "altesses.eu", true */ 'a', 'l', 't', 'e', 's', 's', 'e', 's', '.', 'e', 'u', '\0',
   /* "altestore.com", true */ 'a', 'l', 't', 'e', 's', 't', 'o', 'r', 'e', '.', 'c', 'o', 'm', '\0',
   /* "altonblom.com", true */ 'a', 'l', 't', 'o', 'n', 'b', 'l', 'o', 'm', '.', 'c', 'o', 'm', '\0',
   /* "altopia.com", true */ 'a', 'l', 't', 'o', 'p', 'i', 'a', '.', 'c', 'o', 'm', '\0',
   /* "aluroof.eu", true */ 'a', 'l', 'u', 'r', 'o', 'o', 'f', '.', 'e', 'u', '\0',
   /* "alvicom.hu", true */ 'a', 'l', 'v', 'i', 'c', 'o', 'm', '.', 'h', 'u', '\0',
   /* "alwaysmine.fi", true */ 'a', 'l', 'w', 'a', 'y', 's', 'm', 'i', 'n', 'e', '.', 'f', 'i', '\0',
   /* "alza.at", true */ 'a', 'l', 'z', 'a', '.', 'a', 't', '\0',
   /* "alza.co.uk", true */ 'a', 'l', 'z', 'a', '.', 'c', 'o', '.', 'u', 'k', '\0',
@@ -764,17 +765,16 @@ static const char kSTSHostTable[] = {
   /* "armor.com", true */ 'a', 'r', 'm', 'o', 'r', '.', 'c', 'o', 'm', '\0',
   /* "armored.ninja", true */ 'a', 'r', 'm', 'o', 'r', 'e', 'd', '.', 'n', 'i', 'n', 'j', 'a', '\0',
   /* "armstrongsengineering.com", true */ 'a', 'r', 'm', 's', 't', 'r', 'o', 'n', 'g', 's', 'e', 'n', 'g', 'i', 'n', 'e', 'e', 'r', 'i', 'n', 'g', '.', 'c', 'o', 'm', '\0',
   /* "army24.cz", true */ 'a', 'r', 'm', 'y', '2', '4', '.', 'c', 'z', '\0',
   /* "armyprodej.cz", true */ 'a', 'r', 'm', 'y', 'p', 'r', 'o', 'd', 'e', 'j', '.', 'c', 'z', '\0',
   /* "arnaudfeld.de", true */ 'a', 'r', 'n', 'a', 'u', 'd', 'f', 'e', 'l', 'd', '.', 'd', 'e', '\0',
   /* "arne-petersen.net", true */ 'a', 'r', 'n', 'e', '-', 'p', 'e', 't', 'e', 'r', 's', 'e', 'n', '.', 'n', 'e', 't', '\0',
   /* "arnesolutions.com", true */ 'a', 'r', 'n', 'e', 's', 'o', 'l', 'u', 't', 'i', 'o', 'n', 's', '.', 'c', 'o', 'm', '\0',
-  /* "arnetdigital.eu", true */ 'a', 'r', 'n', 'e', 't', 'd', 'i', 'g', 'i', 't', 'a', 'l', '.', 'e', 'u', '\0',
   /* "arnor.org", true */ 'a', 'r', 'n', 'o', 'r', '.', 'o', 'r', 'g', '\0',
   /* "arokha.com", true */ 'a', 'r', 'o', 'k', 'h', 'a', '.', 'c', 'o', 'm', '\0',
   /* "aroonchande.com", true */ 'a', 'r', 'o', 'o', 'n', 'c', 'h', 'a', 'n', 'd', 'e', '.', 'c', 'o', 'm', '\0',
   /* "arpa.ph", true */ 'a', 'r', 'p', 'a', '.', 'p', 'h', '\0',
   /* "arpr.co", true */ 'a', 'r', 'p', 'r', '.', 'c', 'o', '\0',
   /* "arrakis.se", true */ 'a', 'r', 'r', 'a', 'k', 'i', 's', '.', 's', 'e', '\0',
   /* "arrive.by", true */ 'a', 'r', 'r', 'i', 'v', 'e', '.', 'b', 'y', '\0',
   /* "arrmaforum.com", true */ 'a', 'r', 'r', 'm', 'a', 'f', 'o', 'r', 'u', 'm', '.', 'c', 'o', 'm', '\0',
@@ -914,17 +914,16 @@ static const char kSTSHostTable[] = {
   /* "authint.com", true */ 'a', 'u', 't', 'h', 'i', 'n', 't', '.', 'c', 'o', 'm', '\0',
   /* "author24.ru", true */ 'a', 'u', 't', 'h', 'o', 'r', '2', '4', '.', 'r', 'u', '\0',
   /* "authoritynutrition.com", true */ 'a', 'u', 't', 'h', 'o', 'r', 'i', 't', 'y', 'n', 'u', 't', 'r', 'i', 't', 'i', 'o', 'n', '.', 'c', 'o', 'm', '\0',
   /* "autimatisering.nl", true */ 'a', 'u', 't', 'i', 'm', 'a', 't', 'i', 's', 'e', 'r', 'i', 'n', 'g', '.', 'n', 'l', '\0',
   /* "auto-anleitung.de", true */ 'a', 'u', 't', 'o', '-', 'a', 'n', 'l', 'e', 'i', 't', 'u', 'n', 'g', '.', 'd', 'e', '\0',
   /* "autoauctionsohio.com", true */ 'a', 'u', 't', 'o', 'a', 'u', 'c', 't', 'i', 'o', 'n', 's', 'o', 'h', 'i', 'o', '.', 'c', 'o', 'm', '\0',
   /* "autoauctionsvirginia.com", true */ 'a', 'u', 't', 'o', 'a', 'u', 'c', 't', 'i', 'o', 'n', 's', 'v', 'i', 'r', 'g', 'i', 'n', 'i', 'a', '.', 'c', 'o', 'm', '\0',
   /* "autodeploy.it", true */ 'a', 'u', 't', 'o', 'd', 'e', 'p', 'l', 'o', 'y', '.', 'i', 't', '\0',
-  /* "autojuhos.sk", true */ 'a', 'u', 't', 'o', 'j', 'u', 'h', 'o', 's', '.', 's', 'k', '\0',
   /* "autoledky.sk", true */ 'a', 'u', 't', 'o', 'l', 'e', 'd', 'k', 'y', '.', 's', 'k', '\0',
   /* "auxetek.se", true */ 'a', 'u', 'x', 'e', 't', 'e', 'k', '.', 's', 'e', '\0',
   /* "auxiliumincrementum.co.uk", true */ 'a', 'u', 'x', 'i', 'l', 'i', 'u', 'm', 'i', 'n', 'c', 'r', 'e', 'm', 'e', 'n', 't', 'u', 'm', '.', 'c', 'o', '.', 'u', 'k', '\0',
   /* "ava-creative.de", true */ 'a', 'v', 'a', '-', 'c', 'r', 'e', 'a', 't', 'i', 'v', 'e', '.', 'd', 'e', '\0',
   /* "avaaz.org", true */ 'a', 'v', 'a', 'a', 'z', '.', 'o', 'r', 'g', '\0',
   /* "avacariu.me", true */ 'a', 'v', 'a', 'c', 'a', 'r', 'i', 'u', '.', 'm', 'e', '\0',
   /* "avalon-island.ru", true */ 'a', 'v', 'a', 'l', 'o', 'n', '-', 'i', 's', 'l', 'a', 'n', 'd', '.', 'r', 'u', '\0',
   /* "avanovum.de", true */ 'a', 'v', 'a', 'n', 'o', 'v', 'u', 'm', '.', 'd', 'e', '\0',
@@ -1097,17 +1096,16 @@ static const char kSTSHostTable[] = {
   /* "bc-bd.org", true */ 'b', 'c', '-', 'b', 'd', '.', 'o', 'r', 'g', '\0',
   /* "bcchack.com", true */ 'b', 'c', 'c', 'h', 'a', 'c', 'k', '.', 'c', 'o', 'm', '\0',
   /* "bcdonadio.com", true */ 'b', 'c', 'd', 'o', 'n', 'a', 'd', 'i', 'o', '.', 'c', 'o', 'm', '\0',
   /* "bcheng.cf", true */ 'b', 'c', 'h', 'e', 'n', 'g', '.', 'c', 'f', '\0',
   /* "bchep.com", true */ 'b', 'c', 'h', 'e', 'p', '.', 'c', 'o', 'm', '\0',
   /* "bcmlu.org", true */ 'b', 'c', 'm', 'l', 'u', '.', 'o', 'r', 'g', '\0',
   /* "bcrook.com", false */ 'b', 'c', 'r', 'o', 'o', 'k', '.', 'c', 'o', 'm', '\0',
   /* "bcswampcabins.com", true */ 'b', 'c', 's', 'w', 'a', 'm', 'p', 'c', 'a', 'b', 'i', 'n', 's', '.', 'c', 'o', 'm', '\0',
-  /* "bcvps.com", true */ 'b', 'c', 'v', 'p', 's', '.', 'c', 'o', 'm', '\0',
   /* "bcweightlifting.ca", true */ 'b', 'c', 'w', 'e', 'i', 'g', 'h', 't', 'l', 'i', 'f', 't', 'i', 'n', 'g', '.', 'c', 'a', '\0',
   /* "bddemir.com", true */ 'b', 'd', 'd', 'e', 'm', 'i', 'r', '.', 'c', 'o', 'm', '\0',
   /* "bdikaros-network.net", true */ 'b', 'd', 'i', 'k', 'a', 'r', 'o', 's', '-', 'n', 'e', 't', 'w', 'o', 'r', 'k', '.', 'n', 'e', 't', '\0',
   /* "be-real.life", true */ 'b', 'e', '-', 'r', 'e', 'a', 'l', '.', 'l', 'i', 'f', 'e', '\0',
   /* "beamitapp.com", true */ 'b', 'e', 'a', 'm', 'i', 't', 'a', 'p', 'p', '.', 'c', 'o', 'm', '\0',
   /* "beanjuice.me", true */ 'b', 'e', 'a', 'n', 'j', 'u', 'i', 'c', 'e', '.', 'm', 'e', '\0',
   /* "beans-one.com", false */ 'b', 'e', 'a', 'n', 's', '-', 'o', 'n', 'e', '.', 'c', 'o', 'm', '\0',
   /* "beardydave.com", false */ 'b', 'e', 'a', 'r', 'd', 'y', 'd', 'a', 'v', 'e', '.', 'c', 'o', 'm', '\0',
@@ -1211,17 +1209,16 @@ static const char kSTSHostTable[] = {
   /* "betaworx.eu", true */ 'b', 'e', 't', 'a', 'w', 'o', 'r', 'x', '.', 'e', 'u', '\0',
   /* "betcafearena.ro", false */ 'b', 'e', 't', 'c', 'a', 'f', 'e', 'a', 'r', 'e', 'n', 'a', '.', 'r', 'o', '\0',
   /* "betlander.com", true */ 'b', 'e', 't', 'l', 'a', 'n', 'd', 'e', 'r', '.', 'c', 'o', 'm', '\0',
   /* "betonmoney.com", true */ 'b', 'e', 't', 'o', 'n', 'm', 'o', 'n', 'e', 'y', '.', 'c', 'o', 'm', '\0',
   /* "betpamm.com", true */ 'b', 'e', 't', 'p', 'a', 'm', 'm', '.', 'c', 'o', 'm', '\0',
   /* "betterbabyshop.com.au", true */ 'b', 'e', 't', 't', 'e', 'r', 'b', 'a', 'b', 'y', 's', 'h', 'o', 'p', '.', 'c', 'o', 'm', '.', 'a', 'u', '\0',
   /* "bettercrypto.org", true */ 'b', 'e', 't', 't', 'e', 'r', 'c', 'r', 'y', 'p', 't', 'o', '.', 'o', 'r', 'g', '\0',
   /* "betterhelp.com", true */ 'b', 'e', 't', 't', 'e', 'r', 'h', 'e', 'l', 'p', '.', 'c', 'o', 'm', '\0',
-  /* "betterlifemakers.com", true */ 'b', 'e', 't', 't', 'e', 'r', 'l', 'i', 'f', 'e', 'm', 'a', 'k', 'e', 'r', 's', '.', 'c', 'o', 'm', '\0',
   /* "bettertest.it", true */ 'b', 'e', 't', 't', 'e', 'r', 't', 'e', 's', 't', '.', 'i', 't', '\0',
   /* "bettingbusiness.ru", true */ 'b', 'e', 't', 't', 'i', 'n', 'g', 'b', 'u', 's', 'i', 'n', 'e', 's', 's', '.', 'r', 'u', '\0',
   /* "bettrlifeapp.com", true */ 'b', 'e', 't', 't', 'r', 'l', 'i', 'f', 'e', 'a', 'p', 'p', '.', 'c', 'o', 'm', '\0',
   /* "betulashop.ch", true */ 'b', 'e', 't', 'u', 'l', 'a', 's', 'h', 'o', 'p', '.', 'c', 'h', '\0',
   /* "beulahtabernacle.com", true */ 'b', 'e', 'u', 'l', 'a', 'h', 't', 'a', 'b', 'e', 'r', 'n', 'a', 'c', 'l', 'e', '.', 'c', 'o', 'm', '\0',
   /* "bevinco2020.com", true */ 'b', 'e', 'v', 'i', 'n', 'c', 'o', '2', '0', '2', '0', '.', 'c', 'o', 'm', '\0',
   /* "bevinsco.org", true */ 'b', 'e', 'v', 'i', 'n', 's', 'c', 'o', '.', 'o', 'r', 'g', '\0',
   /* "bewerbungsfibel.de", true */ 'b', 'e', 'w', 'e', 'r', 'b', 'u', 'n', 'g', 's', 'f', 'i', 'b', 'e', 'l', '.', 'd', 'e', '\0',
@@ -1262,17 +1259,16 @@ static const char kSTSHostTable[] = {
   /* "bicranial.io", true */ 'b', 'i', 'c', 'r', 'a', 'n', 'i', 'a', 'l', '.', 'i', 'o', '\0',
   /* "bicycle-events.com", true */ 'b', 'i', 'c', 'y', 'c', 'l', 'e', '-', 'e', 'v', 'e', 'n', 't', 's', '.', 'c', 'o', 'm', '\0',
   /* "biddl.com", true */ 'b', 'i', 'd', 'd', 'l', '.', 'c', 'o', 'm', '\0',
   /* "bielsa.me", true */ 'b', 'i', 'e', 'l', 's', 'a', '.', 'm', 'e', '\0',
   /* "bienici.com", true */ 'b', 'i', 'e', 'n', 'i', 'c', 'i', '.', 'c', 'o', 'm', '\0',
   /* "bierbaumer.net", true */ 'b', 'i', 'e', 'r', 'b', 'a', 'u', 'm', 'e', 'r', '.', 'n', 'e', 't', '\0',
   /* "biergaizi.info", true */ 'b', 'i', 'e', 'r', 'g', 'a', 'i', 'z', 'i', '.', 'i', 'n', 'f', 'o', '\0',
   /* "big-andy.co.uk", true */ 'b', 'i', 'g', '-', 'a', 'n', 'd', 'y', '.', 'c', 'o', '.', 'u', 'k', '\0',
-  /* "big-black.de", false */ 'b', 'i', 'g', '-', 'b', 'l', 'a', 'c', 'k', '.', 'd', 'e', '\0',
   /* "bigbluedoor.net", true */ 'b', 'i', 'g', 'b', 'l', 'u', 'e', 'd', 'o', 'o', 'r', '.', 'n', 'e', 't', '\0',
   /* "bigclassaction.com", true */ 'b', 'i', 'g', 'c', 'l', 'a', 's', 's', 'a', 'c', 't', 'i', 'o', 'n', '.', 'c', 'o', 'm', '\0',
   /* "bight.ca", true */ 'b', 'i', 'g', 'h', 't', '.', 'c', 'a', '\0',
   /* "biguixhe.net", true */ 'b', 'i', 'g', 'u', 'i', 'x', 'h', 'e', '.', 'n', 'e', 't', '\0',
   /* "bike-shack.com", true */ 'b', 'i', 'k', 'e', '-', 's', 'h', 'a', 'c', 'k', '.', 'c', 'o', 'm', '\0',
   /* "bikermusic.net", false */ 'b', 'i', 'k', 'e', 'r', 'm', 'u', 's', 'i', 'c', '.', 'n', 'e', 't', '\0',
   /* "bikiniseli.com", true */ 'b', 'i', 'k', 'i', 'n', 'i', 's', 'e', 'l', 'i', '.', 'c', 'o', 'm', '\0',
   /* "bildermachr.de", true */ 'b', 'i', 'l', 'd', 'e', 'r', 'm', 'a', 'c', 'h', 'r', '.', 'd', 'e', '\0',
@@ -1400,17 +1396,16 @@ static const char kSTSHostTable[] = {
   /* "blackphoenix.de", true */ 'b', 'l', 'a', 'c', 'k', 'p', 'h', 'o', 'e', 'n', 'i', 'x', '.', 'd', 'e', '\0',
   /* "blackscytheconsulting.com", true */ 'b', 'l', 'a', 'c', 'k', 's', 'c', 'y', 't', 'h', 'e', 'c', 'o', 'n', 's', 'u', 'l', 't', 'i', 'n', 'g', '.', 'c', 'o', 'm', '\0',
   /* "blaise.io", true */ 'b', 'l', 'a', 'i', 's', 'e', '.', 'i', 'o', '\0',
   /* "blakerandall.xyz", true */ 'b', 'l', 'a', 'k', 'e', 'r', 'a', 'n', 'd', 'a', 'l', 'l', '.', 'x', 'y', 'z', '\0',
   /* "blancodent.com", true */ 'b', 'l', 'a', 'n', 'c', 'o', 'd', 'e', 'n', 't', '.', 'c', 'o', 'm', '\0',
   /* "blankersfamily.com", true */ 'b', 'l', 'a', 'n', 'k', 'e', 'r', 's', 'f', 'a', 'm', 'i', 'l', 'y', '.', 'c', 'o', 'm', '\0',
   /* "blastersklan.com", true */ 'b', 'l', 'a', 's', 't', 'e', 'r', 's', 'k', 'l', 'a', 'n', '.', 'c', 'o', 'm', '\0',
   /* "blauerhunger.de", true */ 'b', 'l', 'a', 'u', 'e', 'r', 'h', 'u', 'n', 'g', 'e', 'r', '.', 'd', 'e', '\0',
-  /* "blauwwit.be", true */ 'b', 'l', 'a', 'u', 'w', 'w', 'i', 't', '.', 'b', 'e', '\0',
   /* "blayne.me", true */ 'b', 'l', 'a', 'y', 'n', 'e', '.', 'm', 'e', '\0',
   /* "blazor.nl", true */ 'b', 'l', 'a', 'z', 'o', 'r', '.', 'n', 'l', '\0',
   /* "bleche-onlineshop.de", true */ 'b', 'l', 'e', 'c', 'h', 'e', '-', 'o', 'n', 'l', 'i', 'n', 'e', 's', 'h', 'o', 'p', '.', 'd', 'e', '\0',
   /* "blechschmidt.saarland", true */ 'b', 'l', 'e', 'c', 'h', 's', 'c', 'h', 'm', 'i', 'd', 't', '.', 's', 'a', 'a', 'r', 'l', 'a', 'n', 'd', '\0',
   /* "blendle.com", true */ 'b', 'l', 'e', 'n', 'd', 'l', 'e', '.', 'c', 'o', 'm', '\0',
   /* "blendle.nl", true */ 'b', 'l', 'e', 'n', 'd', 'l', 'e', '.', 'n', 'l', '\0',
   /* "blendlecdn.com", true */ 'b', 'l', 'e', 'n', 'd', 'l', 'e', 'c', 'd', 'n', '.', 'c', 'o', 'm', '\0',
   /* "blendr.com", true */ 'b', 'l', 'e', 'n', 'd', 'r', '.', 'c', 'o', 'm', '\0',
@@ -1536,16 +1531,17 @@ static const char kSTSHostTable[] = {
   /* "boxintense.com", true */ 'b', 'o', 'x', 'i', 'n', 't', 'e', 'n', 's', 'e', '.', 'c', 'o', 'm', '\0',
   /* "boxpirates.to", true */ 'b', 'o', 'x', 'p', 'i', 'r', 'a', 't', 'e', 's', '.', 't', 'o', '\0',
   /* "boxview.com", true */ 'b', 'o', 'x', 'v', 'i', 'e', 'w', '.', 'c', 'o', 'm', '\0',
   /* "boypoint.de", true */ 'b', 'o', 'y', 'p', 'o', 'i', 'n', 't', '.', 'd', 'e', '\0',
   /* "bp-wahl.at", true */ 'b', 'p', '-', 'w', 'a', 'h', 'l', '.', 'a', 't', '\0',
   /* "bpadvisors.eu", true */ 'b', 'p', 'a', 'd', 'v', 'i', 's', 'o', 'r', 's', '.', 'e', 'u', '\0',
   /* "bpastudies.org", true */ 'b', 'p', 'a', 's', 't', 'u', 'd', 'i', 'e', 's', '.', 'o', 'r', 'g', '\0',
   /* "bpol-forum.de", true */ 'b', 'p', 'o', 'l', '-', 'f', 'o', 'r', 'u', 'm', '.', 'd', 'e', '\0',
+  /* "bqtoolbox.com", true */ 'b', 'q', 't', 'o', 'o', 'l', 'b', 'o', 'x', '.', 'c', 'o', 'm', '\0',
   /* "br.search.yahoo.com", false */ 'b', 'r', '.', 's', 'e', 'a', 'r', 'c', 'h', '.', 'y', 'a', 'h', 'o', 'o', '.', 'c', 'o', 'm', '\0',
   /* "bradbrockmeyer.com", true */ 'b', 'r', 'a', 'd', 'b', 'r', 'o', 'c', 'k', 'm', 'e', 'y', 'e', 'r', '.', 'c', 'o', 'm', '\0',
   /* "bradkovach.com", true */ 'b', 'r', 'a', 'd', 'k', 'o', 'v', 'a', 'c', 'h', '.', 'c', 'o', 'm', '\0',
   /* "brage.info", true */ 'b', 'r', 'a', 'g', 'e', '.', 'i', 'n', 'f', 'o', '\0',
   /* "brain-e.co", true */ 'b', 'r', 'a', 'i', 'n', '-', 'e', '.', 'c', 'o', '\0',
   /* "brainhub.nl", true */ 'b', 'r', 'a', 'i', 'n', 'h', 'u', 'b', '.', 'n', 'l', '\0',
   /* "brainlag.org", true */ 'b', 'r', 'a', 'i', 'n', 'l', 'a', 'g', '.', 'o', 'r', 'g', '\0',
   /* "brainster.co", false */ 'b', 'r', 'a', 'i', 'n', 's', 't', 'e', 'r', '.', 'c', 'o', '\0',
@@ -1766,17 +1762,16 @@ static const char kSTSHostTable[] = {
   /* "calaborlawnews.com", true */ 'c', 'a', 'l', 'a', 'b', 'o', 'r', 'l', 'a', 'w', 'n', 'e', 'w', 's', '.', 'c', 'o', 'm', '\0',
   /* "calc.pw", true */ 'c', 'a', 'l', 'c', '.', 'p', 'w', '\0',
   /* "calculator-imt.com", true */ 'c', 'a', 'l', 'c', 'u', 'l', 'a', 't', 'o', 'r', '-', 'i', 'm', 't', '.', 'c', 'o', 'm', '\0',
   /* "calculator.tf", true */ 'c', 'a', 'l', 'c', 'u', 'l', 'a', 't', 'o', 'r', '.', 't', 'f', '\0',
   /* "calebmorris.com", false */ 'c', 'a', 'l', 'e', 'b', 'm', 'o', 'r', 'r', 'i', 's', '.', 'c', 'o', 'm', '\0',
   /* "calgoty.com", true */ 'c', 'a', 'l', 'g', 'o', 't', 'y', '.', 'c', 'o', 'm', '\0',
   /* "calibreapp.com", false */ 'c', 'a', 'l', 'i', 'b', 'r', 'e', 'a', 'p', 'p', '.', 'c', 'o', 'm', '\0',
   /* "calibso.net", true */ 'c', 'a', 'l', 'i', 'b', 's', 'o', '.', 'n', 'e', 't', '\0',
-  /* "call.me", false */ 'c', 'a', 'l', 'l', '.', 'm', 'e', '\0',
   /* "callcap.com", false */ 'c', 'a', 'l', 'l', 'c', 'a', 'p', '.', 'c', 'o', 'm', '\0',
   /* "callear.org", true */ 'c', 'a', 'l', 'l', 'e', 'a', 'r', '.', 'o', 'r', 'g', '\0',
   /* "callhub.io", true */ 'c', 'a', 'l', 'l', 'h', 'u', 'b', '.', 'i', 'o', '\0',
   /* "callision.com", true */ 'c', 'a', 'l', 'l', 'i', 's', 'i', 'o', 'n', '.', 'c', 'o', 'm', '\0',
   /* "callsigns.ca", true */ 'c', 'a', 'l', 'l', 's', 'i', 'g', 'n', 's', '.', 'c', 'a', '\0',
   /* "calomel.org", true */ 'c', 'a', 'l', 'o', 'm', 'e', 'l', '.', 'o', 'r', 'g', '\0',
   /* "calories.org", true */ 'c', 'a', 'l', 'o', 'r', 'i', 'e', 's', '.', 'o', 'r', 'g', '\0',
   /* "caltonnutrition.com", true */ 'c', 'a', 'l', 't', 'o', 'n', 'n', 'u', 't', 'r', 'i', 't', 'i', 'o', 'n', '.', 'c', 'o', 'm', '\0',
@@ -2221,17 +2216,16 @@ static const char kSTSHostTable[] = {
   /* "cocaine.ninja", true */ 'c', 'o', 'c', 'a', 'i', 'n', 'e', '.', 'n', 'i', 'n', 'j', 'a', '\0',
   /* "cocker.cc", false */ 'c', 'o', 'c', 'k', 'e', 'r', '.', 'c', 'c', '\0',
   /* "cocktailfuture.fr", true */ 'c', 'o', 'c', 'k', 't', 'a', 'i', 'l', 'f', 'u', 't', 'u', 'r', 'e', '.', 'f', 'r', '\0',
   /* "cocoaheads.at", false */ 'c', 'o', 'c', 'o', 'a', 'h', 'e', 'a', 'd', 's', '.', 'a', 't', '\0',
   /* "cocolovesdaddy.com", true */ 'c', 'o', 'c', 'o', 'l', 'o', 'v', 'e', 's', 'd', 'a', 'd', 'd', 'y', '.', 'c', 'o', 'm', '\0',
   /* "code-poets.co.uk", true */ 'c', 'o', 'd', 'e', '-', 'p', 'o', 'e', 't', 's', '.', 'c', 'o', '.', 'u', 'k', '\0',
   /* "code-well.com", true */ 'c', 'o', 'd', 'e', '-', 'w', 'e', 'l', 'l', '.', 'c', 'o', 'm', '\0',
   /* "code.facebook.com", false */ 'c', 'o', 'd', 'e', '.', 'f', 'a', 'c', 'e', 'b', 'o', 'o', 'k', '.', 'c', 'o', 'm', '\0',
-  /* "code.fm", true */ 'c', 'o', 'd', 'e', '.', 'f', 'm', '\0',
   /* "code.google.com", true */ 'c', 'o', 'd', 'e', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm', '\0',
   /* "code67.com", true */ 'c', 'o', 'd', 'e', '6', '7', '.', 'c', 'o', 'm', '\0',
   /* "codeferm.com", true */ 'c', 'o', 'd', 'e', 'f', 'e', 'r', 'm', '.', 'c', 'o', 'm', '\0',
   /* "codefordus.nrw", true */ 'c', 'o', 'd', 'e', 'f', 'o', 'r', 'd', 'u', 's', '.', 'n', 'r', 'w', '\0',
   /* "codeforhakodate.org", true */ 'c', 'o', 'd', 'e', 'f', 'o', 'r', 'h', 'a', 'k', 'o', 'd', 'a', 't', 'e', '.', 'o', 'r', 'g', '\0',
   /* "codefoundry.it", false */ 'c', 'o', 'd', 'e', 'f', 'o', 'u', 'n', 'd', 'r', 'y', '.', 'i', 't', '\0',
   /* "codeit.guru", true */ 'c', 'o', 'd', 'e', 'i', 't', '.', 'g', 'u', 'r', 'u', '\0',
   /* "codelayer.ca", true */ 'c', 'o', 'd', 'e', 'l', 'a', 'y', 'e', 'r', '.', 'c', 'a', '\0',
@@ -2339,17 +2333,16 @@ static const char kSTSHostTable[] = {
   /* "config.schokokeks.org", false */ 'c', 'o', 'n', 'f', 'i', 'g', '.', 's', 'c', 'h', 'o', 'k', 'o', 'k', 'e', 'k', 's', '.', 'o', 'r', 'g', '\0',
   /* "confiwall.de", true */ 'c', 'o', 'n', 'f', 'i', 'w', 'a', 'l', 'l', '.', 'd', 'e', '\0',
   /* "conflux.tw", true */ 'c', 'o', 'n', 'f', 'l', 'u', 'x', '.', 't', 'w', '\0',
   /* "confucio.cl", true */ 'c', 'o', 'n', 'f', 'u', 'c', 'i', 'o', '.', 'c', 'l', '\0',
   /* "connect.dating", true */ 'c', 'o', 'n', 'n', 'e', 'c', 't', '.', 'd', 'a', 't', 'i', 'n', 'g', '\0',
   /* "connect.ua", false */ 'c', 'o', 'n', 'n', 'e', 'c', 't', '.', 'u', 'a', '\0',
   /* "connected-verhuurservice.nl", true */ 'c', 'o', 'n', 'n', 'e', 'c', 't', 'e', 'd', '-', 'v', 'e', 'r', 'h', 'u', 'u', 'r', 's', 'e', 'r', 'v', 'i', 'c', 'e', '.', 'n', 'l', '\0',
   /* "connectfss.com", true */ 'c', 'o', 'n', 'n', 'e', 'c', 't', 'f', 's', 's', '.', 'c', 'o', 'm', '\0',
-  /* "connectingconcepts.com", true */ 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'n', 'g', 'c', 'o', 'n', 'c', 'e', 'p', 't', 's', '.', 'c', 'o', 'm', '\0',
   /* "connectum.eu", true */ 'c', 'o', 'n', 'n', 'e', 'c', 't', 'u', 'm', '.', 'e', 'u', '\0',
   /* "connext.de", true */ 'c', 'o', 'n', 'n', 'e', 'x', 't', '.', 'd', 'e', '\0',
   /* "connyduck.at", true */ 'c', 'o', 'n', 'n', 'y', 'd', 'u', 'c', 'k', '.', 'a', 't', '\0',
   /* "consciousbrand.co", true */ 'c', 'o', 'n', 's', 'c', 'i', 'o', 'u', 's', 'b', 'r', 'a', 'n', 'd', '.', 'c', 'o', '\0',
   /* "consciousbrand.org.au", true */ 'c', 'o', 'n', 's', 'c', 'i', 'o', 'u', 's', 'b', 'r', 'a', 'n', 'd', '.', 'o', 'r', 'g', '.', 'a', 'u', '\0',
   /* "consciousbranding.org.au", true */ 'c', 'o', 'n', 's', 'c', 'i', 'o', 'u', 's', 'b', 'r', 'a', 'n', 'd', 'i', 'n', 'g', '.', 'o', 'r', 'g', '.', 'a', 'u', '\0',
   /* "consciousbrands.net.au", true */ 'c', 'o', 'n', 's', 'c', 'i', 'o', 'u', 's', 'b', 'r', 'a', 'n', 'd', 's', '.', 'n', 'e', 't', '.', 'a', 'u', '\0',
   /* "console.ninja", true */ 'c', 'o', 'n', 's', 'o', 'l', 'e', '.', 'n', 'i', 'n', 'j', 'a', '\0',
@@ -2421,17 +2414,16 @@ static const char kSTSHostTable[] = {
   /* "cowbird.org", true */ 'c', 'o', 'w', 'b', 'i', 'r', 'd', '.', 'o', 'r', 'g', '\0',
   /* "cowboyim.com", true */ 'c', 'o', 'w', 'b', 'o', 'y', 'i', 'm', '.', 'c', 'o', 'm', '\0',
   /* "coweo.cz", true */ 'c', 'o', 'w', 'e', 'o', '.', 'c', 'z', '\0',
   /* "cozmaadrian.ro", true */ 'c', 'o', 'z', 'm', 'a', 'a', 'd', 'r', 'i', 'a', 'n', '.', 'r', 'o', '\0',
   /* "cozyeggdesigns.com", true */ 'c', 'o', 'z', 'y', 'e', 'g', 'g', 'd', 'e', 's', 'i', 'g', 'n', 's', '.', 'c', 'o', 'm', '\0',
   /* "cprnearme.com", true */ 'c', 'p', 'r', 'n', 'e', 'a', 'r', 'm', 'e', '.', 'c', 'o', 'm', '\0',
   /* "cpuvinf.eu.org", true */ 'c', 'p', 'u', 'v', 'i', 'n', 'f', '.', 'e', 'u', '.', 'o', 'r', 'g', '\0',
   /* "cpvmatch.eu", true */ 'c', 'p', 'v', 'm', 'a', 't', 'c', 'h', '.', 'e', 'u', '\0',
-  /* "cqchome.com", true */ 'c', 'q', 'c', 'h', 'o', 'm', 'e', '.', 'c', 'o', 'm', '\0',
   /* "cracker.in.th", true */ 'c', 'r', 'a', 'c', 'k', 'e', 'r', '.', 'i', 'n', '.', 't', 'h', '\0',
   /* "crackingking.com", false */ 'c', 'r', 'a', 'c', 'k', 'i', 'n', 'g', 'k', 'i', 'n', 'g', '.', 'c', 'o', 'm', '\0',
   /* "crackle.io", true */ 'c', 'r', 'a', 'c', 'k', 'l', 'e', '.', 'i', 'o', '\0',
   /* "crackpfer.de", true */ 'c', 'r', 'a', 'c', 'k', 'p', 'f', 'e', 'r', '.', 'd', 'e', '\0',
   /* "cradlepointecm.com", true */ 'c', 'r', 'a', 'd', 'l', 'e', 'p', 'o', 'i', 'n', 't', 'e', 'c', 'm', '.', 'c', 'o', 'm', '\0',
   /* "craftcms.com", true */ 'c', 'r', 'a', 'f', 't', 'c', 'm', 's', '.', 'c', 'o', 'm', '\0',
   /* "craftcommerce.com", true */ 'c', 'r', 'a', 'f', 't', 'c', 'o', 'm', 'm', 'e', 'r', 'c', 'e', '.', 'c', 'o', 'm', '\0',
   /* "craftinginredlipstick.com", true */ 'c', 'r', 'a', 'f', 't', 'i', 'n', 'g', 'i', 'n', 'r', 'e', 'd', 'l', 'i', 'p', 's', 't', 'i', 'c', 'k', '.', 'c', 'o', 'm', '\0',
@@ -2538,17 +2530,16 @@ static const char kSTSHostTable[] = {
   /* "cuddlecomfort.com", true */ 'c', 'u', 'd', 'd', 'l', 'e', 'c', 'o', 'm', 'f', 'o', 'r', 't', '.', 'c', 'o', 'm', '\0',
   /* "cuecasonline.com.br", true */ 'c', 'u', 'e', 'c', 'a', 's', 'o', 'n', 'l', 'i', 'n', 'e', '.', 'c', 'o', 'm', '.', 'b', 'r', '\0',
   /* "cuibonobo.com", true */ 'c', 'u', 'i', 'b', 'o', 'n', 'o', 'b', 'o', '.', 'c', 'o', 'm', '\0',
   /* "cuisinezest.com", true */ 'c', 'u', 'i', 's', 'i', 'n', 'e', 'z', 'e', 's', 't', '.', 'c', 'o', 'm', '\0',
   /* "cujba.com", true */ 'c', 'u', 'j', 'b', 'a', '.', 'c', 'o', 'm', '\0',
   /* "culinae.nl", true */ 'c', 'u', 'l', 'i', 'n', 'a', 'e', '.', 'n', 'l', '\0',
   /* "cultiv.nl", true */ 'c', 'u', 'l', 't', 'i', 'v', '.', 'n', 'l', '\0',
   /* "culturedcode.com", true */ 'c', 'u', 'l', 't', 'u', 'r', 'e', 'd', 'c', 'o', 'd', 'e', '.', 'c', 'o', 'm', '\0',
-  /* "cumshots-video.ru", true */ 'c', 'u', 'm', 's', 'h', 'o', 't', 's', '-', 'v', 'i', 'd', 'e', 'o', '.', 'r', 'u', '\0',
   /* "cuongquach.com", true */ 'c', 'u', 'o', 'n', 'g', 'q', 'u', 'a', 'c', 'h', '.', 'c', 'o', 'm', '\0',
   /* "cuonic.com", true */ 'c', 'u', 'o', 'n', 'i', 'c', '.', 'c', 'o', 'm', '\0',
   /* "cup.al", true */ 'c', 'u', 'p', '.', 'a', 'l', '\0',
   /* "cupcake.io", true */ 'c', 'u', 'p', 'c', 'a', 'k', 'e', '.', 'i', 'o', '\0',
   /* "cupcake.is", true */ 'c', 'u', 'p', 'c', 'a', 'k', 'e', '.', 'i', 's', '\0',
   /* "cupi.co", true */ 'c', 'u', 'p', 'i', '.', 'c', 'o', '\0',
   /* "curacao-license.com", true */ 'c', 'u', 'r', 'a', 'c', 'a', 'o', '-', 'l', 'i', 'c', 'e', 'n', 's', 'e', '.', 'c', 'o', 'm', '\0',
   /* "curiosity-driven.org", true */ 'c', 'u', 'r', 'i', 'o', 's', 'i', 't', 'y', '-', 'd', 'r', 'i', 'v', 'e', 'n', '.', 'o', 'r', 'g', '\0',
@@ -2830,17 +2821,16 @@ static const char kSTSHostTable[] = {
   /* "deinballon.de", true */ 'd', 'e', 'i', 'n', 'b', 'a', 'l', 'l', 'o', 'n', '.', 'd', 'e', '\0',
   /* "dejandayoff.com", true */ 'd', 'e', 'j', 'a', 'n', 'd', 'a', 'y', 'o', 'f', 'f', '.', 'c', 'o', 'm', '\0',
   /* "delayrefunds.co.uk", true */ 'd', 'e', 'l', 'a', 'y', 'r', 'e', 'f', 'u', 'n', 'd', 's', '.', 'c', 'o', '.', 'u', 'k', '\0',
   /* "delfic.org", true */ 'd', 'e', 'l', 'f', 'i', 'c', '.', 'o', 'r', 'g', '\0',
   /* "deliciisanatoase.ro", true */ 'd', 'e', 'l', 'i', 'c', 'i', 'i', 's', 'a', 'n', 'a', 't', 'o', 'a', 's', 'e', '.', 'r', 'o', '\0',
   /* "deliciousmedia.co.uk", true */ 'd', 'e', 'l', 'i', 'c', 'i', 'o', 'u', 's', 'm', 'e', 'd', 'i', 'a', '.', 'c', 'o', '.', 'u', 'k', '\0',
   /* "delphine.dance", true */ 'd', 'e', 'l', 'p', 'h', 'i', 'n', 'e', '.', 'd', 'a', 'n', 'c', 'e', '\0',
   /* "delta-data.ch", true */ 'd', 'e', 'l', 't', 'a', '-', 'd', 'a', 't', 'a', '.', 'c', 'h', '\0',
-  /* "delvj.org", true */ 'd', 'e', 'l', 'v', 'j', '.', 'o', 'r', 'g', '\0',
   /* "dementiapraecox.de", true */ 'd', 'e', 'm', 'e', 'n', 't', 'i', 'a', 'p', 'r', 'a', 'e', 'c', 'o', 'x', '.', 'd', 'e', '\0',
   /* "demo.swedbank.se", true */ 'd', 'e', 'm', 'o', '.', 's', 'w', 'e', 'd', 'b', 'a', 'n', 'k', '.', 's', 'e', '\0',
   /* "democracy.io", true */ 'd', 'e', 'm', 'o', 'c', 'r', 'a', 'c', 'y', '.', 'i', 'o', '\0',
   /* "demomanca.com", true */ 'd', 'e', 'm', 'o', 'm', 'a', 'n', 'c', 'a', '.', 'c', 'o', 'm', '\0',
   /* "demotops.com", false */ 'd', 'e', 'm', 'o', 't', 'o', 'p', 's', '.', 'c', 'o', 'm', '\0',
   /* "demuzere.be", true */ 'd', 'e', 'm', 'u', 'z', 'e', 'r', 'e', '.', 'b', 'e', '\0',
   /* "demuzere.com", true */ 'd', 'e', 'm', 'u', 'z', 'e', 'r', 'e', '.', 'c', 'o', 'm', '\0',
   /* "demuzere.eu", true */ 'd', 'e', 'm', 'u', 'z', 'e', 'r', 'e', '.', 'e', 'u', '\0',
@@ -2890,17 +2880,16 @@ static const char kSTSHostTable[] = {
   /* "detoxsinutritie.ro", true */ 'd', 'e', 't', 'o', 'x', 's', 'i', 'n', 'u', 't', 'r', 'i', 't', 'i', 'e', '.', 'r', 'o', '\0',
   /* "detteflies.com", true */ 'd', 'e', 't', 't', 'e', 'f', 'l', 'i', 'e', 's', '.', 'c', 'o', 'm', '\0',
   /* "detutorial.com", true */ 'd', 'e', 't', 'u', 't', 'o', 'r', 'i', 'a', 'l', '.', 'c', 'o', 'm', '\0',
   /* "deusu.de", true */ 'd', 'e', 'u', 's', 'u', '.', 'd', 'e', '\0',
   /* "deusu.org", true */ 'd', 'e', 'u', 's', 'u', '.', 'o', 'r', 'g', '\0',
   /* "dev-tek.de", true */ 'd', 'e', 'v', '-', 't', 'e', 'k', '.', 'd', 'e', '\0',
   /* "devb.nl", true */ 'd', 'e', 'v', 'b', '.', 'n', 'l', '\0',
   /* "devcu.com", true */ 'd', 'e', 'v', 'c', 'u', '.', 'c', 'o', 'm', '\0',
-  /* "devcu.net", true */ 'd', 'e', 'v', 'c', 'u', '.', 'n', 'e', 't', '\0',
   /* "devdom.io", true */ 'd', 'e', 'v', 'd', 'o', 'm', '.', 'i', 'o', '\0',
   /* "devdoodle.net", true */ 'd', 'e', 'v', 'd', 'o', 'o', 'd', 'l', 'e', '.', 'n', 'e', 't', '\0',
   /* "developer.mydigipass.com", false */ 'd', 'e', 'v', 'e', 'l', 'o', 'p', 'e', 'r', '.', 'm', 'y', 'd', 'i', 'g', 'i', 'p', 'a', 's', 's', '.', 'c', 'o', 'm', '\0',
   /* "developerfair.com", true */ 'd', 'e', 'v', 'e', 'l', 'o', 'p', 'e', 'r', 'f', 'a', 'i', 'r', '.', 'c', 'o', 'm', '\0',
   /* "developers.facebook.com", false */ 'd', 'e', 'v', 'e', 'l', 'o', 'p', 'e', 'r', 's', '.', 'f', 'a', 'c', 'e', 'b', 'o', 'o', 'k', '.', 'c', 'o', 'm', '\0',
   /* "developfx.com", true */ 'd', 'e', 'v', 'e', 'l', 'o', 'p', 'f', 'x', '.', 'c', 'o', 'm', '\0',
   /* "developmentaid.org", true */ 'd', 'e', 'v', 'e', 'l', 'o', 'p', 'm', 'e', 'n', 't', 'a', 'i', 'd', '.', 'o', 'r', 'g', '\0',
   /* "developmentsites.melbourne", true */ 'd', 'e', 'v', 'e', 'l', 'o', 'p', 'm', 'e', 'n', 't', 's', 'i', 't', 'e', 's', '.', 'm', 'e', 'l', 'b', 'o', 'u', 'r', 'n', 'e', '\0',
@@ -3189,16 +3178,17 @@ static const char kSTSHostTable[] = {
   /* "dranek.com", true */ 'd', 'r', 'a', 'n', 'e', 'k', '.', 'c', 'o', 'm', '\0',
   /* "draugr.de", true */ 'd', 'r', 'a', 'u', 'g', 'r', '.', 'd', 'e', '\0',
   /* "drawesome.uy", true */ 'd', 'r', 'a', 'w', 'e', 's', 'o', 'm', 'e', '.', 'u', 'y', '\0',
   /* "drawingcode.net", true */ 'd', 'r', 'a', 'w', 'i', 'n', 'g', 'c', 'o', 'd', 'e', '.', 'n', 'e', 't', '\0',
   /* "dreamcreator108.com", true */ 'd', 'r', 'e', 'a', 'm', 'c', 'r', 'e', 'a', 't', 'o', 'r', '1', '0', '8', '.', 'c', 'o', 'm', '\0',
   /* "dreaming.solutions", true */ 'd', 'r', 'e', 'a', 'm', 'i', 'n', 'g', '.', 's', 'o', 'l', 'u', 't', 'i', 'o', 'n', 's', '\0',
   /* "dreamsforabetterworld.com.au", true */ 'd', 'r', 'e', 'a', 'm', 's', 'f', 'o', 'r', 'a', 'b', 'e', 't', 't', 'e', 'r', 'w', 'o', 'r', 'l', 'd', '.', 'c', 'o', 'm', '.', 'a', 'u', '\0',
   /* "dreamtechie.com", true */ 'd', 'r', 'e', 'a', 'm', 't', 'e', 'c', 'h', 'i', 'e', '.', 'c', 'o', 'm', '\0',
+  /* "dredgepress.com", true */ 'd', 'r', 'e', 'd', 'g', 'e', 'p', 'r', 'e', 's', 's', '.', 'c', 'o', 'm', '\0',
   /* "dreid.org", true */ 'd', 'r', 'e', 'i', 'd', '.', 'o', 'r', 'g', '\0',
   /* "dreizwosechs.de", true */ 'd', 'r', 'e', 'i', 'z', 'w', 'o', 's', 'e', 'c', 'h', 's', '.', 'd', 'e', '\0',
   /* "drew.red", true */ 'd', 'r', 'e', 'w', '.', 'r', 'e', 'd', '\0',
   /* "dreweryinc.com", true */ 'd', 'r', 'e', 'w', 'e', 'r', 'y', 'i', 'n', 'c', '.', 'c', 'o', 'm', '\0',
   /* "drewgle.net", true */ 'd', 'r', 'e', 'w', 'g', 'l', 'e', '.', 'n', 'e', 't', '\0',
   /* "drhopeson.com", true */ 'd', 'r', 'h', 'o', 'p', 'e', 's', 'o', 'n', '.', 'c', 'o', 'm', '\0',
   /* "driesjtuver.nl", true */ 'd', 'r', 'i', 'e', 's', 'j', 't', 'u', 'v', 'e', 'r', '.', 'n', 'l', '\0',
   /* "driftdude.nl", true */ 'd', 'r', 'i', 'f', 't', 'd', 'u', 'd', 'e', '.', 'n', 'l', '\0',
@@ -3265,17 +3255,16 @@ static const char kSTSHostTable[] = {
   /* "dutyfreeonboard.com", true */ 'd', 'u', 't', 'y', 'f', 'r', 'e', 'e', 'o', 'n', 'b', 'o', 'a', 'r', 'd', '.', 'c', 'o', 'm', '\0',
   /* "duuu.ch", true */ 'd', 'u', 'u', 'u', '.', 'c', 'h', '\0',
   /* "dvbris.co.uk", true */ 'd', 'v', 'b', 'r', 'i', 's', '.', 'c', 'o', '.', 'u', 'k', '\0',
   /* "dvbris.com", true */ 'd', 'v', 'b', 'r', 'i', 's', '.', 'c', 'o', 'm', '\0',
   /* "dvorupotocnych.sk", true */ 'd', 'v', 'o', 'r', 'u', 'p', 'o', 't', 'o', 'c', 'n', 'y', 'c', 'h', '.', 's', 'k', '\0',
   /* "dvotx.org", true */ 'd', 'v', 'o', 't', 'x', '.', 'o', 'r', 'g', '\0',
   /* "dvwc.org", true */ 'd', 'v', 'w', 'c', '.', 'o', 'r', 'g', '\0',
   /* "dwnld.me", true */ 'd', 'w', 'n', 'l', 'd', '.', 'm', 'e', '\0',
-  /* "dworzak.ch", true */ 'd', 'w', 'o', 'r', 'z', 'a', 'k', '.', 'c', 'h', '\0',
   /* "dxa.io", true */ 'd', 'x', 'a', '.', 'i', 'o', '\0',
   /* "dxgl.info", true */ 'd', 'x', 'g', 'l', '.', 'i', 'n', 'f', 'o', '\0',
   /* "dyeager.org", true */ 'd', 'y', 'e', 'a', 'g', 'e', 'r', '.', 'o', 'r', 'g', '\0',
   /* "dyktig.as", true */ 'd', 'y', 'k', 't', 'i', 'g', '.', 'a', 's', '\0',
   /* "dyn-nserve.net", true */ 'd', 'y', 'n', '-', 'n', 's', 'e', 'r', 'v', 'e', '.', 'n', 'e', 't', '\0',
   /* "dyn.im", true */ 'd', 'y', 'n', '.', 'i', 'm', '\0',
   /* "dynaloop.net", true */ 'd', 'y', 'n', 'a', 'l', 'o', 'o', 'p', '.', 'n', 'e', 't', '\0',
   /* "dynamicnet.net", false */ 'd', 'y', 'n', 'a', 'm', 'i', 'c', 'n', 'e', 't', '.', 'n', 'e', 't', '\0',
@@ -3458,16 +3447,17 @@ static const char kSTSHostTable[] = {
   /* "elgosblanc.com", true */ 'e', 'l', 'g', 'o', 's', 'b', 'l', 'a', 'n', 'c', '.', 'c', 'o', 'm', '\0',
   /* "eligible.com", true */ 'e', 'l', 'i', 'g', 'i', 'b', 'l', 'e', '.', 'c', 'o', 'm', '\0',
   /* "eligibleapi.com", true */ 'e', 'l', 'i', 'g', 'i', 'b', 'l', 'e', 'a', 'p', 'i', '.', 'c', 'o', 'm', '\0',
   /* "eligrey.com", true */ 'e', 'l', 'i', 'g', 'r', 'e', 'y', '.', 'c', 'o', 'm', '\0',
   /* "eliolita.com", true */ 'e', 'l', 'i', 'o', 'l', 'i', 't', 'a', '.', 'c', 'o', 'm', '\0',
   /* "eliott.be", true */ 'e', 'l', 'i', 'o', 't', 't', '.', 'b', 'e', '\0',
   /* "elisa.ee", false */ 'e', 'l', 'i', 's', 'a', '.', 'e', 'e', '\0',
   /* "elisabeth-strunz.de", true */