merge mozilla-central to mozilla-inbound. r=merge a=merge
authorSebastian Hengst <archaeopteryx@coole-files.de>
Tue, 10 Oct 2017 06:22:33 -0300
changeset 427907 1caa1ee2d93805f97a8ea4dcbbc931c10e99575c
parent 427856 2e7d53a96af0b7e2a1822c675be44a9cbb88ca9e (current diff)
parent 427906 77a4c52e9987d2359969d7c478183b438b464744 (diff)
child 427908 dfc9fb9a35b32e623cecb470d330623963425e5f
push id97
push userfmarier@mozilla.com
push dateSat, 14 Oct 2017 01:12:59 +0000
reviewersmerge, merge
milestone58.0a1
merge mozilla-central to mozilla-inbound. r=merge a=merge
layout/base/nsLayoutUtils.cpp
testing/marionette/test_wait.js
testing/marionette/wait.js
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -6094,18 +6094,20 @@
           // Focus window for beforeunload dialog so it is seen but don't
           // steal focus from other applications.
           if (event.detail &&
               event.detail.tabPrompt &&
               event.detail.inPermitUnload &&
               Services.focus.activeWindow)
             window.focus();
 
-          // Don't need to act if the tab is already selected:
-          if (tabForEvent.selected)
+          // Don't need to act if the tab is already selected or if there isn't
+          // a tab for the event (e.g. for the webextensions options_ui remote
+          // browsers embedded in the "about:addons" page):
+          if (!tabForEvent || tabForEvent.selected)
             return;
 
           // We always switch tabs for beforeunload tab-modal prompts.
           if (event.detail &&
               event.detail.tabPrompt &&
               !event.detail.inPermitUnload) {
             let docPrincipal = targetIsWindow ? event.target.document.nodePrincipal : null;
             // At least one of these should/will be non-null:
--- a/browser/components/extensions/test/browser/browser-common.ini
+++ b/browser/components/extensions/test/browser/browser-common.ini
@@ -88,16 +88,17 @@ skip-if = (os == 'win' && !debug) # bug 
 [browser_ext_incognito_views.js]
 [browser_ext_incognito_popup.js]
 [browser_ext_lastError.js]
 [browser_ext_menus.js]
 [browser_ext_omnibox.js]
 skip-if = debug || asan # Bug 1354681
 [browser_ext_openPanel.js]
 [browser_ext_optionsPage_browser_style.js]
+[browser_ext_optionsPage_modals.js]
 [browser_ext_optionsPage_privileges.js]
 [browser_ext_pageAction_context.js]
 [browser_ext_pageAction_contextMenu.js]
 [browser_ext_pageAction_popup.js]
 [browser_ext_pageAction_popup_resize.js]
 [browser_ext_pageAction_simple.js]
 [browser_ext_pageAction_telemetry.js]
 [browser_ext_pageAction_title.js]
new file mode 100644
--- /dev/null
+++ b/browser/components/extensions/test/browser/browser_ext_optionsPage_modals.js
@@ -0,0 +1,94 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+"use strict";
+
+add_task(async function test_tab_options_modals() {
+  function backgroundScript() {
+    browser.runtime.openOptionsPage();
+  }
+
+  function optionsScript() {
+    try {
+      alert("WebExtensions OptionsUI Page Modal");
+
+      browser.test.notifyPass("options-ui-modals");
+    } catch (error) {
+      browser.test.log(`Error: ${error} :: ${error.stack}`);
+      browser.test.notifyFail("options-ui-modals");
+    }
+  }
+
+  let extension = ExtensionTestUtils.loadExtension({
+    useAddonManager: "temporary",
+
+    manifest: {
+      "permissions": ["tabs"],
+      "options_ui": {
+        "page": "options.html",
+      },
+    },
+    files: {
+      "options.html": `<!DOCTYPE html>
+        <html>
+          <head>
+            <meta charset="utf-8">
+            <script src="options.js" type="text/javascript"></script>
+          </head>
+        </html>`,
+      "options.js": optionsScript,
+    },
+    background: backgroundScript,
+  });
+
+  await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:addons");
+
+  await extension.startup();
+
+  const onceModalOpened = new Promise(resolve => {
+    const aboutAddonsBrowser = gBrowser.selectedBrowser;
+
+    aboutAddonsBrowser.addEventListener("DOMWillOpenModalDialog", function onModalDialog(event) {
+      if (Cu.isCrossProcessWrapper(event.target)) {
+        // This event fires in both the content and chrome processes. We
+        // want to ignore the one in the content process.
+        return;
+      }
+
+      aboutAddonsBrowser.removeEventListener("DOMWillOpenModalDialog", onModalDialog, true);
+      resolve();
+    }, true);
+  });
+
+  info("Wait the options_ui modal to be opened");
+  await onceModalOpened;
+
+  const optionsBrowser = gBrowser.selectedBrowser.contentDocument
+                                 .getElementById("addon-options");
+
+  let stack;
+
+  // For remote extensions, the stack that contains the tabmodalprompt elements
+  // is the parent of the extensions options_ui browser element, otherwise it would
+  // be the parent of the currently selected tabbrowser's browser.
+  if (optionsBrowser.isRemoteBrowser) {
+    stack = optionsBrowser.parentNode;
+  } else {
+    stack = gBrowser.selectedBrowser.parentNode;
+  }
+
+  let dialogs = stack.querySelectorAll("tabmodalprompt");
+
+  Assert.equal(dialogs.length, 1, "Expect a tab modal opened for the about addons tab");
+
+  info("Close the tab modal prompt");
+  dialogs[0].onButtonClick(0);
+
+  await extension.awaitFinish("options-ui-modals");
+
+  Assert.equal(stack.querySelectorAll("tabmodalprompt").length, 0,
+               "Expect the tab modal to be closed");
+
+  await BrowserTestUtils.removeTab(gBrowser.selectedTab);
+
+  await extension.unload();
+});
--- a/build/autoconf/android.m4
+++ b/build/autoconf/android.m4
@@ -5,17 +5,17 @@ dnl file, You can obtain one at http://m
 AC_DEFUN([MOZ_ANDROID_NDK],
 [
 
 case "$target" in
 *-android*|*-linuxandroid*)
     dnl $android_platform will be set for us by Python configure.
     CPPFLAGS="-idirafter $android_platform/usr/include $CPPFLAGS"
     CFLAGS="-fno-short-enums -fno-exceptions $CFLAGS"
-    CXXFLAGS="-fno-short-enums -fno-exceptions $CXXFLAGS"
+    CXXFLAGS="-fno-short-enums -fno-exceptions $CXXFLAGS $stlport_cppflags"
     ASFLAGS="-idirafter $android_platform/usr/include -DANDROID $ASFLAGS"
 
     dnl Add --allow-shlib-undefined, because libGLESv2 links to an
     dnl undefined symbol (present on the hardware, just not in the
     dnl NDK.)
     LDFLAGS="-L$android_platform/usr/lib -Wl,-rpath-link=$android_platform/usr/lib --sysroot=$android_platform -Wl,--allow-shlib-undefined $LDFLAGS"
     ANDROID_PLATFORM="${android_platform}"
 
@@ -52,63 +52,37 @@ if test "$OS_TARGET" = "Android"; then
     AC_SUBST(ANDROID_CPU_ARCH)
 fi
 ])
 
 AC_DEFUN([MOZ_ANDROID_STLPORT],
 [
 
 if test "$OS_TARGET" = "Android"; then
-    if test -z "$STLPORT_CPPFLAGS$STLPORT_LIBS"; then
+    if test -z "$STLPORT_LIBS"; then
         # android-ndk-r8b and later
-        ndk_base="$android_ndk/sources/cxx-stl"
-        cxx_base="$ndk_base/llvm-libc++"
-        cxx_libs="$cxx_base/libs/$ANDROID_CPU_ARCH"
+        cxx_libs="$android_ndk/sources/cxx-stl/llvm-libc++/libs/$ANDROID_CPU_ARCH"
         # NDK r12 removed the arm/thumb library split and just made
         # everything thumb by default.  Attempt to compensate.
         if test "$MOZ_THUMB2" = 1 -a -d "$cxx_libs/thumb"; then
             cxx_libs="$cxx_libs/thumb"
         fi
-        cxx_include="$cxx_base/libcxx/include"
-        cxxabi_base="$ndk_base/llvm-libc++abi"
-        cxxabi_include="$cxxabi_base/libcxxabi/include"
 
         if ! test -e "$cxx_libs/libc++_static.a"; then
             AC_MSG_ERROR([Couldn't find path to llvm-libc++ in the android ndk])
         fi
 
-        if ! test -e "$cxx_include"; then
-            # NDK r13 removes the inner "libcxx" directory.
-            cxx_include="$cxx_base/include"
-            if ! test -e "$cxx_include"; then
-                AC_MSG_ERROR([Couldn't find path to libc++ includes in the android ndk])
-            fi
-        fi
-
-        if ! test -e "$cxxabi_include"; then
-            # NDK r13 removes the inner "libcxxabi" directory.
-            cxxabi_include="$cxxabi_base/include"
-            if ! test -e "$cxxabi_include"; then
-                AC_MSG_ERROR([Couldn't find path to libc++abi includes in the android ndk])
-            fi
-        fi
-
         STLPORT_LIBS="-L$cxx_libs -lc++_static"
         # NDK r12 split the libc++ runtime libraries into pieces.
         for lib in c++abi unwind android_support; do
             if test -e "$cxx_libs/lib${lib}.a"; then
                  STLPORT_LIBS="$STLPORT_LIBS -l${lib}"
             fi
         done
-        # Add android/support/include/ for prototyping long double math
-        # functions, locale-specific C library functions, multibyte support,
-        # etc.
-        STLPORT_CPPFLAGS="-I$cxx_include -I$android_ndk/sources/android/support/include -I$cxxabi_include"
     fi
-    CXXFLAGS="$CXXFLAGS $STLPORT_CPPFLAGS"
 fi
 AC_SUBST([STLPORT_LIBS])
 
 ])
 
 
 AC_DEFUN([concat],[$1$2$3$4])
 
--- a/build/moz.configure/android-ndk.configure
+++ b/build/moz.configure/android-ndk.configure
@@ -18,19 +18,19 @@ def min_android_version(target):
         return '21'
     return '9'
 
 js_option('--with-android-version',
           nargs=1,
           help='android platform version',
           default=min_android_version)
 
-@depends('--with-android-version', min_android_version)
+@depends('--with-android-version', min_android_version, '--help')
 @imports(_from='__builtin__', _import='ValueError')
-def android_version(value, min_version):
+def android_version(value, min_version, _):
     if not value:
         # Someone has passed --without-android-version.
         die('--with-android-version cannot be disabled.')
 
     try:
         version = int(value[0])
     except ValueError:
         die('--with-android-version expects an integer value')
@@ -38,18 +38,20 @@ def android_version(value, min_version):
     if version < int(min_version):
         die('--with-android-version must be at least %s (got %s)',
             min_version, value[0])
 
     return version
 
 add_old_configure_assignment('android_version', android_version)
 
-@depends('--with-android-ndk', build_project)
-def ndk(value, build_project):
+@depends('--with-android-ndk', build_project, '--help')
+def ndk(value, build_project, help):
+    if help:
+        return
     if build_project == 'mobile/android' and not value:
         die('You must specify --with-android-ndk=/path/to/ndk when '
             'building mobile/android')
     if value:
         return value[0]
 
 set_config('ANDROID_NDK', ndk)
 add_old_configure_assignment('android_ndk', ndk)
@@ -90,20 +92,20 @@ def ndk_minor_version(ndk_version):
         return
     (major, minor, revision) = ndk_version.split('.')
     if minor:
         return minor
     die('Unexpected NDK version string: ' + ndk_version)
 
 set_config('ANDROID_NDK_MINOR_VERSION', ndk_minor_version);
 
-@depends(target, android_version, ndk)
+@depends(target, android_version, ndk, '--help')
 @checking('for android platform directory')
 @imports(_from='os.path', _import='isdir')
-def android_platform(target, android_version, ndk):
+def android_platform(target, android_version, ndk, _):
     if target.os != 'Android':
         return
 
     if 'mips' in target.cpu:
         target_dir_name = 'mips'
     elif 'aarch64' == target.cpu:
         target_dir_name = 'arm64'
     else:
@@ -133,21 +135,21 @@ add_old_configure_assignment('android_pl
 
 @depends(android_platform)
 def extra_toolchain_flags(platform_dir):
     if not platform_dir:
         return []
     return ['-idirafter',
             os.path.join(platform_dir, 'usr', 'include')]
 
-@depends(target, host, ndk, '--with-android-toolchain')
+@depends(target, host, ndk, '--with-android-toolchain', '--help')
 @checking('for the Android toolchain directory', lambda x: x or 'not found')
 @imports(_from='os.path', _import='isdir')
 @imports(_from='mozbuild.shellutil', _import='quote')
-def android_toolchain(target, host, ndk, toolchain):
+def android_toolchain(target, host, ndk, toolchain, _):
     if not ndk:
         return
     if toolchain:
         return toolchain[0]
     else:
         if target.cpu == 'arm' and target.endianness == 'little':
             target_base = 'arm-linux-androideabi'
         elif target.cpu == 'x86':
@@ -170,19 +172,79 @@ def android_toolchain(target, host, ndk,
             log.debug('Trying %s' % quote(toolchain))
         if isdir(toolchain):
             return toolchain
         die('You have to specify --with-android-toolchain='
             '/path/to/ndk/toolchain.')
 
 set_config('ANDROID_TOOLCHAIN', android_toolchain)
 
-@depends(target, android_toolchain)
-def android_toolchain_prefix(target, toolchain):
+@depends(target)
+def android_toolchain_prefix_base(target):
+    if target.cpu == 'x86':
+        # Ideally, the --target should just have the right x86 variant
+        # in the first place.
+        return 'i686-linux-android'
+    return target.toolchain
+
+@depends(android_toolchain_prefix_base, android_toolchain)
+def android_toolchain_prefix(prefix_base, toolchain):
     if toolchain:
-        if target.cpu == 'x86':
-            # Ideally, the --target should just have the right x86 variant
-            # in the first place.
-            return '%s/bin/i686-linux-android-' % toolchain
-        return '%s/bin/%s-' % (toolchain, target.toolchain)
+        return '%s/bin/%s-' % (toolchain, prefix_base)
 
 imply_option('--with-toolchain-prefix', android_toolchain_prefix,
              reason='--with-android-ndk')
+
+option(env='STLPORT_CPPFLAGS',
+       nargs=1,
+       help='Options compiler should pass for standard C++ library')
+
+@depends('STLPORT_CPPFLAGS', ndk, '--help')
+@imports(_from='os.path', _import='isdir')
+def stlport_cppflags(value, ndk, _):
+    if value and len(value):
+        return value
+    if not ndk:
+        return
+
+    ndk_base = os.path.join(ndk, 'sources', 'cxx-stl')
+    cxx_base = os.path.join(ndk_base, 'llvm-libc++')
+    cxx_include = os.path.join(cxx_base, 'libcxx', 'include')
+    cxxabi_base = os.path.join(ndk_base, 'llvm-libc++abi')
+    cxxabi_include = os.path.join(cxxabi_base, 'libcxxabi', 'include')
+
+    if not isdir(cxx_include):
+        # NDK r13 removes the inner "libcxx" directory.
+        cxx_include = os.path.join(cxx_base, 'include')
+        if not isdir(cxx_include):
+            die("Couldn't find path to libc++ includes in the android ndk")
+
+    if not isdir(cxxabi_include):
+        # NDK r13 removes the inner "libcxxabi" directory.
+        cxxabi_include = os.path.join(cxxabi_base, 'include')
+        if not isdir(cxxabi_include):
+            die("Couldn't find path to libc++abi includes in the android ndk")
+
+    # Add android/support/include/ for prototyping long double math
+    # functions, locale-specific C library functions, multibyte support,
+    # etc.
+    return "-I%s -I%s -I%s" % (cxx_include,
+                               os.path.join(ndk, 'sources', 'android',
+                                            'support', 'include'),
+                               cxxabi_include)
+
+add_old_configure_assignment('stlport_cppflags', stlport_cppflags)
+
+@depends(stlport_cppflags, android_platform, android_toolchain,
+         android_toolchain_prefix_base, '--help')
+def bindgen_cflags_defaults(stlport_cppflags, android_platform, toolchain,
+                            toolchain_prefix, _):
+    if not stlport_cppflags:
+        return
+
+    gcc_include = os.path.join(toolchain, 'lib', 'gcc', toolchain_prefix, '4.9')
+
+    cflags_format = "%s -isystem %s -gcc-toolchain %s -I%s -I%s"
+    return cflags_format % (stlport_cppflags,
+                            os.path.join(android_platform, 'usr', 'include'),
+                            toolchain,
+                            os.path.join(gcc_include, 'include'),
+                            os.path.join(gcc_include, 'include-fixed'))
--- a/build/moz.configure/init.configure
+++ b/build/moz.configure/init.configure
@@ -492,17 +492,19 @@ option('--target', nargs=1,
        help='Define the system type where the resulting executables will be '
             'used')
 
 @imports(_from='mozbuild.configure.constants', _import='CPU')
 @imports(_from='mozbuild.configure.constants', _import='CPU_bitness')
 @imports(_from='mozbuild.configure.constants', _import='Endianness')
 @imports(_from='mozbuild.configure.constants', _import='Kernel')
 @imports(_from='mozbuild.configure.constants', _import='OS')
-def split_triplet(triplet):
+@imports(_from='__builtin__', _import='KeyError')
+@imports(_from='__builtin__', _import='ValueError')
+def split_triplet(triplet, allow_unknown=False):
     # The standard triplet is defined as
     #   CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
     # There is also a quartet form:
     #   CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
     # But we can consider the "KERNEL-OPERATING_SYSTEM" as one.
     cpu, manufacturer, os = triplet.split('-', 2)
 
     # Autoconf uses config.sub to validate and canonicalize those triplets,
@@ -539,16 +541,18 @@ def split_triplet(triplet):
     elif os.startswith('freebsd'):
         canonical_os = canonical_kernel = 'FreeBSD'
     elif os.startswith('netbsd'):
         canonical_os = canonical_kernel = 'NetBSD'
     elif os.startswith('openbsd'):
         canonical_os = canonical_kernel = 'OpenBSD'
     elif os.startswith('solaris'):
         canonical_os = canonical_kernel = 'SunOS'
+    elif allow_unknown:
+        canonical_os = canonical_kernel = os
     else:
         die('Unknown OS: %s' % os)
 
     # The CPU granularity is probably not enough. Moving more things from
     # old-configure will tell us if we need more
     if cpu.endswith('86') or (cpu.startswith('i') and '86' in cpu):
         canonical_cpu = 'x86'
         endianness = 'little'
@@ -586,26 +590,40 @@ def split_triplet(triplet):
         canonical_cpu = 'mips64'
         endianness = 'little' if 'el' in cpu else 'big'
     elif cpu.startswith('aarch64'):
         canonical_cpu = 'aarch64'
         endianness = 'little'
     elif cpu == 'sh4':
         canonical_cpu = 'sh4'
         endianness = 'little'
+    elif allow_unknown:
+        canonical_cpu = cpu
+        endianness = 'unknown'
     else:
         die('Unknown CPU type: %s' % cpu)
 
+    def sanitize(cls, value):
+        try:
+            return cls(value)
+        except (KeyError, ValueError):
+            if allow_unknown:
+                return value
+            raise
+
+    def bitness(cpu):
+        return CPU_bitness[cpu]
+
     return namespace(
         alias=triplet,
-        cpu=CPU(canonical_cpu),
-        bitness=CPU_bitness[canonical_cpu],
-        kernel=Kernel(canonical_kernel),
-        os=OS(canonical_os),
-        endianness=Endianness(endianness),
+        cpu=sanitize(CPU, canonical_cpu),
+        bitness=sanitize(bitness, canonical_cpu),
+        kernel=sanitize(Kernel, canonical_kernel),
+        os=sanitize(OS, canonical_os),
+        endianness=sanitize(Endianness, endianness),
         raw_cpu=cpu,
         raw_os=os,
         # Toolchains, most notably for cross compilation may use cpu-os
         # prefixes.
         toolchain='%s-%s' % (cpu, os),
     )
 
 
--- a/build/moz.configure/rust.configure
+++ b/build/moz.configure/rust.configure
@@ -92,99 +92,97 @@ def rust_compiler(rustc_info, cargo_info
         To compile Rust language sources please install at least
         version {} of 'cargo' and make sure it is first in your path.
 
         You can verify this by typing 'cargo --version'.
         ''').format(version, cargo_min_version))
 
     return True
 
+
+@depends(rustc, when=rust_compiler)
+def rust_supported_targets(rustc):
+    out = check_cmd_output(rustc, '--print', 'target-list').splitlines()
+    # The os in the triplets used by rust may match the same OSes, in which
+    # case we need to check the raw_os instead.
+    per_os = {}
+    ambiguous = set()
+    per_raw_os = {}
+    for t in out:
+        t = split_triplet(t, allow_unknown=True)
+        key = (t.cpu, t.os)
+        if key in per_os:
+            previous = per_os[key]
+            per_raw_os[(previous.cpu, previous.raw_os)] = previous
+            del per_os[key]
+            ambiguous.add(key)
+        if key in ambiguous:
+            raw_os = t.raw_os
+            # split_triplet will return a raw_os of 'androideabi' for
+            # rust targets in the form cpu-linux-androideabi, but what
+            # we get from the build system is linux-androideabi, so
+            # normalize.
+            if raw_os == 'androideabi':
+                raw_os = 'linux-androideabi'
+            per_raw_os[(t.cpu, raw_os)] = t
+        else:
+            per_os[key] = t
+    return namespace(per_os=per_os, per_raw_os=per_raw_os)
+
+
 @template
 def rust_triple_alias(host_or_target):
     """Template defining the alias used for rustc's --target flag.
     `host_or_target` is either `host` or `target` (the @depends functions
     from init.configure).
     """
     assert host_or_target in (host, target)
 
-    @depends(rustc, host_or_target, building_with_gcc, when=rust_compiler)
+    @depends(rustc, host_or_target, building_with_gcc, rust_supported_targets,
+             when=rust_compiler)
     @imports('os')
     @imports('subprocess')
     @imports(_from='mozbuild.configure.util', _import='LineIO')
     @imports(_from='mozbuild.shellutil', _import='quote')
     @imports(_from='tempfile', _import='mkstemp')
     @imports(_from='textwrap', _import='dedent')
-    def rust_target(rustc, host_or_target, building_with_gcc):
+    def rust_target(rustc, host_or_target, building_with_gcc,
+                    rust_supported_targets):
         # Rust's --target options are similar to, but not exactly the same
         # as, the autoconf-derived targets we use.  An example would be that
         # Rust uses distinct target triples for targetting the GNU C++ ABI
         # and the MSVC C++ ABI on Win32, whereas autoconf has a single
         # triple and relies on the user to ensure that everything is
         # compiled for the appropriate ABI.  We need to perform appropriate
         # munging to get the correct option to rustc.
-        #
-        # The canonical list of targets supported can be derived from:
-        #
-        # https://github.com/rust-lang/rust/blob/master/src/librustc_back/target/mod.rs
+        # We correlate the autoconf-derived targets with the list of targets
+        # rustc gives us with --print target-list.
+        if host_or_target.kernel == 'WINNT':
+            if building_with_gcc:
+                host_or_target_os = 'windows-gnu'
+            else:
+                host_or_target_os = 'windows-msvc'
+            host_or_target_raw_os = host_or_target_os
+        else:
+            host_or_target_os = host_or_target.os
+            host_or_target_raw_os = host_or_target.raw_os
 
-        # Avoid having to write out os+kernel for all the platforms where
-        # they don't differ.
-        os_or_kernel = host_or_target.kernel if host_or_target.kernel == 'Linux' and host_or_target.os != 'Android' else host_or_target.os
-        # If we are targetting Windows but the compiler is gcc, we need to
-        # use a different rustc target
-        os_or_kernel = 'WINNT-MINGW' if building_with_gcc and host_or_target.kernel == 'WINNT' else os_or_kernel
-        rustc_target = {
-            # DragonFly
-            ('x86_64', 'DragonFly'): 'x86_64-unknown-dragonfly',
-            # FreeBSD
-            ('aarch64', 'FreeBSD'): 'aarch64-unknown-freebsd',
-            ('x86', 'FreeBSD'): 'i686-unknown-freebsd',
-            ('x86_64', 'FreeBSD'): 'x86_64-unknown-freebsd',
-            # NetBSD
-            ('sparc64', 'NetBSD'): 'sparc64-unknown-netbsd',
-            ('x86', 'NetBSD'): 'i686-unknown-netbsd',
-            ('x86_64', 'NetBSD'): 'x86_64-unknown-netbsd',
-            # OpenBSD
-            ('x86', 'OpenBSD'): 'i686-unknown-openbsd',
-            ('x86_64', 'OpenBSD'): 'x86_64-unknown-openbsd',
-            # Linux
-            ('aarch64', 'Linux'): 'aarch64-unknown-linux-gnu',
-            ('arm', 'Linux'): 'armv7-unknown-linux-gnueabihf',
-            ('sparc64', 'Linux'): 'sparc64-unknown-linux-gnu',
-            ('x86', 'Linux'): 'i686-unknown-linux-gnu',
-            ('x86_64', 'Linux'): 'x86_64-unknown-linux-gnu',
-            # OS X
-            ('x86', 'OSX'): 'i686-apple-darwin',
-            ('x86_64', 'OSX'): 'x86_64-apple-darwin',
-            # iOS
-            ('aarch64', 'iOS'): 'aarch64-apple-ios',
-            ('arm', 'iOS'): 'armv7s-apple-ios',
-            ('x86', 'iOS'): 'i386-apple-ios',
-            ('x86_64', 'iOS'): 'x86_64-apple-ios',
-            # Android
-            ('aarch64', 'Android'): 'aarch64-linux-android',
-            ('arm', 'Android'): 'armv7-linux-androideabi',
-            ('x86', 'Android'): 'i686-linux-android',
-            ('x86_64', 'Android'): 'x86_64-linux-android',
-            # Windows
-            ('x86', 'WINNT'): 'i686-pc-windows-msvc',
-            ('x86_64', 'WINNT'): 'x86_64-pc-windows-msvc',
-            ('x86', 'WINNT-MINGW'): 'i686-pc-windows-gnu',
-            ('x86_64', 'WINNT-MINGW'): 'x86_64-pc-windows-gnu',
-            # Solaris
-            ('x86_64', 'SunOS'): 'x86_64-sun-solaris',
-            ('sparc64', 'SunOS'): 'sparcv9-sun-solaris',
-        }.get((host_or_target.cpu, os_or_kernel), None)
+        rustc_target = rust_supported_targets.per_os.get(
+            (host_or_target.cpu, host_or_target_os))
+
+        if rustc_target is None:
+            rustc_target = rust_supported_targets.per_raw_os.get(
+                (host_or_target.cpu, host_or_target_raw_os))
 
         if rustc_target is None:
             die("Don't know how to translate {} for rustc".format(host_or_target.alias))
 
         # Check to see whether our rustc has a reasonably functional stdlib
         # for our chosen target.
-        target_arg = '--target=' + rustc_target
+        target_arg = '--target=' + rustc_target.alias
         in_fd, in_path = mkstemp(prefix='conftest', suffix='.rs')
         out_fd, out_path = mkstemp(prefix='conftest', suffix='.rlib')
         os.close(out_fd)
         try:
             source = 'pub extern fn hello() { println!("Hello world"); }'
             log.debug('Creating `%s` with content:', in_path)
             with LineIO(lambda l: log.debug('| %s', l)) as out:
                 out.write(source)
@@ -201,26 +199,26 @@ def rust_triple_alias(host_or_target):
             ]
             def failed():
                 die(dedent('''\
                 Cannot compile for {} with {}
                 The target may be unsupported, or you may not have
                 a rust std library for that target installed. Try:
 
                   rustup target add {}
-                '''.format(host_or_target.alias, rustc, rustc_target)))
+                '''.format(host_or_target.alias, rustc, rustc_target.alias)))
             check_cmd_output(*cmd, onerror=failed)
             if not os.path.exists(out_path) or os.path.getsize(out_path) == 0:
                 failed()
         finally:
             os.remove(in_path)
             os.remove(out_path)
 
         # This target is usable.
-        return rustc_target
+        return rustc_target.alias
 
     return rust_target
 
 rust_target_triple = rust_triple_alias(target)
 rust_host_triple = rust_triple_alias(host)
 
 set_config('RUST_TARGET', rust_target_triple)
 set_config('RUST_HOST_TARGET', rust_host_triple)
--- a/build/moz.configure/toolchain.configure
+++ b/build/moz.configure/toolchain.configure
@@ -963,16 +963,17 @@ include('compile-checks.configure')
                      check_msg='for 64-bit OS'))
 def check_have_64_bit(have_64_bit, compiler_have_64_bit):
     if have_64_bit != compiler_have_64_bit:
         configure_error('The target compiler does not agree with configure '
                         'about the target bitness.')
 
 option(env='BINDGEN_CFLAGS',
        nargs=1,
+       default=bindgen_cflags_defaults,
        help='Options bindgen should pass to the C/C++ parser')
 
 @depends('BINDGEN_CFLAGS')
 @checking('bindgen cflags', lambda s: s if s and s.strip() else 'no')
 def bindgen_cflags(value):
     if value and len(value):
         # Reformat the env value for substitution into a toml list.
         flags = value[0].split()
--- a/config/check_spidermonkey_style.py
+++ b/config/check_spidermonkey_style.py
@@ -85,22 +85,24 @@ included_inclnames_to_ignore = set([
     'unicode/timezone.h',       # ICU
     'unicode/plurrule.h',       # ICU
     'unicode/ucal.h',           # ICU
     'unicode/uchar.h',          # ICU
     'unicode/uclean.h',         # ICU
     'unicode/ucol.h',           # ICU
     'unicode/udat.h',           # ICU
     'unicode/udatpg.h',         # ICU
+    'unicode/udisplaycontext.h',# ICU
     'unicode/uenum.h',          # ICU
     'unicode/uloc.h',           # ICU
     'unicode/unorm2.h',         # ICU
     'unicode/unum.h',           # ICU
     'unicode/unumsys.h',        # ICU
     'unicode/upluralrules.h',   # ICU
+    'unicode/ureldatefmt.h',    # ICU
     'unicode/ustring.h',        # ICU
     'unicode/utypes.h',         # ICU
     'vtune/VTuneWrapper.h'      # VTune
 ])
 
 # These files have additional constraints on where they are #included, so we
 # ignore #includes of them when checking #include ordering.
 oddly_ordered_inclnames = set([
--- a/config/external/icu/defs.mozbuild
+++ b/config/external/icu/defs.mozbuild
@@ -10,17 +10,16 @@ DEFINES.update(
 
     # Don't include obsolete header files.
     U_NO_DEFAULT_INCLUDE_UTF_HEADERS = 1,
 
     # Remove chunks of the library that we don't need (yet).
     UCONFIG_NO_LEGACY_CONVERSION = True,
     UCONFIG_NO_TRANSLITERATION = True,
     UCONFIG_NO_REGULAR_EXPRESSIONS = True,
-    UCONFIG_NO_BREAK_ITERATION = True,
 
     # We don't need to pass data to and from legacy char* APIs.
     U_CHARSET_IS_UTF8 = True,
 )
 
 if not CONFIG['HAVE_LANGINFO_CODESET']:
     DEFINES['U_HAVE_NL_LANGINFO_CODESET'] = 0
 
--- a/config/system-headers
+++ b/config/system-headers
@@ -1322,19 +1322,21 @@ unicode/numsys.h
 unicode/plurrule.h
 unicode/timezone.h
 unicode/ucal.h
 unicode/uchar.h
 unicode/uclean.h
 unicode/ucol.h
 unicode/udat.h
 unicode/udatpg.h
+unicode/udisplaycontext.h
 unicode/uenum.h
 unicode/unistr.h
 unicode/unorm.h
 unicode/unum.h
 unicode/upluralrules.h
+unicode/ureldatefmt.h
 unicode/ustring.h
 unicode/utypes.h
 #endif
 libutil.h
 unwind.h
 fenv.h
--- a/devtools/client/animationinspector/graph-helper.js
+++ b/devtools/client/animationinspector/graph-helper.js
@@ -351,23 +351,30 @@ SummaryGraphHelper.prototype = {
    * Also, allows null value. In case of null, this graph helper shapes graph using
    * computed timing progress.
    * @param {Object} keyframes - Should have offset and easing, or null.
    */
   setKeyframes: function (keyframes) {
     let frames = null;
     if (keyframes) {
       // Create new keyframes for opacity as computed style.
+      // The reason why we use computed value instead of computed timing progress is to
+      // include the easing in keyframes as well. Although the computed timing progress
+      // is not affected by the easing in keyframes at all, computed value reflects that.
       frames = keyframes.map(keyframe => {
         return {
           opacity: keyframe.offset,
           offset: keyframe.offset,
           easing: keyframe.easing
         };
       });
+
+      // Set the underlying opacity to zero so that if we sample the animation's output
+      // during the delay phase and it is not filling backwards, we get zero.
+      this.targetEl.style.opacity = 0;
     }
     this.animation.effect.setKeyframes(frames);
     this.hasFrames = !!frames;
   },
 
   /*
    * Set animation behavior.
    * In Animation::SetCurrentTime spec, even if current time of animation is over
--- a/devtools/client/animationinspector/test/browser_animation_summarygraph_for_multiple_easings.js
+++ b/devtools/client/animationinspector/test/browser_animation_summarygraph_for_multiple_easings.js
@@ -17,17 +17,16 @@ const TEST_CASES = {
   "no-easing": {
     expectedKeyframeEasingGraphs: [
       [
         { x: 0, y: 0 },
         { x: 25000, y: 0.25 },
         { x: 50000, y: 0.5 },
         { x: 75000, y: 0.75 },
         { x: 99000, y: 0.99 },
-        { x: 100000, y: 1 },
         { x: 100000, y: 0 },
       ]
     ]
   },
   "effect-easing": {
     expectedEffectEasingGraph: [
       { x: 0, y: 0 },
       { x: 19999, y: 0.0 },
@@ -59,17 +58,16 @@ const TEST_CASES = {
   },
   "keyframe-easing": {
     expectedKeyframeEasingGraphs: [
       [
         { x: 0, y: 0 },
         { x: 49999, y: 0.0 },
         { x: 50000, y: 0.5 },
         { x: 99999, y: 0.5 },
-        { x: 100000, y: 1 },
         { x: 100000, y: 0 },
       ]
     ]
   },
   "both-easing": {
     expectedEffectEasingGraph: [
       { x: 0, y: 0 },
       { x: 9999, y: 0.0 },
@@ -102,25 +100,23 @@ const TEST_CASES = {
         { x: 20000, y: 0.2 },
         { x: 39999, y: 0.2 },
         { x: 40000, y: 0.4 },
         { x: 59999, y: 0.4 },
         { x: 60000, y: 0.6 },
         { x: 79999, y: 0.6 },
         { x: 80000, y: 0.8 },
         { x: 99999, y: 0.8 },
-        { x: 100000, y: 1 },
         { x: 100000, y: 0 },
       ],
       [
         { x: 0, y: 0 },
         { x: 49999, y: 0.0 },
         { x: 50000, y: 0.5 },
         { x: 99999, y: 0.5 },
-        { x: 100000, y: 1 },
         { x: 100000, y: 0 },
       ]
     ]
   }
 };
 
 add_task(function* () {
   yield addTab(URL_ROOT + "doc_multiple_easings.html");
--- a/devtools/client/animationinspector/test/browser_animation_timeline_iterationStart.js
+++ b/devtools/client/animationinspector/test/browser_animation_timeline_iterationStart.js
@@ -43,26 +43,46 @@ function checkAnimationTooltip(el, {iter
   }).replace(".", "\\.");
   let iterationStartString = iterationStart.toString().replace(".", "\\.");
 
   let regex = new RegExp("Iteration start: " + iterationStartString +
                          " \\(" + iterationStartTimeString + "s\\)");
   ok(title.match(regex), "The tooltip shows the expected iteration start");
 }
 
-function checkProgressAtStartingTime(el, { iterationStart }) {
+function checkProgressAtStartingTime(el, { delay, iterationStart }) {
   info("Check the progress of starting time");
   const groupEls = el.querySelectorAll("svg g");
   groupEls.forEach(groupEl => {
     const pathEl = groupEl.querySelector(".iteration-path");
     const pathSegList = pathEl.pathSegList;
     const pathSeg = pathSegList.getItem(1);
     const progress = pathSeg.y;
     is(progress, iterationStart % 1,
        `The progress at starting point should be ${ iterationStart % 1 }`);
+
+    if (delay) {
+      const delayPathEl = groupEl.querySelector(".delay-path");
+      const delayPathSegList = delayPathEl.pathSegList;
+      const delayStartingPathSeg = delayPathSegList.getItem(1);
+      const delayEndingPathSeg =
+        delayPathSegList.getItem(delayPathSegList.numberOfItems - 2);
+      const startingX = 0;
+      const endingX = delay;
+      is(delayStartingPathSeg.x, startingX,
+         `The x of starting point should be ${ startingX }`);
+      is(delayStartingPathSeg.y, progress,
+         "The y of starting point should be same to starting point of iteration-path "
+         + progress);
+      is(delayEndingPathSeg.x, endingX,
+         `The x of ending point should be ${ endingX }`);
+      is(delayStartingPathSeg.y, progress,
+         "The y of ending point should be same to starting point of iteration-path "
+         + progress);
+    }
   });
 }
 
 function checkKeyframeOffset(timeBlockEl, frameEl, {iterationStart}) {
   info("Check that the first keyframe is offset correctly");
 
   let start = getKeyframeOffset(frameEl);
   is(start, 0, "The frame offset for iteration start");
--- a/devtools/client/animationinspector/test/browser_animation_timeline_short_duration.js
+++ b/devtools/client/animationinspector/test/browser_animation_timeline_short_duration.js
@@ -77,19 +77,18 @@ function checkSummaryGraph(el, state, is
       // The test animation is not 'forwards' fill-mode.
       // Therefore, the y of second last path segment will be 0.
       const secondLastPathSeg =
         pathSegList.getItem(pathSegList.numberOfItems - 3);
       is(secondLastPathSeg.x, endX,
          `The x of second last segment should be ${ endX }`);
       // We use computed style of 'opacity' to create summary graph.
       // So, if currentTime is same to the duration, although progress is null
-      // opacity is 1.
-      const expectedY =
-        state.iterationCount && expectedIterationCount === index + 1 ? 1 : 0;
+      // opacity is 0.
+      const expectedY = 0;
       is(secondLastPathSeg.y, expectedY,
          `The y of second last segment should be ${ expectedY }`);
 
       const lastPathSeg = pathSegList.getItem(pathSegList.numberOfItems - 2);
       is(lastPathSeg.x, endX, `The x of last segment should be ${ endX }`);
       is(lastPathSeg.y, 0, "The y of last segment should be 0");
 
       const closePathSeg = pathSegList.getItem(pathSegList.numberOfItems - 1);
--- a/devtools/client/animationinspector/test/browser_animation_timeline_shows_delay.js
+++ b/devtools/client/animationinspector/test/browser_animation_timeline_shows_delay.js
@@ -74,26 +74,36 @@ function checkPath(animationEl, state) {
 
     // Check delay path coordinates.
     const pathSegList = delayPathEl.pathSegList;
     const startingPathSeg = pathSegList.getItem(0);
     const endingPathSeg = pathSegList.getItem(pathSegList.numberOfItems - 2);
     if (state.delay < 0) {
       ok(delayPathEl.classList.contains("negative"),
          "The delay path should have 'negative' class");
+      const expectedY = 0;
       const startingX = state.delay;
       const endingX = 0;
       is(startingPathSeg.x, startingX,
          `The x of starting point should be ${ startingX }`);
+      is(startingPathSeg.y, expectedY,
+         `The y of starting point should be ${ expectedY }`);
       is(endingPathSeg.x, endingX,
          `The x of ending point should be ${ endingX }`);
+      is(endingPathSeg.y, expectedY,
+         `The y of ending point should be ${ expectedY }`);
     } else {
       ok(!delayPathEl.classList.contains("negative"),
          "The delay path should not have 'negative' class");
+      const expectedY = 0;
       const startingX = 0;
       const endingX = state.delay;
       is(startingPathSeg.x, startingX,
          `The x of starting point should be ${ startingX }`);
+      is(startingPathSeg.y, expectedY,
+         `The y of starting point should be ${ expectedY }`);
       is(endingPathSeg.x, endingX,
          `The x of ending point should be ${ endingX }`);
+      is(endingPathSeg.y, expectedY,
+         `The y of ending point should be ${ expectedY }`);
     }
   });
 }
--- a/devtools/client/animationinspector/test/doc_script_animation.html
+++ b/devtools/client/animationinspector/test/doc_script_animation.html
@@ -15,22 +15,29 @@
     background: green;
   }
 
   #target3 {
     width: 50px;
     height: 50px;
     background: blue;
   }
+
+  #target4 {
+    width: 50px;
+    height: 50px;
+    background: pink;
+  }
   </style>
 </head>
 <body>
   <div id="target1"></div>
   <div id="target2"></div>
   <div id="target3"></div>
+  <div id="target4"></div>
 
   <script>
     /* globals KeyframeEffect, Animation */
     "use strict";
 
     let animations = [{
       id: "target1",
       frames: [{ opacity: 0, offset: 0 }, { opacity: 1, offset: 1 }],
@@ -53,19 +60,31 @@
       id: "target3",
       frames: [{ opacity: 0, offset: 0 }, { opacity: 1, offset: 1 }],
       timing: {
         duration: 100,
         iterations: 1.5,
         iterationStart: 2.5,
         fill: "both"
       }
+    }, {
+      id: "target4",
+      frames: [{ transform: "translate(0px)", offset: 0 },
+               { transform: "translate(100px)", offset: 1 }],
+      timing: {
+        duration: 100,
+        iterations: 2,
+        iterationStart: 0.5,
+        delay: 10,
+        fill: "both"
+      }
     }];
 
     for (let {id, frames, timing} of animations) {
       let effect = new KeyframeEffect(document.getElementById(id),
                                       frames, timing);
       let animation = new Animation(effect, document.timeline);
       animation.play();
+      animation.pause();
     }
   </script>
 </body>
 </html>
--- a/dom/media/AudioCaptureStream.cpp
+++ b/dom/media/AudioCaptureStream.cpp
@@ -155,17 +155,16 @@ AudioCaptureStream::MixerCallback(AudioD
     PodCopy(out, aMixedBuffer + written, aFrames);
     bufferPtrs[channel] = out;
     written += aFrames;
   }
   AudioChunk chunk;
   chunk.mBuffer = new mozilla::SharedChannelArrayBuffer<AudioDataValue>(&output);
   chunk.mDuration = aFrames;
   chunk.mBufferFormat = aFormat;
-  chunk.mVolume = 1.0f;
   chunk.mChannelData.SetLength(MONO);
   for (uint32_t channel = 0; channel < aChannels; channel++) {
     chunk.mChannelData[channel] = bufferPtrs[channel];
   }
 
   // Now we have mixed data, simply append it to out track.
   EnsureTrack(mTrackId)->Get<AudioSegment>()->AppendAndConsumeChunk(&chunk);
 }
--- a/dom/media/AudioSampleFormat.h
+++ b/dom/media/AudioSampleFormat.h
@@ -15,22 +15,22 @@ namespace mozilla {
  * Audio formats supported in MediaStreams and media elements.
  *
  * Only one of these is supported by AudioStream, and that is determined
  * at compile time (roughly, FLOAT32 on desktops, S16 on mobile). Media decoders
  * produce that format only; queued AudioData always uses that format.
  */
 enum AudioSampleFormat
 {
+  // Silence: format will be chosen later
+  AUDIO_FORMAT_SILENCE,
   // Native-endian signed 16-bit audio samples
   AUDIO_FORMAT_S16,
   // Signed 32-bit float samples
   AUDIO_FORMAT_FLOAT32,
-  // Silence: format will be chosen later
-  AUDIO_FORMAT_SILENCE,
   // The format used for output by AudioStream.
 #ifdef MOZ_SAMPLE_TYPE_S16
   AUDIO_OUTPUT_FORMAT = AUDIO_FORMAT_S16
 #else
   AUDIO_OUTPUT_FORMAT = AUDIO_FORMAT_FLOAT32
 #endif
 };
 
@@ -241,18 +241,18 @@ ScaleAudioSamples(short* aBuffer, int aC
     aBuffer[i] = short((int32_t(aBuffer[i]) * volume) >> 16);
   }
 }
 
 inline const void*
 AddAudioSampleOffset(const void* aBase, AudioSampleFormat aFormat,
                      int32_t aOffset)
 {
-  static_assert(AUDIO_FORMAT_S16 == 0, "Bad constant");
-  static_assert(AUDIO_FORMAT_FLOAT32 == 1, "Bad constant");
+  static_assert(AUDIO_FORMAT_S16 == 1, "Bad constant");
+  static_assert(AUDIO_FORMAT_FLOAT32 == 2, "Bad constant");
   MOZ_ASSERT(aFormat == AUDIO_FORMAT_S16 || aFormat == AUDIO_FORMAT_FLOAT32);
 
-  return static_cast<const uint8_t*>(aBase) + (aFormat + 1)*2*aOffset;
+  return static_cast<const uint8_t*>(aBase) + aFormat*2*aOffset;
 }
 
 } // namespace mozilla
 
 #endif /* MOZILLA_AUDIOSAMPLEFORMAT_H_ */
--- a/dom/media/AudioSegment.h
+++ b/dom/media/AudioSegment.h
@@ -145,20 +145,16 @@ DownmixAndInterleave(const nsTArray<cons
  * of the buffer. An AudioChunk maintains its own duration and channel data
  * pointers so it can represent a subinterval of a buffer without copying.
  * An AudioChunk can store its individual channels anywhere; it maintains
  * separate pointers to each channel's buffer.
  */
 struct AudioChunk {
   typedef mozilla::AudioSampleFormat SampleFormat;
 
-  AudioChunk()
-    : mPrincipalHandle(PRINCIPAL_HANDLE_NONE)
-  {}
-
   // Generic methods
   void SliceTo(StreamTime aStart, StreamTime aEnd)
   {
     MOZ_ASSERT(aStart >= 0 && aStart < aEnd && aEnd <= mDuration,
                "Slice out of bounds");
     if (mBuffer) {
       MOZ_ASSERT(aStart < INT32_MAX, "Can't slice beyond 32-bit sample lengths");
       for (uint32_t channel = 0; channel < mChannelData.Length(); ++channel) {
@@ -244,28 +240,29 @@ struct AudioChunk {
   {
     MOZ_ASSERT(AudioSampleTypeToFormat<T>::Format == mBufferFormat);
     MOZ_ASSERT(!mBuffer->IsShared());
     return static_cast<T*>(const_cast<void*>(mChannelData[aChannel]));
   }
 
   PrincipalHandle GetPrincipalHandle() const { return mPrincipalHandle; }
 
-  StreamTime mDuration; // in frames within the buffer
+  StreamTime mDuration = 0; // in frames within the buffer
   RefPtr<ThreadSharedObject> mBuffer; // the buffer object whose lifetime is managed; null means data is all zeroes
   // one pointer per channel; empty if and only if mBuffer is null
   AutoTArray<const void*,GUESS_AUDIO_CHANNELS> mChannelData;
-  float mVolume; // volume multiplier to apply (1.0f if mBuffer is nonnull)
-  SampleFormat mBufferFormat; // format of frames in mBuffer (only meaningful if mBuffer is nonnull)
+  float mVolume = 1.0f; // volume multiplier to apply
+  // format of frames in mBuffer (or silence if mBuffer is null)
+  SampleFormat mBufferFormat = AUDIO_FORMAT_SILENCE;
 #ifdef MOZILLA_INTERNAL_API
   mozilla::TimeStamp mTimeStamp;           // time at which this has been fetched from the MediaEngine
 #endif
   // principalHandle for the data in this chunk.
   // This can be compared to an nsIPrincipal* when back on main thread.
-  PrincipalHandle mPrincipalHandle;
+  PrincipalHandle mPrincipalHandle = PRINCIPAL_HANDLE_NONE;
 };
 
 /**
  * A list of audio samples consisting of a sequence of slices of SharedBuffers.
  * The audio rate is determined by the track, not stored in this class.
  */
 class AudioSegment : public MediaSegmentBase<AudioSegment, AudioChunk> {
 public:
@@ -341,33 +338,31 @@ public:
                     const nsTArray<const float*>& aChannelData,
                     int32_t aDuration, const PrincipalHandle& aPrincipalHandle)
   {
     AudioChunk* chunk = AppendChunk(aDuration);
     chunk->mBuffer = aBuffer;
     for (uint32_t channel = 0; channel < aChannelData.Length(); ++channel) {
       chunk->mChannelData.AppendElement(aChannelData[channel]);
     }
-    chunk->mVolume = 1.0f;
     chunk->mBufferFormat = AUDIO_FORMAT_FLOAT32;
 #ifdef MOZILLA_INTERNAL_API
     chunk->mTimeStamp = TimeStamp::Now();
 #endif
     chunk->mPrincipalHandle = aPrincipalHandle;
   }
   void AppendFrames(already_AddRefed<ThreadSharedObject> aBuffer,
                     const nsTArray<const int16_t*>& aChannelData,
                     int32_t aDuration, const PrincipalHandle& aPrincipalHandle)
   {
     AudioChunk* chunk = AppendChunk(aDuration);
     chunk->mBuffer = aBuffer;
     for (uint32_t channel = 0; channel < aChannelData.Length(); ++channel) {
       chunk->mChannelData.AppendElement(aChannelData[channel]);
     }
-    chunk->mVolume = 1.0f;
     chunk->mBufferFormat = AUDIO_FORMAT_S16;
 #ifdef MOZILLA_INTERNAL_API
     chunk->mTimeStamp = TimeStamp::Now();
 #endif
     chunk->mPrincipalHandle = aPrincipalHandle;
   }
   // Consumes aChunk, and returns a pointer to the persistent copy of aChunk
   // in the segment.
--- a/dom/media/doctor/gtest/TestMultiWriterQueue.cpp
+++ b/dom/media/doctor/gtest/TestMultiWriterQueue.cpp
@@ -143,17 +143,17 @@ TestMultiWriterQueueMT(int aWriterThread
     NS_RELEASE(array[k]);
   }
   delete[] array;
 
   // There may be a few more elements that haven't been read yet.
   q.PopAll([&pops](const int& i) { ++pops; });
   const int pushes = aWriterThreads * loops;
   EXPECT_EQ(pushes, pops);
-  q.PopAll([&pops](const int& i) { EXPECT_TRUE(false); });
+  q.PopAll([](const int& i) { EXPECT_TRUE(false); });
 
   double duration = mozilla::ToSeconds(mozilla::DDNow()) - start - 0.1;
   printf("%s threads=%dw+%dr loops/thread=%d pushes=pops=%d duration=%fs "
          "pushes/s=%f buffers: live=%d (w %d) reusable=%d (w %d) "
          "alloc=%d (w %d)\n",
          aPrintPrefix,
          aWriterThreads,
          aReaderThreads,
@@ -392,9 +392,9 @@ TEST(MultiWriterQueue, nsDequeBenchmark)
   TestMultiWriterQueueMT<DequeWrapperAW>(
     8, 0, 2 * 1024 * 1024, "DequeWrapperAW ");
   TestMultiWriterQueueMT<DequeWrapperMW>(
     8, 0, 2 * 1024 * 1024, "DequeWrapperMW ");
   TestMultiWriterQueueMT<DequeWrapperMT>(
     8, 0, 2 * 1024 * 1024, "DequeWrapperMT ");
   TestMultiWriterQueueMT<DequeWrapperMT>(
     8, 1, 2 * 1024 * 1024, "DequeWrapperMT ");
-}
\ No newline at end of file
+}
--- a/dom/media/webaudio/AudioBuffer.cpp
+++ b/dom/media/webaudio/AudioBuffer.cpp
@@ -217,17 +217,16 @@ AudioBuffer::SetSharedChannels(
 {
   RefPtr<ThreadSharedFloatArrayBufferList> buffer = aBuffer;
   uint32_t channelCount = buffer->GetChannels();
   mSharedChannels.mChannelData.SetLength(channelCount);
   for (uint32_t i = 0; i < channelCount; ++i) {
     mSharedChannels.mChannelData[i] = buffer->GetData(i);
   }
   mSharedChannels.mBuffer = buffer.forget();
-  mSharedChannels.mVolume = 1.0f;
   mSharedChannels.mBufferFormat = AUDIO_FORMAT_FLOAT32;
 }
 
 /* static */ already_AddRefed<AudioBuffer>
 AudioBuffer::Create(nsPIDOMWindowInner* aWindow, uint32_t aNumberOfChannels,
                     uint32_t aLength, float aSampleRate,
                     already_AddRefed<ThreadSharedFloatArrayBufferList>
                       aInitialContents,
@@ -311,18 +310,17 @@ AudioBuffer::RestoreJSChannelData(JSCont
       bool isShared;
       float* jsData = JS_GetFloat32ArrayData(array, &isShared, nogc);
       MOZ_ASSERT(!isShared); // Was created as unshared above
       CopyChannelDataToFloat(mSharedChannels, i, 0, jsData, Length());
     }
     mJSChannels[i] = array;
   }
 
-  mSharedChannels.mBuffer = nullptr;
-  mSharedChannels.mChannelData.Clear();
+  mSharedChannels.SetNull(Length());
 
   return true;
 }
 
 void
 AudioBuffer::CopyFromChannel(const Float32Array& aDestination, uint32_t aChannelNumber,
                              uint32_t aStartInChannel, ErrorResult& aRv)
 {
--- a/js/public/Class.h
+++ b/js/public/Class.h
@@ -854,17 +854,17 @@ static const uint32_t JSCLASS_FOREGROUND
 // with the following flags. Failure to use JSCLASS_GLOBAL_FLAGS was
 // previously allowed, but is now an ES5 violation and thus unsupported.
 //
 // JSCLASS_GLOBAL_APPLICATION_SLOTS is the number of slots reserved at
 // the beginning of every global object's slots for use by the
 // application.
 static const uint32_t JSCLASS_GLOBAL_APPLICATION_SLOTS = 5;
 static const uint32_t JSCLASS_GLOBAL_SLOT_COUNT =
-    JSCLASS_GLOBAL_APPLICATION_SLOTS + JSProto_LIMIT * 2 + 37;
+    JSCLASS_GLOBAL_APPLICATION_SLOTS + JSProto_LIMIT * 2 + 38;
 
 #define JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(n)                              \
     (JSCLASS_IS_GLOBAL | JSCLASS_HAS_RESERVED_SLOTS(JSCLASS_GLOBAL_SLOT_COUNT + (n)))
 #define JSCLASS_GLOBAL_FLAGS                                                  \
     JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(0)
 #define JSCLASS_HAS_GLOBAL_FLAG_AND_SLOTS(clasp)                              \
   (((clasp)->flags & JSCLASS_IS_GLOBAL)                                       \
    && JSCLASS_RESERVED_SLOTS(clasp) >= JSCLASS_GLOBAL_SLOT_COUNT)
--- a/js/src/builtin/Intl.cpp
+++ b/js/src/builtin/Intl.cpp
@@ -7,16 +7,17 @@
 /*
  * The Intl module specified by standard ECMA-402,
  * ECMAScript Internationalization API Specification.
  */
 
 #include "builtin/Intl.h"
 
 #include "mozilla/Casting.h"
+#include "mozilla/FloatingPoint.h"
 #include "mozilla/HashFunctions.h"
 #include "mozilla/PodOperations.h"
 #include "mozilla/Range.h"
 #include "mozilla/TypeTraits.h"
 
 #include <string.h>
 
 #include "jsapi.h"
@@ -29,21 +30,23 @@
 
 #include "builtin/IntlTimeZoneData.h"
 #include "ds/Sort.h"
 #if ENABLE_INTL_API
 #include "unicode/ucal.h"
 #include "unicode/ucol.h"
 #include "unicode/udat.h"
 #include "unicode/udatpg.h"
+#include "unicode/udisplaycontext.h"
 #include "unicode/uenum.h"
 #include "unicode/uloc.h"
 #include "unicode/unum.h"
 #include "unicode/unumsys.h"
 #include "unicode/upluralrules.h"
+#include "unicode/ureldatefmt.h"
 #include "unicode/ustring.h"
 #endif
 #include "vm/DateTime.h"
 #include "vm/GlobalObject.h"
 #include "vm/Interpreter.h"
 #include "vm/SelfHosting.h"
 #include "vm/Stack.h"
 #include "vm/String.h"
@@ -741,16 +744,69 @@ u_strToUpper(UChar* dest, int32_t destCa
 const char*
 uloc_toUnicodeLocaleType(const char* keyword, const char* value)
 {
     MOZ_CRASH("uloc_toUnicodeLocaleType: Intl API disabled");
 }
 
 } // anonymous namespace
 
+enum UDateRelativeDateTimeFormatterStyle {
+    UDAT_STYLE_LONG,
+    UDAT_STYLE_SHORT,
+    UDAT_STYLE_NARROW
+};
+
+enum URelativeDateTimeUnit {
+    UDAT_REL_UNIT_YEAR,
+    UDAT_REL_UNIT_QUARTER,
+    UDAT_REL_UNIT_MONTH,
+    UDAT_REL_UNIT_WEEK,
+    UDAT_REL_UNIT_DAY,
+    UDAT_REL_UNIT_HOUR,
+    UDAT_REL_UNIT_MINUTE,
+    UDAT_REL_UNIT_SECOND,
+};
+
+enum UDisplayContext {
+    UDISPCTX_STANDARD_NAMES,
+    UDISPCTX_DIALECT_NAMES,
+    UDISPCTX_CAPITALIZATION_NONE,
+    UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE,
+    UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE,
+    UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU,
+    UDISPCTX_CAPITALIZATION_FOR_STANDALONE,
+    UDISPCTX_LENGTH_FULL,
+    UDISPCTX_LENGTH_SHORT
+};
+
+typedef void* URelativeDateTimeFormatter;
+
+URelativeDateTimeFormatter*
+ureldatefmt_open(const char* locale, UNumberFormat* nfToAdopt,
+                 UDateRelativeDateTimeFormatterStyle width, UDisplayContext capitalizationContext,
+                 UErrorCode* status)
+{
+    MOZ_CRASH("ureldatefmt_open: Intl API disabled");
+}
+
+void
+ureldatefmt_close(URelativeDateTimeFormatter *reldatefmt)
+{
+    MOZ_CRASH("ureldatefmt_close: Intl API disabled");
+}
+
+int32_t
+ureldatefmt_format(const URelativeDateTimeFormatter* reldatefmt, double offset,
+                    URelativeDateTimeUnit unit, UChar* result, int32_t resultCapacity,
+                    UErrorCode* status)
+{
+    MOZ_CRASH("ureldatefmt_format: Intl API disabled");
+}
+
 #endif
 
 
 /******************** Common to Intl constructors ********************/
 
 static bool
 IntlInitialize(JSContext* cx, HandleObject obj, Handle<PropertyName*> initializer,
                HandleValue locales, HandleValue options)
@@ -3721,16 +3777,277 @@ js::intl_GetPluralCategories(JSContext* 
         if (!DefineDataElement(cx, res, i++, element))
             return false;
     } while (true);
 
     args.rval().setObject(*res);
     return true;
 }
 
+/**************** RelativeTimeFormat *****************/
+
+const ClassOps RelativeTimeFormatObject::classOps_ = {
+    nullptr, /* addProperty */
+    nullptr, /* delProperty */
+    nullptr, /* enumerate */
+    nullptr, /* newEnumerate */
+    nullptr, /* resolve */
+    nullptr, /* mayResolve */
+    RelativeTimeFormatObject::finalize
+};
+
+const Class RelativeTimeFormatObject::class_ = {
+    js_Object_str,
+    JSCLASS_HAS_RESERVED_SLOTS(RelativeTimeFormatObject::SLOT_COUNT) |
+    JSCLASS_FOREGROUND_FINALIZE,
+    &RelativeTimeFormatObject::classOps_
+};
+
+#if JS_HAS_TOSOURCE
+static bool
+relativeTimeFormat_toSource(JSContext* cx, unsigned argc, Value* vp)
+{
+    CallArgs args = CallArgsFromVp(argc, vp);
+    args.rval().setString(cx->names().RelativeTimeFormat);
+    return true;
+}
+#endif
+
+static const JSFunctionSpec relativeTimeFormat_static_methods[] = {
+    JS_SELF_HOSTED_FN("supportedLocalesOf", "Intl_RelativeTimeFormat_supportedLocalesOf", 1, 0),
+    JS_FS_END
+};
+
+static const JSFunctionSpec relativeTimeFormat_methods[] = {
+    JS_SELF_HOSTED_FN("resolvedOptions", "Intl_RelativeTimeFormat_resolvedOptions", 0, 0),
+    JS_SELF_HOSTED_FN("format", "Intl_RelativeTimeFormat_format", 2, 0),
+#if JS_HAS_TOSOURCE
+    JS_FN(js_toSource_str, relativeTimeFormat_toSource, 0, 0),
+#endif
+    JS_FS_END
+};
+
+/**
+ * RelativeTimeFormat constructor.
+ * Spec: ECMAScript 402 API, RelativeTimeFormat, 1.1
+ */
+static bool
+RelativeTimeFormat(JSContext* cx, unsigned argc, Value* vp)
+{
+    CallArgs args = CallArgsFromVp(argc, vp);
+
+    // Step 1.
+    if (!ThrowIfNotConstructing(cx, args, "Intl.PluralRules"))
+        return false;
+
+    // Step 2 (Inlined 9.1.14, OrdinaryCreateFromConstructor).
+    RootedObject proto(cx);
+    if (!GetPrototypeFromBuiltinConstructor(cx, args, &proto))
+        return false;
+
+    if (!proto) {
+        proto = GlobalObject::getOrCreateRelativeTimeFormatPrototype(cx, cx->global());
+        if (!proto)
+            return false;
+    }
+
+    Rooted<RelativeTimeFormatObject*> relativeTimeFormat(cx);
+    relativeTimeFormat = NewObjectWithGivenProto<RelativeTimeFormatObject>(cx, proto);
+    if (!relativeTimeFormat)
+        return false;
+
+    relativeTimeFormat->setReservedSlot(RelativeTimeFormatObject::INTERNALS_SLOT, NullValue());
+    relativeTimeFormat->setReservedSlot(RelativeTimeFormatObject::URELATIVE_TIME_FORMAT_SLOT, PrivateValue(nullptr));
+
+    HandleValue locales = args.get(0);
+    HandleValue options = args.get(1);
+
+    // Step 3.
+    if (!IntlInitialize(cx, relativeTimeFormat, cx->names().InitializeRelativeTimeFormat, locales, options))
+        return false;
+
+    args.rval().setObject(*relativeTimeFormat);
+    return true;
+}
+
+void
+RelativeTimeFormatObject::finalize(FreeOp* fop, JSObject* obj)
+{
+    MOZ_ASSERT(fop->onActiveCooperatingThread());
+
+    const Value& slot =
+        obj->as<RelativeTimeFormatObject>().getReservedSlot(RelativeTimeFormatObject::URELATIVE_TIME_FORMAT_SLOT);
+    if (URelativeDateTimeFormatter* rtf = static_cast<URelativeDateTimeFormatter*>(slot.toPrivate()))
+        ureldatefmt_close(rtf);
+}
+
+static JSObject*
+CreateRelativeTimeFormatPrototype(JSContext* cx, HandleObject Intl, Handle<GlobalObject*> global)
+{
+    RootedFunction ctor(cx);
+    ctor = global->createConstructor(cx, &RelativeTimeFormat, cx->names().RelativeTimeFormat, 0);
+    if (!ctor)
+        return nullptr;
+
+    RootedObject proto(cx, GlobalObject::createBlankPrototype<PlainObject>(cx, global));
+    if (!proto)
+        return nullptr;
+
+    if (!LinkConstructorAndPrototype(cx, ctor, proto))
+        return nullptr;
+
+    if (!JS_DefineFunctions(cx, ctor, relativeTimeFormat_static_methods))
+        return nullptr;
+
+    if (!JS_DefineFunctions(cx, proto, relativeTimeFormat_methods))
+        return nullptr;
+
+    RootedValue ctorValue(cx, ObjectValue(*ctor));
+    if (!DefineDataProperty(cx, Intl, cx->names().RelativeTimeFormat, ctorValue, 0))
+        return nullptr;
+
+    return proto;
+}
+
+/* static */ bool
+js::GlobalObject::addRelativeTimeFormatConstructor(JSContext* cx, HandleObject intl)
+{
+    Handle<GlobalObject*> global = cx->global();
+
+    {
+        const HeapSlot& slot = global->getReservedSlotRef(RELATIVE_TIME_FORMAT_PROTO);
+        if (!slot.isUndefined()) {
+            MOZ_ASSERT(slot.isObject());
+            JS_ReportErrorASCII(cx,
+                                "the RelativeTimeFormat constructor can't be added "
+                                "multiple times in the same global");
+            return false;
+        }
+    }
+
+    JSObject* relativeTimeFormatProto = CreateRelativeTimeFormatPrototype(cx, intl, global);
+    if (!relativeTimeFormatProto)
+        return false;
+
+    global->setReservedSlot(RELATIVE_TIME_FORMAT_PROTO, ObjectValue(*relativeTimeFormatProto));
+    return true;
+}
+
+bool
+js::AddRelativeTimeFormatConstructor(JSContext* cx, JS::Handle<JSObject*> intl)
+{
+    return GlobalObject::addRelativeTimeFormatConstructor(cx, intl);
+}
+
+
+bool
+js::intl_RelativeTimeFormat_availableLocales(JSContext* cx, unsigned argc, Value* vp)
+{
+    CallArgs args = CallArgsFromVp(argc, vp);
+    MOZ_ASSERT(args.length() == 0);
+
+    RootedValue result(cx);
+    // We're going to use ULocale availableLocales as per ICU recommendation:
+    // https://ssl.icu-project.org/trac/ticket/12756
+    if (!intl_availableLocales(cx, uloc_countAvailable, uloc_getAvailable, &result))
+        return false;
+    args.rval().set(result);
+    return true;
+}
+
+bool
+js::intl_FormatRelativeTime(JSContext* cx, unsigned argc, Value* vp)
+{
+    CallArgs args = CallArgsFromVp(argc, vp);
+    MOZ_ASSERT(args.length() == 3);
+
+    RootedObject relativeTimeFormat(cx, &args[0].toObject());
+
+    RootedObject internals(cx, GetInternals(cx, relativeTimeFormat));
+    if (!internals)
+        return false;
+
+    RootedValue value(cx);
+
+    if (!GetProperty(cx, internals, internals, cx->names().locale, &value))
+        return false;
+    JSAutoByteString locale(cx, value.toString());
+    if (!locale)
+        return false;
+
+    if (!GetProperty(cx, internals, internals, cx->names().style, &value))
+        return false;
+    RootedLinearString style(cx, value.toString()->ensureLinear(cx));
+    if (!style)
+        return false;
+
+    double t = args[1].toNumber();
+
+    UDateRelativeDateTimeFormatterStyle relDateTimeStyle;
+
+    if (StringEqualsAscii(style, "short")) {
+        relDateTimeStyle = UDAT_STYLE_SHORT;
+    } else if (StringEqualsAscii(style, "narrow")) {
+        relDateTimeStyle = UDAT_STYLE_NARROW;
+    } else {
+        MOZ_ASSERT(StringEqualsAscii(style, "long"));
+        relDateTimeStyle = UDAT_STYLE_LONG;
+    }
+
+    JSLinearString* unit = args[2].toString()->ensureLinear(cx);
+    if (!unit)
+        return false;
+
+    URelativeDateTimeUnit relDateTimeUnit;
+
+    if (StringEqualsAscii(unit, "second")) {
+        relDateTimeUnit = UDAT_REL_UNIT_SECOND;
+    } else if (StringEqualsAscii(unit, "minute")) {
+        relDateTimeUnit = UDAT_REL_UNIT_MINUTE;
+    } else if (StringEqualsAscii(unit, "hour")) {
+        relDateTimeUnit = UDAT_REL_UNIT_HOUR;
+    } else if (StringEqualsAscii(unit, "day")) {
+        relDateTimeUnit = UDAT_REL_UNIT_DAY;
+    } else if (StringEqualsAscii(unit, "week")) {
+        relDateTimeUnit = UDAT_REL_UNIT_WEEK;
+    } else if (StringEqualsAscii(unit, "month")) {
+        relDateTimeUnit = UDAT_REL_UNIT_MONTH;
+    } else if (StringEqualsAscii(unit, "quarter")) {
+        relDateTimeUnit = UDAT_REL_UNIT_QUARTER;
+    } else {
+        MOZ_ASSERT(StringEqualsAscii(unit, "year"));
+        relDateTimeUnit = UDAT_REL_UNIT_YEAR;
+    }
+
+    // ICU doesn't handle -0 well: work around this by converting it to +0.
+    // See: http://bugs.icu-project.org/trac/ticket/12936
+    if (IsNegativeZero(t))
+        t = +0.0;
+
+    UErrorCode status = U_ZERO_ERROR;
+    URelativeDateTimeFormatter* rtf =
+        ureldatefmt_open(icuLocale(locale.ptr()), nullptr, relDateTimeStyle,
+                         UDISPCTX_CAPITALIZATION_FOR_STANDALONE, &status);
+    if (U_FAILURE(status)) {
+        JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_INTERNAL_INTL_ERROR);
+        return false;
+    }
+
+    ScopedICUObject<URelativeDateTimeFormatter, ureldatefmt_close> closeRelativeTimeFormat(rtf);
+
+    JSString* str = Call(cx, [rtf, t, relDateTimeUnit](UChar* chars, int32_t size, UErrorCode* status) {
+            return ureldatefmt_format(rtf, t, relDateTimeUnit, chars, size, status);
+        });
+    if (!str)
+        return false;
+
+    args.rval().setString(str);
+    return true;
+}
+
 
 /******************** String ********************/
 
 static const char*
 CaseMappingLocale(JSLinearString* locale)
 {
     MOZ_ASSERT(locale->length() >= 2, "locale is a valid language tag");
 
--- a/js/src/builtin/Intl.h
+++ b/js/src/builtin/Intl.h
@@ -582,16 +582,58 @@ intl_SelectPluralRule(JSContext* cx, uns
  *
  * Example:
  *
  * intl_getPluralCategories('pl', 'cardinal'); // ['one', 'few', 'many', 'other']
  */
 extern MOZ_MUST_USE bool
 intl_GetPluralCategories(JSContext* cx, unsigned argc, Value* vp);
 
+/******************** RelativeTimeFormat ********************/
+
+class RelativeTimeFormatObject : public NativeObject
+{
+  public:
+    static const Class class_;
+
+    static constexpr uint32_t INTERNALS_SLOT = 0;
+    static constexpr uint32_t URELATIVE_TIME_FORMAT_SLOT = 1;
+    static constexpr uint32_t SLOT_COUNT = 2;
+
+    static_assert(INTERNALS_SLOT == INTL_INTERNALS_OBJECT_SLOT,
+                  "INTERNALS_SLOT must match self-hosting define for internals object slot");
+
+  private:
+    static const ClassOps classOps_;
+
+    static void finalize(FreeOp* fop, JSObject* obj);
+};
+
+/**
+ * Returns an object indicating the supported locales for relative time format
+ * by having a true-valued property for each such locale with the
+ * canonicalized language tag as the property name. The object has no
+ * prototype.
+ *
+ * Usage: availableLocales = intl_RelativeTimeFormat_availableLocales()
+ */
+extern MOZ_MUST_USE bool
+intl_RelativeTimeFormat_availableLocales(JSContext* cx, unsigned argc, Value* vp);
+
+/**
+ * Returns a relative time as a string formatted according to the effective
+ * locale and the formatting options of the given RelativeTimeFormat.
+ *
+ * t should be a number representing a number to be formatted.
+ * unit should be "second", "minute", "hour", "day", "week", "month", "quarter", or "year".
+ *
+ * Usage: formatted = intl_FormatRelativeTime(relativeTimeFormat, t, unit)
+ */
+extern MOZ_MUST_USE bool
+intl_FormatRelativeTime(JSContext* cx, unsigned argc, Value* vp);
 
 /******************** Intl ********************/
 
 /**
  * Returns a plain object with calendar information for a single valid locale
  * (callers must perform this validation).  The object will have these
  * properties:
  *
--- a/js/src/builtin/Intl.js
+++ b/js/src/builtin/Intl.js
@@ -1390,17 +1390,18 @@ function intlFallbackSymbol() {
 /**
  * Initializes the INTL_INTERNALS_OBJECT_SLOT of the given object.
  */
 function initializeIntlObject(obj, type, lazyData) {
     assert(IsObject(obj), "Non-object passed to initializeIntlObject");
     assert((type === "Collator" && IsCollator(obj)) ||
            (type === "DateTimeFormat" && IsDateTimeFormat(obj)) ||
            (type === "NumberFormat" && IsNumberFormat(obj)) ||
-           (type === "PluralRules" && IsPluralRules(obj)),
+           (type === "PluralRules" && IsPluralRules(obj)) ||
+           (type === "RelativeTimeFormat" && IsRelativeTimeFormat(obj)),
            "type must match the object's class");
     assert(IsObject(lazyData), "non-object lazy data");
 
     // The meaning of an internals object for an object |obj| is as follows.
     //
     // The .type property indicates the type of Intl object that |obj| is:
     // "Collator", "DateTimeFormat", "NumberFormat", or "PluralRules" (likely
     // with more coming in future Intl specs).
@@ -1457,27 +1458,30 @@ function maybeInternalProperties(interna
  * properties!), with structure specified above.
  *
  * Spec: ECMAScript Internationalization API Specification, 10.3.
  * Spec: ECMAScript Internationalization API Specification, 11.3.
  * Spec: ECMAScript Internationalization API Specification, 12.3.
  */
 function getIntlObjectInternals(obj) {
     assert(IsObject(obj), "getIntlObjectInternals called with non-Object");
-    assert(IsCollator(obj) || IsDateTimeFormat(obj) || IsNumberFormat(obj) || IsPluralRules(obj),
+    assert(IsCollator(obj) || IsDateTimeFormat(obj) ||
+           IsNumberFormat(obj) || IsPluralRules(obj) ||
+           IsRelativeTimeFormat(obj),
            "getIntlObjectInternals called with non-Intl object");
 
     var internals = UnsafeGetReservedSlot(obj, INTL_INTERNALS_OBJECT_SLOT);
 
     assert(IsObject(internals), "internals not an object");
     assert(hasOwn("type", internals), "missing type");
     assert((internals.type === "Collator" && IsCollator(obj)) ||
            (internals.type === "DateTimeFormat" && IsDateTimeFormat(obj)) ||
            (internals.type === "NumberFormat" && IsNumberFormat(obj)) ||
-           (internals.type === "PluralRules" && IsPluralRules(obj)),
+           (internals.type === "PluralRules" && IsPluralRules(obj)) ||
+           (internals.type === "RelativeTimeFormat" && IsRelativeTimeFormat(obj)),
            "type must match the object's class");
     assert(hasOwn("lazyData", internals), "missing lazyData");
     assert(hasOwn("internalProps", internals), "missing internalProps");
 
     return internals;
 }
 
 
@@ -3470,16 +3474,233 @@ function Intl_PluralRules_resolvedOption
         var p = optionalProperties[i];
         if (hasOwn(p, internals))
             _DefineDataProperty(result, p, internals[p]);
     }
     return result;
 }
 
 
+/********** Intl.RelativeTimeFormat **********/
+
+/**
+ * RelativeTimeFormat internal properties.
+ *
+ * Spec: ECMAScript 402 API, RelativeTimeFormat, 1.3.3.
+ */
+var relativeTimeFormatInternalProperties = {
+    localeData: relativeTimeFormatLocaleData,
+    _availableLocales: null,
+    availableLocales: function() // eslint-disable-line object-shorthand
+    {
+        var locales = this._availableLocales;
+        if (locales)
+            return locales;
+
+        locales = intl_RelativeTimeFormat_availableLocales();
+        addSpecialMissingLanguageTags(locales);
+        return (this._availableLocales = locales);
+    },
+    relevantExtensionKeys: [],
+};
+
+function relativeTimeFormatLocaleData() {
+    // RelativeTimeFormat doesn't support any extension keys.
+    return {};
+}
+
+/**
+ * Compute an internal properties object from |lazyRelativeTimeFormatData|.
+ */
+function resolveRelativeTimeFormatInternals(lazyRelativeTimeFormatData) {
+    assert(IsObject(lazyRelativeTimeFormatData), "lazy data not an object?");
+
+    var internalProps = std_Object_create(null);
+
+    var RelativeTimeFormat = relativeTimeFormatInternalProperties;
+
+    // Step 16.
+    const r = ResolveLocale(callFunction(RelativeTimeFormat.availableLocales, RelativeTimeFormat),
+                            lazyRelativeTimeFormatData.requestedLocales,
+                            lazyRelativeTimeFormatData.opt,
+                            RelativeTimeFormat.relevantExtensionKeys,
+                            RelativeTimeFormat.localeData);
+
+    // Step 17.
+    internalProps.locale = r.locale;
+    internalProps.style = lazyRelativeTimeFormatData.style;
+
+    return internalProps;
+}
+
+/**
+ * Returns an object containing the RelativeTimeFormat internal properties of |obj|,
+ * or throws a TypeError if |obj| isn't RelativeTimeFormat-initialized.
+ */
+function getRelativeTimeFormatInternals(obj, methodName) {
+    assert(IsObject(obj), "getRelativeTimeFormatInternals called with non-object");
+    assert(IsRelativeTimeFormat(obj), "getRelativeTimeFormatInternals called with non-RelativeTimeFormat");
+
+    var internals = getIntlObjectInternals(obj);
+    assert(internals.type === "RelativeTimeFormat", "bad type escaped getIntlObjectInternals");
+
+    var internalProps = maybeInternalProperties(internals);
+    if (internalProps)
+        return internalProps;
+
+    internalProps = resolveRelativeTimeFormatInternals(internals.lazyData);
+    setInternalProperties(internals, internalProps);
+    return internalProps;
+}
+
+/**
+ * Initializes an object as a RelativeTimeFormat.
+ *
+ * This method is complicated a moderate bit by its implementing initialization
+ * as a *lazy* concept.  Everything that must happen now, does -- but we defer
+ * all the work we can until the object is actually used as a RelativeTimeFormat.
+ * This later work occurs in |resolveRelativeTimeFormatInternals|; steps not noted
+ * here occur there.
+ *
+ * Spec: ECMAScript 402 API, RelativeTimeFormat, 1.1.1.
+ */
+function InitializeRelativeTimeFormat(relativeTimeFormat, locales, options) {
+    assert(IsObject(relativeTimeFormat),
+           "InitializeRelativeimeFormat called with non-object");
+    assert(IsRelativeTimeFormat(relativeTimeFormat),
+           "InitializeRelativeTimeFormat called with non-RelativeTimeFormat");
+
+    // Lazy RelativeTimeFormat data has the following structure:
+    //
+    //   {
+    //     requestedLocales: List of locales,
+    //     style: "long" / "short" / "narrow",
+    //
+    //     opt: // opt object computer in InitializeRelativeTimeFormat
+    //       {
+    //         localeMatcher: "lookup" / "best fit",
+    //       }
+    //   }
+    //
+    // Note that lazy data is only installed as a final step of initialization,
+    // so every RelativeTimeFormat lazy data object has *all* these properties, never a
+    // subset of them.
+    const lazyRelativeTimeFormatData = std_Object_create(null);
+
+    // Step 3.
+    let requestedLocales = CanonicalizeLocaleList(locales);
+    lazyRelativeTimeFormatData.requestedLocales = requestedLocales;
+
+    // Steps 4-5.
+    if (options === undefined)
+        options = {};
+    else
+        options = ToObject(options);
+
+    // Step 6.
+    let opt = new Record();
+
+    // Steps 7-8.
+    let matcher = GetOption(options, "localeMatcher", "string", ["lookup", "best fit"], "best fit");
+    opt.localeMatcher = matcher;
+
+    lazyRelativeTimeFormatData.opt = opt;
+
+    // Steps 13-14.
+    const style = GetOption(options, "style", "string", ["long", "short", "narrow"], "long");
+    lazyRelativeTimeFormatData.style = style;
+
+    initializeIntlObject(relativeTimeFormat, "RelativeTimeFormat", lazyRelativeTimeFormatData)
+}
+
+/**
+ * Returns the subset of the given locale list for which this locale list has a
+ * matching (possibly fallback) locale. Locales appear in the same order in the
+ * returned list as in the input list.
+ *
+ * Spec: ECMAScript 402 API, RelativeTimeFormat, 1.3.2.
+ */
+function Intl_RelativeTimeFormat_supportedLocalesOf(locales /*, options*/) {
+    var options = arguments.length > 1 ? arguments[1] : undefined;
+
+    // Step 1.
+    var availableLocales = callFunction(relativeTimeFormatInternalProperties.availableLocales,
+                                        relativeTimeFormatInternalProperties);
+    // Step 2.
+    let requestedLocales = CanonicalizeLocaleList(locales);
+
+    // Step 3.
+    return SupportedLocales(availableLocales, requestedLocales, options);
+}
+
+/**
+ * Returns a String value representing the written form of a relative date
+ * formatted according to the effective locale and the formatting options
+ * of this RelativeTimeFormat object.
+ *
+ * Spec: ECMAScript 402 API, RelativeTImeFormat, 1.4.3.
+ */
+function Intl_RelativeTimeFormat_format(value, unit) {
+    // Step 1.
+    let relativeTimeFormat = this;
+
+    // Step 2.
+    if (!IsObject(relativeTimeFormat) || !IsRelativeTimeFormat(relativeTimeFormat))
+        ThrowTypeError(JSMSG_INTL_OBJECT_NOT_INITED, "RelativeTimeFormat", "format", "RelativeTimeFormat");
+
+    // Ensure the RelativeTimeFormat internals are resolved.
+    getRelativeTimeFormatInternals(relativeTimeFormat);
+
+    // Step 3.
+    let t = ToNumber(value);
+
+    // Step 4.
+    let u = ToString(unit);
+
+    switch (u) {
+      case "second":
+      case "minute":
+      case "hour":
+      case "day":
+      case "week":
+      case "month":
+      case "quarter":
+      case "year":
+        break;
+      default:
+        ThrowRangeError(JSMSG_INVALID_OPTION_VALUE, "unit", u);
+    }
+
+    // Step 5.
+    return intl_FormatRelativeTime(relativeTimeFormat, t, u);
+}
+
+/**
+ * Returns the resolved options for a PluralRules object.
+ *
+ * Spec: ECMAScript 402 API, RelativeTimeFormat, 1.4.4.
+ */
+function Intl_RelativeTimeFormat_resolvedOptions() {
+    // Check "this RelativeTimeFormat object" per introduction of section 1.4.
+    if (!IsObject(this) || !IsRelativeTimeFormat(this)) {
+        ThrowTypeError(JSMSG_INTL_OBJECT_NOT_INITED, "RelativeTimeFormat", "resolvedOptions",
+                       "RelativeTimeFormat");
+    }
+
+    var internals = getRelativeTimeFormatInternals(this, "resolvedOptions");
+
+    var result = {
+        locale: internals.locale,
+        style: internals.style,
+    };
+
+    return result;
+}
+
+
 /********** Intl **********/
 
 
 /**
  * 8.2.1 Intl.getCanonicalLocales ( locales )
  *
  * ES2017 Intl draft rev 947aa9a0c853422824a0c9510d8f09be3eb416b9
  */
--- a/js/src/jit/InlinableNatives.h
+++ b/js/src/jit/InlinableNatives.h
@@ -28,16 +28,17 @@
     _(AtomicsIsLockFree)            \
                                     \
     _(Boolean)                      \
                                     \
     _(IntlIsCollator)               \
     _(IntlIsDateTimeFormat)         \
     _(IntlIsNumberFormat)           \
     _(IntlIsPluralRules)            \
+    _(IntlIsRelativeTimeFormat)     \
                                     \
     _(MathAbs)                      \
     _(MathFloor)                    \
     _(MathCeil)                     \
     _(MathRound)                    \
     _(MathClz32)                    \
     _(MathSqrt)                     \
     _(MathATan2)                    \
--- a/js/src/jit/MCallOptimize.cpp
+++ b/js/src/jit/MCallOptimize.cpp
@@ -119,16 +119,18 @@ IonBuilder::inlineNativeCall(CallInfo& c
       case InlinableNative::IntlIsCollator:
         return inlineHasClass(callInfo, &CollatorObject::class_);
       case InlinableNative::IntlIsDateTimeFormat:
         return inlineHasClass(callInfo, &DateTimeFormatObject::class_);
       case InlinableNative::IntlIsNumberFormat:
         return inlineHasClass(callInfo, &NumberFormatObject::class_);
       case InlinableNative::IntlIsPluralRules:
         return inlineHasClass(callInfo, &PluralRulesObject::class_);
+      case InlinableNative::IntlIsRelativeTimeFormat:
+        return inlineHasClass(callInfo, &RelativeTimeFormatObject::class_);
 
       // Math natives.
       case InlinableNative::MathAbs:
         return inlineMathAbs(callInfo);
       case InlinableNative::MathFloor:
         return inlineMathFloor(callInfo);
       case InlinableNative::MathCeil:
         return inlineMathCeil(callInfo);
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -3072,16 +3072,22 @@ ToWindowIfWindowProxy(JSObject* obj);
 // if passed bad input. But the current behavior is entirely under-specified
 // and emphatically not shippable on the web, and it *must* be fixed before
 // this functionality can be exposed in the real world. (There are also some
 // questions about whether the format exposed here is the *right* one to
 // standardize, that will also need to be resolved to ship this.)
 extern bool
 AddMozDateTimeFormatConstructor(JSContext* cx, JS::Handle<JSObject*> intl);
 
+// Create and add the Intl.RelativeTimeFormat constructor function to the provided
+// object.  This function throws if called more than once per realm/global
+// object.
+extern bool
+AddRelativeTimeFormatConstructor(JSContext* cx, JS::Handle<JSObject*> intl);
+
 class MOZ_STACK_CLASS JS_FRIEND_API(AutoAssertNoContentJS)
 {
   public:
     explicit AutoAssertNoContentJS(JSContext* cx);
     ~AutoAssertNoContentJS();
 
   private:
     JSContext* context_;
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -834,16 +834,19 @@ AddIntlExtras(JSContext* cx, unsigned ar
     };
 
     if (!JS_DefineFunctions(cx, intl, funcs))
         return false;
 
     if (!js::AddMozDateTimeFormatConstructor(cx, intl))
         return false;
 
+    if (!js::AddRelativeTimeFormatConstructor(cx, intl))
+        return false;
+
     args.rval().setUndefined();
     return true;
 }
 #endif // ENABLE_INTL_API
 
 static bool
 EvalAndPrint(JSContext* cx, const char* bytes, size_t length,
              int lineno, bool compileOnly)
new file mode 100644
new file mode 100644
--- /dev/null
+++ b/js/src/tests/Intl/RelativeTimeFormat/construct-newtarget.js
@@ -0,0 +1,23 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl")||!this.hasOwnProperty("addIntlExtras"))
+
+/* 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/. */
+
+addIntlExtras(Intl);
+
+var obj = new Intl.RelativeTimeFormat();
+
+// Test that new RTF produces an object with the right prototype.
+assertEq(Object.getPrototypeOf(obj), Intl.RelativeTimeFormat.prototype);
+
+// Test subclassing %Intl.RelativeTimeFormat% works correctly.
+class MyRelativeTimeFormat extends Intl.RelativeTimeFormat {}
+
+var obj = new MyRelativeTimeFormat();
+assertEq(obj instanceof MyRelativeTimeFormat, true);
+assertEq(obj instanceof Intl.RelativeTimeFormat, true);
+assertEq(Object.getPrototypeOf(obj), MyRelativeTimeFormat.prototype);
+
+if (typeof reportCompare === "function")
+    reportCompare(0, 0);
new file mode 100644
--- /dev/null
+++ b/js/src/tests/Intl/RelativeTimeFormat/format.js
@@ -0,0 +1,92 @@
+// |reftest| skip-if(!this.hasOwnProperty('Intl')||!this.hasOwnProperty('addIntlExtras'))
+/* 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/. */
+
+// Tests the format function with a diverse set of locales and options.
+
+var rtf;
+
+addIntlExtras(Intl);
+
+
+rtf = new Intl.RelativeTimeFormat("en-US");
+assertEq(rtf.format(0, "second"), "now");
+assertEq(rtf.format(-0, "second"), "now");
+assertEq(rtf.format(-1, "second"), "1 second ago");
+assertEq(rtf.format(1, "second"), "in 1 second");
+
+assertEq(rtf.format(0, "minute"), "in 0 minutes");
+assertEq(rtf.format(-0, "minute"), "in 0 minutes");
+assertEq(rtf.format(-1, "minute"), "1 minute ago");
+assertEq(rtf.format(1, "minute"), "in 1 minute");
+
+assertEq(rtf.format(0, "hour"), "in 0 hours");
+assertEq(rtf.format(-0, "hour"), "in 0 hours");
+assertEq(rtf.format(-1, "hour"), "1 hour ago");
+assertEq(rtf.format(1, "hour"), "in 1 hour");
+
+assertEq(rtf.format(0, "day"), "today");
+assertEq(rtf.format(-0, "day"), "today");
+assertEq(rtf.format(-1, "day"), "yesterday");
+assertEq(rtf.format(1, "day"), "tomorrow");
+
+assertEq(rtf.format(0, "week"), "this week");
+assertEq(rtf.format(-0, "week"), "this week");
+assertEq(rtf.format(-1, "week"), "last week");
+assertEq(rtf.format(1, "week"), "next week");
+
+assertEq(rtf.format(0, "month"), "this month");
+assertEq(rtf.format(-0, "month"), "this month");
+assertEq(rtf.format(-1, "month"), "last month");
+assertEq(rtf.format(1, "month"), "next month");
+
+assertEq(rtf.format(0, "year"), "this year");
+assertEq(rtf.format(-0, "year"), "this year");
+assertEq(rtf.format(-1, "year"), "last year");
+assertEq(rtf.format(1, "year"), "next year");
+
+rtf = new Intl.RelativeTimeFormat("de");
+assertEq(rtf.format(-1, "day"), "gestern");
+assertEq(rtf.format(1, "day"), "morgen");
+
+rtf = new Intl.RelativeTimeFormat("ar");
+assertEq(rtf.format(-1, "day"), "أمس");
+assertEq(rtf.format(1, "day"), "غدًا");
+
+
+rtf = new Intl.RelativeTimeFormat("en-US");
+assertEq(rtf.format(Infinity, "year"), "in ∞ years");
+assertEq(rtf.format(-Infinity, "year"), "∞ years ago");
+
+var weirdValueCases = [
+  NaN,
+  "word",
+  [0,2],
+  {},
+];
+
+for (let c of weirdValueCases) {
+  assertEq(rtf.format(c, "year"), "in NaN years");
+};
+
+var weirdUnitCases = [
+  "test",
+  "SECOND",
+  "sEcOnD",
+  1,
+  NaN,
+  undefined,
+  null,
+  {},
+];
+
+for (let u of weirdUnitCases) {
+  assertThrows(function() {
+    var rtf = new Intl.RelativeTimeFormat("en-US");
+    rtf.format(1, u);
+  }, RangeError);
+};
+
+
+reportCompare(0, 0, 'ok');
new file mode 100644
--- /dev/null
+++ b/js/src/tests/Intl/RelativeTimeFormat/relativetimeformat.js
@@ -0,0 +1,16 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl")||!this.hasOwnProperty('addIntlExtras'))
+/* 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/. */
+
+// Tests the format function with a diverse set of locales and options.
+
+var rtf;
+
+addIntlExtras(Intl);
+
+rtf = new Intl.RelativeTimeFormat("en-us");
+assertEq(rtf.resolvedOptions().locale, "en-US");
+assertEq(rtf.resolvedOptions().style, "long");
+
+reportCompare(0, 0, 'ok');
new file mode 100644
new file mode 100644
--- /dev/null
+++ b/js/src/tests/Intl/RelativeTimeFormat/supportedLocalesOf.js
@@ -0,0 +1,375 @@
+// |reftest| skip-if(!this.hasOwnProperty('Intl')||!this.hasOwnProperty('addIntlExtras')||xulRuntime.shell)
+// -- test in browser only that ICU has locale data for all Mozilla languages
+
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// This array contains the locales that ICU supports in
+// number formatting whose languages Mozilla localizes Firefox into.
+// Current as of ICU 50.1.2 and Firefox March 2013.
+var locales = [
+    "af",
+    "af-NA",
+    "af-ZA",
+    "ar",
+    "ar-001",
+    "ar-AE",
+    "ar-BH",
+    "ar-DJ",
+    "ar-DZ",
+    "ar-EG",
+    "ar-EH",
+    "ar-ER",
+    "ar-IL",
+    "ar-IQ",
+    "ar-JO",
+    "ar-KM",
+    "ar-KW",
+    "ar-LB",
+    "ar-LY",
+    "ar-MA",
+    "ar-MR",
+    "ar-OM",
+    "ar-PS",
+    "ar-QA",
+    "ar-SA",
+    "ar-SD",
+    "ar-SO",
+    "ar-SY",
+    "ar-TD",
+    "ar-TN",
+    "ar-YE",
+    "as",
+    "as-IN",
+    "be",
+    "be-BY",
+    "bg",
+    "bg-BG",
+    "bn",
+    "bn-BD",
+    "bn-IN",
+    "br",
+    "br-FR",
+    "bs",
+    "bs-Cyrl",
+    "bs-Cyrl-BA",
+    "bs-Latn",
+    "bs-Latn-BA",
+    "ca",
+    "ca-AD",
+    "ca-ES",
+    "cs",
+    "cs-CZ",
+    "cy",
+    "cy-GB",
+    "da",
+    "da-DK",
+    "de",
+    "de-AT",
+    "de-BE",
+    "de-CH",
+    "de-DE",
+    "de-LI",
+    "de-LU",
+    "el",
+    "el-CY",
+    "el-GR",
+    "en",
+    "en-150",
+    "en-AG",
+    "en-AS",
+    "en-AU",
+    "en-BB",
+    "en-BE",
+    "en-BM",
+    "en-BS",
+    "en-BW",
+    "en-BZ",
+    "en-CA",
+    "en-CM",
+    "en-DM",
+    "en-FJ",
+    "en-FM",
+    "en-GB",
+    "en-GD",
+    "en-GG",
+    "en-GH",
+    "en-GI",
+    "en-GM",
+    "en-GU",
+    "en-GY",
+    "en-HK",
+    "en-IE",
+    "en-IM",
+    "en-IN",
+    "en-JE",
+    "en-JM",
+    "en-KE",
+    "en-KI",
+    "en-KN",
+    "en-KY",
+    "en-LC",
+    "en-LR",
+    "en-LS",
+    "en-MG",
+    "en-MH",
+    "en-MP",
+    "en-MT",
+    "en-MU",
+    "en-MW",
+    "en-NA",
+    "en-NG",
+    "en-NZ",
+    "en-PG",
+    "en-PH",
+    "en-PK",
+    "en-PR",
+    "en-PW",
+    "en-SB",
+    "en-SC",
+    "en-SG",
+    "en-SL",
+    "en-SS",
+    "en-SZ",
+    "en-TC",
+    "en-TO",
+    "en-TT",
+    "en-TZ",
+    "en-UG",
+    "en-UM",
+    "en-US",
+    "en-US-posix",
+    "en-VC",
+    "en-VG",
+    "en-VI",
+    "en-VU",
+    "en-WS",
+    "en-ZA",
+    "en-ZM",
+    "en-ZW",
+    "eo",
+    "es",
+    "es-419",
+    "es-AR",
+    "es-BO",
+    "es-CL",
+    "es-CO",
+    "es-CR",
+    "es-CU",
+    "es-DO",
+    "es-EA",
+    "es-EC",
+    "es-ES",
+    "es-GQ",
+    "es-GT",
+    "es-HN",
+    "es-IC",
+    "es-MX",
+    "es-NI",
+    "es-PA",
+    "es-PE",
+    "es-PH",
+    "es-PR",
+    "es-PY",
+    "es-SV",
+    "es-US",
+    "es-UY",
+    "es-VE",
+    "et",
+    "et-EE",
+    "eu",
+    "eu-ES",
+    "fa",
+    "fa-AF",
+    "fa-IR",
+    "ff",
+    "ff-SN",
+    "fi",
+    "fi-FI",
+    "fr",
+    "fr-BE",
+    "fr-BF",
+    "fr-BI",
+    "fr-BJ",
+    "fr-BL",
+    "fr-CA",
+    "fr-CD",
+    "fr-CF",
+    "fr-CG",
+    "fr-CH",
+    "fr-CI",
+    "fr-CM",
+    "fr-DJ",
+    "fr-DZ",
+    "fr-FR",
+    "fr-GA",
+    "fr-GF",
+    "fr-GN",
+    "fr-GP",
+    "fr-GQ",
+    "fr-HT",
+    "fr-KM",
+    "fr-LU",
+    "fr-MA",
+    "fr-MC",
+    "fr-MF",
+    "fr-MG",
+    "fr-ML",
+    "fr-MQ",
+    "fr-MR",
+    "fr-MU",
+    "fr-NC",
+    "fr-NE",
+    "fr-PF",
+    "fr-RE",
+    "fr-RW",
+    "fr-SC",
+    "fr-SN",
+    "fr-SY",
+    "fr-TD",
+    "fr-TG",
+    "fr-TN",
+    "fr-VU",
+    "fr-YT",
+    "ga",
+    "ga-IE",
+    "gl",
+    "gl-ES",
+    "gu",
+    "gu-IN",
+    "he",
+    "he-IL",
+    "hi",
+    "hi-IN",
+    "hr",
+    "hr-BA",
+    "hr-HR",
+    "hu",
+    "hu-HU",
+    "hy",
+    "hy-AM",
+    "id",
+    "id-ID",
+    "is",
+    "is-IS",
+    "it",
+    "it-CH",
+    "it-IT",
+    "it-SM",
+    "ja",
+    "ja-JP",
+    "kk",
+    "kk-Cyrl",
+    "kk-Cyrl-KZ",
+    "km",
+    "km-KH",
+    "kn",
+    "kn-IN",
+    "ko",
+    "ko-KP",
+    "ko-KR",
+    "lt",
+    "lt-LT",
+    "lv",
+    "lv-LV",
+    "mk",
+    "mk-MK",
+    "ml",
+    "ml-IN",
+    "mr",
+    "mr-IN",
+    "nb",
+    "nb-NO",
+    "nl",
+    "nl-AW",
+    "nl-BE",
+    "nl-CW",
+    "nl-NL",
+    "nl-SR",
+    "nl-SX",
+    "nn",
+    "nn-NO",
+    "or",
+    "or-IN",
+    "pa",
+    "pa-Arab",
+    "pa-Arab-PK",
+    "pa-Guru",
+    "pa-Guru-IN",
+    "pl",
+    "pl-PL",
+    "pt",
+    "pt-AO",
+    "pt-BR",
+    "pt-CV",
+    "pt-GW",
+    "pt-MO",
+    "pt-MZ",
+    "pt-PT",
+    "pt-ST",
+    "pt-TL",
+    "rm",
+    "rm-CH",
+    "ro",
+    "ro-MD",
+    "ro-RO",
+    "ru",
+    "ru-BY",
+    "ru-KG",
+    "ru-KZ",
+    "ru-MD",
+    "ru-RU",
+    "ru-UA",
+    "si",
+    "si-LK",
+    "sk",
+    "sk-SK",
+    "sl",
+    "sl-SI",
+    "sq",
+    "sq-AL",
+    "sq-MK",
+    "sr",
+    "sr-Cyrl",
+    "sr-Cyrl-BA",
+    "sr-Cyrl-ME",
+    "sr-Cyrl-RS",
+    "sr-Latn",
+    "sr-Latn-BA",
+    "sr-Latn-ME",
+    "sr-Latn-RS",
+    "sv",
+    "sv-AX",
+    "sv-FI",
+    "sv-SE",
+    "te",
+    "te-IN",
+    "th",
+    "th-TH",
+    "tr",
+    "tr-CY",
+    "tr-TR",
+    "uk",
+    "uk-UA",
+    "vi",
+    "vi-VN",
+    "zh",
+    "zh-Hans",
+    "zh-Hans-CN",
+    "zh-Hans-HK",
+    "zh-Hans-MO",
+    "zh-Hans-SG",
+    "zh-Hant",
+    "zh-Hant-HK",
+    "zh-Hant-MO",
+    "zh-Hant-TW",
+];
+
+addIntlExtras(Intl);
+
+const result = Intl.RelativeTimeFormat.supportedLocalesOf(locales);
+
+assertEqArray(locales, result);
+
+reportCompare(0, 0, 'ok');
--- a/js/src/vm/CommonPropertyNames.h
+++ b/js/src/vm/CommonPropertyNames.h
@@ -180,16 +180,17 @@
     macro(incumbentGlobal, incumbentGlobal, "incumbentGlobal") \
     macro(index, index, "index") \
     macro(infinity, infinity, "infinity") \
     macro(Infinity, Infinity, "Infinity") \
     macro(InitializeCollator, InitializeCollator, "InitializeCollator") \
     macro(InitializeDateTimeFormat, InitializeDateTimeFormat, "InitializeDateTimeFormat") \
     macro(InitializeNumberFormat, InitializeNumberFormat, "InitializeNumberFormat") \
     macro(InitializePluralRules, InitializePluralRules, "InitializePluralRules") \
+    macro(InitializeRelativeTimeFormat, InitializeRelativeTimeFormat, "InitializeRelativeTimeFormat") \
     macro(innermost, innermost, "innermost") \
     macro(inNursery, inNursery, "inNursery") \
     macro(input, input, "input") \
     macro(instanceof, instanceof, "instanceof") \
     macro(int8, int8, "int8") \
     macro(int16, int16, "int16") \
     macro(int32, int32, "int32") \
     macro(Int8x16, Int8x16, "Int8x16") \
@@ -344,16 +345,18 @@
     macro(RegExpFlagsGetter, RegExpFlagsGetter, "RegExpFlagsGetter") \
     macro(RegExpMatcher, RegExpMatcher, "RegExpMatcher") \
     macro(RegExpSearcher, RegExpSearcher, "RegExpSearcher") \
     macro(RegExpTester, RegExpTester, "RegExpTester") \
     macro(RegExp_prototype_Exec, RegExp_prototype_Exec, "RegExp_prototype_Exec") \
     macro(Reify, Reify, "Reify") \
     macro(reject, reject, "reject") \
     macro(rejected, rejected, "rejected") \
+    macro(RelativeTimeFormat, RelativeTimeFormat, "RelativeTimeFormat") \
+    macro(RelativeTimeFormatFormat, RelativeTimeFormatFormat, "Intl_RelativeTimeFormat_Format") \
     macro(RequireObjectCoercible, RequireObjectCoercible, "RequireObjectCoercible") \
     macro(resolve, resolve, "resolve") \
     macro(resumeGenerator, resumeGenerator, "resumeGenerator") \
     macro(return, return_, "return") \
     macro(revoke, revoke, "revoke") \
     macro(rtl, rtl, "rtl") \
     macro(script, script, "script") \
     macro(scripts, scripts, "scripts") \
@@ -412,16 +415,17 @@
     macro(uint16, uint16, "uint16") \
     macro(uint32, uint32, "uint32") \
     macro(Uint8x16, Uint8x16, "Uint8x16") \
     macro(Uint16x8, Uint16x8, "Uint16x8") \
     macro(Uint32x4, Uint32x4, "Uint32x4") \
     macro(unescape, unescape, "unescape") \
     macro(uneval, uneval, "uneval") \
     macro(unicode, unicode, "unicode") \
+    macro(unit, unit, "unit") \
     macro(uninitialized, uninitialized, "uninitialized") \
     macro(unsized, unsized, "unsized") \
     macro(unwatch, unwatch, "unwatch") \
     macro(UnwrapAndCallRegExpBuiltinExec, UnwrapAndCallRegExpBuiltinExec, "UnwrapAndCallRegExpBuiltinExec") \
     macro(url, url, "url") \
     macro(usage, usage, "usage") \
     macro(useAsm, useAsm, "use asm") \
     macro(useGrouping, useGrouping, "useGrouping") \
--- a/js/src/vm/GlobalObject.h
+++ b/js/src/vm/GlobalObject.h
@@ -91,16 +91,17 @@ class GlobalObject : public NativeObject
         MAP_ITERATOR_PROTO,
         SET_ITERATOR_PROTO,
         COLLATOR_PROTO,
         NUMBER_FORMAT,
         NUMBER_FORMAT_PROTO,
         DATE_TIME_FORMAT,
         DATE_TIME_FORMAT_PROTO,
         PLURAL_RULES_PROTO,
+        RELATIVE_TIME_FORMAT_PROTO,
         MODULE_PROTO,
         IMPORT_ENTRY_PROTO,
         EXPORT_ENTRY_PROTO,
         REQUESTED_MODULE_PROTO,
         REGEXP_STATICS,
         RUNTIME_CODEGEN_ENABLED,
         DEBUGGERS,
         INTRINSICS,
@@ -473,16 +474,21 @@ class GlobalObject : public NativeObject
         return getOrCreateObject(cx, global, DATE_TIME_FORMAT_PROTO, initIntlObject);
     }
 
     static JSObject*
     getOrCreatePluralRulesPrototype(JSContext* cx, Handle<GlobalObject*> global) {
         return getOrCreateObject(cx, global, PLURAL_RULES_PROTO, initIntlObject);
     }
 
+    static JSObject*
+    getOrCreateRelativeTimeFormatPrototype(JSContext* cx, Handle<GlobalObject*> global) {
+        return getOrCreateObject(cx, global, RELATIVE_TIME_FORMAT_PROTO, initIntlObject);
+    }
+
     static bool ensureModulePrototypesCreated(JSContext *cx, Handle<GlobalObject*> global);
 
     JSObject* maybeGetModulePrototype() {
         Value value = getSlot(MODULE_PROTO);
         return value.isUndefined() ? nullptr : &value.toObject();
     }
 
     JSObject* maybeGetImportEntryPrototype() {
@@ -773,16 +779,17 @@ class GlobalObject : public NativeObject
     static bool initAsyncGenerators(JSContext* cx, Handle<GlobalObject*> global);
 
     // Implemented in builtin/MapObject.cpp.
     static bool initMapIteratorProto(JSContext* cx, Handle<GlobalObject*> global);
     static bool initSetIteratorProto(JSContext* cx, Handle<GlobalObject*> global);
 
     // Implemented in Intl.cpp.
     static bool initIntlObject(JSContext* cx, Handle<GlobalObject*> global);
+    static bool addRelativeTimeFormatConstructor(JSContext* cx, HandleObject intl);
 
     // Implemented in builtin/ModuleObject.cpp
     static bool initModuleProto(JSContext* cx, Handle<GlobalObject*> global);
     static bool initImportEntryProto(JSContext* cx, Handle<GlobalObject*> global);
     static bool initExportEntryProto(JSContext* cx, Handle<GlobalObject*> global);
     static bool initRequestedModuleProto(JSContext* cx, Handle<GlobalObject*> global);
 
     // Implemented in builtin/TypedObject.cpp
--- a/js/src/vm/SelfHosting.cpp
+++ b/js/src/vm/SelfHosting.cpp
@@ -2595,31 +2595,36 @@ static const JSFunctionSpec intrinsic_fu
     JS_FN("intl_NumberFormat", intl_NumberFormat, 2,0),
     JS_FN("intl_NumberFormat_availableLocales", intl_NumberFormat_availableLocales, 0,0),
     JS_FN("intl_numberingSystem", intl_numberingSystem, 1,0),
     JS_FN("intl_patternForSkeleton", intl_patternForSkeleton, 2,0),
     JS_FN("intl_patternForStyle", intl_patternForStyle, 3,0),
     JS_FN("intl_PluralRules_availableLocales", intl_PluralRules_availableLocales, 0,0),
     JS_FN("intl_GetPluralCategories", intl_GetPluralCategories, 2, 0),
     JS_FN("intl_SelectPluralRule", intl_SelectPluralRule, 2,0),
+    JS_FN("intl_RelativeTimeFormat_availableLocales", intl_RelativeTimeFormat_availableLocales, 0,0),
+    JS_FN("intl_FormatRelativeTime", intl_FormatRelativeTime, 3,0),
     JS_FN("intl_toLocaleLowerCase", intl_toLocaleLowerCase, 2,0),
     JS_FN("intl_toLocaleUpperCase", intl_toLocaleUpperCase, 2,0),
 
     JS_INLINABLE_FN("IsCollator",
                     intrinsic_IsInstanceOfBuiltin<CollatorObject>, 1,0,
                     IntlIsCollator),
     JS_INLINABLE_FN("IsDateTimeFormat",
                     intrinsic_IsInstanceOfBuiltin<DateTimeFormatObject>, 1,0,
                     IntlIsDateTimeFormat),
     JS_INLINABLE_FN("IsNumberFormat",
                     intrinsic_IsInstanceOfBuiltin<NumberFormatObject>, 1,0,
                     IntlIsNumberFormat),
     JS_INLINABLE_FN("IsPluralRules",
                     intrinsic_IsInstanceOfBuiltin<PluralRulesObject>, 1,0,
                     IntlIsPluralRules),
+    JS_INLINABLE_FN("IsRelativeTimeFormat",
+                    intrinsic_IsInstanceOfBuiltin<RelativeTimeFormatObject>, 1,0,
+                    IntlIsRelativeTimeFormat),
     JS_FN("GetDateTimeFormatConstructor",
           intrinsic_GetBuiltinIntlConstructor<GlobalObject::getOrCreateDateTimeFormatConstructor>,
           0,0),
     JS_FN("GetNumberFormatConstructor",
           intrinsic_GetBuiltinIntlConstructor<GlobalObject::getOrCreateNumberFormatConstructor>,
           0,0),
 
     JS_FN("GetOwnPropertyDescriptorToArray", GetOwnPropertyDescriptorToArray, 2,0),
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -3281,16 +3281,18 @@ nsLayoutUtils::GetFramesForArea(nsIFrame
     if (rootScrollFrame) {
       builder.SetIgnoreScrollFrame(rootScrollFrame);
     }
   }
   if (aFlags & IGNORE_CROSS_DOC) {
     builder.SetDescendIntoSubdocuments(false);
   }
 
+  builder.SetHitTestShouldStopAtFirstOpaque(aFlags & ONLY_VISIBLE);
+
   builder.EnterPresShell(aFrame);
 
   builder.SetDirtyRect(aRect);
   aFrame->BuildDisplayListForStackingContext(&builder, &list);
   builder.LeavePresShell(aFrame, nullptr);
 
 #ifdef MOZ_DUMP_PAINTING
   if (gDumpEventList) {
@@ -3298,17 +3300,16 @@ nsLayoutUtils::GetFramesForArea(nsIFrame
 
     std::stringstream ss;
     nsFrame::PrintDisplayList(&builder, list, ss);
     print_stderr(ss);
   }
 #endif
 
   nsDisplayItem::HitTestState hitTestState;
-  builder.SetHitTestShouldStopAtFirstOpaque(aFlags & ONLY_VISIBLE);
   list.HitTest(&builder, aRect, &hitTestState, &aOutFrames);
   list.DeleteAll(&builder);
   builder.EndFrame();
   return NS_OK;
 }
 
 // aScrollFrameAsScrollable must be non-nullptr and queryable to an nsIFrame
 FrameMetrics
--- a/layout/forms/nsHTMLButtonControlFrame.cpp
+++ b/layout/forms/nsHTMLButtonControlFrame.cpp
@@ -108,17 +108,17 @@ nsHTMLButtonControlFrame::BuildDisplayLi
   nsDisplayList onTop;
   if (IsVisibleForPainting(aBuilder)) {
     mRenderer.DisplayButton(aBuilder, aLists.BorderBackground(), &onTop);
   }
 
   nsDisplayListCollection set;
 
   // Do not allow the child subtree to receive events.
-  if (!isForEventDelivery) {
+  if (!isForEventDelivery || aBuilder->HitTestShouldStopAtFirstOpaque()) {
     DisplayListClipState::AutoSaveRestore clipState(aBuilder);
 
     if (ShouldClipPaintingToBorderBox()) {
       nsMargin border = StyleBorder()->GetComputedBorder();
       nsRect rect(aBuilder->ToReferenceFrame(this), GetSize());
       rect.Deflate(border);
       nscoord radii[8];
       bool hasRadii = GetPaddingBoxBorderRadii(radii);
--- a/layout/generic/nsTextFrame.cpp
+++ b/layout/generic/nsTextFrame.cpp
@@ -4115,32 +4115,18 @@ nsTextPaintStyle::InitSelectionColorsAnd
                                 CSSPseudoElementType::mozSelection,
                                 mFrame->StyleContext());
     // Use -moz-selection pseudo class.
     if (sc) {
       mSelectionBGColor =
         sc->GetVisitedDependentColor(&nsStyleBackground::mBackgroundColor);
       mSelectionTextColor =
         sc->GetVisitedDependentColor(&nsStyleText::mWebkitTextFillColor);
-      if (auto* geckoStyleContext = sc->GetAsGecko()) {
-        mHasSelectionShadow =
-          nsRuleNode::HasAuthorSpecifiedRules(geckoStyleContext,
-                                              NS_AUTHOR_SPECIFIED_TEXT_SHADOW,
-                                              true);
-      } else {
-        NS_WARNING("stylo: Need a way to get HasAuthorSpecifiedRules from a "
-                   "raw style context");
-        // Or at least an element and a pseudo-style, which is probably a bit
-        // more doable, since we know that, at least when not in the presence of
-        // first-line / first-letter, we're inheriting from selectionElement.
-        mHasSelectionShadow = true;
-      }
-      if (mHasSelectionShadow) {
-        mSelectionShadow = sc->StyleText()->mTextShadow;
-      }
+      mHasSelectionShadow = true;
+      mSelectionShadow = sc->StyleText()->mTextShadow;
       return true;
     }
   }
 
   nscolor selectionBGColor =
     LookAndFeel::GetColor(LookAndFeel::eColorID_TextSelectBackground);
 
   if (selectionStatus == nsISelectionController::SELECTION_ATTENTION) {
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -5817,17 +5817,26 @@ nsRegion
 nsDisplayWrapList::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
                                    bool* aSnap) const
 {
   *aSnap = false;
   nsRegion result;
   if (mListPtr->IsOpaque()) {
     // Everything within GetBounds that's visible is opaque.
     result = GetBounds(aBuilder, aSnap);
-  }
+  } else if (aBuilder->HitTestShouldStopAtFirstOpaque()) {
+    // If we care about an accurate opaque region, iterate the display list
+    // and build up a region of opaque bounds.
+    nsDisplayItem* item = mList.GetBottom();
+    while (item) {
+      result.OrWith(item->GetOpaqueRegion(aBuilder, aSnap));
+      item = item->GetAbove();
+    }
+  }
+  *aSnap = false;
   return result;
 }
 
 Maybe<nscolor>
 nsDisplayWrapList::IsUniform(nsDisplayListBuilder* aBuilder) const
 {
   // We could try to do something but let's conservatively just return Nothing.
   return Nothing();
new file mode 100644
--- /dev/null
+++ b/layout/style/crashtests/1364139-1.html
@@ -0,0 +1,20 @@
+<html>
+  <head>
+    <script>
+      try { o1 = document.createElement('area');  } catch(e) { };
+      try { o2 = document.createElement('article');  } catch(e) { };
+      try { o3 = document.createElement('iframe');  } catch(e) { };
+      try { o4 = document.createElement('style');  } catch(e) { };
+      try { o1.className = 'c3';  } catch(e) { };
+      try { o2.className = 'c3';  } catch(e) { };
+      try { o2.innerText = "\uE4C9"; } catch(e) { };
+      try { document.documentElement.appendChild(o1); } catch(e) { };
+      try { document.documentElement.appendChild(o2); } catch(e) { };
+      try { document.documentElement.appendChild(o3);  } catch(e) { };
+      try { document.documentElement.appendChild(o4); } catch(e) { };
+      try { document.styleSheets[0].insertRule("*::first-letter, .c3 ~ .c3::first-line { float: right; font-variant-alternates: annotation(\\62 lah); }", 0); } catch(e) { };
+      try { o3.src = "data:text/html,"; } catch(e) { };
+      try { document.styleSheets[0].insertRule(".c3:last-child:nth-of-type(+3n) { }", 0); } catch(e) { };
+    </script>
+  </head>
+</html>
--- a/layout/style/crashtests/crashtests.list
+++ b/layout/style/crashtests/crashtests.list
@@ -162,16 +162,17 @@ load 1319072-1.html
 HTTP load 1320423-1.html
 load 1321357-1.html
 load 1328535-1.html
 load 1331272.html
 HTTP load 1333001-1.html
 pref(dom.animations-api.core.enabled,true) load 1340344.html
 load 1342316-1.html
 load 1356601-1.html
+load 1364139-1.html
 load 1370793-1.xhtml
 skip-if(Android) load 1371450-1.html
 load 1374175-1.html
 load 1375812-1.html
 load 1377053-1.html
 load 1377256-1.html
 load 1378064-1.html
 load 1378814.html
@@ -239,9 +240,11 @@ load 1403465.html
 load 1403592.html
 load 1403615.html
 load 1403712.html
 load 1404180-1.html
 load 1404316.html
 load 1406222-1.html
 load 1406222-2.html
 load 1404324-1.html
+load 1404324-2.html
+load 1404324-3.html
 load 1404057.html
--- a/media/libstagefright/binding/DecoderData.cpp
+++ b/media/libstagefright/binding/DecoderData.cpp
@@ -6,16 +6,17 @@
 #include "mp4_demuxer/AnnexB.h"
 #include "mp4_demuxer/ByteReader.h"
 #include "mp4_demuxer/DecoderData.h"
 #include <media/stagefright/foundation/ABitReader.h>
 #include "media/stagefright/MetaData.h"
 #include "media/stagefright/MediaDefs.h"
 #include "media/stagefright/Utils.h"
 #include "mozilla/ArrayUtils.h"
+#include "mozilla/EndianUtils.h"
 #include "include/ESDS.h"
 #include "VideoUtils.h"
 
 // OpusDecoder header is really needed only by MP4 in rust
 #include "OpusDecoder.h"
 #include "mp4parse.h"
 
 using namespace stagefright;
@@ -199,18 +200,18 @@ MP4AudioInfo::Update(const mp4parse_trac
   if (track->codec == mp4parse_codec_OPUS) {
     mMimeType = NS_LITERAL_CSTRING("audio/opus");
     // The Opus decoder expects the container's codec delay or
     // pre-skip value, in microseconds, as a 64-bit int at the
     // start of the codec-specific config blob.
     MOZ_ASSERT(audio->extra_data.data);
     MOZ_ASSERT(audio->extra_data.length >= 12);
     uint16_t preskip =
-      LittleEndian::readUint16(audio->extra_data.data + 10);
-    OpusDataDecoder::AppendCodecDelay(mCodecSpecificConfig,
+      mozilla::LittleEndian::readUint16(audio->extra_data.data + 10);
+    mozilla::OpusDataDecoder::AppendCodecDelay(mCodecSpecificConfig,
         mozilla::FramesToUsecs(preskip, 48000).value());
   } else if (track->codec == mp4parse_codec_AAC) {
     mMimeType = MEDIA_MIMETYPE_AUDIO_AAC;
   } else if (track->codec == mp4parse_codec_FLAC) {
     mMimeType = MEDIA_MIMETYPE_AUDIO_FLAC;
   } else if (track->codec == mp4parse_codec_MP3) {
     mMimeType = MEDIA_MIMETYPE_AUDIO_MPEG;
   }
--- a/media/libstagefright/binding/MoofParser.cpp
+++ b/media/libstagefright/binding/MoofParser.cpp
@@ -19,17 +19,16 @@ extern mozilla::LogModule* GetDemuxerLog
 #define LOG(name, arg, ...) MOZ_LOG(GetDemuxerLog(), mozilla::LogLevel::Debug, (TOSTRING(name) "(%p)::%s: " arg, this, __func__, ##__VA_ARGS__))
 #else
 #define LOG(...)
 #endif
 
 namespace mp4_demuxer
 {
 
-using namespace stagefright;
 using namespace mozilla;
 
 const uint32_t kKeyIdSize = 16;
 
 bool
 MoofParser::RebuildFragmentedIndex(const MediaByteRangeSet& aByteRanges)
 {
   BoxContext context(mSource, aByteRanges);
--- a/media/libstagefright/binding/SinfParser.cpp
+++ b/media/libstagefright/binding/SinfParser.cpp
@@ -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/. */
 
 #include "mozilla/Unused.h"
 #include "mp4_demuxer/SinfParser.h"
 #include "mp4_demuxer/AtomType.h"
 #include "mp4_demuxer/Box.h"
+#include "mp4_demuxer/Stream.h"
 
 namespace mp4_demuxer {
 
 Sinf::Sinf(Box& aBox)
   : mDefaultIVSize(0)
   , mDefaultEncryptionType()
 {
   SinfParser parser(aBox);
--- a/media/libstagefright/frameworks/av/media/libstagefright/ESDS.cpp
+++ b/media/libstagefright/frameworks/av/media/libstagefright/ESDS.cpp
@@ -15,17 +15,18 @@
  */
 
 //#define LOG_NDEBUG 0
 #undef LOG_TAG
 #define LOG_TAG "ESDS"
 #include <utils/Log.h>
 
 #include "include/ESDS.h"
-
+#include "mozilla/fallible.h"
+#include <new>
 #include <string.h>
 
 namespace stagefright {
 
 ESDS::ESDS(const void *data, size_t size)
     : mData(new (mozilla::fallible) uint8_t[size]),
       mSize(size),
       mInitCheck(NO_INIT),
--- a/media/libstagefright/frameworks/av/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/frameworks/av/media/libstagefright/MPEG4Extractor.cpp
@@ -604,17 +604,17 @@ status_t MPEG4Extractor::parseDrmSINF(of
             SINF *sinf = mFirstSINF;
             while (sinf && (sinf->IPMPDescriptorID != id)) {
                 sinf = sinf->next;
             }
             if (sinf == NULL) {
                 return ERROR_MALFORMED;
             }
             sinf->len = dataLen - 3;
-            sinf->IPMPData = new (fallible) char[sinf->len];
+            sinf->IPMPData = new (mozilla::fallible) char[sinf->len];
             if (!sinf->IPMPData) {
                 return -ENOMEM;
             }
 
             if (mDataSource->readAt(data_offset + 2, sinf->IPMPData, sinf->len) < sinf->len) {
                 return ERROR_IO;
             }
             data_offset += sinf->len;
@@ -1042,17 +1042,17 @@ status_t MPEG4Extractor::parseChunk(off6
             }
 
             if (mDataSource->readAt(data_offset + 4, &pssh.uuid, 16) < 16) {
                 return ERROR_IO;
             }
 
             // Copy the contents of the box (including header) verbatim.
             pssh.datalen = chunk_data_size + 8;
-            pssh.data = new (fallible) uint8_t[pssh.datalen];
+            pssh.data = new (mozilla::fallible) uint8_t[pssh.datalen];
             if (!pssh.data) {
                 return -ENOMEM;
             }
             if (mDataSource->readAt(data_offset - 8, pssh.data, pssh.datalen) < pssh.datalen) {
                 return ERROR_IO;
             }
 
             mPssh.AppendElement(pssh);
@@ -1674,17 +1674,17 @@ status_t MPEG4Extractor::parseChunk(off6
 
         case FOURCC('a', 'v', 'c', 'C'):
         {
             if (chunk_data_size < 7) {
               ALOGE("short avcC chunk (%" PRId64 " bytes)", int64_t(chunk_data_size));
               return ERROR_MALFORMED;
             }
 
-            sp<ABuffer> buffer = new (fallible) ABuffer(chunk_data_size);
+            sp<ABuffer> buffer = new (mozilla::fallible) ABuffer(chunk_data_size);
             if (!buffer.get() || !buffer->data()) {
                 return -ENOMEM;
             }
 
             if (mDataSource->readAt(
                         data_offset, buffer->data(), chunk_data_size) < chunk_data_size) {
                 return ERROR_IO;
             }
@@ -1909,17 +1909,17 @@ status_t MPEG4Extractor::parseChunk(off6
                     kKeyTextFormatData, &type, &data, &size)) {
                 size = 0;
             }
 
             // Make sure (size + chunk_size) isn't going to overflow.
             if (size >= kMAX_ALLOCATION - chunk_size) {
                 return ERROR_MALFORMED;
             }
-            uint8_t *buffer = new (fallible) uint8_t[size + chunk_size];
+            uint8_t *buffer = new (mozilla::fallible) uint8_t[size + chunk_size];
             if (!buffer) {
                 return -ENOMEM;
             }
 
             if (size > 0) {
                 memcpy(buffer, data, size);
             }
 
@@ -1944,17 +1944,17 @@ status_t MPEG4Extractor::parseChunk(off6
         {
             if (mFileMetaData != NULL) {
                 ALOGV("chunk_data_size = %lld and data_offset = %lld",
                         chunk_data_size, data_offset);
                 const int kSkipBytesOfDataBox = 16;
                 if (chunk_data_size <= kSkipBytesOfDataBox) {
                   return ERROR_MALFORMED;
                 }
-                sp<ABuffer> buffer = new (fallible) ABuffer(chunk_data_size + 1);
+                sp<ABuffer> buffer = new (mozilla::fallible) ABuffer(chunk_data_size + 1);
                 if (!buffer.get() || !buffer->data()) {
                     return -ENOMEM;
                 }
                 if (mDataSource->readAt(
                     data_offset, buffer->data(), chunk_data_size) != (ssize_t)chunk_data_size) {
                     return ERROR_IO;
                 }
                 mFileMetaData->setData(
--- a/media/libstagefright/frameworks/av/media/libstagefright/include/SampleTable.h
+++ b/media/libstagefright/frameworks/av/media/libstagefright/include/SampleTable.h
@@ -19,16 +19,17 @@
 #define SAMPLE_TABLE_H_
 
 #include <sys/types.h>
 #include <stdint.h>
 
 #include <media/stagefright/MediaErrors.h>
 #include <utils/RefBase.h>
 #include <utils/threads.h>
+#include "nsTArray.h"
 
 namespace stagefright {
 
 class DataSource;
 struct SampleIterator;
 
 class SampleTable : public RefBase {
 public:
--- a/memory/build/mozjemalloc.cpp
+++ b/memory/build/mozjemalloc.cpp
@@ -639,33 +639,63 @@ struct ExtentTreeBoundsTrait : public Ex
 
     return (key_addr > node_addr) - (key_addr < node_addr);
   }
 };
 
 /******************************************************************************/
 /*
  * Radix tree data structures.
+ *
+ * The number of bits passed to the template is the number of significant bits
+ * in an address to do a radix lookup with.
+ *
+ * An address is looked up by splitting it in kBitsPerLevel bit chunks, except
+ * the most significant bits, where the bit chunk is kBitsAtLevel1 which can be
+ * different if Bits is not a multiple of kBitsPerLevel.
+ *
+ * With e.g. sizeof(void*)=4, Bits=16 and kBitsPerLevel=8, an address is split
+ * like the following:
+ * 0x12345678 -> mRoot[0x12][0x34]
  */
 
-/*
- * Size of each radix tree node (must be a power of 2).  This impacts tree
- * depth.
- */
+template <size_t Bits>
+class AddressRadixTree {
+ // Size of each radix tree node (as a power of 2).
+ // This impacts tree depth.
 #if (SIZEOF_PTR == 4)
-#  define MALLOC_RTREE_NODESIZE (1U << 14)
+  static const size_t kNodeSize2Pow = 14;
 #else
-#  define MALLOC_RTREE_NODESIZE CACHELINE
+  static const size_t kNodeSize2Pow = CACHELINE_2POW;
 #endif
-
-struct malloc_rtree_t {
-	malloc_spinlock_t	lock;
-	void			**root;
-	unsigned		height;
-	unsigned		level2bits[1]; /* Dynamically sized. */
+  static const size_t kBitsPerLevel = kNodeSize2Pow - SIZEOF_PTR_2POW;
+  static const size_t kBitsAtLevel1 =
+    (Bits % kBitsPerLevel) ? Bits % kBitsPerLevel : kBitsPerLevel;
+  static const size_t kHeight = (Bits + kBitsPerLevel - 1) / kBitsPerLevel;
+  static_assert(kBitsAtLevel1 + (kHeight - 1) * kBitsPerLevel == Bits,
+                "AddressRadixTree parameters don't work out");
+
+  malloc_spinlock_t mLock;
+  void** mRoot;
+
+public:
+  bool Init();
+
+  inline void* Get(void* aAddr);
+
+  // Returns whether the value was properly set
+  inline bool Set(void* aAddr, void* aValue);
+
+  inline bool Unset(void* aAddr)
+  {
+    return Set(aAddr, nullptr);
+  }
+
+private:
+  inline void** GetSlot(void* aAddr, bool aCreate = false);
 };
 
 /******************************************************************************/
 /*
  * Arena data structures.
  */
 
 struct arena_t;
@@ -1034,17 +1064,17 @@ struct ArenaTreeTrait
   }
 };
 
 /********/
 /*
  * Chunks.
  */
 
-static malloc_rtree_t *chunk_rtree;
+static AddressRadixTree<(SIZEOF_PTR << 3) - CHUNK_2POW_DEFAULT> gChunkRTree;
 
 /* Protects chunk-related data structures. */
 static malloc_mutex_t	chunks_mtx;
 
 /*
  * Trees of chunks that were previously allocated (trees differ only in node
  * ordering).  These are used when allocating chunks, in an attempt to re-use
  * address space.  Depending on function, different tree orderings are needed,
@@ -1714,155 +1744,111 @@ pages_copy(void *dest, const void *src, 
 	MOZ_ASSERT(n >= VM_COPY_MIN);
 	MOZ_ASSERT((void *)((uintptr_t)src & ~pagesize_mask) == src);
 
 	vm_copy(mach_task_self(), (vm_address_t)src, (vm_size_t)n,
 	    (vm_address_t)dest);
 }
 #endif
 
-static inline malloc_rtree_t *
-malloc_rtree_new(unsigned bits)
+template <size_t Bits>
+bool
+AddressRadixTree<Bits>::Init()
+{
+  malloc_spin_init(&mLock);
+
+  mRoot = (void**)base_calloc(1 << kBitsAtLevel1, sizeof(void*));
+  return mRoot;
+}
+
+template <size_t Bits>
+void**
+AddressRadixTree<Bits>::GetSlot(void* aKey, bool aCreate)
 {
-	malloc_rtree_t *ret;
-	unsigned bits_per_level, height, i;
-
-	bits_per_level = ffs(pow2_ceil((MALLOC_RTREE_NODESIZE /
-	    sizeof(void *)))) - 1;
-	height = bits / bits_per_level;
-	if (height * bits_per_level != bits)
-		height++;
-	MOZ_DIAGNOSTIC_ASSERT(height * bits_per_level >= bits);
-
-	ret = (malloc_rtree_t*)base_calloc(1, sizeof(malloc_rtree_t) +
-	    (sizeof(unsigned) * (height - 1)));
-	if (!ret)
-		return nullptr;
-
-	malloc_spin_init(&ret->lock);
-	ret->height = height;
-	if (bits_per_level * height > bits)
-		ret->level2bits[0] = bits % bits_per_level;
-	else
-		ret->level2bits[0] = bits_per_level;
-	for (i = 1; i < height; i++)
-		ret->level2bits[i] = bits_per_level;
-
-	ret->root = (void**)base_calloc(1, sizeof(void *) << ret->level2bits[0]);
-	if (!ret->root) {
-		/*
-		 * We leak the rtree here, since there's no generic base
-		 * deallocation.
-		 */
-		return nullptr;
-	}
-
-	return (ret);
+  uintptr_t key = reinterpret_cast<uintptr_t>(aKey);
+  uintptr_t subkey;
+  unsigned i, lshift, height, bits;
+  void** node;
+  void** child;
+
+  for (i = lshift = 0, height = kHeight, node = mRoot;
+       i < height - 1;
+       i++, lshift += bits, node = child) {
+    bits = i ? kBitsPerLevel : kBitsAtLevel1;
+    subkey = (key << lshift) >> ((SIZEOF_PTR << 3) - bits);
+    child = (void**) node[subkey];
+    if (!child && aCreate) {
+      child = (void**) base_calloc(1 << kBitsPerLevel, sizeof(void*));
+      if (child) {
+        node[subkey] = child;
+      }
+    }
+    if (!child) {
+      return nullptr;
+    }
+  }
+
+  /*
+   * node is a leaf, so it contains values rather than node
+   * pointers.
+   */
+  bits = i ? kBitsPerLevel : kBitsAtLevel1;
+  subkey = (key << lshift) >> ((SIZEOF_PTR << 3) - bits);
+  return &node[subkey];
 }
 
-#define	MALLOC_RTREE_GET_GENERATE(f)					\
-/* The least significant bits of the key are ignored. */		\
-static inline void *							\
-f(malloc_rtree_t *rtree, uintptr_t key)					\
-{									\
-	void *ret;							\
-	uintptr_t subkey;						\
-	unsigned i, lshift, height, bits;				\
-	void **node, **child;						\
-									\
-	MALLOC_RTREE_LOCK(&rtree->lock);				\
-	for (i = lshift = 0, height = rtree->height, node = rtree->root;\
-	    i < height - 1;						\
-	    i++, lshift += bits, node = child) {			\
-		bits = rtree->level2bits[i];				\
-		subkey = (key << lshift) >> ((SIZEOF_PTR << 3) - bits);	\
-		child = (void**)node[subkey];				\
-		if (!child) {						\
-			MALLOC_RTREE_UNLOCK(&rtree->lock);		\
-			return nullptr;					\
-		}							\
-	}								\
-									\
-	/*								\
-	 * node is a leaf, so it contains values rather than node	\
-	 * pointers.							\
-	 */								\
-	bits = rtree->level2bits[i];					\
-	subkey = (key << lshift) >> ((SIZEOF_PTR << 3) - bits);		\
-	ret = node[subkey];						\
-	MALLOC_RTREE_UNLOCK(&rtree->lock);				\
-									\
-	MALLOC_RTREE_GET_VALIDATE					\
-	return (ret);							\
-}
-
-#ifdef MOZ_DEBUG
-#  define MALLOC_RTREE_LOCK(l)		malloc_spin_lock(l)
-#  define MALLOC_RTREE_UNLOCK(l)	malloc_spin_unlock(l)
-#  define MALLOC_RTREE_GET_VALIDATE
-MALLOC_RTREE_GET_GENERATE(malloc_rtree_get_locked)
-#  undef MALLOC_RTREE_LOCK
-#  undef MALLOC_RTREE_UNLOCK
-#  undef MALLOC_RTREE_GET_VALIDATE
-#endif
-
-#define	MALLOC_RTREE_LOCK(l)
-#define	MALLOC_RTREE_UNLOCK(l)
+template <size_t Bits>
+void*
+AddressRadixTree<Bits>::Get(void* aKey)
+{
+  void* ret = nullptr;
+
+  void** slot = GetSlot(aKey);
+
+  if (slot) {
+    ret = *slot;
+  }
 #ifdef MOZ_DEBUG
-   /*
-    * Suppose that it were possible for a jemalloc-allocated chunk to be
-    * munmap()ped, followed by a different allocator in another thread re-using
-    * overlapping virtual memory, all without invalidating the cached rtree
-    * value.  The result would be a false positive (the rtree would claim that
-    * jemalloc owns memory that it had actually discarded).  I don't think this
-    * scenario is possible, but the following assertion is a prudent sanity
-    * check.
-    */
-#  define MALLOC_RTREE_GET_VALIDATE					\
-	MOZ_ASSERT(malloc_rtree_get_locked(rtree, key) == ret);
-#else
-#  define MALLOC_RTREE_GET_VALIDATE
+  malloc_spin_lock(&mlock);
+  /*
+   * Suppose that it were possible for a jemalloc-allocated chunk to be
+   * munmap()ped, followed by a different allocator in another thread re-using
+   * overlapping virtual memory, all without invalidating the cached rtree
+   * value.  The result would be a false positive (the rtree would claim that
+   * jemalloc owns memory that it had actually discarded).  I don't think this
+   * scenario is possible, but the following assertion is a prudent sanity
+   * check.
+   */
+  if (!slot) {
+    // In case a slot has been created in the meantime.
+    slot = GetSlot(aKey);
+  }
+  if (slot) {
+    // The malloc_spin_lock call above should act as a memory barrier, forcing
+    // the compiler to emit a new read instruction for *slot.
+    MOZ_ASSERT(ret == *slot);
+  } else {
+    MOZ_ASSERT(ret == nullptr);
+  }
+  malloc_spin_unlock(&mlock);
 #endif
-MALLOC_RTREE_GET_GENERATE(malloc_rtree_get)
-#undef MALLOC_RTREE_LOCK
-#undef MALLOC_RTREE_UNLOCK
-#undef MALLOC_RTREE_GET_VALIDATE
-
-static inline bool
-malloc_rtree_set(malloc_rtree_t *rtree, uintptr_t key, void *val)
+  return ret;
+}
+
+template <size_t Bits>
+bool
+AddressRadixTree<Bits>::Set(void* aKey, void* aValue)
 {
-	uintptr_t subkey;
-	unsigned i, lshift, height, bits;
-	void **node, **child;
-
-	malloc_spin_lock(&rtree->lock);
-	for (i = lshift = 0, height = rtree->height, node = rtree->root;
-	    i < height - 1;
-	    i++, lshift += bits, node = child) {
-		bits = rtree->level2bits[i];
-		subkey = (key << lshift) >> ((SIZEOF_PTR << 3) - bits);
-		child = (void**)node[subkey];
-		if (!child) {
-			child = (void**)base_calloc(1, sizeof(void *) <<
-			    rtree->level2bits[i+1]);
-			if (!child) {
-				malloc_spin_unlock(&rtree->lock);
-				return (true);
-			}
-			node[subkey] = child;
-		}
-	}
-
-	/* node is a leaf, so it contains values rather than node pointers. */
-	bits = rtree->level2bits[i];
-	subkey = (key << lshift) >> ((SIZEOF_PTR << 3) - bits);
-	node[subkey] = val;
-	malloc_spin_unlock(&rtree->lock);
-
-	return (false);
+  malloc_spin_lock(&mLock);
+  void** slot = GetSlot(aKey, /* create */ true);
+  if (slot) {
+    *slot = aValue;
+  }
+  malloc_spin_unlock(&mLock);
+  return slot;
 }
 
 /* pages_trim, chunk_alloc_mmap_slow and chunk_alloc_mmap were cherry-picked
  * from upstream jemalloc 3.4.1 to fix Mozilla bug 956501. */
 
 /* Return the offset between a and the nearest aligned address at or below a. */
 #define        ALIGNMENT_ADDR2OFFSET(a, alignment)                                \
         ((size_t)((uintptr_t)(a) & (alignment - 1)))
@@ -2143,17 +2129,17 @@ chunk_alloc(size_t size, size_t alignmen
 		goto RETURN;
 	}
 
 	/* All strategies for allocation failed. */
 	ret = nullptr;
 RETURN:
 
 	if (ret && base == false) {
-		if (malloc_rtree_set(chunk_rtree, (uintptr_t)ret, ret)) {
+		if (!gChunkRTree.Set(ret, ret)) {
 			chunk_dealloc(ret, size, UNKNOWN_CHUNK);
 			return nullptr;
 		}
 	}
 
 	MOZ_ASSERT(CHUNK_ADDR2BASE(ret) == ret);
 	return (ret);
 }
@@ -2275,17 +2261,17 @@ static void
 chunk_dealloc(void *chunk, size_t size, ChunkType type)
 {
 
 	MOZ_ASSERT(chunk);
 	MOZ_ASSERT(CHUNK_ADDR2BASE(chunk) == chunk);
 	MOZ_ASSERT(size != 0);
 	MOZ_ASSERT((size & chunksize_mask) == 0);
 
-	malloc_rtree_set(chunk_rtree, (uintptr_t)chunk, nullptr);
+	gChunkRTree.Unset(chunk);
 
 	if (CAN_RECYCLE(size)) {
 		size_t recycled_so_far = load_acquire_z(&recycled_size);
 		// In case some race condition put us above the limit.
 		if (recycled_so_far < recycle_limit) {
 			size_t recycle_remaining = recycle_limit - recycled_so_far;
 			size_t to_recycle;
 			if (size > recycle_remaining) {
@@ -3477,17 +3463,17 @@ isalloc_validate(const void* ptr)
     return 0;
   }
 
   arena_chunk_t* chunk = (arena_chunk_t*)CHUNK_ADDR2BASE(ptr);
   if (!chunk) {
     return 0;
   }
 
-  if (!malloc_rtree_get(chunk_rtree, (uintptr_t)chunk)) {
+  if (!gChunkRTree.Get(chunk)) {
     return 0;
   }
 
   if (chunk != ptr) {
     MOZ_DIAGNOSTIC_ASSERT(chunk->arena->mMagic == ARENA_MAGIC);
     return arena_salloc(ptr);
   } else {
     size_t ret;
@@ -3547,35 +3533,35 @@ MozJemalloc::jemalloc_ptr_info(const voi
   arena_chunk_t* chunk = (arena_chunk_t*)CHUNK_ADDR2BASE(aPtr);
 
   // Is the pointer null, or within one chunk's size of null?
   if (!chunk) {
     *aInfo = { TagUnknown, nullptr, 0 };
     return;
   }
 
-  // Look for huge allocations before looking for |chunk| in chunk_rtree.
-  // This is necessary because |chunk| won't be in chunk_rtree if it's
+  // Look for huge allocations before looking for |chunk| in gChunkRTree.
+  // This is necessary because |chunk| won't be in gChunkRTree if it's
   // the second or subsequent chunk in a huge allocation.
   extent_node_t* node;
   extent_node_t key;
   malloc_mutex_lock(&huge_mtx);
   key.addr = const_cast<void*>(aPtr);
   node = reinterpret_cast<
     RedBlackTree<extent_node_t, ExtentTreeBoundsTrait>*>(&huge)->Search(&key);
   if (node) {
     *aInfo = { TagLiveHuge, node->addr, node->size };
   }
   malloc_mutex_unlock(&huge_mtx);
   if (node) {
     return;
   }
 
   // It's not a huge allocation. Check if we have a known chunk.
-  if (!malloc_rtree_get(chunk_rtree, (uintptr_t)chunk)) {
+  if (!gChunkRTree.Get(chunk)) {
     *aInfo = { TagUnknown, nullptr, 0 };
     return;
   }
 
   MOZ_DIAGNOSTIC_ASSERT(chunk->arena->mMagic == ARENA_MAGIC);
 
   // Get the page number within the chunk.
   size_t pageind = (((uintptr_t)aPtr - (uintptr_t)chunk) >> pagesize_2pow);
@@ -4505,18 +4491,17 @@ MALLOC_OUT:
    * reset to the default value for the main arena. */
   gMainArena->mMaxDirty = opt_dirty_max;
 
   /*
    * Assign the initial arena to the initial thread.
    */
   thread_arena.set(gMainArena);
 
-  chunk_rtree = malloc_rtree_new((SIZEOF_PTR << 3) - CHUNK_2POW_DEFAULT);
-  if (!chunk_rtree) {
+  if (!gChunkRTree.Init()) {
     return true;
   }
 
   malloc_initialized = true;
 
 #if !defined(XP_WIN) && !defined(XP_DARWIN)
   /* Prevent potential deadlock on malloc locks after fork. */
   pthread_atfork(_malloc_prefork, _malloc_postfork_parent, _malloc_postfork_child);
--- a/mfbt/WindowsVersion.h
+++ b/mfbt/WindowsVersion.h
@@ -2,27 +2,28 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_WindowsVersion_h
 #define mozilla_WindowsVersion_h
 
+#include "mozilla/Atomics.h"
 #include "mozilla/Attributes.h"
 #include <stdint.h>
 #include <windows.h>
 
 namespace mozilla {
 
 inline bool
 IsWindowsVersionOrLater(uint32_t aVersion)
 {
-  static uint32_t minVersion = 0;
-  static uint32_t maxVersion = UINT32_MAX;
+  static Atomic<uint32_t> minVersion(0);
+  static Atomic<uint32_t> maxVersion(UINT32_MAX);
 
   if (minVersion >= aVersion) {
     return true;
   }
 
   if (aVersion >= maxVersion) {
     return false;
   }
@@ -51,18 +52,18 @@ IsWindowsVersionOrLater(uint32_t aVersio
 
   maxVersion = aVersion;
   return false;
 }
 
 inline bool
 IsWindowsBuildOrLater(uint32_t aBuild)
 {
-  static uint32_t minBuild = 0;
-  static uint32_t maxBuild = UINT32_MAX;
+  static Atomic<uint32_t> minBuild(0);
+  static Atomic<uint32_t> maxBuild(UINT32_MAX);
 
   if (minBuild >= aBuild) {
     return true;
   }
 
   if (aBuild >= maxBuild) {
     return false;
   }
@@ -82,18 +83,18 @@ IsWindowsBuildOrLater(uint32_t aBuild)
 
   maxBuild = aBuild;
   return false;
 }
 
 inline bool
 IsWindows10BuildOrLater(uint32_t aBuild)
 {
-  static uint32_t minBuild = 0;
-  static uint32_t maxBuild = UINT32_MAX;
+  static Atomic<uint32_t> minBuild(0);
+  static Atomic<uint32_t> maxBuild(UINT32_MAX);
 
   if (minBuild >= aBuild) {
     return true;
   }
 
   if (aBuild >= maxBuild) {
     return false;
   }
--- a/python/mozbuild/mozbuild/test/configure/test_toolchain_configure.py
+++ b/python/mozbuild/mozbuild/test/configure/test_toolchain_configure.py
@@ -1403,10 +1403,170 @@ class OpenBSDToolchainTest(BaseToolchain
 
     def test_gcc(self):
         self.do_toolchain_test(self.PATHS, {
             'c_compiler': self.GCC_4_9_RESULT,
             'cxx_compiler': self.GXX_4_9_RESULT,
         })
 
 
+class RustTest(BaseConfigureTest):
+    def invoke_cargo(self, stdin, args):
+        if args == ('--version', '--verbose'):
+            return 0, 'cargo 2.0\nrelease: 2.0', ''
+        raise NotImplementedError('unsupported arguments')
+
+    def invoke_rustc(self, stdin, args):
+        if args == ('--version', '--verbose'):
+            return 0, 'rustc 2.0\nrelease: 2.0', ''
+        if args == ('--print', 'target-list'):
+            # Raw list returned by rustc version 1.19, + ios, which somehow
+            # don't appear in the default list.
+            # https://github.com/rust-lang/rust/issues/36156
+            rust_targets = [
+                'aarch64-apple-ios',
+                'aarch64-linux-android',
+                'aarch64-unknown-freebsd',
+                'aarch64-unknown-fuchsia',
+                'aarch64-unknown-linux-gnu',
+                'arm-linux-androideabi',
+                'arm-unknown-linux-gnueabi',
+                'arm-unknown-linux-gnueabihf',
+                'arm-unknown-linux-musleabi',
+                'arm-unknown-linux-musleabihf',
+                'armv5te-unknown-linux-gnueabi',
+                'armv7-linux-androideabi',
+                'armv7-unknown-linux-gnueabihf',
+                'armv7-unknown-linux-musleabihf',
+                'armv7s-apple-ios',
+                'asmjs-unknown-emscripten',
+                'i386-apple-ios',
+                'i586-pc-windows-msvc',
+                'i586-unknown-linux-gnu',
+                'i686-apple-darwin',
+                'i686-linux-android',
+                'i686-pc-windows-gnu',
+                'i686-pc-windows-msvc',
+                'i686-unknown-dragonfly',
+                'i686-unknown-freebsd',
+                'i686-unknown-haiku',
+                'i686-unknown-linux-gnu',
+                'i686-unknown-linux-musl',
+                'i686-unknown-netbsd',
+                'i686-unknown-openbsd',
+                'le32-unknown-nacl',
+                'mips-unknown-linux-gnu',
+                'mips-unknown-linux-musl',
+                'mips-unknown-linux-uclibc',
+                'mips64-unknown-linux-gnuabi64',
+                'mips64el-unknown-linux-gnuabi64',
+                'mipsel-unknown-linux-gnu',
+                'mipsel-unknown-linux-musl',
+                'mipsel-unknown-linux-uclibc',
+                'powerpc-unknown-linux-gnu',
+                'powerpc64-unknown-linux-gnu',
+                'powerpc64le-unknown-linux-gnu',
+                's390x-unknown-linux-gnu',
+                'sparc64-unknown-linux-gnu',
+                'sparc64-unknown-netbsd',
+                'sparcv9-sun-solaris',
+                'thumbv6m-none-eabi',
+                'thumbv7em-none-eabi',
+                'thumbv7em-none-eabihf',
+                'thumbv7m-none-eabi',
+                'wasm32-unknown-emscripten',
+                'x86_64-apple-darwin',
+                'x86_64-apple-ios',
+                'x86_64-linux-android',
+                'x86_64-pc-windows-gnu',
+                'x86_64-pc-windows-msvc',
+                'x86_64-rumprun-netbsd',
+                'x86_64-sun-solaris',
+                'x86_64-unknown-bitrig',
+                'x86_64-unknown-dragonfly',
+                'x86_64-unknown-freebsd',
+                'x86_64-unknown-fuchsia',
+                'x86_64-unknown-haiku',
+                'x86_64-unknown-linux-gnu',
+                'x86_64-unknown-linux-musl',
+                'x86_64-unknown-netbsd',
+                'x86_64-unknown-openbsd',
+                'x86_64-unknown-redox',
+            ]
+            return 0, '\n'.join(rust_targets), ''
+        if (len(args) == 6 and args[:2] == ('--crate-type', 'staticlib') and
+            args[2].startswith('--target=') and args[3] == '-o'):
+            with open(args[4], 'w') as fh:
+                fh.write('foo')
+            return 0, '', ''
+        raise NotImplementedError('unsupported arguments')
+
+    def get_rust_target(self, target, building_with_gcc=True):
+        environ = {
+            'PATH': os.pathsep.join(
+                mozpath.abspath(p) for p in ('/bin', '/usr/bin')),
+        }
+
+        paths = {
+            mozpath.abspath('/usr/bin/cargo'): self.invoke_cargo,
+            mozpath.abspath('/usr/bin/rustc'): self.invoke_rustc,
+        }
+
+        self.TARGET = target
+        sandbox = self.get_sandbox(paths, {}, [], environ)
+
+        # Trick the sandbox into not running the target compiler check
+        dep = sandbox._depends[sandbox['building_with_gcc']]
+        getattr(sandbox, '__value_for_depends')[(dep, False)] = \
+            building_with_gcc
+        return sandbox._value_for(sandbox['rust_target_triple'])
+
+    def test_rust_target(self):
+        # Cases where the output of config.sub matches a rust target
+        for straightforward in (
+            'x86_64-unknown-dragonfly',
+            'aarch64-unknown-freebsd',
+            'i686-unknown-freebsd',
+            'x86_64-unknown-freebsd',
+            'sparc64-unknown-netbsd',
+            'i686-unknown-netbsd',
+            'x86_64-unknown-netbsd',
+            'i686-unknown-openbsd',
+            'x86_64-unknown-openbsd',
+            'aarch64-unknown-linux-gnu',
+            'armv7-unknown-linux-gnueabihf',
+            'sparc64-unknown-linux-gnu',
+            'i686-unknown-linux-gnu',
+            'i686-apple-darwin',
+            'x86_64-apple-darwin',
+            'aarch64-apple-ios',
+            'armv7s-apple-ios',
+            'i386-apple-ios',
+            'x86_64-apple-ios',
+        ):
+            self.assertEqual(self.get_rust_target(straightforward), straightforward)
+
+        # Cases where the output of config.sub is different
+        for autoconf, rust in (
+            ('aarch64-unknown-linux-android', 'aarch64-linux-android'),
+            ('arm-unknown-linux-androideabi', 'armv7-linux-androideabi'),
+            ('armv7-unknown-linux-androideabi', 'armv7-linux-androideabi'),
+            ('i386-unknown-linux-android', 'i686-linux-android'),
+            ('i686-unknown-linux-android', 'i686-linux-android'),
+            ('x86_64-unknown-linux-android', 'x86_64-linux-android'),
+            ('x86_64-pc-linux-gnu', 'x86_64-unknown-linux-gnu'),
+            ('sparcv9-sun-solaris2', 'sparcv9-sun-solaris'),
+            ('x86_64-sun-solaris2', 'x86_64-sun-solaris'),
+        ):
+            self.assertEqual(self.get_rust_target(autoconf), rust)
+
+        # Windows
+        for autoconf, building_with_gcc, rust in (
+            ('i686-pc-mingw32', False, 'i686-pc-windows-msvc'),
+            ('x86_64-pc-mingw32', False, 'x86_64-pc-windows-msvc'),
+            ('i686-pc-mingw32', True, 'i686-pc-windows-gnu'),
+            ('x86_64-pc-mingw32', True, 'x86_64-pc-windows-gnu'),
+        ):
+            self.assertEqual(self.get_rust_target(autoconf, building_with_gcc), rust)
+
+
 if __name__ == '__main__':
     main()
--- a/security/manager/ssl/StaticHPKPins.h
+++ b/security/manager/ssl/StaticHPKPins.h
@@ -1135,9 +1135,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 = 479;
 
 static const int32_t kUnknownId = -1;
 
-static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1516038167454000);
+static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1516081864552000);
--- a/security/manager/ssl/nsSTSPreloadList.errors
+++ b/security/manager/ssl/nsSTSPreloadList.errors
@@ -1,111 +1,129 @@
 0day.su: could not connect to host
+0i0.nl: could not connect to host
+125m125.de: could not connect to host
 174.net.nz: could not connect to host
+27728522.com: could not connect to host
 360live.fr: could not connect to host
 47tech.com: could not connect to host
 4loc.us: could not connect to host
 4x4.lk: could not connect to host
 724go.com: could not connect to host
 8560.be: could not connect to host
+87577.com: could not connect to host
 8887999.com: could not connect to host
+8t88.biz: could not connect to host
 91-freedom.com: could not connect to host
 aamwa.com: could not connect to host
 abolition.co: could not connect to host
 acrossgw.com: could not connect to host
+adrinet.tk: could not connect to host
 aevpn.org: could not connect to host
+agowa.eu: could not connect to host
 aivd.lol: could not connect to host
 akul.co.in: could not connect to host
 alexandros.io: could not connect to host
-alltubedownload.net: could not connect to host
-altestore.com: could not connect to host
+altahrim.net: could not connect to host
 amua.fr: could not connect to host
 annetaan.fi: could not connect to host
 arent.kz: could not connect to host
-arox.eu: could not connect to host
+arksan.com.tr: could not connect to host
+artisense.de: could not connect to host
 assdecoeur.org: could not connect to host
 astral.gq: could not connect to host
+attilagyorffy.com: could not connect to host
+avi9526.pp.ua: could not connect to host
 aviv.nyc: could not connect to host
 azabani.com: could not connect to host
 backschues.com: could not connect to host
 backschues.net: could not connect to host
 balonmano.co: could not connect to host
 bbdos.ru: could not connect to host
 beamitapp.com: could not connect to host
+beelen.fr: could not connect to host
 berna.fr: could not connect to host
-bianinapiccanovias.com: could not connect to host
-bilder-designs.de: could not connect to host
 bip.gov.sa: could not connect to host
 black-khat.com: could not connect to host
 blumen-garage.de: could not connect to host
+bodrumfarm.com: could not connect to host
 brettabel.com: could not connect to host
 buyshoe.org: could not connect to host
 by1898.com: could not connect to host
 cais.de: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 119"  data: no]
 cake-time.co.uk: could not connect to host
 capekeen.com: could not connect to host
+capellidipremoli.com: could not connect to host
 casperpanel.com: could not connect to host
-chattergalerie.eu: could not connect to host
-chattergallery.com: could not connect to host
+cbdev.de: could not connect to host
 chloehorler.com: could not connect to host
 chonghe.org: could not connect to host
 christina-quast.de: could not connect to host
 cielly.com: could not connect to host
 cirfi.com: could not connect to host
 clearviewwealthprojector.com.au: could not connect to host
 cloudbased.info: could not connect to host
 cloudbleed.info: could not connect to host
 cmpr.es: could not connect to host
 cnlic.com: could not connect to host
 colleencornez.com: could not connect to host
-cosirex.com: could not connect to host
 cpaneltips.com: could not connect to host
+criticalaim.com: could not connect to host
+cry.nu: could not connect to host
 csgo77.com: could not connect to host
-cyberxpert.nl: could not connect to host
 cypherpunk.ws: could not connect to host
 czlx.co: could not connect to host
 dahlberg.cologne: could not connect to host
-danielalvarez.net: could not connect to host
-danonsecurity.com: could not connect to host
+dataprotectionadvisors.com: could not connect to host
 datorb.com: could not connect to host
 dawnson.is: could not connect to host
 dcc.moe: could not connect to host
 de-servers.de: could not connect to host
 decoyrouting.com: could not connect to host
 derivativeshub.pro: could not connect to host
-deutschland-dsl.de: could not connect to host
 dev-talk.eu: could not connect to host
+dick.red: could not connect to host
 digioccumss.ddns.net: could not connect to host
 dijks.com: could not connect to host
+dillewijnzwapak.nl: could not connect to host
 dingcc.xyz: could not connect to host
 disco-crazy-world.de: could not connect to host
 dkravchenko.su: could not connect to host
 donotspellitgav.in: could not connect to host
+dorianmuthig.com: could not connect to host
+dostavkakurierom.ru: could not connect to host
 dreizwosechs.de: could not connect to host
 drkmtrx.xyz: could not connect to host
 duch.cloud: could not connect to host
 duelsow.eu: could not connect to host
 duo.money: could not connect to host
-dutchweballiance.nl: could not connect to host
 dyeager.org: could not connect to host
-economy.st: could not connect to host
+dynamicsnetwork.net: could not connect to host
+dynts.pro: could not connect to host
+ecotruck-pooling.com: could not connect to host
 ectora.com: could not connect to host
 edit.yahoo.com: could not connect to host
 educatoys.com.br: could not connect to host
+eduif.nl: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 119"  data: no]
+eez.ee: could not connect to host
 ehuber.info: could not connect to host
+elia.cloud: could not connect to host
 endlessdiy.ca: could not connect to host
 estan.cn: could not connect to host
 eurostrategy.vn.ua: could not connect to host
-evony.eu: could not connect to host
+expatads.com: could not connect to host
+farm24.co.uk: could not connect to host
 ficklenote.net: could not connect to host
 filhomes.ph: could not connect to host
 firebaseio.com: could not connect to host
 firexarxa.de: could not connect to host
+first-time-offender.com: could not connect to host
 fixate.ru: could not connect to host
 fixmyglitch.com: could not connect to host
+fortress.sk: could not connect to host
 fossewayflowers.co.uk: could not connect to host
 fossewayflowers.com: could not connect to host
 foxmay.co.uk: could not connect to host
 fukuko.biz: could not connect to host
 fukuko.xyz: could not connect to host
 fuliydys.com: could not connect to host
 funfunmstdn.tokyo: could not connect to host
 funideas.org: could not connect to host
@@ -114,63 +132,65 @@ fyol.pw: could not connect to host
 g4w.co: could not connect to host
 gam3rs.de: could not connect to host
 gdevpenze.ru: could not connect to host
 getwarden.net: could not connect to host
 gevaulug.fr: could not connect to host
 gfoss.gr: could not connect to host
 globalgivingtime.com: could not connect to host
 gmantra.org: could not connect to host
+goanalyse.co.uk: could not connect to host
 google: could not connect to host
 gottfridsberg.org: could not connect to host
-gra2.com: could not connect to host
 gradsm-ci.net: could not connect to host
 gritte.net: could not connect to host
 gtdgo.com: could not connect to host
 gvt2.com: could not connect to host
 gvt3.com: could not connect to host
 happygadget.me: could not connect to host
+head.org: could not connect to host
 heijblok.com: could not connect to host
 here.ml: could not connect to host
 hg881.com: could not connect to host
+homeownersassociationmanagementla.com: could not connect to host
 hoodoo.io: could not connect to host
 hoodoo.tech: could not connect to host
-hopesb.org: could not connect to host
 hostam.link: could not connect to host
 hukkatavara.com: could not connect to host
+hundter.com: could not connect to host
 ifxnet.com: could not connect to host
-ikwilthepiratebay.org: could not connect to host
 imouyang.com: could not connect to host
 industreiler.com: could not connect to host
 industreiler.com.br: could not connect to host
 inexpensivecomputers.net: could not connect to host
 ipv6.watch: could not connect to host
 iskai.net: could not connect to host
 islief.com: could not connect to host
 isoroc-nidzica.pl: could not connect to host
 jaredfraser.com: could not connect to host
 javascriptlab.fr: could not connect to host
+jcyz.cf: could not connect to host
 jeffreymagee.com: could not connect to host
 jhburton.co.uk: could not connect to host
 jie.dance: could not connect to host
 johnblackbourn.com: could not connect to host
 just-pools.co.za: could not connect to host
 justmy.website: could not connect to host
-kabus.org: could not connect to host
 kamikaichimaru.com: could not connect to host
 kapo.info: could not connect to host
+karanlyons.com: could not connect to host
 kenrogers.co: could not connect to host
+kevinmeijer.nl: could not connect to host
 kieranweightman.me: could not connect to host
 knapp.noip.me: could not connect to host
-kostya.net: could not connect to host
 kousaku.jp: could not connect to host
 kozmik.co: could not connect to host
 kteen.info: could not connect to host
-kuoruan.com: could not connect to host
 lacasa.fr: could not connect to host
+laglab.org: could not connect to host
 lathamlabs.com: could not connect to host
 lathamlabs.net: could not connect to host
 lathamlabs.org: could not connect to host
 lcht.ch: could not connect to host
 legitaxi.com: could not connect to host
 leninalbertop.com.ve: could not connect to host
 lezdomsm.com: could not connect to host
 lheinrich.org: could not connect to host
@@ -178,160 +198,169 @@ libscode.com: could not connect to host
 linksanitizer.com: could not connect to host
 lipex.com: could not connect to host
 littleservice.cn: could not connect to host
 livnev.me: could not connect to host
 logcat.info: could not connect to host
 logimagine.com: could not connect to host
 luav.org: could not connect to host
 lunix.io: could not connect to host
+m4570.xyz: could not connect to host
+maartenterpstra.xyz: could not connect to host
 macedopesca.com.br: could not connect to host
+mader.jp: could not connect to host
 martin-mattel.com: could not connect to host
 martinrogalla.com: could not connect to host
-mattferderer.com: could not connect to host
 mc-team.org: could not connect to host
 mcdanieldevelopmentservices.com: could not connect to host
 mcea-hld.jp: could not connect to host
 mchopkins.net: could not connect to host
 metachris.com: could not connect to host
+mikropixel.de: could not connect to host
 mingy.ddns.net: could not connect to host
+mmalisz.com: could not connect to host
 mmstick.tk: could not connect to host
 modded-minecraft-server-list.com: could not connect to host
-montage-kaika.de: could not connect to host
+moderntld.net: could not connect to host
 mosaique-lachenaie.fr: could not connect to host
 muh.io: could not connect to host
 muj-svet.cz: could not connect to host
-multimedia-pool.com: could not connect to host
 munduch.cz: could not connect to host
+mynetworkingbuddy.com: could not connect to host
 navdeep.ca: could not connect to host
 ncdesigns-studio.com: could not connect to host
 necesitodinero.org: could not connect to host
 nedcf.org.uk: could not connect to host
 negai.moe: could not connect to host
 nevolution.me: could not connect to host
 nginxyii.tk: could not connect to host
 nikolasbradshaw.com: could not connect to host
 nnote.net: could not connect to host
 nostraspace.com: could not connect to host
-noxlogic.nl: could not connect to host
-nqesh.com: could not connect to host
 nsbfalconacademy.org: could not connect to host
 nup.pw: could not connect to host
 oliverspringer.eu: could not connect to host
 onewebdev.info: could not connect to host
 onstud.com: could not connect to host
 opengg.me: could not connect to host
 optimist.bg: could not connect to host
 oranges.tokyo: could not connect to host
 oscsdp.cz: could not connect to host
+oshell.me: could not connect to host
 osterkraenzchen.de: could not connect to host
 oxygaming.com: could not connect to host
 oxymc.com: could not connect to host
+oxynux.xyz: could not connect to host
 pandymic.com: could not connect to host
 paragon.edu: could not connect to host
 pascalchristen.ch: could not connect to host
 pe-bank.co.jp: could not connect to host
 pengisatelier.net: could not connect to host
 perkbrian.com: could not connect to host
 persjrp.ca: could not connect to host
 persoform.ch: could not connect to host
 picallo.es: could not connect to host
 pkov.cz: could not connect to host
 plaasprodukte.com: could not connect to host
+pointagri.com: could not connect to host
 polit.im: could not connect to host
 poolinstallers.co.za: could not connect to host
 pouets.ovh: could not connect to host
 projectasterk.com: could not connect to host
 proxydesk.eu: could not connect to host
-psylab.cc: could not connect to host
-psylab.vip: could not connect to host
 pythia.nz: could not connect to host
 qionouu.cn: could not connect to host
 qto.net: could not connect to host
-quantumfurball.net: could not connect to host
+quikrmovies.to: could not connect to host
 rainbin.com: could not connect to host
 real-compare.com: could not connect to host
 refactor.zone: could not connect to host
 reignsphere.net: could not connect to host
 reinaertvandecruys.me: could not connect to host
 rolodato.com: could not connect to host
+rtvi.com: could not connect to host
+s1mplescripts.de: could not connect to host
 sallysubs.com: could not connect to host
+sanael.net: could not connect to host
 sanatrans.com: could not connect to host
 sarndipity.com: could not connect to host
 schlachter.ca: could not connect to host
 security201.co.uk: could not connect to host
 securitymap.wiki: could not connect to host
 semantheme.fr: could not connect to host
 shadowplus.net: could not connect to host
 shadowrocket.net: could not connect to host
-sharekey.com: could not connect to host
 sharevari.com: could not connect to host
 shavingks.com: could not connect to host
 shirakaba-cc.com: could not connect to host
 simbolo.co.uk: could not connect to host
 simonkjellberg.com: could not connect to host
 simplerses.com: could not connect to host
 slaughterhouse.fr: could not connect to host
+snille.com: could not connect to host
 socialworkout.com: could not connect to host
 socialworkout.net: could not connect to host
 socialworkout.org: could not connect to host
 socialworkout.tv: could not connect to host
 sonic.sk: could not connect to host
+soontm.de: could not connect to host
 soubriquet.org: could not connect to host
 soulema.com: could not connect to host
+sowingseasons.com: could not connect to host
 spicywombat.com: could not connect to host
 sputnik1net.org: could not connect to host
 sss3s.com: could not connect to host
 stadionmanager.com: could not connect to host
 stitthappens.com: could not connect to host
 stytt.com: could not connect to host
 surdam.casa: could not connect to host
 sviz.pro: could not connect to host
-taberu-fujitsubo.com: could not connect to host
 taidu.news: could not connect to host
 taskotron.stg.fedoraproject.org: could not connect to host
 tech-blog.fr: could not connect to host
-techademy.nl: could not connect to host
 tenispopular.com: could not connect to host
 terminalvelocity.co.nz: could not connect to host
 thesehighsandlows.com: could not connect to host
+theworldsend.eu: could not connect to host
 thinkcash.nl: could not connect to host
 tiliaze.info: could not connect to host
 tiliaze.net: could not connect to host
 totch.de: could not connect to host
 totot.net: could not connect to host
 transcendmotor.sg: could not connect to host
 turn-sticks.com: could not connect to host
-uptimed.com: could not connect to host
+underskatten.tk: could not connect to host
+unicorncloud.org: could not connect to host
 venmos.com: could not connect to host
 viditut.com: could not connect to host
 vilog.me: could not connect to host
 visionless.me: could not connect to host
 vitapingu.de: could not connect to host
 vmgirls.com: could not connect to host
-waffle.at: could not connect to host
-watchinventory.com: could not connect to host
+warlions.info: could not connect to host
 watchweasel.com: could not connect to host
 weareincognito.org: could not connect to host
 webart-factory.de: could not connect to host
 webduck.nl: could not connect to host
+websiteadvice.com.au: could not connect to host
+weed.ren: could not connect to host
 weicn.org: could not connect to host
 welby.cat: could not connect to host
 werhatunsverraten.eu: could not connect to host
 whilsttraveling.com: could not connect to host
+wipc.net: could not connect to host
 wm-talk.net: could not connect to host
 wnnc.co.uk: could not connect to host
 wordpresspro.cl: could not connect to host
 www-8887999.com: could not connect to host
 www.simbolo.co.uk: could not connect to host
 xa1.uk: could not connect to host
 xing.ml: could not connect to host
 xtremenutrition.com.br: could not connect to host
 xyfun.net: could not connect to host
-yoonas.com: could not connect to host
 zenfusion.fr: could not connect to host
 zenghx.tk: could not connect to host
 zmk.fr: could not connect to host
 zulu7.com: could not connect to host
 zuviel.space: could not connect to host
 zzw.ca: could not connect to host
 0-1.party: did not receive HSTS header
 0005.com: could not connect to host
@@ -367,17 +396,16 @@ 123.gg: could not connect to host
 123share.org: could not connect to host
 123test.de: did not receive HSTS header
 123test.es: did not receive HSTS header
 123test.fr: did not receive HSTS header
 126ium.moe: could not connect to host
 127011-networks.ch: could not connect to host
 12vpn.org: could not connect to host
 12vpnchina.com: could not connect to host
-1359826938.rsc.cdn77.org: did not receive HSTS header
 13826145000.com: could not connect to host
 1391kj.com: did not receive HSTS header
 1396.net: could not connect to host
 1536.cf: could not connect to host
 163pwd.com: could not connect to host
 166166.com: could not connect to host
 16deza.com: did not receive HSTS header
 16packets.com: could not connect to host
@@ -453,17 +481,17 @@ 4cclothing.com: could not connect to hos
 4elements.com: did not receive HSTS header
 4eyes.ch: did not receive HSTS header
 4miners.net: could not connect to host
 4ourty2.org: did not receive HSTS header
 4sqsu.eu: could not connect to host
 4w-performers.link: could not connect to host
 50millionablaze.org: could not connect to host
 513vpn.net: did not receive HSTS header
-517vpn.cn: did not receive HSTS header
+517vpn.cn: could not connect to host
 540.co: did not receive HSTS header
 54bf.com: could not connect to host
 55558522.com: could not connect to host
 56ct.com: could not connect to host
 5piecesofadvice.com: could not connect to host
 5w5.la: could not connect to host
 60ych.net: did not receive HSTS header
 6120.eu: did not receive HSTS header
@@ -889,17 +917,16 @@ approlys.fr: did not receive HSTS header
 apps-for-fishing.com: could not connect to host
 appsbystudio.co.uk: did not receive HSTS header
 appsdash.io: could not connect to host
 aquaundine.net: could not connect to host
 aquilalab.com: could not connect to host
 arabdigitalexpression.org: did not receive HSTS header
 aradulconteaza.ro: could not connect to host
 aran.me.uk: could not connect to host
-arbeitslosenverwaltung.de: did not receive HSTS header
 arboineuropa.nl: did not receive HSTS header
 arboleda-hurtado.com: could not connect to host
 arbu.eu: max-age too low: 2419200
 arcbit.io: could not connect to host
 ardao.me: could not connect to host
 ardorlabs.se: could not connect to host
 arewedubstepyet.com: could not connect to host
 areyouever.me: did not receive HSTS header
@@ -1206,16 +1233,17 @@ bf.am: max-age too low: 0
 bfd.vodka: did not receive HSTS header
 bfear.com: could not connect to host
 bfelob.gov: max-age too low: 86400
 bffm.biz: could not connect to host
 bgcparkstad.nl: did not receive HSTS header
 bgmn.net: max-age too low: 0
 bhatia.at: [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 119"  data: no]
 bi.search.yahoo.com: did not receive HSTS header
+biblerhymes.com: did not receive HSTS header
 bidon.ca: did not receive HSTS header
 bieberium.de: could not connect to host
 biego.cn: did not receive HSTS header
 bielsa.me: could not connect to host
 bienenblog.cc: could not connect to host
 bierbringer.at: could not connect to host
 big-black.de: did not receive HSTS header
 bigbbqbrush.bid: could not connect to host
@@ -1238,17 +1266,17 @@ binaryfigments.com: max-age too low: 864
 binderapp.net: could not connect to host
 bioespuna.eu: did not receive HSTS header
 biofam.ru: did not receive HSTS header
 bioknowme.com: did not receive HSTS header
 bionicspirit.com: could not connect to host
 biophysik-ssl.de: did not receive HSTS header
 birkman.com: did not receive HSTS header
 bisterfeldt.com: could not connect to host
-bit-rapid.com: did not receive HSTS header
+bit-rapid.com: could not connect to host
 bitbit.org: did not receive HSTS header
 bitcantor.com: did not receive HSTS header
 bitchan.it: could not connect to host
 bitcoinprivacy.net: did not receive HSTS header
 bitcoinworld.me: could not connect to host
 bitconcepts.co.uk: could not connect to host
 biteoftech.com: did not receive HSTS header
 bitf.ly: could not connect to host
@@ -1508,31 +1536,31 @@ calcularpagerank.com.br: could not conne
 calendarr.com: did not receive HSTS header
 calgaryconstructionjobs.com: could not connect to host
 calix.com: max-age too low: 0
 calltrackingreports.com: could not connect to host
 calomel.org: max-age too low: 2764800
 caltonnutrition.com: did not receive HSTS header
 calvin.me: max-age too low: 2592000
 calvinallen.net: could not connect to host
+calyxinstitute.org: max-age too low: 500
 camashop.de: did not receive HSTS header
 cambridgeanalytica.net: could not connect to host
 cambridgeanalytica.org: did not receive HSTS header
 camelservers.com: did not receive HSTS header
 camisadotorcedor.com.br: did not receive HSTS header
 camjackson.net: did not receive HSTS header
 cammarkets.com: could not connect to host
 camolist.com: could not connect to host
 campaignelves.com: did not receive HSTS header
 campbellsoftware.co.uk: could not connect to host
 campfire.co.il: did not receive HSTS header
 campusdrugprevention.gov: did not receive HSTS header
 camsanalytics.com: could not connect to host
 canadiangamblingchoice.com: did not receive HSTS header
-cancelmyprofile.com: could not connect to host
 candicontrols.com: did not receive HSTS header
 candratech.com: could not connect to host
 candygirl.shop: could not connect to host
 cannyfoxx.me: could not connect to host
 canyonshoa.com: did not receive HSTS header
 capecycles.co.za: did not receive HSTS header
 capeyorkfire.com.au: did not receive HSTS header
 capogna.com: could not connect to host
@@ -1585,16 +1613,17 @@ ccsys.com: could not connect to host
 cctech.ph: could not connect to host
 cd.search.yahoo.com: did not receive HSTS header
 cd0.us: could not connect to host
 cdcpartners.gov: could not connect to host
 cdnb.co: could not connect to host
 cdndepo.com: could not connect to host
 cdreporting.co.uk: did not receive HSTS header
 cdt.org: did not receive HSTS header
+cekaja.com: did not receive HSTS header
 celeirorural.com.br: did not receive HSTS header
 celina-reads.de: did not receive HSTS header
 cellsites.nz: could not connect to host
 centennialrewards.com: did not receive HSTS header
 centralpoint.be: did not receive HSTS header
 centralpoint.nl: did not receive HSTS header
 centralvacsunlimited.net: could not connect to host
 centrepoint-community.com: could not connect to host
@@ -1704,17 +1733,17 @@ cityoflaurel.org: did not receive HSTS h
 ciuciucadou.ro: could not connect to host
 cium.ru: could not connect to host
 cjcaron.org: could not connect to host
 claimit.ml: could not connect to host
 clan-ww.com: did not receive HSTS header
 clara-baumert.de: could not connect to host
 claralabs.com: did not receive HSTS header
 classicday.nl: could not connect to host
-classicsandexotics.com: did not receive HSTS header
+classicsandexotics.com: could not connect to host
 classicshop.ua: did not receive HSTS header
 classicspublishing.com: could not connect to host
 classifiedssa.co.za: could not connect to host
 clcleaningco.com: could not connect to host
 cleanexperts.co.uk: could not connect to host
 cleaningsquad.ca: did not receive HSTS header
 cleanmta.com: could not connect to host
 clearc.tk: could not connect to host
@@ -1802,29 +1831,29 @@ cohesive.io: did not receive HSTS header
 coinbit.trade: did not receive HSTS header
 coindam.com: could not connect to host
 coldlostsick.net: could not connect to host
 colearnr.com: could not connect to host
 collabra.email: did not receive HSTS header
 collard.tk: did not receive HSTS header
 collegepulse.org: could not connect to host
 collies.eu: max-age too low: 3
-collins.kg: did not receive HSTS header
 collins.press: did not receive HSTS header
 collision.fyi: could not connect to host
 colmexpro.com: did not receive HSTS header
 colognegaming.net: could not connect to host
 coloradocomputernetworking.net: could not connect to host
 colorlib.com: did not receive HSTS header
 comfortdom.ua: did not receive HSTS header
 comfortticket.de: did not receive HSTS header
 comfy.cafe: did not receive HSTS header
 comfy.moe: did not receive HSTS header
 comicspines.com: could not connect to host
 comicspornos.com: max-age too low: 2592000
+comiteaintriathlon.fr: did not receive HSTS header
 comitesaustria.at: could not connect to host
 comiteshopping.com: could not connect to host
 commercialplanet.eu: could not connect to host
 commune-preuilly.fr: did not receive HSTS header
 comotalk.com: could not connect to host
 compalytics.com: could not connect to host
 comparamejor.com: did not receive HSTS header
 compareinsurance.com.au: did not receive HSTS header
@@ -2045,18 +2074,16 @@ dancerdates.net: could not connect to ho
 dane-bre.net: did not receive HSTS header
 daniel-du.com: could not connect to host
 daniel-mosquera.com: could not connect to host
 daniel-steuer.de: could not connect to host
 danielcowie.me: could not connect to host
 danieldk.eu: did not receive HSTS header
 danielheal.net: could not connect to host
 danieliancu.com: could not connect to host
-danielmostertman.com: did not receive HSTS header
-danielmostertman.nl: did not receive HSTS header
 danielverlaan.nl: did not receive HSTS header
 danielworthy.com: did not receive HSTS header
 danijobs.com: could not connect to host
 danishenanigans.com: could not connect to host
 dankeblog.com: could not connect to host
 danmark.guide: did not receive HSTS header
 dannycrichton.com: did not receive HSTS header
 danrl.de: could not connect to host
@@ -2378,17 +2405,17 @@ drycreekapiary.com: could not connect to
 ds-christiansen.de: could not connect to host
 dshiv.io: could not connect to host
 dtub.co: could not connect to host
 dualias.xyz: could not connect to host
 dubik.su: did not receive HSTS header
 duelysthub.com: could not connect to host
 duerls.de: did not receive HSTS header
 dukec.me: could not connect to host
-dullsir.com: did not receive HSTS header
+dullsir.com: could not connect to host
 dungi.org: could not connect to host
 duongpho.com: did not receive HSTS header
 duskopy.top: could not connect to host
 dutchessuganda.com: did not receive HSTS header
 dutchrank.com: did not receive HSTS header
 duuu.ch: could not connect to host
 dycontrol.de: could not connect to host
 dylanscott.com.au: did not receive HSTS header
@@ -2404,17 +2431,16 @@ e-hon.link: could not connect to host
 e-isfa.eu: did not receive HSTS header
 e-newshub.com: could not connect to host
 e-pokupki.eu: did not receive HSTS header
 e-rickroll-r.pw: could not connect to host
 e-sa.com: did not receive HSTS header
 e-verify.gov: could not connect to host
 e30gruppe.com: did not receive HSTS header
 e3amn2l.com: could not connect to host
-eam-gmbh.com: max-age too low: 604800
 earga.sm: could not connect to host
 earlybirdsnacks.com: could not connect to host
 earthrise16.com: could not connect to host
 earthsystemprediction.gov: could not connect to host
 easez.net: did not receive HSTS header
 easychiller.org: could not connect to host
 easyocm.hu: did not receive HSTS header
 easyplane.it: did not receive HSTS header
@@ -2490,16 +2516,17 @@ ego-world.org: could not connect to host
 ehealthcounselor.com: could not connect to host
 ehipaadev.com: could not connect to host
 ehito.ovh: could not connect to host
 ehrenamt-skpfcw.de: could not connect to host
 eicfood.com: could not connect to host
 eidolonhost.com: did not receive HSTS header
 eigo.work: could not connect to host
 einhorn.space: could not connect to host
+einsteinathome.org: did not receive HSTS header
 ekbanden.nl: could not connect to host
 eksik.com: could not connect to host
 elaintehtaat.fi: did not receive HSTS header
 elan-organics.com: did not receive HSTS header
 elanguest.pl: could not connect to host
 elanguest.ro: could not connect to host
 elanguest.ru: could not connect to host
 elaon.de: did not receive HSTS header
@@ -2820,17 +2847,17 @@ fingent.com: did not receive HSTS header
 finiteheap.com: did not receive HSTS header
 finpt.com: could not connect to host
 fintechnics.com: did not receive HSTS header
 fiodental.com.br: did not receive HSTS header
 firebaseio-demo.com: could not connect to host
 firebaseio.com: could not connect to host (error ignored - included regardless)
 firebird.io: could not connect to host
 firefall.rocks: could not connect to host
-fireinthedeep.com: did not receive HSTS header
+fireinthedeep.com: could not connect to host
 firemail.io: could not connect to host
 firenza.org: did not receive HSTS header
 fireorbit.de: did not receive HSTS header
 firmenverzeichnis.nu: could not connect to host
 firstdogonthemoon.com.au: did not receive HSTS header
 firstforex.co.uk: did not receive HSTS header
 firstlook.org: did not receive HSTS header
 fit4medien.de: did not receive HSTS header
@@ -3176,18 +3203,16 @@ go4it.solutions: did not receive HSTS he
 goabonga.com: could not connect to host
 goalsetup.com: did not receive HSTS header
 goaltree.ch: did not receive HSTS header
 goarmy.eu: could not connect to host
 goat.chat: did not receive HSTS header
 goat.xyz: max-age too low: 86400
 goben.ch: could not connect to host
 goblins.net: did not receive HSTS header
-godsofhell.com: did not receive HSTS header
-godsofhell.de: did not receive HSTS header
 goedeke.ml: could not connect to host
 goerner.me: did not receive HSTS header
 goge.site: could not connect to host
 gogenenglish.com: could not connect to host
 gogetssl.com: did not receive HSTS header
 goggs.eu: could not connect to host
 gogold-g.com: could not connect to host
 gokhankesici.com: did not receive HSTS header
@@ -3665,17 +3690,16 @@ ierna.com: did not receive HSTS header
 ies-italia.it: did not receive HSTS header
 ies.id.lv: could not connect to host
 ievgenialehner.com: did not receive HSTS header
 ifad.org: did not receive HSTS header
 ifastuniversity.com: did not receive HSTS header
 ifleurs.com: could not connect to host
 ifx.ee: could not connect to host
 igforums.com: could not connect to host
-igi.codes: did not receive HSTS header
 igiftcards.nl: did not receive HSTS header
 ignatisd.gr: did not receive HSTS header
 ignatovich.by: could not connect to host
 ignatovich.me: could not connect to host
 iguana.com.ec: 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
@@ -3937,17 +3961,17 @@ jameshale.me: did not receive HSTS heade
 jamesmaurer.com: did not receive HSTS header
 jamourtney.com: could not connect to host
 jan-daniels.de: did not receive HSTS header
 jan-roenspies.de: 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
 jangho.me: could not connect to host
-janking.de: did not receive HSTS header
+janking.de: could not connect to host
 jannyrijneveld.nl: did not receive HSTS header
 janus-engineering.de: did not receive HSTS header
 janverlaan.nl: did not receive HSTS header
 japaripark.com: could not connect to host
 japlex.com: could not connect to host
 jaqen.ch: could not connect to host
 jaroslavtrsek.cz: did not receive HSTS header
 jarsater.com: could not connect to host
@@ -4016,17 +4040,17 @@ jimmycai.org: could not connect to host
 jingyuesi.com: could not connect to host
 jinmaguoji.com: could not connect to host
 jinshavip.com: did not receive HSTS header
 jirav.io: could not connect to host
 jitsi.org: did not receive HSTS header
 jiyue.com: did not receive HSTS header
 jkb.pics: could not connect to host
 jkbuster.com: could not connect to host
-jkng.eu: did not receive HSTS header
+jkng.eu: could not connect to host
 jko.works: could not connect to host
 jm06.com: did not receive HSTS header
 jm22.com: could not connect to host
 jmdekker.it: could not connect to host
 joakimalgroy.com: could not connect to host
 jobflyapp.com: could not connect to host
 jobshq.com: did not receive HSTS header
 jobss.co.uk: did not receive HSTS header
@@ -4337,16 +4361,17 @@ la-flora-negra.de: could not connect to 
 la-grande-jaugue.fr: did not receive HSTS header
 la-retraite-info.com: could not connect to host
 labaia.info: could not connect to host
 labina.com.tr: did not receive HSTS header
 laboiteapc.fr: did not receive HSTS header
 labordata.io: could not connect to host
 laborie.io: could not connect to host
 labrador-retrievers.com.au: did not receive HSTS header
+labrat.mobi: did not receive HSTS header
 labs.directory: could not connect to host
 labs.moscow: did not receive HSTS header
 lacaverne.nl: could not connect to host
 lacentral.com: did not receive HSTS header
 lachlankidson.net: did not receive HSTS header
 lacledeslan.ninja: could not connect to host
 lacocinadelila.com: did not receive HSTS header
 ladylucks.co.uk: did not receive HSTS header
@@ -4489,17 +4514,17 @@ lifecoachproviders.com: did not receive 
 lifeguard.aecom.com: did not receive HSTS header
 lifeinitsownway.com: could not connect to host
 lifeskillsdirect.com: did not receive HSTS header
 lifetimemoneymachine.com: did not receive HSTS header
 lightarmory.com: could not connect to host
 lightning-ashe.com: did not receive HSTS header
 lightpaste.com: could not connect to host
 lightworx.io: did not receive HSTS header
-lila.pink: did not receive HSTS header
+lila.pink: could not connect to host
 lillepuu.com: did not receive HSTS header
 lillpopp.eu: max-age too low: 10
 lilpwny.com: could not connect to host
 lilycms.com: could not connect to host
 lim-light.com: did not receive HSTS header
 limalama.eu: max-age too low: 1
 limeyeti.com: could not connect to host
 limiteddata.co.uk: did not receive HSTS header
@@ -4620,24 +4645,22 @@ ltu.social: could not connect to host
 lu.search.yahoo.com: did not receive HSTS header
 lucas-garte.com: did not receive HSTS header
 lucaterzini.com: could not connect to host
 luclu7.pw: could not connect to host
 ludwig.click: did not receive HSTS header
 ludwiggrill.de: did not receive HSTS header
 lufthansaexperts.com: max-age too low: 2592000
 luis-checa.com: could not connect to host
-lukeistschuld.de: did not receive HSTS header
 lukeng.me: could not connect to host
 lukonet.com: did not receive HSTS header
 luludapomerania.com: could not connect to host
 lumd.me: could not connect to host
 lumi.do: did not receive HSTS header
 lumi.pw: could not connect to host
-lunafag.ru: could not connect to host
 lunarift.com: could not connect to host
 lunarlog.com: could not connect to host
 lunarrift.net: could not connect to host
 luneta.nearbuysystems.com: could not connect to host
 luno.io: could not connect to host
 luody.info: could not connect to host
 luoe.ml: could not connect to host
 luoxiao.im: could not connect to host
@@ -4675,17 +4698,16 @@ machbach.net: could not connect to host
 macsandcheesedreams.com: could not connect to host
 madars.org: did not receive HSTS header
 maddin.ga: could not connect to host
 madebyfalcon.co.uk: did not receive HSTS header
 madebymagnitude.com: did not receive HSTS header
 maderwin.com: did not receive HSTS header
 madesoftware.com.br: could not connect to host
 mafamane.com: could not connect to host
-mafiaforum.de: did not receive HSTS header
 mafiareturns.com: max-age too low: 2592000
 magenx.com: did not receive HSTS header
 magia360.com: did not receive HSTS header
 mahamed91.pw: could not connect to host
 mahfouzadedimeji.com: did not receive HSTS header
 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)
 mailchuck.com: could not connect to host
@@ -4763,17 +4785,16 @@ markorszulak.com: did not receive HSTS h
 markrobin.de: did not receive HSTS header
 marksill.com: could not connect to host
 marktboten.de: did not receive HSTS header
 marktissink.nl: did not receive HSTS header
 markus-dev.com: did not receive HSTS header
 marleyresort.com: did not receive HSTS header
 marriottvetcareers.com: could not connect to host
 marshut.net: could not connect to host
-martensen.me: max-age too low: 0
 martensson.io: did not receive HSTS header
 martialc.be: could not connect to host
 martiert.com: could not connect to host
 martijnvhoof.nl: could not connect to host
 martinec.co.uk: could not connect to host
 martinestyle.com: could not connect to host
 martineve.com: did not receive HSTS header
 martinp.no: could not connect to host
@@ -4829,23 +4850,24 @@ maxserver.com: did not receive HSTS head
 maya.mg: could not connect to host
 mazz-tech.com: could not connect to host
 mbconsultancy.nu: did not receive HSTS header
 mc81.com: could not connect to host
 mca2017.org: did not receive HSTS header
 mcard.vn: did not receive HSTS header
 mcc.re: could not connect to host
 mccarty.io: could not connect to host
-mcdonalds.ru: could not connect to host
+mcdonalds.ru: did not receive HSTS header
 mcga.media: could not connect to host
 mclab.su: could not connect to host
 mclist.it: could not connect to host
 mclyr.com: max-age too low: 7776000
 mcooperlaw.com: did not receive HSTS header
 mdfnet.se: did not receive HSTS header
+mdkr.nl: did not receive HSTS header
 mdscomp.net: did not receive HSTS header
 meadowfen.farm: could not connect to host
 meadowfenfarm.com: could not connect to host
 meamod.com: max-age too low: 0
 meat-education.com: could not connect to host
 mebio.us: did not receive HSTS header
 mecenat-cassous.com: did not receive HSTS header
 mechmk1.me: did not receive HSTS header
@@ -4922,17 +4944,17 @@ mh-bloemen.co.jp: could not connect to h
 mhdsyarif.com: did not receive HSTS header
 mhealthdemocamp.com: could not connect to host
 mhertel.com: did not receive HSTS header
 mhict.nl: could not connect to host
 mht-travel.com: could not connect to host
 mhx.pw: could not connect to host
 mi80.com: could not connect to host
 mia.to: could not connect to host
-mianfei-vpn.com: did not receive HSTS header
+mianfei-vpn.com: could not connect to host
 michaeldemuth.com: could not connect to host
 michaelfitzpatrickruth.com: could not connect to host
 michaelmorpurgo.com: did not receive HSTS header
 michaeln.net: could not connect to host
 michaelscrivo.com: did not receive HSTS header
 michaelwaite.org: could not connect to host
 michal-kral.cz: could not connect to host
 michalborka.cz: could not connect to host
@@ -5166,17 +5188,16 @@ musewearflipflops.com: could not connect
 mushroomandfern.com: could not connect to host
 musi.cx: could not connect to host
 musicalbim.com.br: could not connect to host
 musicchris.de: did not receive HSTS header
 musikkfondene.no: did not receive HSTS header
 mustardking.me: did not receive HSTS header
 mustika.cf: could not connect to host
 mutamatic.com: could not connect to host
-mutuals.cool: did not receive HSTS header
 mutuelle-obligatoire-pme.fr: did not receive HSTS header
 muzgra.in: did not receive HSTS header
 muzykaprzeszladoplay.pl: could not connect to host
 mvanmarketing.nl: did not receive HSTS header
 mvsecurity.nl: could not connect to host
 mw.search.yahoo.com: did not receive HSTS header
 mwohlfarth.de: did not receive HSTS header
 my-owncloud.com: could not connect to host
@@ -5374,28 +5395,26 @@ niconode.com: could not connect to host
 nidux.com: did not receive HSTS header
 niduxcomercial.com: could not connect to host
 nien.chat: could not connect to host
 nightsnack.cf: could not connect to host
 nightwinds.tk: could not connect to host
 niho.jp: did not receive HSTS header
 nikcub.com: could not connect to host
 niklaslindblad.se: did not receive HSTS header
-nikobradshaw.com: did not receive HSTS header
 niloxy.com: did not receive HSTS header
 ninchisho-online.com: did not receive HSTS header
 ninhs.org: could not connect to host
 ninjaspiders.com: did not receive HSTS header
 nippler.org: did not receive HSTS header
 nippombashi.net: did not receive HSTS header
 nipponcareers.com: did not receive HSTS header
 nitropanel.com: did not receive HSTS header
 nixien.fr: could not connect to host
 nixmag.net: could not connect to host
-nkb.in.th: could not connect to host
 nll.fi: could not connect to host
 nmadda.com: could not connect to host
 nmctest.net: could not connect to host
 nmueller.at: could not connect to host
 nnya.cat: could not connect to host
 no-ip.cz: did not receive HSTS header
 no17sifangjie.cc: could not connect to host
 nocallaghan.com: could not connect to host
@@ -5409,17 +5428,16 @@ nodi.at: did not receive HSTS header
 noexpect.org: could not connect to host
 noima.com: did not receive HSTS header
 noisebridge.social: could not connect to host
 nolberg.net: did not receive HSTS header
 nolimitsbook.de: did not receive HSTS header
 nolte.work: could not connect to host
 nomorebytes.de: could not connect to host
 noodlesandwich.com: did not receive HSTS header
-nootropicsource.com: did not receive HSTS header
 nope.website: could not connect to host
 nopex.no: could not connect to host
 nopol.de: could not connect to host
 norandom.com: could not connect to host
 norb.at: could not connect to host
 nordlicht.photography: did not receive HSTS header
 norge.guide: did not receive HSTS header
 northcutt.com: did not receive HSTS header
@@ -5427,16 +5445,17 @@ nosecretshop.com: could not connect to h
 notadd.com: did not receive HSTS header
 notadd.io: could not connect to host
 notarankastojkovic.me: could not connect to host
 notenoughtime.de: could not connect to host
 nothing.net.nz: max-age too low: 7776000
 noticia.do: did not receive HSTS header
 notjustbitchy.com: did not receive HSTS header
 nottheonion.net: did not receive HSTS header
+nottres.com: did not receive HSTS header
 nou.si: could not connect to host
 nouvelle-vague-saint-cast.fr: did not receive HSTS header
 nova-elearning.com: did not receive HSTS header
 novaco.in: max-age too low: 3600
 novacoast.com: did not receive HSTS header
 novacraft.me: did not receive HSTS header
 novatrucking.de: could not connect to host
 novavoidhowl.com: did not receive HSTS header
@@ -5444,16 +5463,17 @@ novelabs.de: could not connect to host
 novelabs.eu: could not connect to host
 novurania.com: did not receive HSTS header
 nowak.ninja: did not receive HSTS header
 noworrywp.com: could not connect to host
 nozoe.jp: could not connect to host
 np.search.yahoo.com: did not receive HSTS header
 npol.de: could not connect to host
 nq7.pl: could not connect to host
+nqesh.com: did not receive HSTS header
 nrd.li: could not connect to host
 nrechn.de: could not connect to host
 nrizzio.me: could not connect to host
 nsweb.solutions: could not connect to host
 ntbs.pro: could not connect to host
 ntse.xyz: could not connect to host
 nu3.at: did not receive HSTS header
 nu3.ch: did not receive HSTS header
@@ -5844,17 +5864,16 @@ pgcpbc.com: could not connect to host
 pgpm.io: could not connect to host
 pgtb.be: did not receive HSTS header
 phalconist.com: could not connect to host
 pharmgkb.org: could not connect to host
 phdsupply.com: did not receive HSTS header
 phillipgoldfarb.com: did not receive HSTS header
 phillmoore.com: did not receive HSTS header
 phillprice.com: could not connect to host
-philphonic.de: did not receive HSTS header
 philpropertygroup.com: could not connect to host
 phoebe.co.nz: did not receive HSTS header
 phoenixlogan.com: could not connect to host
 phonenumberinfo.co.uk: could not connect to host
 phongmay24h.com: could not connect to host
 photoancestry.com: did not receive HSTS header
 photoblogverona.com: could not connect to host
 php-bach.org: could not connect to host
@@ -5862,17 +5881,16 @@ phperformances.fr: did not receive HSTS 
 phrasing.me: could not connect to host
 physicaltherapist.com: did not receive HSTS header
 pi-eng.fr: did not receive HSTS header
 pianetaottica.net: could not connect to host
 pianetaottica.org: could not connect to host
 picardiascr.com: did not receive HSTS header
 pickersurvey.org: could not connect to host
 pickr.co: did not receive HSTS header
-picone.com.au: could not connect to host
 picotronic.biz: could not connect to host
 picscare.co.uk: did not receive HSTS header
 pidatacenters.com: did not receive HSTS header
 pieterjangeeroms.me: could not connect to host
 piggott.me.uk: did not receive HSTS header
 pilgermaske.org: did not receive HSTS header
 piligrimname.com: could not connect to host
 pillowandpepper.com: did not receive HSTS header
@@ -5973,25 +5991,24 @@ pontualcomp.com: could not connect to ho
 pony.today: did not receive HSTS header
 ponythread.com: did not receive HSTS header
 poolsandstuff.com: did not receive HSTS header
 poon.tech: could not connect to host
 popi.se: did not receive HSTS header
 popkins.ml: could not connect to host
 poris.web.id: could not connect to host
 porno-gif.ru: did not receive HSTS header
-pornstars.me: did not receive HSTS header
+pornstars.me: could not connect to host
 portalm.tk: could not connect to host
 portalplatform.net: could not connect to host
 portaluniversalista.org: did not receive HSTS header
 portofacil.com: did not receive HSTS header
 poshpak.com: max-age too low: 86400
 postback.io: could not connect to host
 postcodewise.co.uk: did not receive HSTS header
-posterspy.com: did not receive HSTS header
 postscheduler.org: could not connect to host
 posylka.de: did not receive HSTS header
 potatoheads.net: could not connect to host
 potbar.com: could not connect to host
 potlytics.com: could not connect to host
 potsky.com: did not receive HSTS header
 poussinooz.fr: could not connect to host
 povitria.net: could not connect to host
@@ -6030,17 +6047,16 @@ press-anime-nenkan.com: did not receive 
 pressenews.net: did not receive HSTS header
 pressfreedomfoundation.org: did not receive HSTS header
 prettygrouse.com: did not receive HSTS header
 pretzlaff.info: did not receive HSTS header
 preworkout.me: could not connect to host
 prezola.com: did not receive HSTS header
 prgslab.net: could not connect to host
 pridoc.se: did not receive HSTS header
-prielwurmjaeger.de: did not receive HSTS header
 printerest.io: could not connect to host
 printersonline.be: did not receive HSTS header
 printfn.com: could not connect to host
 priolkar.com: did not receive HSTS header
 privacylabs.io: did not receive HSTS header
 privacyrup.net: could not connect to host
 privytime.com: could not connect to host
 prnt.li: did not receive HSTS header
@@ -6323,17 +6339,16 @@ res-rheingau.de: did not receive HSTS he
 res42.com: could not connect to host
 reserve-online.net: did not receive HSTS header
 residentsinsurance.co.uk: did not receive HSTS header
 resl20.servehttp.com: could not connect to host
 respice.xyz: could not connect to host
 respostas.com.br: did not receive HSTS header
 restaurace-klokocka.cz: did not receive HSTS header
 restchart.com: did not receive HSTS header
-restioson.me: could not connect to host
 restrealitaet.de: did not receive HSTS header
 returnofwar.com: could not connect to host
 revapost.ch: could not connect to host
 revealdata.com: did not receive HSTS header
 revelaciones.tv: could not connect to host
 revello.org: did not receive HSTS header
 reverie.pw: could not connect to host
 review.info: did not receive HSTS header
@@ -6368,18 +6383,16 @@ rijndael.xyz: could not connect to host
 rika.me: could not connect to host
 ring0.xyz: did not receive HSTS header
 ringh.am: could not connect to host
 rionewyork.com.br: did not receive HSTS header
 ripa.io: did not receive HSTS header
 rippleunion.com: could not connect to host
 riskmgt.com.au: could not connect to host
 rithm.ch: did not receive HSTS header
-rivaforum.de: did not receive HSTS header
-rivastation.de: did not receive HSTS header
 rivlo.com: could not connect to host
 rix.ninja: could not connect to host
 rizon.me: could not connect to host
 rj.gg: could not connect to host
 rk6.cz: could not connect to host
 rkkhok.hu: did not receive HSTS header
 rkmantpur.org: did not receive HSTS header
 rme.li: did not receive HSTS header
@@ -6700,37 +6713,39 @@ sessionslogning.dk: could not connect to
 sethcaplan.com: could not connect to host
 setphaserstostun.org: could not connect to host
 setuid.de: could not connect to host
 setuid.io: did not receive HSTS header
 seyahatsagliksigortalari.com: could not connect to host
 sfashion.si: did not receive HSTS header
 sfhobbies.com.br: could not connect to host
 sfsltd.com: did not receive HSTS header
+sg-elektro.de: did not receive HSTS header
 sh11.pp.ua: did not receive HSTS header
 shadoom.com: did not receive HSTS header
 shadow-socks.net: did not receive HSTS header
-shadow-socks.org: did not receive HSTS header
+shadow-socks.org: could not connect to host
 shadowguardian507-irl.tk: did not receive HSTS header
 shadowguardian507.tk: did not receive HSTS header
 shadowmorph.info: did not receive HSTS header
 shadowshocks.net: did not receive HSTS header
-shadowsocks.gift: did not receive HSTS header
+shadowsocks.gift: could not connect to host
 shadowsocks.net: could not connect to host
-shadowsocks.vc: did not receive HSTS header
+shadowsocks.vc: could not connect to host
 shadowsocks.wiki: did not receive HSTS header
 shadowsoks.com: could not connect to host
 shakebox.de: could not connect to host
 shanekoster.net: could not connect to host
 shanesage.com: could not connect to host
 shaobin.wang: could not connect to host
 shapesedinburgh.co.uk: did not receive HSTS header
 shardsoft.com: could not connect to host
 shareimg.xyz: could not connect to host
 sharejoy.cn: did not receive HSTS header
+sharekey.com: did not receive HSTS header
 sharepass.pw: could not connect to host
 sharepic.xyz: could not connect to host
 sharezen.de: could not connect to host
 shauncrowley.co.uk: could not connect to host
 shaunwheelhou.se: could not connect to host
 shawnh.net: could not connect to host
 shellsec.pw: did not receive HSTS header
 shep.co.il: did not receive HSTS header
@@ -6745,17 +6760,16 @@ shiinko.com: could not connect to host
 shindorei.fr: did not receive HSTS header
 shinebijoux.com.br: could not connect to host
 shinju.moe: could not connect to host
 shiona.xyz: could not connect to host
 shipinsight.com: did not receive HSTS header
 shipmile.com: did not receive HSTS header
 shipping24h.com: did not receive HSTS header
 shirosaki.org: could not connect to host
-shirt2go.shop: did not receive HSTS header
 shiseki.top: could not connect to host
 shitposting.life: could not connect to host
 shm-forum.org.uk: could not connect to host
 shocksrv.com: did not receive HSTS header
 shooshosha.com: could not connect to host
 shopherbal.co.za: did not receive HSTS header
 shopontarget.com: did not receive HSTS header
 shoprose.ru: could not connect to host
@@ -6872,17 +6886,16 @@ smarterskies.gov: did not receive HSTS h
 smartfon4you.ru: did not receive HSTS header
 smarthomedna.com: did not receive HSTS header
 smartofficesandsmarthomes.com: did not receive HSTS header
 smartphone.continental.com: could not connect to host
 smartrak.co.nz: did not receive HSTS header
 smdev.fr: could not connect to host
 smet.us: could not connect to host
 smexpt.com: did not receive HSTS header
-smiledirectsales.com: did not receive HSTS header
 smimea.com: could not connect to host
 smirkingwhorefromhighgarden.pro: could not connect to host
 smittix.co.uk: did not receive HSTS header
 smkn1lengkong.sch.id: did not receive HSTS header
 smksi2.com: could not connect to host
 smksultanismail2.com: did not receive HSTS header
 smove.sg: did not receive HSTS header
 smplix.com: could not connect to host
@@ -7108,16 +7121,17 @@ streamingmagazin.de: could not connect t
 strictlysudo.com: could not connect to host
 strife.tk: could not connect to host
 strila.me: could not connect to host
 strivephysmed.com: did not receive HSTS header
 stroeercrm.de: could not connect to host
 strongest-privacy.com: could not connect to host
 stuartbaxter.co: could not connect to host
 student-scientist.org: did not receive HSTS header
+student.andover.edu: did not receive HSTS header
 studentrdh.com: did not receive HSTS header
 studentresearcher.org: did not receive HSTS header
 studentskydenik.cz: could not connect to host
 studenttravel.cz: did not receive HSTS header
 studinf.xyz: could not connect to host
 studio-panic.com: did not receive HSTS header
 studiozelden.com: did not receive HSTS header
 studybay.com: did not receive HSTS header
@@ -7227,16 +7241,17 @@ sytpartners.com: max-age too low: 0
 szaszm.tk: max-age too low: 0
 t-complex.space: could not connect to host
 t-ken.xyz: could not connect to host
 t-tz.com: could not connect to host
 t0dd.eu: could not connect to host
 t4c-rebirth.com: could not connect to host
 t4x.org: could not connect to host
 taabe.xyz: could not connect to host
+taberu-fujitsubo.com: did not receive HSTS header
 tabino.top: could not connect to host
 tacomafia.net: did not receive HSTS header
 tadigitalstore.com: could not connect to host
 tafoma.com: did not receive HSTS header
 tageau.com: could not connect to host
 taglondon.org: did not receive HSTS header
 tailify.com: did not receive HSTS header
 tails.com.ar: did not receive HSTS header
@@ -7273,17 +7288,16 @@ tasmansecurity.com: could not connect to
 tassup.com: could not connect to host
 tastyyy.co: could not connect to host
 tatilbus.com: did not receive HSTS header
 tatt.io: could not connect to host
 tauchkater.de: could not connect to host
 tavoittaja.fi: did not receive HSTS header
 tavopica.lt: did not receive HSTS header
 taxbench.com: could not connect to host
-taxi-24std.de: did not receive HSTS header
 taxiindenbosch.nl: did not receive HSTS header
 taxsnaps.co.nz: did not receive HSTS header
 tazz.in: could not connect to host
 tbspace.de: did not receive HSTS header
 tc-bonito.de: did not receive HSTS header
 tcao.info: could not connect to host
 tcby45.xyz: could not connect to host
 tcdw.net: could not connect to host
@@ -7367,16 +7381,17 @@ teulon.eu: could not connect to host
 texte-zur-taufe.de: did not receive HSTS header
 textoplano.xyz: could not connect to host
 textracer.dk: could not connect to host
 tf2stadium.com: did not receive HSTS header
 tfcoms-sp-tracker-client.azurewebsites.net: could not connect to host
 tffans.com: could not connect to host
 tfl.lu: did not receive HSTS header
 tgr.re: could not connect to host
+th-bl.de: did not receive HSTS header
 thaihostcool.com: did not receive HSTS header
 thailandpropertylistings.com: did not receive HSTS header
 thalmann.fr: did not receive HSTS header
 the-construct.com: could not connect to host
 the-delta.net.eu.org: could not connect to host
 the-sky-of-valkyries.com: could not connect to host
 theamateurs.net: did not receive HSTS header
 theamp.com: did not receive HSTS header
@@ -7476,17 +7491,17 @@ thomasschweizer.net: could not connect t
 thorgames.nl: did not receive HSTS header
 thorncreek.net: did not receive HSTS header
 thriveapproach.co.uk: did not receive HSTS header
 thrivewellnesshub.co.za: did not receive HSTS header
 throughthelookingglasslens.co.uk: could not connect to host
 thumbtack.com: did not receive HSTS header
 thundercampaign.com: could not connect to host
 ti.blog.br: could not connect to host
-tianxing.pro: did not receive HSTS header
+tianxing.pro: could not connect to host
 tianxingvpn.pro: could not connect to host
 tibbitshall.ca: did not receive HSTS header
 tickopa.co.uk: could not connect to host
 tickreport.com: did not receive HSTS header
 ticktock.today: did not receive HSTS header
 tictactux.de: could not connect to host
 tidmore.us: could not connect to host
 tiendschuurstraat.nl: could not connect to host
@@ -7496,17 +7511,17 @@ tierrarp.com: could not connect to host
 tightlineproductions.com: did not receive HSTS header
 tikutiku.pl: could not connect to host
 tildebot.com: could not connect to host
 tiliaze.be: could not connect to host
 tiliaze.biz: could not connect to host
 tiliaze.eu: did not receive HSTS header
 tilient.eu: [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 119"  data: no]
 tilikum.io: did not receive HSTS header
-tilkah.com.au: could not connect to host
+tilkah.com.au: did not receive HSTS header
 tillcraft.com: could not connect to host
 timbeilby.com: could not connect to host
 timbuktutimber.com: did not receive HSTS header
 timcamara.com: could not connect to host
 time-river.xyz: could not connect to host
 timesavingplugins.com: could not connect to host
 timesavingplugins.net: could not connect to host
 timeserver0.de: could not connect to host
@@ -7534,17 +7549,16 @@ titouan.co: did not receive HSTS header
 tittarpuls.se: could not connect to host
 titties.ml: could not connect to host
 tjc.host: did not receive HSTS header
 tjc.wiki: could not connect to host
 tjeckien.guide: did not receive HSTS header
 tjullrich.de: could not connect to host
 tkappertjedemetamorfose.nl: could not connect to host
 tkonstantopoulos.tk: could not connect to host
-tlach.cz: did not receive HSTS header
 tlcdn.net: could not connect to host
 tlo.hosting: could not connect to host
 tlo.link: could not connect to host
 tlo.network: could not connect to host
 tls.li: could not connect to host
 tlsbv.nl: did not receive HSTS header
 tlshost.net: could not connect to host
 tm-solutions.eu: did not receive HSTS header
@@ -7642,17 +7656,16 @@ trance-heal.me: did not receive HSTS hea
 tranceheal.com: did not receive HSTS header
 tranceheal.de: did not receive HSTS header
 tranceheal.me: did not receive HSTS header
 transdirect.com.au: did not receive HSTS header
 transformify.org: did not receive HSTS header
 transl8.eu: did not receive HSTS header
 translate.googleapis.com: did not receive HSTS header (error ignored - included regardless)
 transportal.sk: did not receive HSTS header
-trashnothing.com: did not receive HSTS header
 travality.ru: could not connect to host
 travel-kuban.ru: did not receive HSTS header
 travelinsightswriter.com: could not connect to host
 travelinsurance.co.nz: did not receive HSTS header
 trazosdearte.com: did not receive HSTS header
 treatprostatewithhifu.com: could not connect to host
 treeby.net: could not connect to host
 treeremovaljohannesburg.co.za: could not connect to host
@@ -7719,17 +7732,16 @@ twee-onder-een-kap-woning-in-pekela-kope
 twee-onder-een-kap-woning-in-rijnwaarden-kopen.nl: could not connect to host
 twee-onder-een-kap-woning-in-sudwest-fryslan-kopen.nl: could not connect to host
 twee-onder-een-kap-woning-in-veendam-kopen.nl: could not connect to host
 twee-onder-een-kap-woning-in-zuidplas-kopen.nl: could not connect to host
 twee-onder-een-kap-woning-in-zwartewaterland-kopen.nl: could not connect to host
 tweeondereenkapverkopen.nl: could not connect to host
 tweeondereenkapwoningverkopen.nl: could not connect to host
 tweetify.io: could not connect to host
-twem.ddns.net: could not connect to host
 twillionmas.com: could not connect to host
 twinkseason.ca: could not connect to host
 twinkseason.co: could not connect to host
 twinkseason.co.uk: could not connect to host
 twinkseason.com: could not connect to host
 twinkseason.net: could not connect to host
 twinkseason.org: could not connect to host
 twinkseason.xyz: could not connect to host
@@ -7835,23 +7847,25 @@ unsystem.net: could not connect to host
 unwiredbrain.com: could not connect to host
 unyq.me: could not connect to host
 uonstaffhub.com: could not connect to host
 uow.ninja: could not connect to host
 up1.ca: could not connect to host
 upaknship.com: did not receive HSTS header
 upboard.jp: could not connect to host
 upldr.pw: could not connect to host
+upload.cat: did not receive HSTS header
 uporoops.com: could not connect to host
 uprotect.it: could not connect to host
 upstats.eu: could not connect to host
 ur-lauber.de: did not receive HSTS header
 urandom.eu.org: did not receive HSTS header
 urban-garden.lt: could not connect to host
 urban-garden.lv: could not connect to host
+urbanstylestaging.com: did not receive HSTS header
 urbpic.com: could not connect to host
 urlchomp.com: did not receive HSTS header
 urphp.com: could not connect to host
 us-immigration.com: did not receive HSTS header
 usaab.org: did not receive HSTS header
 usafuelservice.com: did not receive HSTS header
 usbirthcertificate.com: did not receive HSTS header
 usbtypeccompliant.com: could not connect to host
@@ -7936,17 +7950,17 @@ veggiesbourg.fr: did not receive HSTS he
 vegis.ro: did not receive HSTS header
 vehent.org: did not receive HSTS header
 vehicleuplift.co.uk: did not receive HSTS header
 vemokin.net: could not connect to host
 vendigital.com: did not receive HSTS header
 venicecomputerrepair.com: did not receive HSTS header
 venixplays-stream.ml: could not connect to host
 vennet.fr: did not receive HSTS header
-venturepro.com: did not receive HSTS header
+venturepro.com: could not connect to host
 ventzke.com: did not receive HSTS header
 venzocrm.com: did not receive HSTS header
 verifikatorindonesia.com: could not connect to host
 vermontcareergateway.org: could not connect to host
 veryhax.de: could not connect to host
 vestacp.top: could not connect to host
 vetdnacenter.com: did not receive HSTS header
 veterinaire-cazeres-foucault.fr: could not connect to host
@@ -8310,18 +8324,19 @@ www-1117.com: could not connect to host
 www-39988.com: did not receive HSTS header
 www-507.net: did not receive HSTS header
 www-746.com: could not connect to host
 www-771122.com: did not receive HSTS header
 www-8003.com: did not receive HSTS header
 www-88599.com: did not receive HSTS header
 www-9995.com: did not receive HSTS header
 www-djbet.com: did not receive HSTS header
-www-jinshavip.com: did not receive HSTS header
+www-jinshavip.com: could not connect to host
 www.braintreepayments.com: did not receive HSTS header
+www.calyxinstitute.org: max-age too low: 500
 www.cueup.com: could not connect to host
 www.cyveillance.com: did not receive HSTS header
 www.developer.mydigipass.com: could not connect to host
 www.elanex.biz: did not receive HSTS header
 www.gamesdepartment.co.uk: did not receive HSTS header
 www.gmail.com: did not receive HSTS header (error ignored - included regardless)
 www.googlemail.com: did not receive HSTS header (error ignored - included regardless)
 www.greplin.com: could not connect to host
@@ -8530,17 +8545,16 @@ zahyantechnologies.com: could not connec
 zakoncontrol.com: did not receive HSTS header
 zamorano.edu: could not connect to host
 zamos.ru: max-age too low: 0
 zaneweb.org: could not connect to host
 zao.fi: did not receive HSTS header
 zaoshanghao-dajia.rhcloud.com: did not receive HSTS header
 zap.yt: did not receive HSTS header
 zarooba.com: could not connect to host
-zary.me: did not receive HSTS header
 zavca.com: could not connect to host
 zbigniewgalucki.eu: did not receive HSTS header
 zcon.nl: could not connect to host
 zdravotnickasluzba.eu: could not connect to host
 zebrababy.cn: could not connect to host
 zebry.nl: could not connect to host
 zecrypto.com: could not connect to host
 zeedroom.be: did not receive HSTS header
@@ -8594,22 +8608,21 @@ zju.tv: could not connect to host
 zjubtv.com: could not connect to host
 zjutv.com: could not connect to host
 zk.gd: did not receive HSTS header
 zkillboard.com: did not receive HSTS header
 zking.ga: could not connect to host
 zmsastro.co.za: could not connect to host
 zmy.im: did not receive HSTS header
 zocken.com: did not receive HSTS header
-zockenbiszumumfallen.de: did not receive HSTS header
 zoe.vc: could not connect to host
 zohar.link: could not connect to host
 zomiac.pp.ua: could not connect to host
 zoneminder.com: did not receive HSTS header
-zoners.si: did not receive HSTS header
+zoners.si: could not connect to host
 zonky.io: could not connect to host
 zoo24.de: did not receive HSTS header
 zoofaeth.de: did not receive HSTS header
 zoomingin.net: max-age too low: 5184000
 zoommailing.com: did not receive HSTS header
 zorasvobodova.cz: did not receive HSTS header
 zortium.report: could not connect to host
 zoznamrealit.sk: did not receive HSTS header
--- 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(1518457357921000);
+const PRTime gPreloadListExpirationTime = INT64_C(1518501054306000);
 %%
 0.me.uk, 1
 00001.am, 1
 00002.am, 1
 0005pay.com, 1
 0010100.net, 1
 00220022.net, 1
 007-preisvergleich.de, 1
@@ -108,16 +108,17 @@ 123midterm.com, 1
 123plons.nl, 1
 123test.com, 1
 123test.nl, 1
 125m125.de, 1
 12vpn.net, 1
 130.ua, 1
 132kv.ch, 1
 13318522.com, 1
+1359826938.rsc.cdn77.org, 1
 1395kj.com, 1
 1396.cc, 1
 1453914078.rsc.cdn77.org, 1
 1464424382.rsc.cdn77.org, 1
 14it.de, 1
 14x3.de, 1
 15-10.com, 1
 1511774230.rsc.cdn77.org, 1
@@ -1666,16 +1667,17 @@ aranel.me, 1
 aranycsillag.net, 1
 araratour.com, 1
 araro.ch, 1
 araseifudousan.com, 1
 arawaza.biz, 1
 arawaza.com, 0
 arawaza.info, 1
 arbeitskreis-asyl-eningen.de, 1
+arbeitslosenverwaltung.de, 1
 arbitrarion.com, 1
 arbitrary.ch, 1
 arboworks.com, 1
 arcadiaeng.com, 1
 arcaik.net, 1
 arcenergy.co.uk, 1
 archii.ca, 1
 archimedicx.com, 1
@@ -2779,17 +2781,16 @@ bia.gov, 0
 biaggeo.com, 1
 bianinapiccanovias.com, 1
 biapinheiro.com.br, 1
 biasmath.es, 1
 biathloncup.ru, 1
 bible-maroc.com, 1
 bible.ru, 1
 bibleonline.ru, 1
-biblerhymes.com, 1
 bibliaon.com, 1
 biblio.wiki, 1
 biblioblog.fr, 1
 bibliomarkt.ch, 1
 biblionaut.net, 1
 bibliotekarien.se, 1
 biboumail.fr, 1
 bibuch.com, 1
@@ -3868,17 +3869,16 @@ calleveryday.com, 1
 callhub.io, 1
 callision.com, 1
 callsigns.ca, 1
 calltoar.ms, 1
 calories.org, 1
 calvin.my, 1
 calypsogames.net, 1
 calyxengineers.com, 1
-calyxinstitute.org, 0
 camaradivisas.com, 1
 camaya.net, 1
 cambier.org, 1
 cambiowatch.ch, 1
 cambodian.dating, 1
 camconn.cc, 1
 camda.online, 1
 camel2243.com, 1
@@ -3914,16 +3914,17 @@ canadalife.de, 1
 canadasmotorcycle.ca, 1
 canadian.dating, 1
 canadianchristianity.com, 0
 canadiantouristboard.com, 1
 canalsidehouse.be, 1
 canalsidehouse.com, 1
 canarianlegalalliance.com, 1
 canarymod.net, 0
+cancelmyprofile.com, 1
 cancerdata.nhs.uk, 1
 cancreate.nl, 1
 candicecity.com, 1
 candidasa.com, 1
 cando.eu, 1
 candy-it.de, 1
 candylion.rocks, 1
 candyout.com, 1
@@ -4174,17 +4175,16 @@ ced-services.nl, 1
 cedriccassimo.ch, 1
 cedriccassimo.com, 1
 cee.io, 1
 ceebee.com, 1
 cefak.org.br, 1
 cegfw.com, 1
 ceilingpac.org, 1
 cejhon.cz, 0
-cekaja.com, 1
 celebphotos.blog, 1
 celebrityscope.net, 1
 celec.gob.ec, 0
 celiendev.ch, 1
 celigo.com, 1
 celltek-server.de, 1
 celti.ie.eu.org, 1
 celti.name, 1
@@ -5003,16 +5003,17 @@ collbox.co, 1
 collectdocs.com, 1
 collectfood.com, 1
 collectiblebeans.com, 1
 collectosaurus.com, 1
 colleencornez.com, 1
 collegepaperworld.com, 1
 collinghammethodist.org.uk, 1
 collinmbarrett.com, 1
+collins.kg, 1
 collinsartworks.com, 1
 colo-tech.com, 1
 colombian.dating, 1
 coloppe.com, 1
 coloradolottery.com, 1
 coloraid.net, 1
 colorbrush.ru, 1
 colorcentertoner.com.br, 1
@@ -5041,17 +5042,16 @@ cometcache.com, 1
 cometonovascotia.ca, 1
 comff.net, 1
 comfintouch.com, 1
 comflores.com.br, 1
 comfypc.com, 1
 comhack.com, 1
 comico.info, 1
 comiq.io, 1
-comiteaintriathlon.fr, 1
 comm.cx, 1
 commania.co.kr, 1
 commencepayments.com, 1
 commerciallocker.com, 0
 commitsandrebases.com, 1
 common.io, 1
 commoncode.com.au, 1
 commoncode.io, 1
@@ -5818,16 +5818,18 @@ danielehniss.de, 1
 danielepestilli.com, 1
 danielhochleitner.de, 1
 danieljamesscott.org, 1
 danieljireh.com, 1
 danielkoster.nl, 1
 danielkratz.com, 1
 danielmarquard.com, 1
 danielmoch.com, 1
+danielmostertman.com, 1
+danielmostertman.nl, 1
 danielrozenberg.com, 1
 danielsblog.org, 1
 danielschreurs.com, 1
 danielstach.cz, 1
 danielthompson.info, 1
 danieltollot.de, 1
 danielvoogsgerd.nl, 1
 danielzuzevich.com, 1
@@ -7186,16 +7188,17 @@ eagle-aluminum.com, 1
 eagle-yard.de, 1
 eagleindustriesltd.com, 1
 eagleridgecampground.com, 1
 eaglesecurity.com, 1
 eagletechz.com.br, 1
 eagleyecs.com, 1
 eaimty.com, 1
 ealev.de, 1
+eam-gmbh.com, 1
 eames-clayton.us, 1
 eapestudioweb.com, 1
 earl.org.uk, 1
 earlyyearshub.com, 1
 earmarks.gov, 1
 earth-people.org, 1
 earticleblog.com, 1
 earvinkayonga.com, 1
@@ -7435,17 +7438,16 @@ einar.io, 1
 einaros.is, 1
 einfachbahn.de, 1
 einfachmaldiefressehalten.de, 1
 einheft.info, 1
 einheizpreis.de, 1
 einmonolog.de, 1
 einsatzstellenverwaltung.de, 1
 einsatzstiefel.info, 1
-einsteinathome.org, 1
 eintageinzug.de, 1
 eintragsservice24.de, 1
 eipione.com, 1
 eirastudios.co.uk, 0
 eisaev.ru, 1
 eisp.it, 0
 eit-web.de, 0
 eitler.cx, 1
@@ -8561,17 +8563,17 @@ fhdhelp.de, 0
 fhdhilft.de, 0
 fhfaoig.gov, 1
 fhg90.com, 1
 fhsseniormens.club, 1
 fi-sanki.co.jp, 1
 fi.google.com, 1
 fi.search.yahoo.com, 0
 fiam.me, 1
-fiareapp.red, 1
+fiareapp.red, 0
 ficklenote.net, 1
 fickweiler.nl, 1
 ficlab.com, 1
 ficus.io, 1
 fid-elite.ch, 1
 fid.to, 1
 fidanza.eu, 1
 fidel.uk, 1
@@ -9926,16 +9928,18 @@ goanalyse.co.uk, 1
 goapunks.net, 1
 goatcloud.com, 1
 gocardless.com, 1
 gochu.se, 1
 gocleanerslondon.co.uk, 1
 godesigner.ru, 1
 godrealms.com, 1
 godrive.ga, 1
+godsofhell.com, 1
+godsofhell.de, 1
 goededoelkerstkaarten.nl, 1
 goedverzekerd.net, 1
 goemail.me, 1
 goerres2014.de, 1
 goetemp.de, 1
 goffrie.com, 1
 gofigure.fr, 0
 gofoiayourself.org, 1
@@ -11495,16 +11499,17 @@ iftrue.de, 1
 ifxnet.com, 1
 ifxor.com, 1
 iga-semi.jp, 1
 igamingforums.com, 1
 igglabs.com, 1
 iggprivate.com, 1
 iggsoft.com, 1
 iggsoftware.com, 1
+igi.codes, 1
 igiftcards.de, 1
 igimusic.com, 1
 igm-be.ch, 1
 ignace72.eu, 1
 ignat.by, 1
 ignitedmindz.in, 1
 igotoffer.com, 0
 igrivi.com, 1
@@ -13816,17 +13821,16 @@ labelleza.com.br, 1
 labfox.de, 1
 laboiteanem.fr, 1
 labourreedevergheas.fr, 1
 laboutiquemarocaineduconvoyeur.com, 1
 laboutiquemarocaineduconvoyeur.ma, 1
 laboxfaitsoncinema.com, 1
 labradorpuppiesforsalebyregisteredlabradorbreeders.com, 1
 labrasaq8.com, 1
-labrat.mobi, 1
 lacarpesaintaubinoise.fr, 1
 lacasa.fr, 1
 lacasabelucci.com, 1
 lacasseroy.com, 1
 lacetsroses.ch, 1
 lachainedesentrepreneurs.fr, 1
 lachawoj.de, 1
 lachlan.com, 1
@@ -14066,17 +14070,17 @@ learnflakes.net, 1
 learningis1.st, 1
 learninglaw.com, 1
 learntube.cz, 1
 leaseit24.com, 1
 leaseit24.de, 1
 leasit.at, 1
 leasit.de, 1
 leatherfurnitureexpo.com, 1
-leaversmith.com, 1
+leaversmith.com, 0
 leavesofchangeweekly.org, 1
 lebal.se, 1
 lebanesearmy.gov.lb, 1
 lebarmy.gov.lb, 1
 lebens-fluss.at, 1
 lebihan.pl, 1
 leblanc.io, 1
 lebosse.me, 1
@@ -14846,19 +14850,21 @@ lukasschauer.de, 1
 lukasschick.de, 1
 lukasunger.cz, 1
 lukasunger.net, 1
 lukaszdolan.com, 1
 lukaszorn.de, 1
 lukasztkacz.com, 1
 lukatz.de, 1
 luke.ch, 1
+lukeistschuld.de, 1
 lukeng.net, 1
 lukmanulhakim.id, 1
 lumiere.com, 1
+lunafag.ru, 1
 lunakit.org, 1
 lunapps.com, 1
 lunar6.ch, 1
 lunarshark.com, 1
 lunarsoft.net, 1
 lunartail.nl, 1
 lunasqu.ee, 1
 lunchbunch.me, 1
@@ -15003,16 +15009,17 @@ madusecurity.com, 1
 mae-berlinistanbul.com, 1
 maedchenflohmarkt.at, 1
 maedchenflohmarkt.de, 1
 maelstrom.ninja, 1
 maestrano.com, 1
 maff.co.uk, 1
 maff.scot, 0
 mafia.network, 1
+mafiaforum.de, 1
 mafiasi.de, 1
 magasinsalledebains.be, 1
 magasinsalledebains.fr, 1
 magazin3513.com, 1
 magazinedabeleza.net, 1
 magazinedotreino.com.br, 1
 magdic.eu, 1
 magebankin.com, 1
@@ -15308,16 +15315,17 @@ marqueswines.co.uk, 1
 marrai.de, 1
 marriage-shrine.jp, 1
 marrickvilleapartments.com.au, 1
 marsanvet.com, 1
 marsatapp.com, 1
 marsble.com, 1
 marshmallow.co, 1
 martelange.ovh, 1
+martensen.me, 0
 martensmxservice.nl, 1
 marti201.ga, 1
 martiestrimsalon.nl, 1
 martin-arend.de, 1
 martin-mattel.com, 1
 martin-smith.info, 1
 martine.nu, 1
 martingansler.de, 1
@@ -15554,17 +15562,16 @@ mcynews.com, 1
 mcyukon.com, 1
 md5file.com, 1
 md5hashing.net, 1
 mdcloudpracticesolutions.com, 1
 mdcloudps.com, 1
 mdek.at, 1
 mdewendt.de, 1
 mdf-bis.com, 1
-mdkr.nl, 1
 mdma.net, 1
 mdmed.clinic, 1
 mdosch.de, 1
 mdpraha.cz, 1
 mdsave.com, 1
 mdwftw.com, 1
 mdx.no, 1
 mdxn.org, 1
@@ -16425,17 +16432,17 @@ mpetroff.net, 1
 mpg-universal.com, 1
 mpg.ovh, 1
 mpi-sa.fr, 1
 mpintaamalabanna.it, 1
 mplanetphl.fr, 1
 mplant.io, 1
 mplicka.cz, 1
 mplusm.eu, 1
-mpreserver.com, 1
+mpreserver.com, 0
 mpserver12.org, 1
 mpsgarage.com.au, 1
 mpsoundcraft.com, 1
 mpy.ovh, 1
 mr-anderson.org, 1
 mr-labo.jp, 1
 mr-nachhilfe.de, 1
 mr-wolf.nl, 1
@@ -16596,16 +16603,17 @@ musmann.io, 1
 muspla.com, 1
 muspla.com.br, 1
 musselsblog.com, 1
 mustard.co.uk, 1
 musthavesforreal.com, 1
 mutantmonkey.in, 1
 mutantmonkey.info, 1
 mutantmonkey.sexy, 1
+mutuals.cool, 1
 mutuelle.fr, 1
 muusikoiden.net, 1
 muwatenraqamy.org, 1
 muzeumkomiksu.eu, 1
 muzi.cz, 1
 mv-wohnen.de, 1
 mvbits.com, 1
 mvnet.com.br, 1
@@ -17413,16 +17421,17 @@ nikandcara.com, 1
 nikao-tech.com, 1
 nikavandenbos.nl, 1
 nikimix.com, 1
 nikkila.me, 1
 nikklassen.ca, 1
 nikksno.io, 1
 niklas.pw, 1
 niklasbabel.com, 1
+nikobradshaw.com, 1
 nikolaichik.photo, 1
 nikolasbradshaw.com, 1
 nikolasgrottendieck.com, 1
 nikomo.fi, 0
 nikz.in, 1
 nil.gs, 1
 nilrem.org, 1
 nimeshjm.com, 1
@@ -17464,16 +17473,17 @@ niu.moe, 1
 niva.synology.me, 1
 nivi.ca, 1
 nix.org.ua, 0
 niyawe.de, 1
 nja.id.au, 1
 njpjanssen.nl, 1
 nkadvertising.online, 1
 nkautoservice.nl, 1
+nkb.in.th, 1
 nkinka.de, 1
 nkp-media.de, 1
 nl-ix.net, 1
 nl.search.yahoo.com, 0
 nlap.ca, 1
 nlegall.fr, 1
 nlm.gov, 1
 nlrb.gov, 1
@@ -17539,16 +17549,17 @@ noob-box.net, 1
 noobunbox.net, 1
 noodles.net.nz, 1
 noodplan.co.za, 1
 noodweer.be, 1
 noop.ch, 1
 noordsee.de, 1
 noorsolidarity.com, 1
 nootropic.com, 1
+nootropicsource.com, 1
 nopaste.xyz, 1
 nord-sud.be, 1
 nordakademie.de, 1
 nordic-survival.de, 1
 nordiccasinocommunity.com, 1
 nordinfo.fi, 1
 nordnetz-hamburg.de, 1
 nordor.homeip.net, 1
@@ -17611,17 +17622,16 @@ noticiasdehumor.com, 1
 notificami.com, 1
 notify.moe, 1
 notinglife.com, 1
 notjustvacs.com, 1
 notnize.net, 1
 notnl.com, 1
 notoriousdev.com, 1
 notrecourrier.net, 1
-nottres.com, 1
 notypiesni.sk, 0
 noudjalink.nl, 1
 nova-dess.ch, 1
 nova-wd.org.uk, 1
 nova.live, 1
 novabench.com, 1
 novafreixo.pt, 1
 novaopcaofestas.com.br, 1
@@ -17641,17 +17651,16 @@ nowlas.org, 1
 nowloading.co, 1
 nowprotein.com, 1
 noxlogic.nl, 1
 noyocenter.org, 1
 npath.de, 1
 npm.li, 1
 npmcdn.com, 1
 npw.net, 1
-nqesh.com, 1
 nrdstd.io, 1
 nrev.ch, 1
 nrkn.fr, 1
 nrnjn.xyz, 1
 ns-frontier.com, 1
 nsa.lol, 1
 nsa.wtf, 1
 nsbfalconacademy.org, 1
@@ -18894,16 +18903,17 @@ philippbirkholz.de, 1
 philipperoose.be, 1
 philippheenen.de, 1
 philippkeschl.at, 1
 phillippi.me, 1
 philonas.net, 1
 philosoftware.com.br, 1
 philosopherswool.com, 1
 philosophyguides.org, 1
+philphonic.de, 1
 philsturgeon.uk, 1
 philux.ch, 1
 phishingusertraining.com, 1
 phocean.net, 1
 phoenicis.com.ua, 1
 phoenix.dj, 1
 phone-service-center.de, 1
 phood.be, 1
@@ -18963,16 +18973,17 @@ pic.gov, 1
 pic.sr, 1
 pic2map.com, 1
 picallo.es, 1
 piccirello.com, 1
 pickme.nl, 1
 picksin.club, 1
 piclect.com, 1
 picoauto.com, 1
+picone.com.au, 1
 piconepress.com, 1
 picotech.com, 1
 picotronic.de, 1
 picsandtours.com, 1
 picster.at, 1
 picsto.re, 1
 pictr.nl, 1
 picture.team, 1
@@ -19380,16 +19391,17 @@ postblue.info, 1
 postbox.life, 1
 postcardpayment.com, 1
 postcode.nl, 1
 postcodegarant.nl, 1
 postdarwinian.com, 1
 postdarwinism.com, 1
 postdeck.de, 1
 posteo.de, 0
+posterspy.com, 1
 postfinance.ch, 1
 postmatescode.com, 1
 postn.eu, 1
 postpot.co.kr, 1
 posttigo.com, 1
 potatiz.com, 1
 potatofrom.space, 0
 potatopro.com, 1
@@ -19502,16 +19514,17 @@ pretix.eu, 1
 pretrialservices.gov, 1
 pretty.hu, 1
 prettytunesapp.com, 1
 pretzelx.com, 1
 prevenir.ch, 1
 priceholic.com, 1
 prideindomination.com, 1
 pridetechdesign.com, 1
+prielwurmjaeger.de, 1
 prifo.se, 1
 prilock.com, 1
 primaconsulting.net, 1
 primates.com, 1
 primewho.org, 1
 primordialsnooze.com, 1
 prinbanat.ngo, 1
 princeagency.com, 1
@@ -20478,16 +20491,17 @@ responer.com, 1
 responsibledisclosure.nl, 0
 ressl.ch, 1
 restaurant-mangal.ch, 1
 restaurant-rosengarten.at, 1
 restaurantesimonetti.com.br, 1
 restaurantmangal.ch, 1
 rester-a-domicile.ch, 1
 rester-autonome-chez-soi.ch, 1
+restioson.me, 1
 restoran-radovce.me, 1
 restoreresearchstudy.com, 1
 restoruns.com, 1
 restoruns.xyz, 1
 restrito.org, 1
 resursedigitale.ro, 1
 retcor.net, 1
 retetenoi.net, 1
@@ -20632,17 +20646,19 @@ rishikeshyoga.in, 1
 risiinfo.com, 1
 risingsun.red, 1
 riskmitigation.ch, 1
 rissato.com.br, 1
 ristioja.ee, 1
 ristoarea.it, 1
 ristorantefattoamano.eu, 1
 ristorantefattoamano.it, 1
+rivaforum.de, 1
 rivalsa.cn, 1
+rivastation.de, 1
 riverbanktearooms.co.uk, 1
 rivercruiseadvisor.com, 1
 riverford.co.uk, 1
 rivermendhealthcenters.com, 1
 rivermist.com.au, 1
 riversideauto.net, 1
 riversideradio.nl, 1
 riverweb.gr, 1
@@ -21866,17 +21882,16 @@ sexy-store.nl, 1
 seydaozcan.com, 1
 seyfarth.de, 1
 seyr.it, 1
 seyr.me, 1
 sfg-nordholz.de, 1
 sfirat-haomer.com, 1
 sfo-fog.ch, 1
 sftool.gov, 1
-sg-elektro.de, 1
 sg.search.yahoo.com, 0
 sgcaccounts.co.uk, 1
 sgroup-hitoduma.com, 1
 sgroup-rec.com, 1
 sgtcodfish.com, 1
 sgthotshot.com, 1
 sgtsnookums.net, 1
 sgtt.ch, 1
@@ -21930,17 +21945,16 @@ shang-yu.cn, 1
 shannoneichorn.com, 1
 shansing.cn, 1
 shansing.com, 1
 shansing.net, 1
 shansing.space, 1
 sharanyamunsi.net, 1
 sharedhost.de, 1
 shareeri.com, 1
-sharekey.com, 1
 shareoffice.ch, 1
 shareoine.com, 1
 sharepointdrive.com, 1
 sharescope.co.uk, 0
 shareselecttools.com, 1
 sharesplitter.com, 1
 sharevari.com, 1
 shareworx.net, 1
@@ -22006,16 +22020,17 @@ shinobi-fansub.ro, 1
 shinonome-lab.eu.org, 1
 shintoism.com, 1
 shinyuu.net, 1
 shipard.com, 1
 shipard.cz, 1
 shipcloud.io, 1
 shirakaba-cc.com, 1
 shiroki-k.net, 1
+shirt2go.shop, 1
 shirtsofholland.com, 1
 shishamania.de, 1
 shishkin.link, 1
 shishkin.us, 1
 shishlik.net, 1
 shitagi-shop.com, 1
 shitbeast.institute, 1
 shitfest.info, 1
@@ -22532,16 +22547,17 @@ smatch.com, 1
 smb445.com, 1
 smdavis.us, 1
 smdcn.net, 1
 sme-gmbh.net, 1
 smeetsengraas.com, 1
 smiatek.name, 1
 smileandpay.com, 1
 smileawei.com, 1
+smiledirectsales.com, 1
 smime.io, 1
 smipty.cn, 1
 smipty.com, 1
 smit.com.ua, 1
 smith.is, 1
 smithandcanova.co.uk, 1
 smkw.com, 0
 sml.lc, 1
@@ -23356,17 +23372,16 @@ strutta.me, 1
 struxureon.com, 1
 strydom.me.uk, 1
 stt.wiki, 1
 stuartbell.co.uk, 1
 stuco.co, 1
 studenckiemetody.pl, 1
 student-eshop.cz, 1
 student-eshop.sk, 1
-student.andover.edu, 1
 studentforums.biz, 1
 studentite.bg, 0
 studentloans.gov, 1
 studentrightsadvocate.org, 1
 studentshare.net, 1
 studenttenant.com, 1
 studer.su, 1
 studienportal.eu, 1
@@ -23709,17 +23724,16 @@ t3rror.net, 1
 t7e.de, 0
 ta-65.com, 1
 ta-sports.net, 1
 ta65.com, 1
 taartenfeesies.nl, 1
 tab.watch, 1
 tabelfirme.ro, 1
 tabernadovinho.com.br, 1
-taberu-fujitsubo.com, 1
 tabithawebb.co.uk, 1
 tabla-periodica.com, 1
 tablescraps.com, 1
 tablet.facebook.com, 0
 tablotv.com, 0
 taboragroup.com, 0
 taborsky.cz, 1
 tac-volley.com, 1
@@ -23835,16 +23849,17 @@ tateesq.com, 1
 tatiloley.com, 1
 tatort-fanpage.de, 1
 tatsidou.gr, 1
 tattoo.dating, 1
 tattvaayoga.com, 1
 tavolaquadrada.com.br, 1
 tavsys.net, 1
 taxaroo.com, 1
+taxi-24std.de, 1
 taxi-chamonix.fr, 1
 taxi-collectif.ch, 1
 taxicollectif.ch, 1
 taxis-collectifs.ch, 1
 taxisafmatosinhos.pt, 1
 taxiscollectifs.ch, 1
 taxlab.co.nz, 1
 taxmadras.com, 1
@@ -24152,17 +24167,16 @@ tfxstartup.com.br, 1
 tgbyte.com, 1
 tgbyte.de, 1
 tgexport.eu, 1
 tgmkanis.com, 1
 tgod.co, 1
 tgui.eu, 1
 tgui.net, 1
 tgw.com, 1
-th-bl.de, 1
 th.search.yahoo.com, 0
 th3nd.com, 1
 thackbarth.net, 1
 thaedal.net, 1
 thagki9.com, 1
 thai.dating, 1
 thai.land, 0
 thaianthro.com, 1
@@ -24633,16 +24647,17 @@ tjs.me, 1
 tkacz.pro, 1
 tkarstens.de, 0
 tkat.ch, 1
 tkgpm.com, 1
 tkjg.fi, 1
 tkn.tokyo, 1
 tkts.cl, 1
 tkusano.jp, 1
+tlach.cz, 1
 tlehseasyads.com, 1
 tlo.xyz, 1
 tloxygen.com, 1
 tls.builders, 1
 tls.care, 1
 tls1914.org, 1
 tlsrobot.se, 1
 tlthings.net, 1
@@ -25041,16 +25056,17 @@ translate.stg.fedoraproject.org, 1
 translateblender.ru, 1
 translatoruk.co.uk, 1
 transmisjeonline.pl, 1
 transmithe.net, 1
 transparentcorp.com, 1
 transport.eu, 1
 transsexualpantyhose.com, 1
 transverify.com, 1
+trashnothing.com, 1
 trask.no, 1
 trauertexte.info, 1
 traumhuetten.de, 1
 traut.cloud, 1
 travador.com, 1
 travaux-toiture-idf.fr, 1
 travel-dealz.de, 1
 travel-to-nature.ch, 1
@@ -25301,16 +25317,17 @@ twd2.me, 1
 twd2.net, 0
 tweakers.net, 1
 tweakersbadge.nl, 1
 tweaktown.com, 1
 tweetfreq.net, 0
 twelve.rocks, 1
 twelve.today, 1
 twelverocks.com, 1
+twem.ddns.net, 1
 twenty71.com, 1
 twentymilliseconds.com, 1
 twilleys.com, 1
 twincitynissantxparts.com, 1
 twiri.net, 1
 twistapp.com, 1
 twistedwave.com, 1
 twisto.cz, 1
@@ -25591,17 +25608,16 @@ upbad.com, 1
 upbeatrobot.com, 1
 upbeatrobot.eu, 1
 upgamerengine.com, 1
 upgamerengine.net, 1
 upgauged.com, 1
 upitnik.rs, 1
 uplaqui.com.br, 1
 uplinklabs.net, 1
-upload.cat, 1
 upload.facebook.com, 0
 uploadbeta.com, 1
 upmchealthsecurity.us, 1
 upnext.io, 1
 upperbeaconsfield.org.au, 1
 upplevelse.com, 1
 upr-info.org, 1
 upr.com.ua, 1
@@ -25624,17 +25640,16 @@ urban-culture.fr, 1
 urban.melbourne, 1
 urbanesecurity.com, 1
 urbanfi.sh, 1
 urbanguerillas.de, 1
 urbanietz-immobilien.de, 1
 urbanmelbourne.info, 1
 urbannewsservice.com, 1
 urbansparrow.in, 1
-urbanstylestaging.com, 1
 urbanwildlifealliance.org, 1
 urbexdk.nl, 1
 urcentral.com, 1
 urcentral.org, 1
 ureka.org, 1
 urgences-valais.ch, 1
 uripura.de, 1
 urist1011.ru, 1
@@ -27136,17 +27151,16 @@ www.amazon.com.br, 1
 www.amazon.com.mx, 1
 www.amazon.de, 1
 www.amazon.es, 1
 www.amazon.fr, 1
 www.amazon.it, 1
 www.amazon.nl, 1
 www.apollo-auto.com, 0
 www.banking.co.at, 0
-www.calyxinstitute.org, 0
 www.capitainetrain.com, 0
 www.captaintrain.com, 0
 www.cloudflare.com, 0
 www.cnet.com, 1
 www.dropbox.com, 1
 www.dropcam.com, 0
 www.entropia.de, 0
 www.eternalgoth.co.uk, 1
@@ -27800,16 +27814,17 @@ zamis.net, 1
 zamocosmeticos.com.br, 1
 zamow.co, 1
 zandcell.com, 1
 zanthra.com, 1
 zapier.com, 1
 zappbuildapps.com, 1
 zaratan.fr, 1
 zarmarket.org, 1
+zary.me, 1
 zaufanatrzeciastrona.pl, 1
 zavetaji.lv, 1
 zawo-electric.de, 1
 zbasenem.pl, 1
 zbchen.com, 1
 zberger.com, 1
 zbetcheck.in, 1
 zbp.at, 0
@@ -27938,16 +27953,17 @@ zlatosnadno.cz, 1
 zlavomat.sk, 1
 zlc1994.com, 1
 zlima12.com, 1
 zmk.fr, 0
 znacite.com, 1
 znation.nl, 1
 zning.net.cn, 1
 zobraz.cz, 1
+zockenbiszumumfallen.de, 1
 zoeller.me, 1
 zohar.shop, 1
 zohar.wang, 0
 zoigl.club, 1
 zojadravai.com, 1
 zoki.art, 1
 zokster.net, 1
 zolokar.xyz, 1
--- a/services/fxaccounts/FxAccounts.jsm
+++ b/services/fxaccounts/FxAccounts.jsm
@@ -1286,16 +1286,17 @@ FxAccountsInternal.prototype = {
   },
 
   _rejectWhenVerified(currentState, error) {
     currentState.whenVerifiedDeferred.reject(error);
     delete currentState.whenVerifiedDeferred;
   },
 
   requiresHttps() {
+    // Also used in FxAccountsOAuthGrantClient.jsm.
     let allowHttp = Services.prefs.getBoolPref("identity.fxaccounts.allowHttp", false);
     return allowHttp !== true;
   },
 
   promiseAccountsSignUpURI() {
     return FxAccountsConfig.promiseAccountsSignUpURI();
   },
 
--- a/services/fxaccounts/FxAccountsOAuthGrantClient.jsm
+++ b/services/fxaccounts/FxAccountsOAuthGrantClient.jsm
@@ -10,21 +10,24 @@
 
 this.EXPORTED_SYMBOLS = ["FxAccountsOAuthGrantClient", "FxAccountsOAuthGrantClientError"];
 
 const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
 
 Cu.import("resource://gre/modules/Log.jsm");
 Cu.import("resource://gre/modules/FxAccountsCommon.js");
 Cu.import("resource://services-common/rest.js");
+Cu.import("resource://gre/modules/Services.jsm");
 
 Cu.importGlobalProperties(["URL"]);
 
 const AUTH_ENDPOINT = "/authorization";
 const DESTROY_ENDPOINT = "/destroy";
+// This is the same pref that's used by FxAccounts.jsm.
+const ALLOW_HTTP_PREF = "identity.fxaccounts.allowHttp";
 
 /**
  * Create a new FxAccountsOAuthClient for browser some service.
  *
  * @param {Object} options Options
  *   @param {Object} options.parameters
  *     @param {String} options.parameters.client_id
  *     OAuth id returned from client registration
@@ -40,16 +43,21 @@ this.FxAccountsOAuthGrantClient = functi
   this.parameters = options;
 
   try {
     this.serverURL = new URL(this.parameters.serverURL);
   } catch (e) {
     throw new Error("Invalid 'serverURL'");
   }
 
+  let forceHTTPS = !Services.prefs.getBoolPref(ALLOW_HTTP_PREF, false);
+  if (forceHTTPS && this.serverURL.protocol != "https:") {
+    throw new Error("'serverURL' must be HTTPS");
+  }
+
   log.debug("FxAccountsOAuthGrantClient Initialized");
 };
 
 this.FxAccountsOAuthGrantClient.prototype = {
 
   /**
    * Retrieves an OAuth access token for the signed in user
    *
--- a/services/fxaccounts/tests/xpcshell/test_accounts.js
+++ b/services/fxaccounts/tests/xpcshell/test_accounts.js
@@ -1192,17 +1192,17 @@ add_test(function test_getOAuthToken() {
   let alice = getTestUser("alice");
   alice.verified = true;
   let getTokenFromAssertionCalled = false;
 
   fxa.internal._d_signCertificate.resolve("cert1");
 
   // create a mock oauth client
   let client = new FxAccountsOAuthGrantClient({
-    serverURL: "http://example.com/v1",
+    serverURL: "https://example.com/v1",
     client_id: "abc123"
   });
   client.getTokenFromAssertion = function() {
     getTokenFromAssertionCalled = true;
     return Promise.resolve({ access_token: "token" });
   };
 
   fxa.setSignedInUser(alice).then(
@@ -1224,17 +1224,17 @@ add_test(function test_getOAuthTokenScop
   let alice = getTestUser("alice");
   alice.verified = true;
   let getTokenFromAssertionCalled = false;
 
   fxa.internal._d_signCertificate.resolve("cert1");
 
   // create a mock oauth client
   let client = new FxAccountsOAuthGrantClient({
-    serverURL: "http://example.com/v1",
+    serverURL: "https://example.com/v1",
     client_id: "abc123"
   });
   client.getTokenFromAssertion = function(assertion, scopeString) {
     equal(scopeString, "foo bar");
     getTokenFromAssertionCalled = true;
     return Promise.resolve({ access_token: "token" });
   };
 
@@ -1257,17 +1257,17 @@ add_task(async function test_getOAuthTok
   let alice = getTestUser("alice");
   alice.verified = true;
   let numTokenFromAssertionCalls = 0;
 
   fxa.internal._d_signCertificate.resolve("cert1");
 
   // create a mock oauth client
   let client = new FxAccountsOAuthGrantClient({
-    serverURL: "http://example.com/v1",
+    serverURL: "https://example.com/v1",
     client_id: "abc123"
   });
   client.getTokenFromAssertion = function() {
     numTokenFromAssertionCalls += 1;
     return Promise.resolve({ access_token: "token" });
   };
 
   await fxa.setSignedInUser(alice);
@@ -1290,17 +1290,17 @@ add_task(async function test_getOAuthTok
   let alice = getTestUser("alice");
   alice.verified = true;
   let numTokenFromAssertionCalls = 0;
 
   fxa.internal._d_signCertificate.resolve("cert1");
 
   // create a mock oauth client
   let client = new FxAccountsOAuthGrantClient({
-    serverURL: "http://example.com/v1",
+    serverURL: "https://example.com/v1",
     client_id: "abc123"
   });
   client.getTokenFromAssertion = function() {
     numTokenFromAssertionCalls += 1;
     return Promise.resolve({ access_token: "token" });
   };
 
   await fxa.setSignedInUser(alice);
@@ -1388,17 +1388,17 @@ add_test(function test_getOAuthToken_net
   let fxa = new MockFxAccounts();
   let alice = getTestUser("alice");
   alice.verified = true;
 
   fxa.internal._d_signCertificate.resolve("cert1");
 
   // create a mock oauth client
   let client = new FxAccountsOAuthGrantClient({
-    serverURL: "http://example.com/v1",
+    serverURL: "https://example.com/v1",
     client_id: "abc123"
   });
   client.getTokenFromAssertion = function() {
     return Promise.reject(new FxAccountsOAuthGrantClientError({
       error: ERROR_NETWORK,
       errno: ERRNO_NETWORK
     }));
   };
@@ -1417,17 +1417,17 @@ add_test(function test_getOAuthToken_aut
   let fxa = new MockFxAccounts();
   let alice = getTestUser("alice");
   alice.verified = true;
 
   fxa.internal._d_signCertificate.resolve("cert1");
 
   // create a mock oauth client
   let client = new FxAccountsOAuthGrantClient({
-    serverURL: "http://example.com/v1",
+    serverURL: "https://example.com/v1",
     client_id: "abc123"
   });
   client.getTokenFromAssertion = function() {
     return Promise.reject(new FxAccountsOAuthGrantClientError({
       error: ERROR_INVALID_FXA_ASSERTION,
       errno: ERRNO_INVALID_FXA_ASSERTION
     }));
   };
@@ -1446,17 +1446,17 @@ add_test(function test_getOAuthToken_unk
   let fxa = new MockFxAccounts();
   let alice = getTestUser("alice");
   alice.verified = true;
 
   fxa.internal._d_signCertificate.resolve("cert1");
 
   // create a mock oauth client
   let client = new FxAccountsOAuthGrantClient({
-    serverURL: "http://example.com/v1",
+    serverURL: "https://example.com/v1",
     client_id: "abc123"
   });
   client.getTokenFromAssertion = function() {
     return Promise.reject("boom");
   };
 
   fxa.setSignedInUser(alice).then(() => {
     fxa.getOAuthToken({ scope: "profile", client })
--- a/services/fxaccounts/tests/xpcshell/test_oauth_grant_client.js
+++ b/services/fxaccounts/tests/xpcshell/test_oauth_grant_client.js
@@ -2,17 +2,17 @@
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 Cu.import("resource://gre/modules/FxAccountsCommon.js");
 Cu.import("resource://gre/modules/FxAccountsOAuthGrantClient.jsm");
 
 const CLIENT_OPTIONS = {
-  serverURL: "http://127.0.0.1:9010/v1",
+  serverURL: "https://127.0.0.1:9010/v1",
   client_id: "abc123"
 };
 
 const STATUS_SUCCESS = 200;
 
 /**
  * Mock request responder
  * @param {String} response
@@ -131,17 +131,17 @@ add_test(function serverErrorResponse() 
       do_check_eq(e.error, "Bad Request");
       do_check_eq(e.message, "Unauthorized");
       run_next_test();
     });
 });
 
 add_test(function networkErrorResponse() {
   let client = new FxAccountsOAuthGrantClient({
-    serverURL: "http://domain.dummy",
+    serverURL: "https://domain.dummy",
     client_id: "abc123"
   });
   Services.prefs.setBoolPref("identity.fxaccounts.skipDeviceRegistration", true);
   client.getTokenFromAssertion("assertion", "scope")
     .catch(function(e) {
       do_check_eq(e.name, "FxAccountsOAuthGrantClientError");
       do_check_eq(e.code, null);
       do_check_eq(e.errno, ERRNO_NETWORK);
@@ -200,24 +200,36 @@ add_test(function incorrectErrno() {
 
 add_test(function constructorTests() {
   validationHelper(undefined,
     "Error: Missing configuration options");
 
   validationHelper({},
     "Error: Missing 'serverURL' parameter");
 
-  validationHelper({ serverURL: "http://example.com" },
+  validationHelper({ serverURL: "https://example.com" },
+    "Error: Missing 'client_id' parameter");
+
+  validationHelper({ serverURL: "https://example.com" },
     "Error: Missing 'client_id' parameter");
 
   validationHelper({ client_id: "123ABC" },
     "Error: Missing 'serverURL' parameter");
 
-  validationHelper({ client_id: "123ABC", serverURL: "badUrl" },
-    "Error: Invalid 'serverURL'");
+  validationHelper({ client_id: "123ABC", serverURL: "http://example.com" },
+    "Error: 'serverURL' must be HTTPS");
+
+  try {
+    Services.prefs.setBoolPref("identity.fxaccounts.allowHttp", true);
+    validationHelper({ client_id: "123ABC", serverURL: "http://example.com" }, null);
+  } finally {
+    Services.prefs.clearUserPref("identity.fxaccounts.allowHttp");
+  }
+
+
 
   run_next_test();
 });
 
 add_test(function errorTests() {
   let error1 = new FxAccountsOAuthGrantClientError();
   do_check_eq(error1.name, "FxAccountsOAuthGrantClientError");
   do_check_eq(error1.code, null);
@@ -245,25 +257,44 @@ add_test(function errorTests() {
   do_check_eq(fields2.errno, statusCode);
   do_check_eq(fields2.error, "Error");
   do_check_eq(fields2.message, "Something");
 
   do_check_true(error2.toString().indexOf("Something") >= 0);
   run_next_test();
 });
 
+
+add_test(function networkErrorResponse() {
+  let client = new FxAccountsOAuthGrantClient({
+    serverURL: "https://domain.dummy",
+    client_id: "abc123"
+  });
+  Services.prefs.setBoolPref("identity.fxaccounts.skipDeviceRegistration", true);
+  client.getTokenFromAssertion("assertion", "scope")
+    .catch(function(e) {
+      do_check_eq(e.name, "FxAccountsOAuthGrantClientError");
+      do_check_eq(e.code, null);
+      do_check_eq(e.errno, ERRNO_NETWORK);
+      do_check_eq(e.error, ERROR_NETWORK);
+      run_next_test();
+    }).catch(() => {}).then(() =>
+      Services.prefs.clearUserPref("identity.fxaccounts.skipDeviceRegistration"));
+});
+
+
 /**
  * Quick way to test the "FxAccountsOAuthGrantClient" constructor.
  *
  * @param {Object} options
  *        FxAccountsOAuthGrantClient constructor options
  * @param {String} expected
- *        Expected error message
+ *        Expected error message, or null if it's expected to pass.
  * @returns {*}
  */
 function validationHelper(options, expected) {
   try {
     new FxAccountsOAuthGrantClient(options);
   } catch (e) {
     return do_check_eq(e.toString(), expected);
   }
-  throw new Error("Validation helper error");
+  return do_check_eq(expected, null);
 }
--- a/services/fxaccounts/tests/xpcshell/test_oauth_grant_client_server.js
+++ b/services/fxaccounts/tests/xpcshell/test_oauth_grant_client_server.js
@@ -2,16 +2,17 @@
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // A test of FxAccountsOAuthGrantClient but using a real server it can
 // hit.
 "use strict";
 
 Cu.import("resource://gre/modules/FxAccountsCommon.js");
 Cu.import("resource://gre/modules/FxAccountsOAuthGrantClient.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
 
 // handlers for our server.
 var numTokenFetches;
 var activeTokens;
 
 function authorize(request, response) {
   response.setStatusLine("1.1", 200, "OK");
   let token = "token" + numTokenFetches;
@@ -46,24 +47,29 @@ function startServer() {
 
 function promiseStopServer(server) {
   return new Promise(resolve => {
     server.stop(resolve);
   });
 }
 
 add_task(async function getAndRevokeToken() {
+  Services.prefs.setBoolPref("identity.fxaccounts.allowHttp", true);
   let server = startServer();
-  let clientOptions = {
-    serverURL: "http://localhost:" + server.identity.primaryPort + "/v1",
-    client_id: "abc123",
-  }
+  try {
+    let clientOptions = {
+      serverURL: "http://localhost:" + server.identity.primaryPort + "/v1",
+      client_id: "abc123",
+    }
 
-  let client = new FxAccountsOAuthGrantClient(clientOptions);
-  let result = await client.getTokenFromAssertion("assertion", "scope");
-  equal(result.access_token, "token0");
-  equal(numTokenFetches, 1, "we hit the server to fetch a token");
-  await client.destroyToken("token0");
-  equal(activeTokens.size, 0, "We hit the server to revoke it");
-  await promiseStopServer(server);
+    let client = new FxAccountsOAuthGrantClient(clientOptions);
+    let result = await client.getTokenFromAssertion("assertion", "scope");
+    equal(result.access_token, "token0");
+    equal(numTokenFetches, 1, "we hit the server to fetch a token");
+    await client.destroyToken("token0");
+    equal(activeTokens.size, 0, "We hit the server to revoke it");
+  } finally {
+    await promiseStopServer(server);
+    Services.prefs.clearUserPref("identity.fxaccounts.allowHttp");
+  }
 });
 
 // XXX - TODO - we should probably add more tests for unexpected responses etc.
--- a/servo/Cargo.lock
+++ b/servo/Cargo.lock
@@ -468,17 +468,17 @@ dependencies = [
 
 [[package]]
 name = "compositing"
 version = "0.0.1"
 dependencies = [
  "euclid 0.15.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "gfx_traits 0.0.1",
  "gleam 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "image 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "image 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "ipc-channel 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "msg 0.0.1",
  "net_traits 0.0.1",
  "profile_traits 0.0.1",
  "script_traits 0.0.1",
  "servo_config 0.0.1",
  "servo_geometry 0.0.1",
@@ -1191,17 +1191,17 @@ dependencies = [
  "libservo 0.0.1",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "msg 0.0.1",
  "net_traits 0.0.1",
  "osmesa-src 17.2.0-devel (git+https://github.com/servo/osmesa-src)",
  "osmesa-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "script_traits 0.0.1",
  "servo-egl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "servo-glutin 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "servo-glutin 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "servo_config 0.0.1",
  "servo_geometry 0.0.1",
  "servo_url 0.0.1",
  "style_traits 0.0.1",
  "user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "webrender_api 0.52.0 (git+https://github.com/servo/webrender)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "x11 2.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1354,44 +1354,47 @@ source = "registry+https://github.com/ru
 dependencies = [
  "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-bidi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-normalization 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "image"
-version = "0.14.0"
+version = "0.16.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "gif 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "jpeg-decoder 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-iter 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-rational 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
- "png 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "png 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "scoped_threadpool 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "immeta"
 version = "0.3.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "arrayvec 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "inflate"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "adler32 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
 
 [[package]]
 name = "influent"
 version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2009,17 +2012,17 @@ dependencies = [
 name = "net_traits"
 version = "0.0.1"
 dependencies = [
  "cookie 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)",
  "hyper_serde 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "image 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "image 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "ipc-channel 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "msg 0.0.1",
  "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "servo_config 0.0.1",
  "servo_url 0.0.1",
@@ -2330,22 +2333,22 @@ dependencies = [
  "compiletest_helper 0.0.1",
  "deny_public_fields 0.0.1",
  "script 0.0.1",
  "script_plugins 0.0.1",
 ]
 
 [[package]]
 name = "png"
-version = "0.8.0"
+version = "0.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "deflate 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "inflate 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "inflate 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-iter 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "precomputed-hash"
 version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
@@ -2601,17 +2604,17 @@ dependencies = [
  "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "gleam 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "half 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "html5ever 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)",
  "hyper_serde 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "image 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "image 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "ipc-channel 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "js 0.1.6 (git+https://github.com/servo/rust-mozjs)",
  "jstraceable_derive 0.0.1",
  "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "metrics 0.0.1",
  "mime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2861,28 +2864,28 @@ version = "4.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cmake 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "servo-glutin"
-version = "0.12.0"
+version = "0.12.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "android_glue 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "cgl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "cocoa 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-foundation 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-graphics 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "dwmapi-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "gl_generator 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "image 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "image 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
  "objc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "osmesa-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "shared_library 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "shell32-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2901,17 +2904,17 @@ dependencies = [
  "expat-sys 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "gleam 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "glx 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "io-surface 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
  "servo-egl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "servo-fontconfig-sys 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "servo-freetype-sys 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "servo-glutin 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "servo-glutin 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "x11 2.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "servo-websocket"
 version = "0.19.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
@@ -3596,17 +3599,17 @@ dependencies = [
 [[package]]
 name = "webdriver_server"
 version = "0.0.1"
 dependencies = [
  "base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "cookie 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.15.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)",
- "image 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "image 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "ipc-channel 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "msg 0.0.1",
  "net_traits 0.0.1",
  "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "script_traits 0.0.1",
  "servo_config 0.0.1",
@@ -3894,19 +3897,19 @@ dependencies = [
 "checksum heartbeats-simple-sys 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e1a408c0011427cc0e0049f7861c70377819aedfc006e8c901b1c70fd98fb1a4"
 "checksum html5ever 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5bfb46978eb757a603b7dfe2dafb1c62cb4dee3428d8ac1de734d83d6b022d06"
 "checksum httparse 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a6e7a63e511f9edffbab707141fbb8707d1a3098615fb2adbd5769cdfcc9b17d"
 "checksum hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)" = "368cb56b2740ebf4230520e2b90ebb0461e69034d85d1945febd9b3971426db2"
 "checksum hyper-openssl 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "85a372eb692590b3fe014c196c30f9f52d4c42f58cd49dd94caeee1593c9cc37"
 "checksum hyper_serde 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cbe43f514f80494e9329c9fc47d61b85b167d245685424637a0f4a409177e444"
 "checksum ident_case 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c9826188e666f2ed92071d2dadef6edc430b11b158b5b2b3f4babbcc891eaaa"
 "checksum idna 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2233d4940b1f19f0418c158509cd7396b8d70a5db5705ce410914dc8fa603b37"
-"checksum image 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d61d2b3f000fb41d268312b92d4dd5ee7823163ceee71a67c676271585dfe598"
+"checksum image 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e70634e5518ee89975b43c4bbd1667c4012c0313392aa2dfa2db5563c28e34c2"
 "checksum immeta 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0b9260463a221bfe3f02100c56e2d14c050d5ffe7e44a43d0a1b2b1f2b523502"
-"checksum inflate 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d1238524675af3938a7c74980899535854b88ba07907bb1c944abe5b8fc437e5"
+"checksum inflate 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "10ec05638adf7c5c788bc0cfa608cd479a13572beda20feb4898fe1d85d2c64b"
 "checksum influent 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a22b311b83431be3ab9af96ca9ea41554bb4a8551ea871ae44c3ce0c57e55f2c"
 "checksum io-surface 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad4578cee6ed49a17766fa608a4425008313c55ebb7a267622cbddd6b01751e2"
 "checksum iovec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "29d062ee61fccdf25be172e70f34c9f6efc597e1fb8f6526e8437b2046ab26be"
 "checksum ipc-channel 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a38ad662f104525ac57012e0b79aad07507e3fc11e3bae668bf416264e760ebb"
 "checksum itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4833d6978da405305126af4ac88569b5d71ff758581ce5a987dbfa3755f694fc"
 "checksum itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2f404fbc66fd9aac13e998248505e7ecb2ad8e44ab6388684c5fb11c6c251c"
 "checksum jpeg-decoder 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2805ccb10ffe4d10e06ef68a158ff94c255211ecbae848fbde2146b098f93ce7"
 "checksum js 0.1.6 (git+https://github.com/servo/rust-mozjs)" = "<none>"
@@ -3969,17 +3972,17 @@ dependencies = [
 "checksum peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
 "checksum percent-encoding 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de154f638187706bde41d9b4738748933d64e6b37bdbffc0b47a97d16a6ae356"
 "checksum phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "cb325642290f28ee14d8c6201159949a872f220c62af6e110a56ea914fbe42fc"
 "checksum phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "d62594c0bb54c464f633175d502038177e90309daf2e0158be42ed5f023ce88f"
 "checksum phf_generator 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "6b07ffcc532ccc85e3afc45865469bf5d9e4ef5bfcf9622e3cfe80c2d275ec03"
 "checksum phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "07e24b0ca9643bdecd0632f2b3da6b1b89bbb0030e0b992afc1113b23a7bc2f2"
 "checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903"
 "checksum plane-split 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e57800a97ca52c556db6b6184a3201f05366ad5e11876f7d17e234589ca2fa26"
-"checksum png 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6535266009941ceac9a17e6d681cd2adc75611cd4833db853282e8d4c470239c"
+"checksum png 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b5c59debbb04e708775b004dce99d66984d5448625d63408ad502014d2880cd"
 "checksum precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
 "checksum procedural-masquerade 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c93cdc1fb30af9ddf3debc4afbdb0f35126cbd99daa229dd76cdd5349b41d989"
 "checksum pulldown-cmark 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1058d7bb927ca067656537eec4e02c2b4b70eaaa129664c5b90c111e20326f41"
 "checksum push-trait 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fdc13b1a53bc505b526086361221aaa612fefb9b0ecf2853f9d31f807764e004"
 "checksum quasi 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18c45c4854d6d1cf5d531db97c75880feb91c958b0720f4ec1057135fec358b3"
 "checksum quasi_codegen 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "51b9e25fa23c044c1803f43ca59c98dac608976dd04ce799411edd58ece776d4"
 "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
 "checksum rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "022e0636ec2519ddae48154b028864bdce4eaf7d35226ab8e65c611be97b189d"
@@ -4004,17 +4007,17 @@ dependencies = [
 "checksum serde_bytes 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a73f5ad9bb83e1e407254c7a355f4efdaffe3c1442fc0657ddb8b9b6b225655"
 "checksum serde_derive 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "812ff66056fd9a9a5b7c119714243b0862cf98340e7d4b5ee05a932c40d5ea6c"
 "checksum serde_derive_internals 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bd381f6d01a6616cdba8530492d453b7761b456ba974e98768a18cad2cd76f58"
 "checksum serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "48b04779552e92037212c3615370f6bd57a40ebba7f20e554ff9f55e41a69a7b"
 "checksum servo-egl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "21069a884c33fe6ee596975e1f3849ed88c4ec857fbaf11d33672d8ebe051217"
 "checksum servo-fontconfig 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "93f799b649b4a2bf362398910eca35240704c7e765e780349b2bb1070d892262"
 "checksum servo-fontconfig-sys 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6be80777ee6edecbbbf8774c76e19dddfe336256c57a4ded06d6ad3df7be358e"
 "checksum servo-freetype-sys 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9232032c2e85118c0282c6562c84cab12316e655491ba0a5d1905b2320060d1b"
-"checksum servo-glutin 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "974a617661e0c1bbd6227736d116c1fff73ac9c4e4592abe39b374f9e249e5d8"
+"checksum servo-glutin 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05bfa660ed7bceb5df3d79ca5a9c99a59fa7019c4477cbe52b70f80034bce568"
 "checksum servo-skia 0.30000006.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1c104b3a0b3938f760772c09584fd6b2bb7ca205e2553a767b357f8ddbfbccbc"
 "checksum servo-websocket 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8a1ff13c5d852c2793805226e688044309f2c1d8f063784805a13e99cb75b611"
 "checksum sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cc30b1e1e8c40c121ca33b86c23308a090d19974ef001b4bf6e61fd1a0fb095c"
 "checksum shared_library 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fb04126b6fcfd2710fb5b6d18f4207b6c535f2850a7e1a43bcd526d44f30a79a"
 "checksum shell32-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "72f20b8f3c060374edb8046591ba28f62448c369ccbdc7b02075103fb3a9e38d"
 "checksum sig 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c6649e43c1a1e68d29ed56d0dc3b5b6cf3b901da77cf107c4066b9e3da036df5"
 "checksum signpost 0.1.0 (git+https://github.com/pcwalton/signpost.git)" = "<none>"
 "checksum simd 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a94d14a2ae1f1f110937de5fb69e494372560181c7e1739a097fcc2cee37ba0"
--- a/servo/components/compositing/Cargo.toml
+++ b/servo/components/compositing/Cargo.toml
@@ -8,17 +8,17 @@ publish = false
 [lib]
 name = "compositing"
 path = "lib.rs"
 
 [dependencies]
 euclid = "0.15"
 gfx_traits = {path = "../gfx_traits"}
 gleam = "0.4"
-image = "0.14"
+image = "0.16"
 ipc-channel = "0.8"
 log = "0.3.5"
 msg = {path = "../msg"}
 net_traits = {path = "../net_traits"}
 profile_traits = {path = "../profile_traits"}
 script_traits = {path = "../script_traits"}
 servo_config = {path = "../config"}
 servo_geometry = {path = "../geometry", features = ["servo"]}
--- a/servo/components/net_traits/Cargo.toml
+++ b/servo/components/net_traits/Cargo.toml
@@ -10,17 +10,17 @@ name = "net_traits"
 path = "lib.rs"
 
 [dependencies]
 cookie = "0.6"
 heapsize = "0.4"
 heapsize_derive = "0.1"
 hyper = "0.10"
 hyper_serde = "0.7"
-image = "0.14"
+image = "0.16"
 ipc-channel = "0.8"
 lazy_static = "0.2"
 log = "0.3.5"
 msg = {path = "../msg"}
 num-traits = "0.1.32"
 serde = "1.0"
 servo_config = {path = "../config"}
 servo_url = {path = "../url"}
--- a/servo/components/script/Cargo.toml
+++ b/servo/components/script/Cargo.toml
@@ -43,17 +43,17 @@ euclid = "0.15"
 fnv = "1.0"
 gleam = "0.4"
 half = "1.0"
 heapsize = "0.4"
 heapsize_derive = "0.1"
 html5ever = {version = "0.20", features = ["heap_size"]}
 hyper = "0.10"
 hyper_serde = "0.7"
-image = "0.14"
+image = "0.16"
 ipc-channel = "0.8"
 js = {git = "https://github.com/servo/rust-mozjs", features = ["promises"]}
 jstraceable_derive = {path = "../jstraceable_derive"}
 lazy_static = "0.2"
 libc = "0.2"
 log = "0.3.5"
 metrics = {path = "../metrics"}
 mitochondria = "1.1.2"
--- a/servo/components/webdriver_server/Cargo.toml
+++ b/servo/components/webdriver_server/Cargo.toml
@@ -9,17 +9,17 @@ publish = false
 name = "webdriver_server"
 path = "lib.rs"
 
 [dependencies]
 base64 = "0.6"
 cookie = "0.6"
 euclid = "0.15"
 hyper = "0.10"
-image = "0.14"
+image = "0.16"
 ipc-channel = "0.8"
 log = "0.3.5"
 msg = {path = "../msg"}
 net_traits = {path = "../net_traits"}
 regex = "0.2"
 rustc-serialize = "0.3.4"
 script_traits = {path = "../script_traits"}
 servo_config = {path = "../config"}
--- a/servo/etc/ci/manifest_changed.sh
+++ b/servo/etc/ci/manifest_changed.sh
@@ -3,19 +3,23 @@
 # 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/.
 
 set -o errexit
 set -o nounset
 set -o pipefail
 
+echo "About to update manifest."
+
 # We shouldn't need any binary at all to update the manifests.
 # Adding "SKIP_TESTS" to skip tests, it doesn't really skip the tests.
 # It will run "run_wpt" with "'test_list': ['SKIP_TESTS']",
 # and then pass it into wptrunner, which won't be able to find any tests named
 # "SKIP_TESTS", and thus won't run any.
 # Adding "--binary=" to skip looking for a compiled servo binary.
-./mach test-wpt --manifest-update --binary= SKIP_TESTS > /dev/null
+./mach test-wpt --manifest-update --binary= SKIP_TESTS
+
+echo "Updated manifest; about to check if any changes were made to it."
 
 diff="$(git diff -- tests/*/MANIFEST.json)"
 echo "${diff}"
 [[ -z "${diff}" ]]
--- a/servo/ports/glutin/window.rs
+++ b/servo/ports/glutin/window.rs
@@ -34,16 +34,18 @@ use servo_url::ServoUrl;
 use std::cell::{Cell, RefCell};
 #[cfg(any(target_os = "linux", target_os = "macos"))]
 use std::ffi::CString;
 #[cfg(any(target_os = "linux", target_os = "macos"))]
 use std::mem;
 use std::os::raw::c_void;
 use std::ptr;
 use std::rc::Rc;
+use std::thread;
+use std::time;
 use style_traits::DevicePixel;
 use style_traits::cursor::Cursor;
 #[cfg(target_os = "windows")]
 use user32;
 use webrender_api::{DeviceUintRect, DeviceUintSize, ScrollLocation};
 #[cfg(target_os = "windows")]
 use winapi;
 
@@ -679,17 +681,23 @@ impl Window {
         // such as mouse click.
         if poll {
             match self.kind {
                 WindowKind::Window(ref window) => {
                     while let Some(event) = window.poll_events().next() {
                         close_event = self.handle_window_event(event) || close_event;
                     }
                 }
-                WindowKind::Headless(..) => {}
+                WindowKind::Headless(..) => {
+                    // Sleep the main thread to avoid using 100% CPU
+                    // This can be done better, see comments in #18777
+                    if events.is_empty() {
+                        thread::sleep(time::Duration::from_millis(5));
+                    }
+                }
             }
         } else {
             close_event = self.handle_next_event();
         }
 
         if close_event {
             events.push(WindowEvent::Quit)
         }
--- a/testing/marionette/driver.js
+++ b/testing/marionette/driver.js
@@ -42,17 +42,20 @@ Cu.import("chrome://marionette/content/e
 Cu.import("chrome://marionette/content/event.js");
 Cu.import("chrome://marionette/content/interaction.js");
 Cu.import("chrome://marionette/content/l10n.js");
 Cu.import("chrome://marionette/content/legacyaction.js");
 Cu.import("chrome://marionette/content/modal.js");
 Cu.import("chrome://marionette/content/proxy.js");
 Cu.import("chrome://marionette/content/reftest.js");
 Cu.import("chrome://marionette/content/session.js");
-const {wait, TimedPromise} = Cu.import("chrome://marionette/content/wait.js", {});
+const {
+  PollPromise,
+  TimedPromise,
+} = Cu.import("chrome://marionette/content/sync.js", {});
 
 Cu.importGlobalProperties(["URL"]);
 
 this.EXPORTED_SYMBOLS = ["GeckoDriver", "Context"];
 
 const FRAME_SCRIPT = "chrome://marionette/content/listener.js";
 const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
 
@@ -1483,30 +1486,30 @@ GeckoDriver.prototype.setWindowRect = as
       win.resizeTo(width, height);
     });
   }
 
   // Wait until window size has changed.  We can't wait for the
   // user-requested window size as this may not be achievable on the
   // current system.
   const windowResizeChange = async () => {
-    return wait.until((resolve, reject) => {
+    return new PollPromise((resolve, reject) => {
       let curRect = this.curBrowser.rect;
       if (curRect.width != origRect.width &&
           curRect.height != origRect.height) {
         resolve();
       } else {
         reject();
       }
     });
   };
 
   // Wait for the window position to change.
   async function windowPosition(x, y) {
-    return wait.until((resolve, reject) => {
+    return new PollPromise((resolve, reject) => {
       if ((x == win.screenX && y == win.screenY) ||
           (win.screenX != origRect.x || win.screenY != origRect.y)) {
         resolve();
       } else {
         reject();
       }
     });
   }
@@ -3044,17 +3047,17 @@ GeckoDriver.prototype.maximizeWindow = a
 
   const origSize = {
     outerWidth: win.outerWidth,
     outerHeight: win.outerHeight,
   };
 
   // Wait for the window size to change.
   async function windowSizeChange() {
-    return wait.until((resolve, reject) => {
+    return new PollPromise((resolve, reject) => {
       let curSize = {
         outerWidth: win.outerWidth,
         outerHeight: win.outerHeight,
       };
       if (curSize.outerWidth != origSize.outerWidth ||
           curSize.outerHeight != origSize.outerHeight) {
         resolve();
       } else {
--- a/testing/marionette/element.js
+++ b/testing/marionette/element.js
@@ -10,17 +10,17 @@ const {classes: Cc, interfaces: Ci, util
 Cu.import("chrome://marionette/content/assert.js");
 Cu.import("chrome://marionette/content/atom.js");
 const {
   InvalidSelectorError,
   NoSuchElementError,
   pprint,
   StaleElementReferenceError,
 } = Cu.import("chrome://marionette/content/error.js", {});
-Cu.import("chrome://marionette/content/wait.js");
+const {PollPromise} = Cu.import("chrome://marionette/content/sync.js", {});
 
 this.EXPORTED_SYMBOLS = ["element"];
 
 const XMLNS = "http://www.w3.org/1999/xhtml";
 const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
 
 const uuidGen = Cc["@mozilla.org/uuid-generator;1"]
     .getService(Ci.nsIUUIDGenerator);
@@ -233,35 +233,37 @@ element.Store = class {
  *     If <var>strategy</var> is unknown.
  * @throws InvalidSelectorError
  *     If <var>selector</var> is malformed.
  * @throws NoSuchElementError
  *     If a single element is requested, this error will throw if the
  *     element is not found.
  */
 element.find = function(container, strategy, selector, opts = {}) {
-  opts.all = !!opts.all;
-  opts.timeout = opts.timeout || 0;
+  let all = !!opts.all;
+  let timeout = opts.timeout || 0;
+  let startNode = opts.startNode;
 
   let searchFn;
   if (opts.all) {
     searchFn = findElements.bind(this);
   } else {
     searchFn = findElement.bind(this);
   }
 
   return new Promise((resolve, reject) => {
-    let findElements = wait.until((resolve, reject) => {
-      let res = find_(container, strategy, selector, searchFn, opts);
+    let findElements = new PollPromise((resolve, reject) => {
+      let res = find_(container, strategy, selector, searchFn,
+          {all, startNode});
       if (res.length > 0) {
         resolve(Array.from(res));
       } else {
         reject([]);
       }
-    }, opts.timeout);
+    }, {timeout});
 
     findElements.then(foundEls => {
       // the following code ought to be moved into findElement
       // and findElements when bug 1254486 is addressed
       if (!opts.all && (!foundEls || foundEls.length == 0)) {
         let msg;
         switch (strategy) {
           case element.Strategy.AnonAttribute:
@@ -279,23 +281,21 @@ element.find = function(container, strat
       if (opts.all) {
         resolve(foundEls);
       }
       resolve(foundEls[0]);
     }, reject);
   });
 };
 
-function find_(container, strategy, selector, searchFn, opts) {
+function find_(container, strategy, selector, searchFn,
+    {startNode = null, all = false} = {}) {
   let rootNode = container.shadowRoot || container.frame.document;
-  let startNode;
 
-  if (opts.startNode) {
-    startNode = opts.startNode;
-  } else {
+  if (!startNode) {
     switch (strategy) {
       // For anonymous nodes the start node needs to be of type
       // DOMElement, which will refer to :root in case of a DOMDocument.
       case element.Strategy.Anon:
       case element.Strategy.AnonAttribute:
         if (rootNode instanceof Ci.nsIDOMDocument) {
           startNode = rootNode.documentElement;
         }
@@ -310,17 +310,17 @@ function find_(container, strategy, sele
   try {
     res = searchFn(strategy, selector, rootNode, startNode);
   } catch (e) {
     throw new InvalidSelectorError(
         `Given ${strategy} expression "${selector}" is invalid: ${e}`);
   }
 
   if (res) {
-    if (opts.all) {
+    if (all) {
       return res;
     }
     return [res];
   }
   return [];
 }
 
 /**
--- a/testing/marionette/jar.mn
+++ b/testing/marionette/jar.mn
@@ -12,17 +12,17 @@ marionette.jar:
   content/interaction.js (interaction.js)
   content/accessibility.js (accessibility.js)
   content/listener.js (listener.js)
   content/element.js (element.js)
   content/frame.js (frame.js)
   content/cert.js (cert.js)
   content/event.js  (event.js)
   content/error.js (error.js)
-  content/wait.js (wait.js)
+  content/sync.js (sync.js)
   content/message.js (message.js)
   content/modal.js (modal.js)
   content/proxy.js (proxy.js)
   content/capture.js (capture.js)
   content/cookie.js (cookie.js)
   content/atom.js (atom.js)
   content/evaluate.js (evaluate.js)
   content/navigate.js (navigate.js)
rename from testing/marionette/wait.js
rename to testing/marionette/sync.js
--- a/testing/marionette/wait.js
+++ b/testing/marionette/sync.js
@@ -6,25 +6,18 @@
 
 const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
 
 const {
   error,
   TimeoutError,
 } = Cu.import("chrome://marionette/content/error.js", {});
 
-/* exported TimedPromise */
-this.EXPORTED_SYMBOLS = ["wait", "TimedPromise"];
-
-/**
- * Poll-waiting utilities.
- *
- * @namespace
- */
-this.wait = {};
+/* exported PollPromise, TimedPromise */
+this.EXPORTED_SYMBOLS = ["PollPromise", "TimedPromise"];
 
 const {TYPE_ONE_SHOT, TYPE_REPEATING_SLACK} = Ci.nsITimer;
 
 /**
  * @callback Condition
  *
  * @param {function(*)} resolve
  *     To be called when the condition has been met.  Will return the
@@ -34,63 +27,67 @@ const {TYPE_ONE_SHOT, TYPE_REPEATING_SLA
  *     the condition to be revaluated or time out.
  *
  * @return {*}
  *     The value from calling <code>resolve</code>.
  */
 
 /**
  * Runs a promise-like function off the main thread until it is resolved
- * through |resolve| or |rejected| callbacks.  The function is guaranteed
- * to be run at least once, irregardless of the timeout.
+ * through <code>resolve</code> or <code>rejected</code> callbacks.
+ * The function is guaranteed to be run at least once, irregardless of
+ * the timeout.
  *
- * The |func| is evaluated every |interval| for as long as its runtime
- * duration does not exceed |interval|.  Evaluations occur sequentially,
- * meaning that evaluations of |func| are queued if the runtime evaluation
- * duration of |func| is greater than |interval|.
+ * The <var>func</var> is evaluated every <var>interval</var> for as
+ * long as its runtime duration does not exceed <var>interval</var>.
+ * Evaluations occur sequentially, meaning that evaluations of
+ * <var>func</var> are queued if the runtime evaluation duration of
+ * <var>func</var> is greater than <var>interval</var>.
  *
- * |func| is given two arguments, |resolve| and |reject|, of which one
- * must be called for the evaluation to complete.  Calling |resolve| with
- * an argument indicates that the expected wait condition was met and
- * will return the passed value to the caller.  Conversely, calling
- * |reject| will evaluate |func| again until the |timeout| duration has
- * elapsed or |func| throws.  The passed value to |reject| will also be
+ * <var>func</var> is given two arguments, <code>resolve</code> and
+ * <code>reject</code>, of which one must be called for the evaluation
+ * to complete.  Calling <code>resolve</code> with an argument
+ * indicates that the expected wait condition was met and will return
+ * the passed value to the caller.  Conversely, calling
+ * <code>reject</code> will evaluate <var>func</var> again until
+ * the <var>timeout</var> duration has elapsed or <var>func</var>
+ * throws.  The passed value to <code>reject</code> will also be
  * returned to the caller once the wait has expired.
  *
  * Usage:
  *
  * <pre><code>
- *     let els = wait.until((resolve, reject) => {
+ *     let els = new PollPromise((resolve, reject) => {
  *       let res = document.querySelectorAll("p");
  *       if (res.length > 0) {
  *         resolve(Array.from(res));
  *       } else {
  *         reject([]);
  *       }
  *     });
  * </pre></code>
  *
  * @param {Condition} func
  *     Function to run off the main thread.
- * @param {number=} timeout
- *     Desired timeout.  If 0 or less than the runtime evaluation time
- *     of |func|, |func| is guaranteed to run at least once.  The default
- *     is 2000 milliseconds.
- * @param {number=} interval
- *     Duration between each poll of |func| in milliseconds.  Defaults to
- *     10 milliseconds.
+ * @param {number=} [timeout=2000] timeout
+ *     Desired timeout.  If 0 or less than the runtime evaluation
+ *     time of <var>func</var>, <var>func</var> is guaranteed to run
+ *     at least once.  The default is 2000 milliseconds.
+ * @param {number=} [interval=10] interval
+ *     Duration between each poll of <var>func</var> in milliseconds.
+ *     Defaults to 10 milliseconds.
  *
  * @return {Promise.<*>}
- *     Yields the value passed to |func|'s |resolve| or |reject|
- *     callbacks.
+ *     Yields the value passed to <var>func</var>'s
+ *     <code>resolve</code> or <code>reject</code> callbacks.
  *
  * @throws {*}
- *     If |func| throws, its error is propagated.
+ *     If <var>func</var> throws, its error is propagated.
  */
-wait.until = function(func, timeout = 2000, interval = 10) {
+function PollPromise(func, {timeout = 2000, interval = 10} = {}) {
   const timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
 
   return new Promise((resolve, reject) => {
     const start = new Date().getTime();
     const end = start + timeout;
 
     let evalFn = () => {
       new Promise(func).then(resolve, rejected => {
@@ -114,17 +111,17 @@ wait.until = function(func, timeout = 20
 
   }).then(res => {
     timer.cancel();
     return res;
   }, err => {
     timer.cancel();
     throw err;
   });
-};
+}
 
 /**
  * The <code>TimedPromise</code> object represents the timed, eventual
  * completion (or failure) of an asynchronous operation, and its
  * resulting value.
  *
  * In contrast to a regular {@link Promise}, it times out after
  * <var>timeout</var>.
new file mode 100644
--- /dev/null
+++ b/testing/marionette/test_sync.js
@@ -0,0 +1,76 @@
+/* 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/. */
+
+const {utils: Cu} = Components;
+
+const {PollPromise} = Cu.import("chrome://marionette/content/sync.js", {});
+
+const DEFAULT_TIMEOUT = 2000;
+
+add_task(async function test_PollPromise_types() {
+  for (let typ of [true, false, "foo", 42, [], {}]) {
+    strictEqual(typ, await new PollPromise(resolve => resolve(typ)));
+  }
+});
+
+add_task(async function test_PollPromise_timeoutElapse() {
+  let nevals = 0;
+  let start = new Date().getTime();
+  await new PollPromise((resolve, reject) => {
+    ++nevals;
+    reject();
+  });
+  let end = new Date().getTime();
+  greaterOrEqual((end - start), DEFAULT_TIMEOUT);
+  greaterOrEqual(nevals, 15);
+});
+
+add_task(async function test_PollPromise_rethrowError() {
+  let nevals = 0;
+  let err;
+  try {
+    await PollPromise(() => {
+      ++nevals;
+      throw new Error();
+    });
+  } catch (e) {
+    err = e;
+  }
+  equal(1, nevals);
+  ok(err instanceof Error);
+});
+
+add_task(async function test_PollPromise_noTimeout() {
+  // run at least once when timeout is 0
+  let nevals = 0;
+  let start = new Date().getTime();
+  await new PollPromise((resolve, reject) => {
+    ++nevals;
+    reject();
+  }, {timeout: 0});
+  let end = new Date().getTime();
+  equal(1, nevals);
+  less((end - start), DEFAULT_TIMEOUT);
+});
+
+add_task(async function test_PollPromise_timeout() {
+  let nevals = 0;
+  let start = new Date().getTime();
+  await new PollPromise((resolve, reject) => {
+    ++nevals;
+    reject();
+  }, {timeout: 100});
+  let end = new Date().getTime();
+  greater(nevals, 1);
+  greaterOrEqual((end - start), 100);
+});
+
+add_task(async function test_PollPromise_interval() {
+  let nevals = 0;
+  await new PollPromise((resolve, reject) => {
+    ++nevals;
+    reject();
+  }, {timeout: 100, interval: 100});
+  equal(2, nevals);
+});
deleted file mode 100644
--- a/testing/marionette/test_wait.js
+++ /dev/null
@@ -1,74 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-const {utils: Cu} = Components;
-
-Cu.import("chrome://marionette/content/wait.js");
-
-add_task(async function test_until_types() {
-  for (let typ of [true, false, "foo", 42, [], {}]) {
-    strictEqual(typ, await wait.until(resolve => resolve(typ)));
-  }
-});
-
-add_task(async function test_until_timeoutElapse() {
-  let nevals = 0;
-  let start = new Date().getTime();
-  await wait.until((resolve, reject) => {
-    ++nevals;
-    reject();
-  });
-  let end = new Date().getTime();
-  greaterOrEqual((end - start), 2000);
-  greaterOrEqual(nevals, 15);
-});
-
-add_task(async function test_until_rethrowError() {
-  let nevals = 0;
-  let err;
-  try {
-    await wait.until(() => {
-      ++nevals;
-      throw new Error();
-    });
-  } catch (e) {
-    err = e;
-  }
-  equal(1, nevals);
-  ok(err instanceof Error);
-});
-
-add_task(async function test_until_noTimeout() {
-  // run at least once when timeout is 0
-  let nevals = 0;
-  let start = new Date().getTime();
-  await wait.until((resolve, reject) => {
-    ++nevals;
-    reject();
-  }, 0);
-  let end = new Date().getTime();
-  equal(1, nevals);
-  less((end - start), 2000);
-});
-
-add_task(async function test_until_timeout() {
-  let nevals = 0;
-  let start = new Date().getTime();
-  await wait.until((resolve, reject) => {
-    ++nevals;
-    reject();
-  }, 100);
-  let end = new Date().getTime();
-  greater(nevals, 1);
-  greaterOrEqual((end - start), 100);
-});
-
-add_task(async function test_until_interval() {
-  let nevals = 0;
-  await wait.until((resolve, reject) => {
-    ++nevals;
-    reject();
-  }, 100, 100);
-  equal(2, nevals);
-});
--- a/testing/marionette/unit.ini
+++ b/testing/marionette/unit.ini
@@ -11,9 +11,9 @@ skip-if = appname == "thunderbird"
 [test_assert.js]
 [test_cookie.js]
 [test_dom.js]
 [test_element.js]
 [test_error.js]
 [test_message.js]
 [test_navigate.js]
 [test_session.js]
-[test_wait.js]
+[test_sync.js]
--- a/toolkit/components/addoncompat/RemoteAddonsParent.jsm
+++ b/toolkit/components/addoncompat/RemoteAddonsParent.jsm
@@ -433,20 +433,25 @@ var EventTargetParent = {
 
     if (target instanceof Ci.nsIDOMXULElement) {
       if (target.localName == "browser") {
         return target;
       } else if (target.localName == "tab") {
         return target.linkedBrowser;
       }
 
-      // Check if |target| is somewhere on the patch from the
+      // Check if |target| is somewhere on the path from the
       // <tabbrowser> up to the root element.
       let window = target.ownerGlobal;
-      if (window && target.contains(window.gBrowser)) {
+
+      // Some non-browser windows define gBrowser globals which are not elements
+      // and can't be passed to target.contains().
+      if (window &&
+          window.gBrowser instanceof Ci.nsIDOMXULElement &&
+          target.contains(window.gBrowser)) {
         return window;
       }
     }
 
     return null;
   },
 
   // When a given event fires in the child, we fire it on the
--- a/toolkit/components/typeaheadfind/nsITypeAheadFind.idl
+++ b/toolkit/components/typeaheadfind/nsITypeAheadFind.idl
@@ -52,19 +52,22 @@ interface nsITypeAheadFind : nsISupports
    * the selection. */
   void setSelectionModeAndRepaint(in short toggle);
 
   /* Collapse the "found match" selection to its start.  Because not all
    * matches are owned by the same selection controller, this doesn't
    * necessarily happen automatically. */
   void collapseSelection();
 
-  /* Check if a range is visible */
+  /* Check if a range is visible using heuristics */
   boolean isRangeVisible(in nsIDOMRange aRange, in boolean aMustBeInViewPort);
 
+  /* Check if a range is actually rendered (out of viewport always false) */
+  boolean isRangeRendered(in nsIDOMRange aRange);
+
   /******************************* Attributes ******************************/
 
   readonly attribute AString searchString;
                                         // Most recent search string
   attribute boolean caseSensitive;      // Searches are case sensitive
   attribute boolean entireWord;         // Search for whole words only
   readonly attribute nsIDOMElement foundLink;
                                         // Most recent elem found, if a link
--- a/toolkit/components/typeaheadfind/nsTypeAheadFind.cpp
+++ b/toolkit/components/typeaheadfind/nsTypeAheadFind.cpp
@@ -1213,32 +1213,32 @@ nsTypeAheadFind::IsRangeVisible(nsIPresS
   nsCOMPtr<nsIDOMNode> node;
   aRange->GetStartContainer(getter_AddRefs(node));
 
   nsCOMPtr<nsIContent> content(do_QueryInterface(node));
   if (!content)
     return false;
 
   nsIFrame *frame = content->GetPrimaryFrame();
-  if (!frame)
+  if (!frame) {
     return false;  // No frame! Not visible then.
+  }
 
-  if (!frame->StyleVisibility()->IsVisible())
+  if (!frame->StyleVisibility()->IsVisible()) {
     return false;
+  }
 
   // Detect if we are _inside_ a text control, or something else with its own
   // selection controller.
   if (aUsesIndependentSelection) {
     *aUsesIndependentSelection =
       (frame->GetStateBits() & NS_FRAME_INDEPENDENT_SELECTION);
   }
 
   // ---- We have a frame ----
-  if (!aMustBeInViewPort)
-    return true; //  Don't need it to be on screen, just in rendering tree
 
   // Get the next in flow frame that contains the range start
   int32_t startFrameOffset, endFrameOffset;
   uint32_t startRangeOffset;
   aRange->GetStartOffset(&startRangeOffset);
   while (true) {
     frame->GetOffsets(startFrameOffset, endFrameOffset);
     if (static_cast<int32_t>(startRangeOffset) < endFrameOffset) {
@@ -1264,37 +1264,48 @@ nsTypeAheadFind::IsRangeVisible(nsIPresS
 
   if (!aGetTopVisibleLeaf && !frame->GetRect().IsEmpty()) {
     rectVisibility =
       aPresShell->GetRectVisibility(frame,
                                     nsRect(nsPoint(0,0), frame->GetSize()),
                                     minDistance);
 
     if (rectVisibility != nsRectVisibility_kAboveViewport) {
-      return true;
+      // This is an early exit case, where we return true iff the range
+      // is actually rendered.
+      return IsRangeRendered(aPresShell, aPresContext, aRange);
     }
   }
 
-  // We know that the target range isn't usable because it's not in the
-  // view port. Move range forward to first visible point,
+  // Below this point, we know the range is not in the viewport.
+
+  if (!aMustBeInViewPort) {
+    // This is an early exit case because we don't care that that range
+    // is out of viewport, so we return that the range is "visible".
+    return true;
+  }
+
+  // The range isn't in the viewport, but we could scroll it into view.
+  // Move range forward to first visible point,
   // this speeds us up a lot in long documents
   nsCOMPtr<nsIFrameEnumerator> frameTraversal;
   nsCOMPtr<nsIFrameTraversal> trav(do_CreateInstance(kFrameTraversalCID));
   if (trav)
     trav->NewFrameTraversal(getter_AddRefs(frameTraversal),
                             aPresContext, frame,
                             eLeaf,
                             false, // aVisual
                             false, // aLockInScrollView
                             false, // aFollowOOFs
                             false  // aSkipPopupChecks
                             );
 
-  if (!frameTraversal)
+  if (!frameTraversal) {
     return false;
+  }
 
   while (rectVisibility == nsRectVisibility_kAboveViewport) {
     frameTraversal->Next();
     frame = frameTraversal->CurrentItem();
     if (!frame)
       return false;
 
     if (!frame->GetRect().IsEmpty()) {
@@ -1313,16 +1324,96 @@ nsTypeAheadFind::IsRangeVisible(nsIPresS
       (*aFirstVisibleRange)->SetStart(firstVisibleNode, startFrameOffset);
       (*aFirstVisibleRange)->SetEnd(firstVisibleNode, endFrameOffset);
     }
   }
 
   return false;
 }
 
+NS_IMETHODIMP
+nsTypeAheadFind::IsRangeRendered(nsIDOMRange *aRange,
+                                bool *aResult)
+{
+  // Jump through hoops to extract the docShell from the range.
+  nsCOMPtr<nsIDOMNode> node;
+  aRange->GetStartContainer(getter_AddRefs(node));
+  nsCOMPtr<nsIDOMDocument> document;
+  node->GetOwnerDocument(getter_AddRefs(document));
+  nsCOMPtr<mozIDOMWindowProxy> window;
+  document->GetDefaultView(getter_AddRefs(window));
+  nsCOMPtr<nsIWebNavigation> navNav (do_GetInterface(window));
+  nsCOMPtr<nsIDocShell> docShell (do_GetInterface(navNav));
+
+  // Set up the arguments needed to check if a range is visible.
+  nsCOMPtr<nsIPresShell> presShell (docShell->GetPresShell());
+  RefPtr<nsPresContext> presContext = presShell->GetPresContext();
+  *aResult = IsRangeRendered(presShell, presContext, aRange);
+  return NS_OK;
+}
+
+bool
+nsTypeAheadFind::IsRangeRendered(nsIPresShell *aPresShell,
+                                 nsPresContext *aPresContext,
+                                 nsIDOMRange *aRange)
+{
+  NS_ASSERTION(aPresShell && aPresContext && aRange,
+               "params are invalid");
+
+  nsCOMPtr<nsIDOMNode> node;
+  aRange->GetCommonAncestorContainer(getter_AddRefs(node));
+
+  nsCOMPtr<nsIContent> content(do_QueryInterface(node));
+  if (!content) {
+    return false;
+  }
+
+  nsIFrame *frame = content->GetPrimaryFrame();
+  if (!frame) {
+    return false;  // No frame! Not visible then.
+  }
+
+  if (!frame->StyleVisibility()->IsVisible()) {
+    return false;
+  }
+
+  // Having a primary frame doesn't mean that the range is visible inside the
+  // viewport. Do a hit-test to determine that quickly and properly.
+  AutoTArray<nsIFrame*,8> frames;
+  nsIFrame *rootFrame = aPresShell->GetRootFrame();
+  RefPtr<nsRange> range = static_cast<nsRange*>(aRange);
+  RefPtr<mozilla::dom::DOMRectList> rects = range->GetClientRects(true, true);
+  for (uint32_t i = 0; i < rects->Length(); ++i) {
+    RefPtr<mozilla::dom::DOMRect> rect = rects->Item(i);
+    nsRect r(nsPresContext::CSSPixelsToAppUnits((float)rect->X()),
+             nsPresContext::CSSPixelsToAppUnits((float)rect->Y()),
+             nsPresContext::CSSPixelsToAppUnits((float)rect->Width()),
+             nsPresContext::CSSPixelsToAppUnits((float)rect->Height()));
+    // Append visible frames to frames array.
+    nsLayoutUtils::GetFramesForArea(rootFrame, r, frames,
+      nsLayoutUtils::IGNORE_PAINT_SUPPRESSION |
+      nsLayoutUtils::IGNORE_ROOT_SCROLL_FRAME |
+      nsLayoutUtils::ONLY_VISIBLE);
+
+    // See if any of the frames contain the content. If they do, then the range
+    // is visible. We search for the content rather than the original frame,
+    // because nsTextContinuation frames might be returned instead of the
+    // original frame.
+    for (const auto &f: frames) {
+      if (f->GetContent() == content) {
+        return true;
+      }
+    }
+
+    frames.ClearAndRetainStorage();
+  }
+
+  return false;
+}
+
 already_AddRefed<nsIPresShell>
 nsTypeAheadFind::GetPresShell()
 {
   if (!mPresShell)
     return nullptr;
 
   nsCOMPtr<nsIPresShell> shell = do_QueryReferent(mPresShell);
   if (shell) {
--- a/toolkit/components/typeaheadfind/nsTypeAheadFind.h
+++ b/toolkit/components/typeaheadfind/nsTypeAheadFind.h
@@ -55,16 +55,18 @@ protected:
   void GetSelection(nsIPresShell *aPresShell, nsISelectionController **aSelCon,
                     nsISelection **aDomSel);
   // *aNewRange may not be collapsed.  If you want to collapse it in a
   // particular way, you need to do it yourself.
   bool IsRangeVisible(nsIPresShell *aPresShell, nsPresContext *aPresContext,
                         nsIDOMRange *aRange, bool aMustBeVisible,
                         bool aGetTopVisibleLeaf, nsIDOMRange **aNewRange,
                         bool *aUsesIndependentSelection);
+  bool IsRangeRendered(nsIPresShell *aPresShell, nsPresContext *aPresContext,
+                          nsIDOMRange *aRange);
   nsresult FindItNow(nsIPresShell *aPresShell, bool aIsLinksOnly,
                      bool aIsFirstVisiblePreferred, bool aFindPrev,
                      uint16_t* aResult);
   nsresult GetSearchContainers(nsISupports *aContainer,
                                nsISelectionController *aSelectionController,
                                bool aIsFirstVisiblePreferred,
                                bool aFindPrev, nsIPresShell **aPresShell,
                                nsPresContext **aPresContext);
--- a/toolkit/modules/FinderHighlighter.jsm
+++ b/toolkit/modules/FinderHighlighter.jsm
@@ -1124,16 +1124,19 @@ FinderHighlighter.prototype = {
     if (paintContent || dict.modalHighlightAllMask) {
       // No need to update dynamic ranges separately when we already about to
       // update all of them anyway.
       if (!dict.updateAllRanges)
         this._updateDynamicRangesRects(dict);
 
       let DOMRect = window.DOMRect;
       for (let [range, rectsAndTexts] of dict.modalHighlightRectsMap) {
+        if (!this.finder._fastFind.isRangeVisible(range, false))
+          continue;
+
         if (dict.updateAllRanges)
           rectsAndTexts = this._updateRangeRects(range);
 
         // If a geometry change was detected, we bail out right away here, because
         // the current set of ranges has been invalidated.
         if (dict.detectedGeometryChange)
           return;
 
--- a/toolkit/modules/FinderIterator.jsm
+++ b/toolkit/modules/FinderIterator.jsm
@@ -8,16 +8,17 @@ this.EXPORTED_SYMBOLS = ["FinderIterator
 
 const { interfaces: Ci, classes: Cc, utils: Cu } = Components;
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/Timer.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "NLP", "resource://gre/modules/NLP.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "Rect", "resource://gre/modules/Geometry.jsm");
 
 const kDebug = false;
 const kIterationSizeMax = 100;
 const kTimeoutPref = "findbar.iteratorTimeout";
 
 /**
  * FinderIterator singleton. See the documentation for the `start()` method to
  * learn more.
@@ -574,27 +575,23 @@ this.FinderIterator = {
    */
   _collectFrames(window, finder) {
     let frames = [];
     if (!("frames" in window) || !window.frames.length)
       return frames;
 
     // Casting `window.frames` to an Iterator doesn't work, so we're stuck with
     // a plain, old for-loop.
+    let dwu = window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
     for (let i = 0, l = window.frames.length; i < l; ++i) {
       let frame = window.frames[i];
-      // Don't count matches in hidden frames.
+      // Don't count matches in hidden frames; get the frame element rect and
+      // check if it's empty. We shan't flush!
       let frameEl = frame && frame.frameElement;
-      if (!frameEl)
-        continue;
-      // Construct a range around the frame element to check its visiblity.
-      let range = window.document.createRange();
-      range.setStart(frameEl, 0);
-      range.setEnd(frameEl, 0);
-      if (!finder._fastFind.isRangeVisible(range, this._getDocShell(range), true))
+      if (!frameEl || Rect.fromRect(dwu.getBoundsWithoutFlushing(frameEl)).isEmpty())
         continue;
       // All conditions pass, so push the current frame and its children on the
       // stack.
       frames.push(frame, ...this._collectFrames(frame, finder));
     }
 
     return frames;
   },
--- a/toolkit/mozapps/extensions/content/extensions.js
+++ b/toolkit/mozapps/extensions/content/extensions.js
@@ -1,17 +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/. */
 
 "use strict";
 
 /* import-globals-from ../../../content/contentAreaUtils.js */
 /* globals XMLStylesheetProcessingInstruction */
-/* exported UPDATES_RELEASENOTES_TRANSFORMFILE, XMLURI_PARSE_ERROR, loadView */
+/* exported UPDATES_RELEASENOTES_TRANSFORMFILE, XMLURI_PARSE_ERROR, loadView, gBrowser */
 
 var Cc = Components.classes;
 var Ci = Components.interfaces;
 var Cu = Components.utils;
 var Cr = Components.results;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
@@ -3646,25 +3646,25 @@ var gDetailView = {
 
     var rows = document.getElementById("detail-downloads").parentNode;
 
     try {
       if (this._addon.optionsType == AddonManager.OPTIONS_TYPE_INLINE_BROWSER) {
         whenViewLoaded(async () => {
           await this._addon.startupPromise;
 
-          let browser = await this.createOptionsBrowser(rows);
+          const browserContainer = await this.createOptionsBrowser(rows);
 
           // Make sure the browser is unloaded as soon as we change views,
           // rather than waiting for the next detail view to load.
           document.addEventListener("ViewChanged", function() {
-            browser.remove();
+            browserContainer.remove();
           }, {once: true});
 
-          finish(browser);
+          finish(browserContainer);
         });
 
         if (aCallback)
           aCallback();
       } else {
         var xhr = new XMLHttpRequest();
         xhr.open("GET", this._addon.optionsURL, true);
         xhr.responseType = "xml";
@@ -3729,16 +3729,19 @@ var gDetailView = {
       let detailViewBoxObject = gDetailView.node.boxObject;
       top -= detailViewBoxObject.y;
 
       detailViewBoxObject.scrollTo(0, top);
     }
   },
 
   async createOptionsBrowser(parentNode) {
+    let stack = document.createElement("stack");
+    stack.setAttribute("id", "addon-options-prompts-stack");
+
     let browser = document.createElement("browser");
     browser.setAttribute("type", "content");
     browser.setAttribute("disableglobalhistory", "true");
     browser.setAttribute("id", "addon-options");
     browser.setAttribute("class", "inline-options-browser");
     browser.setAttribute("transparent", "true");
     browser.setAttribute("forcemessagemanager", "true");
     browser.setAttribute("selectmenulist", "ContentSelectDropdown");
@@ -3757,31 +3760,32 @@ var gDetailView = {
     if (remote) {
       browser.setAttribute("remote", "true");
       browser.setAttribute("remoteType", E10SUtils.EXTENSION_REMOTE_TYPE);
       readyPromise = promiseEvent("XULFrameLoaderCreated", browser);
     } else {
       readyPromise = promiseEvent("load", browser, true);
     }
 
-    parentNode.appendChild(browser);
+    stack.appendChild(browser);
+    parentNode.appendChild(stack);
 
     // Force bindings to apply synchronously.
     browser.clientTop;
 
     await readyPromise;
     ExtensionParent.apiManager.emit("extension-browser-inserted", browser);
 
     return new Promise(resolve => {
       let messageListener = {
         receiveMessage({name, data}) {
           if (name === "Extension:BrowserResized")
             browser.style.height = `${data.height}px`;
           else if (name === "Extension:BrowserContentLoaded")
-            resolve(browser);
+            resolve(stack);
         },
       };
 
       let mm = browser.messageManager;
       mm.loadFrameScript("chrome://extensions/content/ext-browser-content.js",
                          false);
       mm.addMessageListener("Extension:BrowserContentLoaded", messageListener);
       mm.addMessageListener("Extension:BrowserResized", messageListener);
@@ -4127,8 +4131,23 @@ var gDragDrop = {
           AddonManager.installAddonFromAOM(browser, document.documentURIObject, install);
         }, "application/x-xpinstall");
       }
     }
 
     aEvent.preventDefault();
   }
 };
+
+// Stub tabbrowser implementation for use by the tab-modal alert code
+// when an alert/prompt/confirm method is called in a WebExtensions options_ui page
+// (See Bug 1385548 for rationale).
+var gBrowser = {
+  getTabModalPromptBox(browser) {
+    const parentWindow = document.docShell.chromeEventHandler.ownerGlobal;
+
+    if (parentWindow.gBrowser) {
+      return parentWindow.gBrowser.getTabModalPromptBox(browser);
+    }
+
+    return null;
+  }
+};
--- a/toolkit/mozapps/extensions/test/browser/browser_inlinesettings_browser.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_inlinesettings_browser.js
@@ -91,27 +91,29 @@ async function openDetailsBrowser(addonI
   await TestUtils.topicObserved(AddonManager.OPTIONS_NOTIFICATION_DISPLAYED,
                                 (subject, data) => data == addonId);
 
   is(gManagerWindow.gViewController.currentViewId,
      `addons://detail/${encodeURIComponent(addonId)}/preferences`,
      "Current view should scroll to preferences");
 
   var browser = gManagerWindow.document.querySelector(
-    "#detail-grid > rows > .inline-options-browser");
-  var rows = browser.parentNode;
+    "#detail-grid > rows > stack > .inline-options-browser");
+  var rows = browser.parentNode.parentNode;
 
   let url = await ContentTask.spawn(browser, {}, () => content.location.href);
 
-  ok(browser, "Grid should have a browser child");
-  is(browser.localName, "browser", "Grid should have a browser child");
+  ok(browser, "Grid should have a browser descendant");
+  is(browser.localName, "browser", "Grid should have a browser descendant");
   is(url, addon.mAddon.optionsURL, "Browser has the expected options URL loaded")
 
+  is(browser.clientWidth, browser.parentNode.clientWidth,
+     "Browser should be the same width as its direct parent");
   is(browser.clientWidth, rows.clientWidth,
-     "Browser should be the same width as its parent node");
+     "Browser should be the same width as its rows ancestor");
 
   button = gManagerWindow.document.getElementById("detail-prefs-btn");
   is_element_hidden(button, "Preferences button should not be visible");
 
   return browser;
 }
 
 
--- a/toolkit/mozapps/extensions/test/browser/browser_webext_options.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_webext_options.js
@@ -25,27 +25,29 @@ async function runTest(installer) {
 
   await TestUtils.topicObserved(AddonManager.OPTIONS_NOTIFICATION_DISPLAYED,
                                 (subject, data) => data == id);
 
   is(mgrWindow.gViewController.currentViewId,
      `addons://detail/${encodeURIComponent(id)}/preferences`,
      "Current view should scroll to preferences");
 
-  var browser = mgrWindow.document.querySelector("#detail-grid > rows > .inline-options-browser");
+  var browser = mgrWindow.document.querySelector("#detail-grid > rows > stack > .inline-options-browser");
   var rows = browser.parentNode;
 
   let url = await ContentTask.spawn(browser, {}, () => content.location.href);
 
-  ok(browser, "Grid should have a browser child");
-  is(browser.localName, "browser", "Grid should have a browser child");
+  ok(browser, "Grid should have a browser descendant");
+  is(browser.localName, "browser", "Grid should have a browser descendant");
   is(url, element.mAddon.optionsURL, "Browser has the expected options URL loaded")
 
+  is(browser.clientWidth, browser.parentNode.clientWidth,
+     "Browser should be the same width as its direct parent");
   is(browser.clientWidth, rows.clientWidth,
-     "Browser should be the same width as its parent node");
+     "Browser should be the same width as its rows ancestor");
 
   button = mgrWindow.document.getElementById("detail-prefs-btn");
   is_element_hidden(button, "Preferences button should not be visible");
 
   await close_manager(mgrWindow);
 
   addon.uninstall();
 }