Merge mozilla-central to mozilla-inbound r=merge
authorDorel Luca <dluca@mozilla.com>
Tue, 16 Jan 2018 06:09:12 +0200
changeset 399375 8aec32412f04950fd53d81e8dc4a15d657f59378
parent 399317 1f1f863ea198cd04e1a90af2be6d953e0f5502ad (current diff)
parent 399374 a3887394965f161d011eebc74e8987a653366e4b (diff)
child 399376 c4c4ce0c895b129717af8fa9042af6bc50b43740
child 399399 e4107773cffb1baefd5446666fce22c4d6eb0517
push id98941
push userdluca@mozilla.com
push dateTue, 16 Jan 2018 04:09:40 +0000
treeherdermozilla-inbound@8aec32412f04 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone59.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge mozilla-central to mozilla-inbound r=merge
mobile/android/app/src/main/res/values-v13/search_styles.xml
mobile/android/app/src/main/res/values-v16/search_styles.xml
mobile/android/base/geckoview.ddf
mobile/android/base/java/org/mozilla/gecko/db/PerProfileDatabaseProvider.java
mobile/android/base/java/org/mozilla/gecko/home/HomeExpandableListView.java
mobile/android/base/resources/values-v17/themes.xml
mobile/android/build/classycle/LICENSE.txt
mobile/android/build/classycle/classycle-1.4.1.jar
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -98,16 +98,19 @@
 #endif
 #endif
 #ifdef MOZ_ICU_DATA_ARCHIVE
 @RESPATH@/@ICU_DATA_FILE@
 #endif
 #ifdef MOZ_GTK3
 @BINPATH@/@DLL_PREFIX@mozgtk@DLL_SUFFIX@
 @BINPATH@/gtk2/@DLL_PREFIX@mozgtk@DLL_SUFFIX@
+#ifdef MOZ_WAYLAND
+@BINPATH@/@DLL_PREFIX@mozwayland@DLL_SUFFIX@
+#endif
 #endif
 
 ; We don't have a complete view of which dlls to expect when doing an artifact
 ; build because we haven't run all of configure, so we trust what's in
 ; dist/bin, because everything there was extracted from our original build's
 ; package.
 #if defined(MOZ_ARTIFACT_BUILDS) && defined(XP_WIN)
 @BINPATH@/*.dll
--- a/build.gradle
+++ b/build.gradle
@@ -11,17 +11,16 @@ def tryInt = { string ->
 allprojects {
     // Expose the per-object-directory configuration to all projects.
     ext {
         mozconfig = gradle.mozconfig
         topsrcdir = gradle.mozconfig.topsrcdir
         topobjdir = gradle.mozconfig.topobjdir
 
         compileSdkVersion = tryInt(mozconfig.substs.ANDROID_COMPILE_SDK_VERSION)
-        buildToolsVersion = tryInt(mozconfig.substs.ANDROID_BUILD_TOOLS_VERSION)
         targetSdkVersion = tryInt(mozconfig.substs.ANDROID_TARGET_SDK)
         minSdkVersion = tryInt(mozconfig.substs.MOZ_ANDROID_MIN_SDK_VERSION)
         manifestPlaceholders = [
             ANDROID_PACKAGE_NAME: mozconfig.substs.ANDROID_PACKAGE_NAME,
             ANDROID_TARGET_SDK: mozconfig.substs.ANDROID_TARGET_SDK,
             MOZ_ANDROID_MIN_SDK_VERSION: mozconfig.substs.MOZ_ANDROID_MIN_SDK_VERSION,
             MOZ_ANDROID_SHARED_ID: "${mozconfig.substs.ANDROID_PACKAGE_NAME}.sharedID",
         ]
@@ -47,17 +46,17 @@ buildscript {
         }
         // For in tree plugins.
         maven {
             url "file://${gradle.mozconfig.topsrcdir}/mobile/android/gradle/m2repo"
         }
     }
 
     dependencies {
-        classpath 'com.android.tools.build:gradle:2.3.3'
+        classpath 'com.android.tools.build:gradle:3.0.0'
         // Provided in tree.
         classpath 'com.getkeepsafe.dexcount:dexcount-gradle-plugin:0.7.3'
     }
 }
 
 if ('multi' == System.env.AB_CD) {
     // Multi-l10n builds set `AB_CD=multi`, which isn't a valid locale.  This
     // causes the
--- a/build/clang-plugin/mozsearch-plugin/FileOperations.cpp
+++ b/build/clang-plugin/mozsearch-plugin/FileOperations.cpp
@@ -7,16 +7,17 @@
 
 #include <stdio.h>
 #include <stdlib.h>
 
 #if defined(_WIN32) || defined(_WIN64)
 #include <direct.h>
 #include <io.h>
 #include <windows.h>
+#include "StringOperations.h"
 #else
 #include <sys/file.h>
 #include <sys/time.h>
 #include <unistd.h>
 #endif
 
 #include <fcntl.h>
 #include <sys/stat.h>
@@ -45,17 +46,17 @@ void ensurePath(std::string Path) {
     }
 
     Pos++;
   }
 }
 
 #if defined(_WIN32) || defined(_WIN64)
 AutoLockFile::AutoLockFile(const std::string &Filename) {
-  std::string Hash = Hash(filename);
+  std::string Hash = hash(Filename);
   std::string MutexName = std::string("Local\\searchfox-") + Hash;
   std::wstring WideMutexName;
   WideMutexName.assign(MutexName.begin(), MutexName.end());
   Handle = CreateMutex(nullptr, false, WideMutexName.c_str());
   if (Handle == NULL) {
     return;
   }
 
@@ -80,17 +81,17 @@ FILE *AutoLockFile::openFile(const char 
   return _fdopen(_dup(FileDescriptor), Mode);
 }
 
 bool AutoLockFile::truncateFile(size_t Length) {
   return _chsize(FileDescriptor, Length) == 0;
 }
 
 std::string getAbsolutePath(const std::string &Filename) {
-  char full[_MAX_PATH];
+  char Full[_MAX_PATH];
   if (!_fullpath(Full, Filename.c_str(), _MAX_PATH)) {
     return std::string("");
   }
   return std::string(Full);
 }
 #else
 AutoLockFile::AutoLockFile(const std::string &Filename) {
   FileDescriptor = open(Filename.c_str(), O_RDWR | O_CREAT, 0666);
--- a/build/docs/toolchains.rst
+++ b/build/docs/toolchains.rst
@@ -65,47 +65,43 @@ an internal Mozilla server.  The build a
 verify, and extract these archive before building.  These archives
 provide a self-contained Gradle and Maven repository so that machines
 don't need to fetch additional Maven dependencies at build time.
 (Gradle and the downloaded Maven dependencies can be both
 redistributed publicly.)
 
 Archiving the Gradle executable is straight-forward, but archiving a
 local Maven repository is not.  Therefore a special Task Cluster
-Docker image and job exist for producing the required archives.  The
-Docker image definition is rooted in
-``taskcluster/docker/android-build``.  The Task Cluster job
-definition is in
-``testing/taskcluster/tasks/builds/android_api_16_gradle_dependencies.yml``.
-The job runs in a container based on the custom Docker image and
-spawns a Sonatype Nexus proxying Maven repository process in the
-background.  The job builds Firefox for Android using Gradle and the
-in-tree Gradle configuration rooted at ``build.gradle``.  The spawned
-proxying Maven repository downloads external dependencies and collects
-them.  After the Gradle build completes, the job archives the Gradle
-version used to build, and the downloaded Maven repository, and
-exposes them as Task Cluster artifacts.
-
-Here is `an example try job fetching these dependencies
-<https://treeherder.mozilla.org/#/jobs?repo=try&revision=75bc98935147&selectedJob=17793653>`_.
-The resulting task produced a `Gradle archive
-<https://queue.taskcluster.net/v1/task/CeYMgAP3Q-KF8h37nMhJjg/runs/0/artifacts/public%2Fbuild%2Fgradle.tar.xz>`_
-and a `Maven repository archive
-<https://queue.taskcluster.net/v1/task/CeYMgAP3Q-KF8h37nMhJjg/runs/0/artifacts/public%2Fbuild%2Fjcentral.tar.xz>`_.
-These archives were then uploaded (manually) to Mozilla automation
-using tooltool for consumption in Gradle builds.
+Docker image and toolchain job exist for producing the required
+archives.  The Docker image definition is rooted in
+``taskcluster/docker/android-build``.  The Task Cluster toolchain job
+is named `android-gradle-dependencies`.  The job runs in a container
+based on the custom Docker image and spawns a Sonatype Nexus proxying
+Maven repository process in the background.  The job builds Firefox
+for Android using Gradle and the in-tree Gradle configuration rooted
+at ``build.gradle``.  The spawned proxying Maven repository downloads
+external dependencies and collects them.  After the Gradle build
+completes, the job archives the Gradle version used to build, and the
+downloaded Maven repository, and exposes them as Task Cluster
+artifacts.
 
 To update the version of Gradle in the archive produced, update
 ``gradle/wrapper/gradle-wrapper.properties``.  Be sure to also update
 the SHA256 checksum to prevent poisoning the build machines!
 
 To update the versions of Gradle dependencies used, update
 ``dependencies`` sections in the in-tree Gradle configuration rooted
 at ``build.gradle``.  Once you are confident your changes build
-locally, push a fresh try build with an invocation like::
+locally, push a fresh build to try.  The `android-gradle-dependencies`
+toolchain should run automatically, fetching your new dependencies and
+wiring them into the appropriate try build jobs.
 
-   $ hg push-to-try -m "try: -b o -p android-api-16-gradle-dependencies"
+To update the version of Sonatype Nexus, update `NEXUS_VERSION` in the
+`android-build` Docker image.
 
-Then `upload your archives to tooltool
-<https://wiki.mozilla.org/ReleaseEngineering/Applications/Tooltool#How_To_Upload_To_Tooltool>`_,
-update the in-tree manifests in
-``mobile/android/config/tooltool-manifests``, and push a fresh try
-build.
+To modify the Sonatype Nexus configuration, typically to proxy a new
+remote Maven repository, modify
+`taskcluster/scripts/misc/android-gradle-dependencies/nexus.xml`.
+
+There is also a toolchain job that fetches the Android SDK and related
+packages.  To update the versions of packaged fetched, modify
+`python/mozboot/mozboot/android-packages.txt` and update the various
+in-tree versions accordingly.
--- a/build/unix/build-gtk3/build-gtk3.sh
+++ b/build/unix/build-gtk3/build-gtk3.sh
@@ -6,32 +6,37 @@ fontconfig_version=2.8.0
 libffi_version=3.0.13
 glib_version=2.34.3
 gdk_pixbuf_version=2.26.5
 pixman_version=0.20.2
 cairo_version=1.10.2
 pango_version=1.30.1
 atk_version=2.2.0
 gtk__version=3.4.4
+pulseaudio_version=2.0
 
 fontconfig_url=http://www.freedesktop.org/software/fontconfig/release/fontconfig-${fontconfig_version}.tar.gz
 libffi_url=ftp://sourceware.org/pub/libffi/libffi-${libffi_version}.tar.gz
 glib_url=http://ftp.gnome.org/pub/gnome/sources/glib/${glib_version%.*}/glib-${glib_version}.tar.xz
 gdk_pixbuf_url=http://ftp.gnome.org/pub/gnome/sources/gdk-pixbuf/${gdk_pixbuf_version%.*}/gdk-pixbuf-${gdk_pixbuf_version}.tar.xz
 pixman_url=http://cairographics.org/releases/pixman-${pixman_version}.tar.gz
 cairo_url=http://cairographics.org/releases/cairo-${cairo_version}.tar.gz
 pango_url=http://ftp.gnome.org/pub/GNOME/sources/pango/${pango_version%.*}/pango-${pango_version}.tar.xz
 atk_url=http://ftp.gnome.org/pub/GNOME/sources/atk/${atk_version%.*}/atk-${atk_version}.tar.xz
 gtk__url=http://ftp.gnome.org/pub/gnome/sources/gtk+/${gtk__version%.*}/gtk+-${gtk__version}.tar.xz
+pulseaudio_url=https://freedesktop.org/software/pulseaudio/releases/pulseaudio-${pulseaudio_version}.tar.xz
 
 root_dir=$(mktemp -d)
 cd $root_dir
 
 make_flags=-j$(nproc)
 
+# Install a few packages for pulseaudio.
+yum install -y libtool-ltdl-devel libtool-ltdl-devel.i686 json-c-devel json-c-devel.i686 libsndfile-devel libsndfile-devel.i686
+
 build() {
 	name=$1
 	shift
 	pkg=$(echo $name | tr '+-' '__')
 	version=$(eval echo \$${pkg}_version)
 	url=$(eval echo \$${pkg}_url)
 	wget -c -P $root_dir $url
 	tar -axf $root_dir/$name-$version.tar.*
@@ -67,16 +72,17 @@ build libffi
 build glib
 build gdk-pixbuf --without-libtiff --without-libjpeg
 build pixman --disable-gtk
 build cairo --enable-tee
 build pango
 build atk
 make_flags="$make_flags GLIB_COMPILE_SCHEMAS=glib-compile-schemas"
 build gtk+
+build pulseaudio --disable-nls
 
 done
 
 rm -rf $root_dir
 
 echo /usr/local/lib > /etc/ld.so.conf.d/local.conf
 echo /usr/local/lib64 >> /etc/ld.so.conf.d/local.conf
 ldconfig
--- a/devtools/client/shared/components/reps/reps.css
+++ b/devtools/client/shared/components/reps/reps.css
@@ -273,16 +273,22 @@
   flex-shrink: 0;
 }
 
 /* Align with expandables siblings (where we have the arrow) */
 .tree-node[data-expandable="false"] .tree-indent:last-of-type {
   margin-inline-end: 15px;
 }
 
+/* For non expandable root nodes, we don't have .tree-indent elements, so we declare
+   the margin on the start of the node */
+.tree-node[data-expandable="false"][aria-level="0"] {
+  padding-inline-start: 15px
+}
+
 .tree .tree-node[data-expandable="true"] {
   cursor: default;
 }
 
 .tree .tree-node:not(.focused):hover {
   background-color: #F0F9FE;
 }
 
--- a/devtools/client/shared/components/reps/reps.js
+++ b/devtools/client/shared/components/reps/reps.js
@@ -2,17 +2,17 @@
 	if(typeof exports === 'object' && typeof module === 'object')
 		module.exports = factory(require("devtools/client/shared/vendor/react-dom-factories"), require("devtools/client/shared/vendor/lodash"), require("devtools/client/shared/vendor/react-prop-types"), require("devtools/client/shared/vendor/react"));
 	else if(typeof define === 'function' && define.amd)
 		define(["devtools/client/shared/vendor/react-dom-factories", "devtools/client/shared/vendor/lodash", "devtools/client/shared/vendor/react-prop-types", "devtools/client/shared/vendor/react"], factory);
 	else {
 		var a = typeof exports === 'object' ? factory(require("devtools/client/shared/vendor/react-dom-factories"), require("devtools/client/shared/vendor/lodash"), require("devtools/client/shared/vendor/react-prop-types"), require("devtools/client/shared/vendor/react")) : factory(root["devtools/client/shared/vendor/react-dom-factories"], root["devtools/client/shared/vendor/lodash"], root["devtools/client/shared/vendor/react-prop-types"], root["devtools/client/shared/vendor/react"]);
 		for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];
 	}
-})(this, function(__WEBPACK_EXTERNAL_MODULE_1__, __WEBPACK_EXTERNAL_MODULE_53__, __WEBPACK_EXTERNAL_MODULE_2__, __WEBPACK_EXTERNAL_MODULE_7__) {
+})(this, function(__WEBPACK_EXTERNAL_MODULE_1__, __WEBPACK_EXTERNAL_MODULE_58__, __WEBPACK_EXTERNAL_MODULE_2__, __WEBPACK_EXTERNAL_MODULE_6__) {
 return /******/ (function(modules) { // webpackBootstrap
 /******/ 	// The module cache
 /******/ 	var installedModules = {};
 /******/
 /******/ 	// The require function
 /******/ 	function __webpack_require__(moduleId) {
 /******/
 /******/ 		// Check if module is in cache
@@ -65,17 +65,17 @@ return /******/ (function(modules) { // 
 /******/
 /******/ 	// Object.prototype.hasOwnProperty.call
 /******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
 /******/
 /******/ 	// __webpack_public_path__
 /******/ 	__webpack_require__.p = "/assets/build";
 /******/
 /******/ 	// Load entry module and return exports
-/******/ 	return __webpack_require__(__webpack_require__.s = 17);
+/******/ 	return __webpack_require__(__webpack_require__.s = 18);
 /******/ })
 /************************************************************************/
 /******/ ([
 /* 0 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
@@ -518,50 +518,50 @@ module.exports = {
 
 "use strict";
 
 
 /* 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/. */
 
-__webpack_require__(18);
+__webpack_require__(19);
 
 // Load all existing rep templates
-const Undefined = __webpack_require__(19);
-const Null = __webpack_require__(20);
-const StringRep = __webpack_require__(6);
-const LongStringRep = __webpack_require__(21);
-const Number = __webpack_require__(22);
+const Undefined = __webpack_require__(20);
+const Null = __webpack_require__(21);
+const StringRep = __webpack_require__(7);
+const LongStringRep = __webpack_require__(22);
+const Number = __webpack_require__(23);
 const ArrayRep = __webpack_require__(10);
-const Obj = __webpack_require__(23);
-const SymbolRep = __webpack_require__(24);
-const InfinityRep = __webpack_require__(25);
-const NaNRep = __webpack_require__(26);
-const Accessor = __webpack_require__(27);
+const Obj = __webpack_require__(24);
+const SymbolRep = __webpack_require__(25);
+const InfinityRep = __webpack_require__(26);
+const NaNRep = __webpack_require__(27);
+const Accessor = __webpack_require__(28);
 
 // DOM types (grips)
-const Attribute = __webpack_require__(28);
-const DateTime = __webpack_require__(29);
-const Document = __webpack_require__(30);
-const Event = __webpack_require__(31);
-const Func = __webpack_require__(32);
-const PromiseRep = __webpack_require__(36);
-const RegExp = __webpack_require__(37);
-const StyleSheet = __webpack_require__(38);
-const CommentNode = __webpack_require__(39);
-const ElementNode = __webpack_require__(40);
-const TextNode = __webpack_require__(41);
-const ErrorRep = __webpack_require__(42);
-const Window = __webpack_require__(43);
-const ObjectWithText = __webpack_require__(44);
-const ObjectWithURL = __webpack_require__(45);
-const GripArray = __webpack_require__(13);
-const GripMap = __webpack_require__(14);
-const GripMapEntry = __webpack_require__(15);
+const Attribute = __webpack_require__(29);
+const DateTime = __webpack_require__(30);
+const Document = __webpack_require__(31);
+const Event = __webpack_require__(32);
+const Func = __webpack_require__(33);
+const PromiseRep = __webpack_require__(38);
+const RegExp = __webpack_require__(39);
+const StyleSheet = __webpack_require__(40);
+const CommentNode = __webpack_require__(41);
+const ElementNode = __webpack_require__(42);
+const TextNode = __webpack_require__(43);
+const ErrorRep = __webpack_require__(44);
+const Window = __webpack_require__(45);
+const ObjectWithText = __webpack_require__(46);
+const ObjectWithURL = __webpack_require__(47);
+const GripArray = __webpack_require__(12);
+const GripMap = __webpack_require__(13);
+const GripMapEntry = __webpack_require__(14);
 const Grip = __webpack_require__(8);
 
 // List of all registered template.
 // XXX there should be a way for extensions to register a new
 // or modify an existing rep.
 let reps = [RegExp, StyleSheet, Event, DateTime, CommentNode, ElementNode, TextNode, Attribute, LongStringRep, Func, PromiseRep, ArrayRep, Document, Window, ObjectWithText, ObjectWithURL, ErrorRep, GripArray, GripMap, GripMapEntry, Grip, Undefined, Null, StringRep, Number, SymbolRep, InfinityRep, NaNRep, Accessor];
 
 /**
@@ -734,16 +734,22 @@ function PropRep(props) {
   }, equal), Rep(Object.assign({}, props))];
 }
 
 // Exports from this module
 module.exports = wrapRender(PropRep);
 
 /***/ }),
 /* 6 */
+/***/ (function(module, exports) {
+
+module.exports = __WEBPACK_EXTERNAL_MODULE_6__;
+
+/***/ }),
+/* 7 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 /* 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/. */
@@ -933,22 +939,16 @@ function supportsObject(object, noGrip =
 // Exports from this module
 
 module.exports = {
   rep: wrapRender(StringRep),
   supportsObject
 };
 
 /***/ }),
-/* 7 */
-/***/ (function(module, exports) {
-
-module.exports = __WEBPACK_EXTERNAL_MODULE_7__;
-
-/***/ }),
 /* 8 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 /* 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
@@ -1263,33 +1263,33 @@ module.exports = Grip;
 
 /***/ }),
 /* 9 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
-var _svgInlineReact = __webpack_require__(11);
+var _svgInlineReact = __webpack_require__(34);
 
 var _svgInlineReact2 = _interopRequireDefault(_svgInlineReact);
 
 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
 
 /* 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 React = __webpack_require__(7);
+const React = __webpack_require__(6);
 const PropTypes = __webpack_require__(2);
 
 
 const svg = {
-  "open-inspector": __webpack_require__(34),
-  "jump-definition": __webpack_require__(35)
+  "open-inspector": __webpack_require__(36),
+  "jump-definition": __webpack_require__(37)
 };
 
 Svg.propTypes = {
   className: PropTypes.string
 };
 
 function Svg(name, props) {
   if (!svg[name]) {
@@ -1456,114 +1456,16 @@ module.exports = {
 
 /***/ }),
 /* 11 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
-Object.defineProperty(exports, "__esModule", {
-    value: true
-});
-
-var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
-
-var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
-
-var _react = __webpack_require__(7);
-
-var _react2 = _interopRequireDefault(_react);
-
-var _propTypes = __webpack_require__(2);
-
-var _util = __webpack_require__(33);
-
-function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
-
-function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; }
-
-function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
-
-function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
-
-function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
-
-var process = process || { env: {} };
-
-var InlineSVG = function (_React$Component) {
-    _inherits(InlineSVG, _React$Component);
-
-    function InlineSVG() {
-        _classCallCheck(this, InlineSVG);
-
-        return _possibleConstructorReturn(this, (InlineSVG.__proto__ || Object.getPrototypeOf(InlineSVG)).apply(this, arguments));
-    }
-
-    _createClass(InlineSVG, [{
-        key: 'componentWillReceiveProps',
-        value: function componentWillReceiveProps(_ref) {
-            var children = _ref.children;
-
-            if ("production" !== process.env.NODE_ENV && children != null) {
-                console.info('<InlineSVG />: `children` prop will be ignored.');
-            }
-        }
-    }, {
-        key: 'render',
-        value: function render() {
-            var Element = void 0,
-                __html = void 0,
-                svgProps = void 0;
-
-            var _props = this.props,
-                element = _props.element,
-                raw = _props.raw,
-                src = _props.src,
-                otherProps = _objectWithoutProperties(_props, ['element', 'raw', 'src']);
-
-            if (raw === true) {
-                Element = 'svg';
-                svgProps = (0, _util.extractSVGProps)(src);
-                __html = (0, _util.getSVGFromSource)(src).innerHTML;
-            }
-            __html = __html || src;
-            Element = Element || element;
-            svgProps = svgProps || {};
-
-            return _react2.default.createElement(Element, _extends({}, svgProps, otherProps, { src: null, children: null,
-                dangerouslySetInnerHTML: { __html: __html } }));
-        }
-    }]);
-
-    return InlineSVG;
-}(_react2.default.Component);
-
-exports.default = InlineSVG;
-
-
-InlineSVG.defaultProps = {
-    element: 'i',
-    raw: false,
-    src: ''
-};
-
-InlineSVG.propTypes = {
-    src: _propTypes.string.isRequired,
-    element: _propTypes.string,
-    raw: _propTypes.bool
-};
-
-/***/ }),
-/* 12 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-
 /* 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/. */
 
 module.exports = {
   ELEMENT_NODE: 1,
   ATTRIBUTE_NODE: 2,
   TEXT_NODE: 3,
@@ -1582,17 +1484,17 @@ module.exports = {
   DOCUMENT_POSITION_PRECEDING: 0x02,
   DOCUMENT_POSITION_FOLLOWING: 0x04,
   DOCUMENT_POSITION_CONTAINS: 0x08,
   DOCUMENT_POSITION_CONTAINED_BY: 0x10,
   DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC: 0x20
 };
 
 /***/ }),
-/* 13 */
+/* 12 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 /* 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/. */
@@ -1800,17 +1702,17 @@ maxLengthMap.set(MODE.LONG, 10);
 module.exports = {
   rep: wrapRender(GripArray),
   supportsObject,
   maxLengthMap,
   getLength
 };
 
 /***/ }),
-/* 14 */
+/* 13 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 /* 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/. */
@@ -2008,17 +1910,17 @@ maxLengthMap.set(MODE.LONG, 10);
 module.exports = {
   rep: wrapRender(GripMap),
   supportsObject,
   maxLengthMap,
   getLength
 };
 
 /***/ }),
-/* 15 */
+/* 14 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 /* 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/. */
@@ -2086,32 +1988,128 @@ function createGripMapEntry(key, value) 
 // Exports from this module
 module.exports = {
   rep: wrapRender(GripMapEntry),
   createGripMapEntry,
   supportsObject
 };
 
 /***/ }),
-/* 16 */
+/* 15 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 /* 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 { get, has } = __webpack_require__(53);
+const client = __webpack_require__(16);
+const loadProperties = __webpack_require__(57);
+const node = __webpack_require__(17);
+
+module.exports = {
+  client,
+  loadProperties,
+  node
+};
+
+/***/ }),
+/* 16 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+async function enumIndexedProperties(objectClient, start, end) {
+  try {
+    const { iterator } = await objectClient.enumProperties({ ignoreNonIndexedProperties: true });
+    const response = await iteratorSlice(iterator, start, end);
+    return response;
+  } catch (e) {
+    console.error("Error in enumIndexedProperties", e);
+    return {};
+  }
+} /* 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/. */
+
+async function enumNonIndexedProperties(objectClient, start, end) {
+  try {
+    const { iterator } = await objectClient.enumProperties({ ignoreIndexedProperties: true });
+    const response = await iteratorSlice(iterator, start, end);
+    return response;
+  } catch (e) {
+    console.error("Error in enumNonIndexedProperties", e);
+    return {};
+  }
+}
+
+async function enumEntries(objectClient, start, end) {
+  try {
+    const { iterator } = await objectClient.enumEntries();
+    const response = await iteratorSlice(iterator, start, end);
+    return response;
+  } catch (e) {
+    console.error("Error in enumEntries", e);
+    return {};
+  }
+}
+
+async function enumSymbols(objectClient, start, end) {
+  try {
+    const { iterator } = await objectClient.enumSymbols();
+    const response = await iteratorSlice(iterator, start, end);
+    return response;
+  } catch (e) {
+    console.error("Error in enumSymbols", e);
+    return {};
+  }
+}
+
+async function getPrototype(objectClient) {
+  if (typeof objectClient.getPrototype !== "function") {
+    console.error("objectClient.getPrototype is not a function");
+    return Promise.resolve({});
+  }
+  return objectClient.getPrototype();
+}
+
+function iteratorSlice(iterator, start, end) {
+  start = start || 0;
+  const count = end ? end - start + 1 : iterator.count;
+  return iterator.slice(start, count);
+}
+
+module.exports = {
+  enumEntries,
+  enumIndexedProperties,
+  enumNonIndexedProperties,
+  enumSymbols,
+  getPrototype
+};
+
+/***/ }),
+/* 17 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+/* 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 { get, has } = __webpack_require__(58);
 const { maybeEscapePropertyName } = __webpack_require__(0);
 const ArrayRep = __webpack_require__(10);
-const GripArrayRep = __webpack_require__(13);
-const GripMap = __webpack_require__(14);
-const GripMapEntryRep = __webpack_require__(15);
+const GripArrayRep = __webpack_require__(12);
+const GripMap = __webpack_require__(13);
+const GripMapEntryRep = __webpack_require__(14);
 
 const MAX_NUMERICAL_PROPERTIES = 100;
 
 const NODE_TYPES = {
   BUCKET: Symbol("[n…n]"),
   DEFAULT_PROPERTIES: Symbol("[default properties]"),
   ENTRIES: Symbol("<entries>"),
   GET: Symbol("<get>"),
@@ -2679,53 +2677,16 @@ function getClosestNonBucketNode(item) {
   const parent = getParent(item);
   if (!parent) {
     return null;
   }
 
   return getClosestNonBucketNode(parent);
 }
 
-function shouldLoadItemIndexedProperties(item, loadedProperties = new Map()) {
-  const gripItem = getClosestGripNode(item);
-  const value = getValue(gripItem);
-
-  return value && nodeHasProperties(gripItem) && !loadedProperties.has(item.path) && !nodeIsProxy(item) && !nodeNeedsNumericalBuckets(item) && !nodeIsEntries(getClosestNonBucketNode(item))
-  // The data is loaded when expanding the window node.
-  && !nodeIsDefaultProperties(item);
-}
-
-function shouldLoadItemNonIndexedProperties(item, loadedProperties = new Map()) {
-  const gripItem = getClosestGripNode(item);
-  const value = getValue(gripItem);
-
-  return value && nodeHasProperties(gripItem) && !loadedProperties.has(item.path) && !nodeIsProxy(item) && !nodeIsEntries(getClosestNonBucketNode(item)) && !nodeIsBucket(item)
-  // The data is loaded when expanding the window node.
-  && !nodeIsDefaultProperties(item);
-}
-
-function shouldLoadItemEntries(item, loadedProperties = new Map()) {
-  const gripItem = getClosestGripNode(item);
-  const value = getValue(gripItem);
-
-  return value && nodeIsEntries(getClosestNonBucketNode(item)) && !nodeHasAllEntriesInPreview(gripItem) && !loadedProperties.has(item.path) && !nodeNeedsNumericalBuckets(item);
-}
-
-function shouldLoadItemPrototype(item, loadedProperties = new Map()) {
-  const value = getValue(item);
-
-  return value && !loadedProperties.has(item.path) && !nodeIsBucket(item) && !nodeIsMapEntry(item) && !nodeIsEntries(item) && !nodeIsDefaultProperties(item) && !nodeHasAccessors(item) && !nodeIsPrimitive(item);
-}
-
-function shouldLoadItemSymbols(item, loadedProperties = new Map()) {
-  const value = getValue(item);
-
-  return value && !loadedProperties.has(item.path) && !nodeIsBucket(item) && !nodeIsMapEntry(item) && !nodeIsEntries(item) && !nodeIsDefaultProperties(item) && !nodeHasAccessors(item) && !nodeIsPrimitive(item) && !nodeIsProxy(item);
-}
-
 module.exports = {
   createNode,
   getChildren,
   getClosestGripNode,
   getClosestNonBucketNode,
   getParent,
   getNumericalPropertiesCount,
   getValue,
@@ -2751,42 +2712,37 @@ module.exports = {
   nodeIsPromise,
   nodeIsPrototype,
   nodeIsProxy,
   nodeIsSetter,
   nodeIsWindow,
   nodeNeedsNumericalBuckets,
   nodeSupportsNumericalBucketing,
   setNodeChildren,
-  shouldLoadItemEntries,
-  shouldLoadItemIndexedProperties,
-  shouldLoadItemNonIndexedProperties,
-  shouldLoadItemPrototype,
-  shouldLoadItemSymbols,
   sortProperties,
   NODE_TYPES,
   // Export for testing purpose.
   SAFE_PATH_PREFIX
 };
 
 /***/ }),
-/* 17 */
+/* 18 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 /* 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 { MODE } = __webpack_require__(3);
 const { REPS, getRep } = __webpack_require__(4);
-const ObjectInspector = __webpack_require__(46);
-const ObjectInspectorUtils = __webpack_require__(16);
+const ObjectInspector = __webpack_require__(48);
+const ObjectInspectorUtils = __webpack_require__(15);
 
 const {
   parseURLEncodedText,
   parseURLParams,
   maybeEscapePropertyName,
   getGripPreviewItems
 } = __webpack_require__(0);
 
@@ -2798,23 +2754,23 @@ module.exports = {
   parseURLEncodedText,
   parseURLParams,
   getGripPreviewItems,
   ObjectInspector,
   ObjectInspectorUtils
 };
 
 /***/ }),
-/* 18 */
+/* 19 */
 /***/ (function(module, exports) {
 
 // removed by extract-text-webpack-plugin
 
 /***/ }),
-/* 19 */
+/* 20 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 /* 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/. */
@@ -2846,17 +2802,17 @@ function supportsObject(object, noGrip =
 // Exports from this module
 
 module.exports = {
   rep: wrapRender(Undefined),
   supportsObject
 };
 
 /***/ }),
-/* 20 */
+/* 21 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 /* 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/. */
@@ -2888,17 +2844,17 @@ function supportsObject(object, noGrip =
 // Exports from this module
 
 module.exports = {
   rep: wrapRender(Null),
   supportsObject
 };
 
 /***/ }),
-/* 21 */
+/* 22 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 /* 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/. */
@@ -2965,17 +2921,17 @@ function supportsObject(object, noGrip =
 
 // Exports from this module
 module.exports = {
   rep: wrapRender(LongStringRep),
   supportsObject
 };
 
 /***/ }),
-/* 22 */
+/* 23 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 /* 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/. */
@@ -3017,17 +2973,17 @@ function supportsObject(object, noGrip =
 // Exports from this module
 
 module.exports = {
   rep: wrapRender(Number),
   supportsObject
 };
 
 /***/ }),
-/* 23 */
+/* 24 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 /* 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/. */
@@ -3195,17 +3151,17 @@ function supportsObject(object) {
 
 // Exports from this module
 module.exports = {
   rep: wrapRender(ObjectRep),
   supportsObject
 };
 
 /***/ }),
-/* 24 */
+/* 25 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 /* 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/. */
@@ -3247,17 +3203,17 @@ function supportsObject(object, noGrip =
 
 // Exports from this module
 module.exports = {
   rep: wrapRender(SymbolRep),
   supportsObject
 };
 
 /***/ }),
-/* 25 */
+/* 26 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 /* 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/. */
@@ -3295,17 +3251,17 @@ function supportsObject(object, noGrip =
 
 // Exports from this module
 module.exports = {
   rep: wrapRender(InfinityRep),
   supportsObject
 };
 
 /***/ }),
-/* 26 */
+/* 27 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 /* 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/. */
@@ -3332,17 +3288,17 @@ function supportsObject(object, noGrip =
 
 // Exports from this module
 module.exports = {
   rep: wrapRender(NaNRep),
   supportsObject
 };
 
 /***/ }),
-/* 27 */
+/* 28 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 /* 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/. */
@@ -3402,17 +3358,17 @@ function supportsObject(object, noGrip =
 
 // Exports from this module
 module.exports = {
   rep: wrapRender(Accessor),
   supportsObject
 };
 
 /***/ }),
-/* 28 */
+/* 29 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 /* 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/. */
@@ -3423,17 +3379,17 @@ const dom = __webpack_require__(1);
 const { span } = dom;
 
 // Reps
 const {
   getGripType,
   isGrip,
   wrapRender
 } = __webpack_require__(0);
-const { rep: StringRep } = __webpack_require__(6);
+const { rep: StringRep } = __webpack_require__(7);
 
 /**
  * Renders DOM attribute
  */
 Attribute.propTypes = {
   object: PropTypes.object.isRequired
 };
 
@@ -3463,17 +3419,17 @@ function supportsObject(grip, noGrip = f
 }
 
 module.exports = {
   rep: wrapRender(Attribute),
   supportsObject
 };
 
 /***/ }),
-/* 29 */
+/* 30 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 /* 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/. */
@@ -3530,17 +3486,17 @@ function supportsObject(grip, noGrip = f
 
 // Exports from this module
 module.exports = {
   rep: wrapRender(DateTime),
   supportsObject
 };
 
 /***/ }),
-/* 30 */
+/* 31 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 /* 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/. */
@@ -3597,17 +3553,17 @@ function supportsObject(object, noGrip =
 
 // Exports from this module
 module.exports = {
   rep: wrapRender(Document),
   supportsObject
 };
 
 /***/ }),
-/* 31 */
+/* 32 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 /* 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/. */
@@ -3704,17 +3660,17 @@ function supportsObject(grip, noGrip = f
 
 // Exports from this module
 module.exports = {
   rep: wrapRender(Event),
   supportsObject
 };
 
 /***/ }),
-/* 32 */
+/* 33 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 /* 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/. */
@@ -3865,17 +3821,115 @@ function supportsObject(grip, noGrip = f
 module.exports = {
   rep: wrapRender(FunctionRep),
   supportsObject,
   // exported for testing purpose.
   getFunctionName
 };
 
 /***/ }),
-/* 33 */
+/* 34 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+
+var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
+
+var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
+
+var _react = __webpack_require__(6);
+
+var _react2 = _interopRequireDefault(_react);
+
+var _propTypes = __webpack_require__(2);
+
+var _util = __webpack_require__(35);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
+
+function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
+
+var process = process || { env: {} };
+
+var InlineSVG = function (_React$Component) {
+    _inherits(InlineSVG, _React$Component);
+
+    function InlineSVG() {
+        _classCallCheck(this, InlineSVG);
+
+        return _possibleConstructorReturn(this, (InlineSVG.__proto__ || Object.getPrototypeOf(InlineSVG)).apply(this, arguments));
+    }
+
+    _createClass(InlineSVG, [{
+        key: 'componentWillReceiveProps',
+        value: function componentWillReceiveProps(_ref) {
+            var children = _ref.children;
+
+            if ("production" !== process.env.NODE_ENV && children != null) {
+                console.info('<InlineSVG />: `children` prop will be ignored.');
+            }
+        }
+    }, {
+        key: 'render',
+        value: function render() {
+            var Element = void 0,
+                __html = void 0,
+                svgProps = void 0;
+
+            var _props = this.props,
+                element = _props.element,
+                raw = _props.raw,
+                src = _props.src,
+                otherProps = _objectWithoutProperties(_props, ['element', 'raw', 'src']);
+
+            if (raw === true) {
+                Element = 'svg';
+                svgProps = (0, _util.extractSVGProps)(src);
+                __html = (0, _util.getSVGFromSource)(src).innerHTML;
+            }
+            __html = __html || src;
+            Element = Element || element;
+            svgProps = svgProps || {};
+
+            return _react2.default.createElement(Element, _extends({}, svgProps, otherProps, { src: null, children: null,
+                dangerouslySetInnerHTML: { __html: __html } }));
+        }
+    }]);
+
+    return InlineSVG;
+}(_react2.default.Component);
+
+exports.default = InlineSVG;
+
+
+InlineSVG.defaultProps = {
+    element: 'i',
+    raw: false,
+    src: ''
+};
+
+InlineSVG.propTypes = {
+    src: _propTypes.string.isRequired,
+    element: _propTypes.string,
+    raw: _propTypes.bool
+};
+
+/***/ }),
+/* 35 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
     value: true
 });
@@ -3920,29 +3974,29 @@ function getSVGFromSource(src) {
 
 // get <svg /> element props
 function extractSVGProps(src) {
     var map = getSVGFromSource(src).attributes;
     return map.length > 0 ? serializeAttrs(map) : null;
 }
 
 /***/ }),
-/* 34 */
+/* 36 */
 /***/ (function(module, exports) {
 
 module.exports = "<!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --><svg viewBox=\"0 0 16 16\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M8,3L12,3L12,7L14,7L14,8L12,8L12,12L8,12L8,14L7,14L7,12L3,12L3,8L1,8L1,7L3,7L3,3L7,3L7,1L8,1L8,3ZM10,10L10,5L5,5L5,10L10,10Z\"></path></svg>"
 
 /***/ }),
-/* 35 */
+/* 37 */
 /***/ (function(module, exports) {
 
 module.exports = "<!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --><svg viewBox=\"0 0 16 16\" xmlns=\"http://www.w3.org/2000/svg\"><g stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\" stroke-linecap=\"round\"><g id=\"arrow\" transform=\"translate(1.000000, 3.000000)\"><path d=\"M4.5,0.5 L6.5,2.5\"></path><path d=\"M4.5,2.5 L6.5,4.5\" transform=\"translate(5.500000, 3.500000) scale(1, -1) translate(-5.500000, -3.500000) \"></path><path d=\"M6.00090144,2.5 C4.67806937,2.5 3.67938478,2.5 3.00484766,2.5 C1.99304199,2.5 1.01049805,3.5168457 0.993840144,4.52403846 C0.988750751,4.54723808 0.988750751,5.87097168 0.993840144,8.49523926\" id=\"Path-2\" stroke-linejoin=\"round\"></path></g><g id=\"content-lines\" transform=\"translate(9.000000, 2.000000)\"><path d=\"M1.5,3.5 L5.5,3.5\"></path><path d=\"M0.5,1.5 L5.5,1.5\"></path><path d=\"M0.5,5.5 L5.5,5.5\"></path></g></g></svg>"
 
 /***/ }),
-/* 36 */
+/* 38 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 /* 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/. */
@@ -4042,17 +4096,17 @@ function supportsObject(object, noGrip =
 
 // Exports from this module
 module.exports = {
   rep: wrapRender(PromiseRep),
   supportsObject
 };
 
 /***/ }),
-/* 37 */
+/* 39 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 /* 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/. */
@@ -4101,17 +4155,17 @@ function supportsObject(object, noGrip =
 
 // Exports from this module
 module.exports = {
   rep: wrapRender(RegExp),
   supportsObject
 };
 
 /***/ }),
-/* 38 */
+/* 40 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 /* 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/. */
@@ -4169,17 +4223,17 @@ function supportsObject(object, noGrip =
 // Exports from this module
 
 module.exports = {
   rep: wrapRender(StyleSheet),
   supportsObject
 };
 
 /***/ }),
-/* 39 */
+/* 41 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 /* 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/. */
@@ -4188,17 +4242,17 @@ module.exports = {
 const PropTypes = __webpack_require__(2);
 const {
   isGrip,
   cropString,
   cropMultipleLines,
   wrapRender
 } = __webpack_require__(0);
 const { MODE } = __webpack_require__(3);
-const nodeConstants = __webpack_require__(12);
+const nodeConstants = __webpack_require__(11);
 const dom = __webpack_require__(1);
 const { span } = dom;
 
 /**
  * Renders DOM comment node.
  */
 CommentNode.propTypes = {
   object: PropTypes.object.isRequired,
@@ -4235,17 +4289,17 @@ function supportsObject(object, noGrip =
 
 // Exports from this module
 module.exports = {
   rep: wrapRender(CommentNode),
   supportsObject
 };
 
 /***/ }),
-/* 40 */
+/* 42 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 /* 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/. */
@@ -4253,19 +4307,19 @@ module.exports = {
 // ReactJS
 const PropTypes = __webpack_require__(2);
 
 // Utils
 const {
   isGrip,
   wrapRender
 } = __webpack_require__(0);
-const { rep: StringRep } = __webpack_require__(6);
+const { rep: StringRep } = __webpack_require__(7);
 const { MODE } = __webpack_require__(3);
-const nodeConstants = __webpack_require__(12);
+const nodeConstants = __webpack_require__(11);
 const Svg = __webpack_require__(9);
 
 const dom = __webpack_require__(1);
 const { span } = dom;
 
 /**
  * Renders DOM element node.
  */
@@ -4367,17 +4421,17 @@ function supportsObject(object, noGrip =
 
 // Exports from this module
 module.exports = {
   rep: wrapRender(ElementNode),
   supportsObject
 };
 
 /***/ }),
-/* 41 */
+/* 43 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 /* 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/. */
@@ -4476,17 +4530,17 @@ function supportsObject(grip, noGrip = f
 
 // Exports from this module
 module.exports = {
   rep: wrapRender(TextNode),
   supportsObject
 };
 
 /***/ }),
-/* 42 */
+/* 44 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 /* 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/. */
@@ -4560,17 +4614,17 @@ function supportsObject(object, noGrip =
 
 // Exports from this module
 module.exports = {
   rep: wrapRender(ErrorRep),
   supportsObject
 };
 
 /***/ }),
-/* 43 */
+/* 45 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 /* 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/. */
@@ -4638,17 +4692,17 @@ function supportsObject(object, noGrip =
 
 // Exports from this module
 module.exports = {
   rep: wrapRender(WindowRep),
   supportsObject
 };
 
 /***/ }),
-/* 44 */
+/* 46 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 /* 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/. */
@@ -4657,17 +4711,17 @@ module.exports = {
 const PropTypes = __webpack_require__(2);
 
 // Reps
 const {
   isGrip,
   wrapRender
 } = __webpack_require__(0);
 
-const String = __webpack_require__(6).rep;
+const String = __webpack_require__(7).rep;
 
 const dom = __webpack_require__(1);
 const { span } = dom;
 
 /**
  * Renders a grip object with textual data.
  */
 ObjectWithText.propTypes = {
@@ -4703,17 +4757,17 @@ function supportsObject(grip, noGrip = f
 
 // Exports from this module
 module.exports = {
   rep: wrapRender(ObjectWithText),
   supportsObject
 };
 
 /***/ }),
-/* 45 */
+/* 47 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 /* 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/. */
@@ -4769,82 +4823,75 @@ function supportsObject(grip, noGrip = f
 
 // Exports from this module
 module.exports = {
   rep: wrapRender(ObjectWithURL),
   supportsObject
 };
 
 /***/ }),
-/* 46 */
+/* 48 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
-var _devtoolsComponents = __webpack_require__(47);
+var _devtoolsComponents = __webpack_require__(49);
 
 var _devtoolsComponents2 = _interopRequireDefault(_devtoolsComponents);
 
 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
 
 /* 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 { Component, createFactory } = __webpack_require__(7);
+const { Component, createFactory } = __webpack_require__(6);
 const PropTypes = __webpack_require__(2);
 const dom = __webpack_require__(1);
 
 const Tree = createFactory(_devtoolsComponents2.default.Tree);
-__webpack_require__(51);
-
-const classnames = __webpack_require__(52);
+__webpack_require__(55);
+
+const classnames = __webpack_require__(56);
 
 const {
   REPS: {
     Rep,
     Grip
   }
 } = __webpack_require__(4);
 const {
   MODE
 } = __webpack_require__(3);
 
+const Utils = __webpack_require__(15);
+
 const {
   getChildren,
   getClosestGripNode,
   getParent,
   getValue,
   nodeHasAccessors,
   nodeHasProperties,
   nodeIsDefaultProperties,
   nodeIsFunction,
   nodeIsGetter,
   nodeIsMapEntry,
   nodeIsMissingArguments,
   nodeIsOptimizedOut,
   nodeIsPrimitive,
   nodeIsPrototype,
   nodeIsSetter,
-  nodeIsWindow,
-  shouldLoadItemEntries,
-  shouldLoadItemIndexedProperties,
-  shouldLoadItemNonIndexedProperties,
-  shouldLoadItemPrototype,
-  shouldLoadItemSymbols
-} = __webpack_require__(16);
+  nodeIsWindow
+} = Utils.node;
 
 const {
-  enumEntries,
-  enumIndexedProperties,
-  enumNonIndexedProperties,
-  getPrototype,
-  enumSymbols
-} = __webpack_require__(54);
+  loadItemProperties
+} = Utils.loadProperties;
 
 // This implements a component that renders an interactive inspector
 // for looking at JavaScript objects. It expects descriptions of
 // objects from the protocol, and will dynamically fetch child
 // properties as objects are expanded.
 //
 // If you want to inspect a single object, pass the name and the
 // protocol descriptor of it:
@@ -4959,89 +5006,42 @@ class ObjectInspector extends Component 
       return {
         expandedPaths: newPaths
       };
     });
 
     if (expand === true) {
       const gripItem = getClosestGripNode(item);
       const value = getValue(gripItem);
-
       const path = item.path;
-      const [start, end] = item.meta ? [item.meta.startIndex, item.meta.endIndex] : [];
-
-      let promises = [];
-      let objectClient;
-      const getObjectClient = () => {
-        if (objectClient) {
-          return objectClient;
-        }
-        return this.props.createObjectClient(value);
-      };
-
-      if (shouldLoadItemIndexedProperties(item, loadedProperties)) {
-        promises.push(enumIndexedProperties(getObjectClient(), start, end));
-      }
-
-      if (shouldLoadItemNonIndexedProperties(item, loadedProperties)) {
-        promises.push(enumNonIndexedProperties(getObjectClient(), start, end));
-      }
-
-      if (shouldLoadItemEntries(item, loadedProperties)) {
-        promises.push(enumEntries(getObjectClient(), start, end));
-      }
-
-      if (shouldLoadItemPrototype(item, loadedProperties)) {
-        promises.push(getPrototype(getObjectClient()));
-      }
-
-      if (shouldLoadItemSymbols(item, loadedProperties)) {
-        promises.push(enumSymbols(getObjectClient(), start, end));
-      }
-
-      if (promises.length > 0) {
-        // Set the loading state with the pending promises.
+
+      const onItemPropertiesLoaded = loadItemProperties(item, this.props.createObjectClient, loadedProperties);
+      if (onItemPropertiesLoaded !== null) {
         this.setState((prevState, props) => {
           const nextLoading = new Map(prevState.loading);
-          nextLoading.set(path, promises);
+          nextLoading.set(path, onItemPropertiesLoaded);
           return {
             loading: nextLoading
           };
         });
 
-        const responses = await Promise.all(promises);
-
-        // Let's loop through the responses to build a single response object.
-        const response = responses.reduce((accumulator, res) => {
-          Object.entries(res).forEach(([k, v]) => {
-            if (accumulator.hasOwnProperty(k)) {
-              if (Array.isArray(accumulator[k])) {
-                accumulator[k].push(...v);
-              } else if (typeof accumulator[k] === "object") {
-                accumulator[k] = Object.assign({}, accumulator[k], v);
-              }
-            } else {
-              accumulator[k] = v;
-            }
-          });
-          return accumulator;
-        }, {});
+        const properties = await onItemPropertiesLoaded;
 
         this.setState((prevState, props) => {
           const nextLoading = new Map(prevState.loading);
           nextLoading.delete(path);
 
           const isRoot = this.props.roots.some(root => {
             const rootValue = getValue(root);
             return rootValue && rootValue.actor === value.actor;
           });
 
           return {
             actors: isRoot ? prevState.actors : new Set(prevState.actors).add(value.actor),
-            loadedProperties: new Map(prevState.loadedProperties).set(path, response),
+            loadedProperties: new Map(prevState.loadedProperties).set(path, properties),
             loading: nextLoading
           };
         });
       }
     }
   }
 
   focusItem(item) {
@@ -5205,76 +5205,72 @@ ObjectInspector.propTypes = {
   onFocus: PropTypes.func,
   onDoubleClick: PropTypes.func,
   onLabelClick: PropTypes.func
 };
 
 module.exports = ObjectInspector;
 
 /***/ }),
-/* 47 */
+/* 49 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+var _tree = __webpack_require__(50);
+
+var _tree2 = _interopRequireDefault(_tree);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+module.exports = {
+  Tree: _tree2.default
+}; /* 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/. */
+
+/***/ }),
+/* 50 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 
-var _tree = __webpack_require__(48);
-
-var _tree2 = _interopRequireDefault(_tree);
-
-function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
-
-exports.default = {
-  Tree: _tree2.default
-}; /* 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/. */
-
-/***/ }),
-/* 48 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
-  value: true
-});
-
-var _react = __webpack_require__(7);
+var _react = __webpack_require__(6);
 
 var _react2 = _interopRequireDefault(_react);
 
 var _reactDomFactories = __webpack_require__(1);
 
 var _reactDomFactories2 = _interopRequireDefault(_reactDomFactories);
 
 var _propTypes = __webpack_require__(2);
 
 var _propTypes2 = _interopRequireDefault(_propTypes);
 
-var _svgInlineReact = __webpack_require__(11);
+var _svgInlineReact = __webpack_require__(51);
 
 var _svgInlineReact2 = _interopRequireDefault(_svgInlineReact);
 
-var _arrow = __webpack_require__(49);
+var _arrow = __webpack_require__(53);
 
 var _arrow2 = _interopRequireDefault(_arrow);
 
 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
 
 const { Component, createFactory, createElement } = _react2.default; /* 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/. */
 
-__webpack_require__(50);
+__webpack_require__(54);
 
 const AUTO_EXPAND_DEPTH = 0; // depth
 
 /**
  * An arrow that displays whether its node is expanded (▼) or collapsed
  * (▶). When its node has no children, it is hidden.
  */
 class ArrowExpander extends Component {
@@ -6022,35 +6018,188 @@ class Tree extends Component {
       style
     }, nodes);
   }
 }
 
 exports.default = Tree;
 
 /***/ }),
-/* 49 */
+/* 51 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+
+var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
+
+var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
+
+var _react = __webpack_require__(6);
+
+var _react2 = _interopRequireDefault(_react);
+
+var _propTypes = __webpack_require__(2);
+
+var _util = __webpack_require__(52);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
+
+function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
+
+var process = process || { env: {} };
+
+var InlineSVG = function (_React$Component) {
+    _inherits(InlineSVG, _React$Component);
+
+    function InlineSVG() {
+        _classCallCheck(this, InlineSVG);
+
+        return _possibleConstructorReturn(this, (InlineSVG.__proto__ || Object.getPrototypeOf(InlineSVG)).apply(this, arguments));
+    }
+
+    _createClass(InlineSVG, [{
+        key: 'componentWillReceiveProps',
+        value: function componentWillReceiveProps(_ref) {
+            var children = _ref.children;
+
+            if ("production" !== process.env.NODE_ENV && children != null) {
+                console.info('<InlineSVG />: `children` prop will be ignored.');
+            }
+        }
+    }, {
+        key: 'render',
+        value: function render() {
+            var Element = void 0,
+                __html = void 0,
+                svgProps = void 0;
+
+            var _props = this.props,
+                element = _props.element,
+                raw = _props.raw,
+                src = _props.src,
+                otherProps = _objectWithoutProperties(_props, ['element', 'raw', 'src']);
+
+            if (raw === true) {
+                Element = 'svg';
+                svgProps = (0, _util.extractSVGProps)(src);
+                __html = (0, _util.getSVGFromSource)(src).innerHTML;
+            }
+            __html = __html || src;
+            Element = Element || element;
+            svgProps = svgProps || {};
+
+            return _react2.default.createElement(Element, _extends({}, svgProps, otherProps, { src: null, children: null,
+                dangerouslySetInnerHTML: { __html: __html } }));
+        }
+    }]);
+
+    return InlineSVG;
+}(_react2.default.Component);
+
+exports.default = InlineSVG;
+
+
+InlineSVG.defaultProps = {
+    element: 'i',
+    raw: false,
+    src: ''
+};
+
+InlineSVG.propTypes = {
+    src: _propTypes.string.isRequired,
+    element: _propTypes.string,
+    raw: _propTypes.bool
+};
+
+/***/ }),
+/* 52 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+exports.convertReactSVGDOMProperty = convertReactSVGDOMProperty;
+exports.startsWith = startsWith;
+exports.serializeAttrs = serializeAttrs;
+exports.getSVGFromSource = getSVGFromSource;
+exports.extractSVGProps = extractSVGProps;
+// Transform DOM prop/attr names applicable to `<svg>` element but react-limited
+
+function convertReactSVGDOMProperty(str) {
+    return str.replace(/[-|:]([a-z])/g, function (g) {
+        return g[1].toUpperCase();
+    });
+}
+
+function startsWith(str, substring) {
+    return str.indexOf(substring) === 0;
+}
+
+var DataPropPrefix = 'data-';
+// Serialize `Attr` objects in `NamedNodeMap`
+function serializeAttrs(map) {
+    var ret = {};
+    for (var prop, i = 0; i < map.length; i++) {
+        var key = map[i].name;
+        if (!startsWith(key, DataPropPrefix)) {
+            prop = convertReactSVGDOMProperty(key);
+        }
+        ret[prop] = map[i].value;
+    }
+    return ret;
+}
+
+function getSVGFromSource(src) {
+    var svgContainer = document.createElement('div');
+    svgContainer.innerHTML = src;
+    var svg = svgContainer.firstElementChild;
+    svg.remove(); // deref from parent element
+    return svg;
+}
+
+// get <svg /> element props
+function extractSVGProps(src) {
+    var map = getSVGFromSource(src).attributes;
+    return map.length > 0 ? serializeAttrs(map) : null;
+}
+
+/***/ }),
+/* 53 */
 /***/ (function(module, exports) {
 
 module.exports = "<!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --><svg viewBox=\"0 0 16 16\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M8 13.4c-.5 0-.9-.2-1.2-.6L.4 5.2C0 4.7-.1 4.3.2 3.7S1 3 1.6 3h12.8c.6 0 1.2.1 1.4.7.3.6.2 1.1-.2 1.6l-6.4 7.6c-.3.4-.7.5-1.2.5z\"></path></svg>"
 
 /***/ }),
-/* 50 */
+/* 54 */
 /***/ (function(module, exports) {
 
 // removed by extract-text-webpack-plugin
 
 /***/ }),
-/* 51 */
+/* 55 */
 /***/ (function(module, exports) {
 
 // removed by extract-text-webpack-plugin
 
 /***/ }),
-/* 52 */
+/* 56 */
 /***/ (function(module, exports, __webpack_require__) {
 
 var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
   Copyright (c) 2016 Jed Watson.
   Licensed under the MIT License (MIT), see
   http://jedwatson.github.io/classnames
 */
 /* global define */
@@ -6095,91 +6244,153 @@ var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBP
 				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
 	} else {
 		window.classNames = classNames;
 	}
 }());
 
 
 /***/ }),
-/* 53 */
-/***/ (function(module, exports) {
-
-module.exports = __WEBPACK_EXTERNAL_MODULE_53__;
-
-/***/ }),
-/* 54 */
+/* 57 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
-async function enumIndexedProperties(objectClient, start, end) {
-  try {
-    const { iterator } = await objectClient.enumProperties({ ignoreNonIndexedProperties: true });
-    const response = await iteratorSlice(iterator, start, end);
-    return response;
-  } catch (e) {
-    console.error("Error in enumIndexedProperties", e);
-    return {};
-  }
-} /* 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/. */
-
-async function enumNonIndexedProperties(objectClient, start, end) {
-  try {
-    const { iterator } = await objectClient.enumProperties({ ignoreIndexedProperties: true });
-    const response = await iteratorSlice(iterator, start, end);
-    return response;
-  } catch (e) {
-    console.error("Error in enumNonIndexedProperties", e);
-    return {};
-  }
-}
-
-async function enumEntries(objectClient, start, end) {
-  try {
-    const { iterator } = await objectClient.enumEntries();
-    const response = await iteratorSlice(iterator, start, end);
-    return response;
-  } catch (e) {
-    console.error("Error in enumEntries", e);
-    return {};
-  }
-}
-
-async function enumSymbols(objectClient, start, end) {
-  try {
-    const { iterator } = await objectClient.enumSymbols();
-    const response = await iteratorSlice(iterator, start, end);
-    return response;
-  } catch (e) {
-    console.error("Error in enumSymbols", e);
-    return {};
-  }
-}
-
-async function getPrototype(objectClient) {
-  if (typeof objectClient.getPrototype !== "function") {
-    console.error("objectClient.getPrototype is not a function");
-    return Promise.resolve({});
-  }
-  return objectClient.getPrototype();
-}
-
-function iteratorSlice(iterator, start, end) {
-  start = start || 0;
-  const count = end ? end - start + 1 : iterator.count;
-  return iterator.slice(start, count);
+/* 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 {
+  enumEntries,
+  enumIndexedProperties,
+  enumNonIndexedProperties,
+  getPrototype,
+  enumSymbols
+} = __webpack_require__(16);
+
+const {
+  getClosestGripNode,
+  getClosestNonBucketNode,
+  getValue,
+  nodeHasAccessors,
+  nodeHasAllEntriesInPreview,
+  nodeHasProperties,
+  nodeIsBucket,
+  nodeIsDefaultProperties,
+  nodeIsEntries,
+  nodeIsMapEntry,
+  nodeIsPrimitive,
+  nodeIsProxy,
+  nodeNeedsNumericalBuckets
+} = __webpack_require__(17);
+
+function loadItemProperties(item, createObjectClient, loadedProperties) {
+  const [start, end] = item.meta ? [item.meta.startIndex, item.meta.endIndex] : [];
+
+  let objectClient;
+  const getObjectClient = () => {
+    if (objectClient) {
+      return objectClient;
+    }
+
+    const gripItem = getClosestGripNode(item);
+    const value = getValue(gripItem);
+    return createObjectClient(value);
+  };
+
+  let loadingPromises = [];
+  if (shouldLoadItemIndexedProperties(item, loadedProperties)) {
+    loadingPromises.push(enumIndexedProperties(getObjectClient(), start, end));
+  }
+
+  if (shouldLoadItemNonIndexedProperties(item, loadedProperties)) {
+    loadingPromises.push(enumNonIndexedProperties(getObjectClient(), start, end));
+  }
+
+  if (shouldLoadItemEntries(item, loadedProperties)) {
+    loadingPromises.push(enumEntries(getObjectClient(), start, end));
+  }
+
+  if (shouldLoadItemPrototype(item, loadedProperties)) {
+    loadingPromises.push(getPrototype(getObjectClient()));
+  }
+
+  if (shouldLoadItemSymbols(item, loadedProperties)) {
+    loadingPromises.push(enumSymbols(getObjectClient(), start, end));
+  }
+
+  if (loadingPromises.length === 0) {
+    return null;
+  }
+
+  return Promise.all(loadingPromises).then(responses => responses.reduce((accumulator, res) => {
+    // Let's loop through the responses to build a single response object.
+    Object.entries(res).forEach(([k, v]) => {
+      if (accumulator.hasOwnProperty(k)) {
+        if (Array.isArray(accumulator[k])) {
+          accumulator[k].push(...v);
+        } else if (typeof accumulator[k] === "object") {
+          accumulator[k] = Object.assign({}, accumulator[k], v);
+        }
+      } else {
+        accumulator[k] = v;
+      }
+    });
+    return accumulator;
+  }, {}));
+}
+
+function shouldLoadItemIndexedProperties(item, loadedProperties = new Map()) {
+  const gripItem = getClosestGripNode(item);
+  const value = getValue(gripItem);
+
+  return value && nodeHasProperties(gripItem) && !loadedProperties.has(item.path) && !nodeIsProxy(item) && !nodeNeedsNumericalBuckets(item) && !nodeIsEntries(getClosestNonBucketNode(item))
+  // The data is loaded when expanding the window node.
+  && !nodeIsDefaultProperties(item);
+}
+
+function shouldLoadItemNonIndexedProperties(item, loadedProperties = new Map()) {
+  const gripItem = getClosestGripNode(item);
+  const value = getValue(gripItem);
+
+  return value && nodeHasProperties(gripItem) && !loadedProperties.has(item.path) && !nodeIsProxy(item) && !nodeIsEntries(getClosestNonBucketNode(item)) && !nodeIsBucket(item)
+  // The data is loaded when expanding the window node.
+  && !nodeIsDefaultProperties(item);
+}
+
+function shouldLoadItemEntries(item, loadedProperties = new Map()) {
+  const gripItem = getClosestGripNode(item);
+  const value = getValue(gripItem);
+
+  return value && nodeIsEntries(getClosestNonBucketNode(item)) && !nodeHasAllEntriesInPreview(gripItem) && !loadedProperties.has(item.path) && !nodeNeedsNumericalBuckets(item);
+}
+
+function shouldLoadItemPrototype(item, loadedProperties = new Map()) {
+  const value = getValue(item);
+
+  return value && !loadedProperties.has(item.path) && !nodeIsBucket(item) && !nodeIsMapEntry(item) && !nodeIsEntries(item) && !nodeIsDefaultProperties(item) && !nodeHasAccessors(item) && !nodeIsPrimitive(item);
+}
+
+function shouldLoadItemSymbols(item, loadedProperties = new Map()) {
+  const value = getValue(item);
+
+  return value && !loadedProperties.has(item.path) && !nodeIsBucket(item) && !nodeIsMapEntry(item) && !nodeIsEntries(item) && !nodeIsDefaultProperties(item) && !nodeHasAccessors(item) && !nodeIsPrimitive(item) && !nodeIsProxy(item);
 }
 
 module.exports = {
-  enumEntries,
-  enumIndexedProperties,
-  enumNonIndexedProperties,
-  enumSymbols,
-  getPrototype
+  loadItemProperties,
+  shouldLoadItemEntries,
+  shouldLoadItemIndexedProperties,
+  shouldLoadItemNonIndexedProperties,
+  shouldLoadItemPrototype,
+  shouldLoadItemSymbols
 };
 
+/***/ }),
+/* 58 */
+/***/ (function(module, exports) {
+
+module.exports = __WEBPACK_EXTERNAL_MODULE_58__;
+
 /***/ })
 /******/ ]);
 });
\ No newline at end of file
--- a/devtools/client/webconsole/new-console-output/test/mochitest/browser.ini
+++ b/devtools/client/webconsole/new-console-output/test/mochitest/browser.ini
@@ -275,21 +275,17 @@ skip-if = (e10s && debug) || (e10s && os
 [browser_webconsole_file_uri.js]
 skip-if = true #	Bug 1404382
 [browser_webconsole_filter_scroll.js]
 [browser_webconsole_filters.js]
 [browser_webconsole_filters_persist.js]
 [browser_webconsole_highlighter_console_helper.js]
 [browser_webconsole_history_arrow_keys.js]
 [browser_webconsole_hpkp_invalid-headers.js]
-skip-if = true #	Bug 1405340
-# old console skip-if = (os == 'win' && bits == 64) # Bug 1390001
 [browser_webconsole_hsts_invalid-headers.js]
-skip-if = true #	Bug 1405341
-# old console skip-if = e10s # Bug 1042253 - webconsole e10s tests
 [browser_webconsole_iframe_wrong_hud.js]
 skip-if = true #	Bug 1404378
 [browser_webconsole_ineffective_iframe_sandbox_warning.js]
 skip-if = true #	Bug 1404883
 # old console skip-if = (os == 'win' && bits == 64) # Bug 1390001
 [browser_webconsole_init.js]
 [browser_webconsole_input_expansion.js]
 skip-if = true #	Bug 1404371
--- a/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_hpkp_invalid-headers.js
+++ b/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_hpkp_invalid-headers.js
@@ -1,126 +1,107 @@
-/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
-/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
-// Tests that errors about invalid HPKP security headers are logged to the web
-// console.
+// Tests that errors about invalid HPKP security headers are logged to the web console.
 
 "use strict";
 
-const TEST_URI = "data:text/html;charset=utf-8,Web Console HPKP invalid " +
-                 "header test";
+const TEST_URI = "data:text/html;charset=utf-8,Web Console HPKP invalid header test";
 const SJS_URL = "https://example.com/browser/devtools/client/webconsole/" +
-                "test/test_hpkp-invalid-headers.sjs";
-const LEARN_MORE_URI = "https://developer.mozilla.org/docs/Web/HTTP/" +
-                       "Public_Key_Pinning" + DOCS_GA_PARAMS;
-const NON_BUILTIN_ROOT_PREF = "security.cert_pinning.process_headers_from_" +
-                              "non_builtin_roots";
+                "new-console-output/test/mochitest/test_hpkp-invalid-headers.sjs";
+const LEARN_MORE_URI =
+  "https://developer.mozilla.org/docs/Web/HTTP/Public_Key_Pinning" + DOCS_GA_PARAMS;
+const NON_BUILTIN_ROOT_PREF =
+  "security.cert_pinning.process_headers_from_non_builtin_roots";
 
-add_task(function* () {
+add_task(async function () {
   registerCleanupFunction(() => {
     Services.prefs.clearUserPref(NON_BUILTIN_ROOT_PREF);
   });
 
-  yield loadTab(TEST_URI);
+  let hud = await openNewTabAndConsole(TEST_URI);
 
-  let hud = yield openConsole();
-
-  yield* checkForMessage({
+  await navigateAndCheckForWarningMessage({
     url: SJS_URL + "?badSyntax",
     name: "Could not parse header error displayed successfully",
     text: "Public-Key-Pins: The site specified a header that could not be " +
           "parsed successfully."
   }, hud);
 
-  yield* checkForMessage({
+  await navigateAndCheckForWarningMessage({
     url: SJS_URL + "?noMaxAge",
     name: "No max-age error displayed successfully",
     text: "Public-Key-Pins: The site specified a header that did not include " +
           "a \u2018max-age\u2019 directive."
   }, hud);
 
-  yield* checkForMessage({
+  await navigateAndCheckForWarningMessage({
     url: SJS_URL + "?invalidIncludeSubDomains",
     name: "Invalid includeSubDomains error displayed successfully",
     text: "Public-Key-Pins: The site specified a header that included an " +
           "invalid \u2018includeSubDomains\u2019 directive."
   }, hud);
 
-  yield* checkForMessage({
+  await navigateAndCheckForWarningMessage({
     url: SJS_URL + "?invalidMaxAge",
     name: "Invalid max-age error displayed successfully",
     text: "Public-Key-Pins: The site specified a header that included an " +
           "invalid \u2018max-age\u2019 directive."
   }, hud);
 
-  yield* checkForMessage({
+  await navigateAndCheckForWarningMessage({
     url: SJS_URL + "?multipleIncludeSubDomains",
     name: "Multiple includeSubDomains error displayed successfully",
     text: "Public-Key-Pins: The site specified a header that included " +
           "multiple \u2018includeSubDomains\u2019 directives."
   }, hud);
 
-  yield* checkForMessage({
+  await navigateAndCheckForWarningMessage({
     url: SJS_URL + "?multipleMaxAge",
     name: "Multiple max-age error displayed successfully",
     text: "Public-Key-Pins: The site specified a header that included " +
           "multiple \u2018max-age\u2019 directives."
   }, hud);
 
-  yield* checkForMessage({
+  await navigateAndCheckForWarningMessage({
     url: SJS_URL + "?multipleReportURIs",
     name: "Multiple report-uri error displayed successfully",
     text: "Public-Key-Pins: The site specified a header that included " +
           "multiple \u2018report-uri\u2019 directives."
   }, hud);
 
   // The root used for mochitests is not built-in, so set the relevant pref to
   // true to have the PKP implementation return more specific errors.
   Services.prefs.setBoolPref(NON_BUILTIN_ROOT_PREF, true);
 
-  yield* checkForMessage({
+  await navigateAndCheckForWarningMessage({
     url: SJS_URL + "?pinsetDoesNotMatch",
     name: "Non-matching pinset error displayed successfully",
     text: "Public-Key-Pins: The site specified a header that did not include " +
           "a matching pin."
   }, hud);
 
   Services.prefs.setBoolPref(NON_BUILTIN_ROOT_PREF, false);
 
-  yield* checkForMessage({
+  await navigateAndCheckForWarningMessage({
     url: SJS_URL + "?pinsetDoesNotMatch",
     name: "Non-built-in root error displayed successfully",
     text: "Public-Key-Pins: The certificate used by the site was not issued " +
           "by a certificate in the default root certificate store. To " +
           "prevent accidental breakage, the specified header was ignored."
   }, hud);
 });
 
-function* checkForMessage(curTest, hud) {
-  hud.jsterm.clearOutput();
-
-  BrowserTestUtils.loadURI(gBrowser.selectedBrowser, curTest.url);
+async function navigateAndCheckForWarningMessage({name, text, url}, hud) {
+  hud.jsterm.clearOutput(true);
 
-  let results = yield waitForMessages({
-    webconsole: hud,
-    messages: [
-      {
-        name: curTest.name,
-        text: curTest.text,
-        category: CATEGORY_SECURITY,
-        severity: SEVERITY_WARNING,
-        objects: true,
-      },
-    ],
-  });
+  const onMessage = waitForMessage(hud, text, ".message.warning");
+  BrowserTestUtils.loadURI(gBrowser.selectedBrowser, url);
+  const {node} = await onMessage;
+  ok(node, name);
 
-  yield testClickOpenNewTab(hud, results);
+  let learnMoreNode = node.querySelector(".learn-more-link");
+  ok(learnMoreNode, `There is a "Learn more" link`);
+  const navigatedLink = await simulateLinkClick(learnMoreNode);
+  is(navigatedLink, LEARN_MORE_URI,
+    "Click on the learn more link navigates the user to the expected url");
 }
-
-function testClickOpenNewTab(hud, results) {
-  let warningNode = results[0].clickableElements[0];
-  ok(warningNode, "link element");
-  ok(warningNode.classList.contains("learn-more-link"), "link class name");
-  return simulateMessageLinkClick(warningNode, LEARN_MORE_URI);
-}
--- a/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_hsts_invalid-headers.js
+++ b/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_hsts_invalid-headers.js
@@ -1,92 +1,73 @@
-/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
-/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
-// Tests that errors about invalid HSTS security headers are logged
-//  to the web console.
+// Tests that errors about invalid HSTS security headers are logged to the web console.
 
 "use strict";
 
-const TEST_URI = "data:text/html;charset=utf-8,Web Console HSTS invalid " +
-                 "header test";
+const TEST_URI = "data:text/html;charset=utf-8,Web Console HSTS invalid header test";
 const SJS_URL = "https://example.com/browser/devtools/client/webconsole/" +
-                "test/test_hsts-invalid-headers.sjs";
+                "/new-console-output/test/mochitest/test_hsts-invalid-headers.sjs";
 const LEARN_MORE_URI = "https://developer.mozilla.org/docs/Web/HTTP/Headers/" +
                        "Strict-Transport-Security" + DOCS_GA_PARAMS;
 
-add_task(function* () {
-  yield loadTab(TEST_URI);
+add_task(async function () {
+  const hud = await openNewTabAndConsole(TEST_URI);
 
-  let hud = yield openConsole();
-
-  yield* checkForMessage({
+  await navigateAndCheckWarningMessage({
     url: SJS_URL + "?badSyntax",
     name: "Could not parse header error displayed successfully",
     text: "Strict-Transport-Security: The site specified a header that could " +
           "not be parsed successfully."
   }, hud);
 
-  yield* checkForMessage({
+  await navigateAndCheckWarningMessage({
     url: SJS_URL + "?noMaxAge",
     name: "No max-age error displayed successfully",
     text: "Strict-Transport-Security: The site specified a header that did " +
           "not include a \u2018max-age\u2019 directive."
   }, hud);
 
-  yield* checkForMessage({
+  await navigateAndCheckWarningMessage({
     url: SJS_URL + "?invalidIncludeSubDomains",
     name: "Invalid includeSubDomains error displayed successfully",
     text: "Strict-Transport-Security: The site specified a header that " +
           "included an invalid \u2018includeSubDomains\u2019 directive."
   }, hud);
 
-  yield* checkForMessage({
+  await navigateAndCheckWarningMessage({
     url: SJS_URL + "?invalidMaxAge",
     name: "Invalid max-age error displayed successfully",
     text: "Strict-Transport-Security: The site specified a header that " +
           "included an invalid \u2018max-age\u2019 directive."
   }, hud);
 
-  yield* checkForMessage({
+  await navigateAndCheckWarningMessage({
     url: SJS_URL + "?multipleIncludeSubDomains",
     name: "Multiple includeSubDomains error displayed successfully",
     text: "Strict-Transport-Security: The site specified a header that " +
           "included multiple \u2018includeSubDomains\u2019 directives."
   }, hud);
 
-  yield* checkForMessage({
+  await navigateAndCheckWarningMessage({
     url: SJS_URL + "?multipleMaxAge",
     name: "Multiple max-age error displayed successfully",
     text: "Strict-Transport-Security: The site specified a header that " +
           "included multiple \u2018max-age\u2019 directives."
   }, hud);
 });
 
-function* checkForMessage(curTest, hud) {
-  hud.jsterm.clearOutput();
-
-  BrowserTestUtils.loadURI(gBrowser.selectedBrowser, curTest.url);
+async function navigateAndCheckWarningMessage({url, name, text}, hud) {
+  hud.jsterm.clearOutput(true);
 
-  let results = yield waitForMessages({
-    webconsole: hud,
-    messages: [
-      {
-        name: curTest.name,
-        text: curTest.text,
-        category: CATEGORY_SECURITY,
-        severity: SEVERITY_WARNING,
-        objects: true,
-      },
-    ],
-  });
+  const onMessage = waitForMessage(hud, text, ".message.warning");
+  BrowserTestUtils.loadURI(gBrowser.selectedBrowser, url);
+  const {node} = await onMessage;
+  ok(node, name);
 
-  yield testClickOpenNewTab(hud, results);
+  let learnMoreNode = node.querySelector(".learn-more-link");
+  ok(learnMoreNode, `There is a "Learn more" link`);
+  const navigatedLink = await simulateLinkClick(learnMoreNode);
+  is(navigatedLink, LEARN_MORE_URI,
+    "Click on the learn more link navigates the user to the expected url");
 }
-
-function testClickOpenNewTab(hud, results) {
-  let warningNode = results[0].clickableElements[0];
-  ok(warningNode, "link element");
-  ok(warningNode.classList.contains("learn-more-link"), "link class name");
-  return simulateMessageLinkClick(warningNode, LEARN_MORE_URI);
-}
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,3 +1,4 @@
 org.gradle.parallel=true
 org.gradle.daemon=true
 org.gradle.jvmargs=-Xmx2560M
+android.enableAapt2=false
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,7 +1,7 @@
 #Fri Sep 16 15:41:50 PDT 2016
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-3.4.1-all.zip
-distributionSha256Sum=ed7e9c8bb41bd10d4c9339c95b2f8b122f5bf13188bd90504a26e0f00b123b0d
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip
+distributionSha256Sum=5c07b3bac2209fbc98fb1fdf6fd831f72429cdf8c503807404eae03d8c8099e5
--- a/mobile/android/app/build.gradle
+++ b/mobile/android/app/build.gradle
@@ -1,22 +1,23 @@
 buildDir "${topobjdir}/gradle/build/mobile/android/app"
 
 apply plugin: 'com.android.application'
 apply plugin: 'checkstyle'
 apply plugin: 'com.getkeepsafe.dexcount'
 apply plugin: 'findbugs'
 
+apply from: "${topsrcdir}/mobile/android/gradle/product_flavors.gradle"
+
 dexcount {
     format = "tree"
 }
 
 android {
     compileSdkVersion project.ext.compileSdkVersion
-    buildToolsVersion project.ext.buildToolsVersion
 
     defaultConfig {
         targetSdkVersion project.ext.targetSdkVersion
         minSdkVersion project.ext.minSdkVersion
         manifestPlaceholders = project.ext.manifestPlaceholders
 
         applicationId mozconfig.substs.ANDROID_PACKAGE_NAME
         testApplicationId 'org.mozilla.roboexample.test'
@@ -79,45 +80,23 @@ android {
     // The "audience" flavour dimension distinguishes between _local_ builds (intended for
     // development) and _official_ builds (intended for testing in automation and to ship in one of
     // the Fennec distribution channels).
     //
     // The "skin" flavor dimension distinguishes between different user interfaces.  We sometimes
     // want to develop significant new user interface pieces in-tree that don't ship (even in the
     // Nightly channel) while under development.  A new "skin" flavour allows us to develop such
     // pieces in Gradle without changing the mainline configuration.
-    flavorDimensions "audience", "skin"
+
+    project.configureProductFlavors.delegate = it
+    project.configureProductFlavors()
+
+    flavorDimensions "audience", "geckoBinaries", "minApi", "skin"
 
     productFlavors {
-        // For API 21+ - with pre-dexing, this will be faster for local development.
-        local {
-            dimension "audience"
-
-            // For pre-dexing, setting `minSdkVersion 21` allows the Android gradle plugin to
-            // pre-DEX each module and produce an APK that can be tested on
-            // Android Lollipop without time consuming DEX merging processes.
-            minSdkVersion 21
-            dexOptions {
-                preDexLibraries true
-            }
-        }
-        // For API < 21 - does not support pre-dexing because local development
-        // is slow in that case.
-        localOld {
-            dimension "audience"
-        }
-
-        // Automation builds.  We use "official" rather than "automation" to drive these builds down
-        // the list of configurations that Android Studio offers, thereby making it _not_ the
-        // default.  This avoids a common issue with "omni.ja" not being packed into the default APK
-        // built and deployed by Android Studio.
-        official {
-             dimension "audience"
-        }
-
         // Since Firefox 57, the mobile user interface has followed the Photon design.
         // Before Firefox 57, the user interface followed the Australis design.
         photon {
             dimension "skin"
         }
     }
 
     sourceSets {
@@ -157,48 +136,33 @@ android {
                 } else {
                     exclude 'org/mozilla/gecko/mma/MmaLeanplumImp.java'
                 }
 
                 if (!mozconfig.substs.MOZ_ANDROID_GCM) {
                     exclude 'org/mozilla/gecko/gcm/**/*.java'
                     exclude 'org/mozilla/gecko/push/**/*.java'
                 }
-
-                srcDir "${project.buildDir}/generated/source/preprocessed_code" // See syncPreprocessedCode.
             }
 
             res {
                 srcDir "${topsrcdir}/${mozconfig.substs.MOZ_BRANDING_DIRECTORY}/res"
-                srcDir "${project.buildDir}/generated/source/preprocessed_resources" // See syncPreprocessedResources.
                 srcDir "${topsrcdir}/mobile/android/services/src/main/res"
                 if (mozconfig.substs.MOZ_CRASHREPORTER) {
                     srcDir "${topsrcdir}/mobile/android/base/crashreporter/res"
                 }
             }
 
             assets {
                 if (mozconfig.substs.MOZ_ANDROID_DISTRIBUTION_DIRECTORY) {
                     srcDir "${mozconfig.substs.MOZ_ANDROID_DISTRIBUTION_DIRECTORY}/assets"
                 }
             }
         }
 
-        // Every configuration needs the stub manifest at
-        // src/main/AndroidManifest.xml and the generated manifest.  We can't
-        // use the main sourceSet without losing the stub, so we cover all the
-        // configurations by enumerating the buildTypes here.
-        debug {
-            manifest.srcFile "${project.buildDir}/generated/source/preprocessed_manifest/AndroidManifest.xml"
-        }
-
-        release {
-            manifest.srcFile "${project.buildDir}/generated/source/preprocessed_manifest/AndroidManifest.xml"
-        }
-
         test {
             java {
                 // Bug 1229149 tracks pushing this into a :services Gradle project.
                 srcDir "${topsrcdir}/mobile/android/services/src/test/java"
 
                 if (!mozconfig.substs.MOZ_ANDROID_GCM) {
                     exclude 'org/mozilla/gecko/gcm/**/*.java'
                     exclude 'org/mozilla/gecko/push/**/*.java'
@@ -222,169 +186,176 @@ android {
             }
             assets {
                 srcDir "${topsrcdir}/mobile/android/tests/browser/robocop/assets"
             }
         }
     }
 
     testOptions {
+        // For Robolectric: see https://github.com/robolectric/robolectric/issues/3333#issuecomment-324300418.
+        unitTests.includeAndroidResources true
+
         unitTests.all {
             // We'd like to use (Runtime.runtime.availableProcessors()/2), but
             // we have tests that start test servers and the bound ports
             // collide.  We'll fix this soon to have much faster test cycles.
             maxParallelForks 1
         }
     }
 }
 
 dependencies {
-    compile "com.android.support:support-v4:${mozconfig.substs.ANDROID_SUPPORT_LIBRARY_VERSION}"
-    compile "com.android.support:appcompat-v7:${mozconfig.substs.ANDROID_SUPPORT_LIBRARY_VERSION}"
-    compile "com.android.support:cardview-v7:${mozconfig.substs.ANDROID_SUPPORT_LIBRARY_VERSION}"
-    compile "com.android.support:recyclerview-v7:${mozconfig.substs.ANDROID_SUPPORT_LIBRARY_VERSION}"
-    compile "com.android.support:design:${mozconfig.substs.ANDROID_SUPPORT_LIBRARY_VERSION}"
-    compile "com.android.support:customtabs:${mozconfig.substs.ANDROID_SUPPORT_LIBRARY_VERSION}"
+    implementation "com.android.support:support-v4:${mozconfig.substs.ANDROID_SUPPORT_LIBRARY_VERSION}"
+    implementation "com.android.support:appcompat-v7:${mozconfig.substs.ANDROID_SUPPORT_LIBRARY_VERSION}"
+    implementation "com.android.support:cardview-v7:${mozconfig.substs.ANDROID_SUPPORT_LIBRARY_VERSION}"
+    implementation "com.android.support:recyclerview-v7:${mozconfig.substs.ANDROID_SUPPORT_LIBRARY_VERSION}"
+    implementation "com.android.support:design:${mozconfig.substs.ANDROID_SUPPORT_LIBRARY_VERSION}"
+    implementation "com.android.support:customtabs:${mozconfig.substs.ANDROID_SUPPORT_LIBRARY_VERSION}"
+    implementation "com.android.support:palette-v7:${mozconfig.substs.ANDROID_SUPPORT_LIBRARY_VERSION}"
 
     if (mozconfig.substs.MOZ_NATIVE_DEVICES) {
-        compile "com.android.support:mediarouter-v7:${mozconfig.substs.ANDROID_SUPPORT_LIBRARY_VERSION}"
-        compile "com.google.android.gms:play-services-basement:${mozconfig.substs.ANDROID_GOOGLE_PLAY_SERVICES_VERSION}"
-        compile "com.google.android.gms:play-services-base:${mozconfig.substs.ANDROID_GOOGLE_PLAY_SERVICES_VERSION}"
-        compile "com.google.android.gms:play-services-cast:${mozconfig.substs.ANDROID_GOOGLE_PLAY_SERVICES_VERSION}"
+        implementation "com.android.support:mediarouter-v7:${mozconfig.substs.ANDROID_SUPPORT_LIBRARY_VERSION}"
+        implementation "com.google.android.gms:play-services-basement:${mozconfig.substs.ANDROID_GOOGLE_PLAY_SERVICES_VERSION}"
+        implementation "com.google.android.gms:play-services-base:${mozconfig.substs.ANDROID_GOOGLE_PLAY_SERVICES_VERSION}"
+        implementation "com.google.android.gms:play-services-cast:${mozconfig.substs.ANDROID_GOOGLE_PLAY_SERVICES_VERSION}"
     }
 
     if (mozconfig.substs.MOZ_INSTALL_TRACKING) {
-        compile "com.google.android.gms:play-services-analytics:${mozconfig.substs.ANDROID_GOOGLE_PLAY_SERVICES_VERSION}"
-        compile "com.google.android.gms:play-services-basement:${mozconfig.substs.ANDROID_GOOGLE_PLAY_SERVICES_VERSION}"
+        implementation "com.google.android.gms:play-services-analytics:${mozconfig.substs.ANDROID_GOOGLE_PLAY_SERVICES_VERSION}"
+        implementation "com.google.android.gms:play-services-basement:${mozconfig.substs.ANDROID_GOOGLE_PLAY_SERVICES_VERSION}"
     }
 
     if (mozconfig.substs.MOZ_ANDROID_GCM) {
-        compile "com.google.android.gms:play-services-basement:${mozconfig.substs.ANDROID_GOOGLE_PLAY_SERVICES_VERSION}"
-        compile "com.google.android.gms:play-services-base:${mozconfig.substs.ANDROID_GOOGLE_PLAY_SERVICES_VERSION}"
-        compile "com.google.android.gms:play-services-gcm:${mozconfig.substs.ANDROID_GOOGLE_PLAY_SERVICES_VERSION}"
-        compile "com.google.android.gms:play-services-measurement:${mozconfig.substs.ANDROID_GOOGLE_PLAY_SERVICES_VERSION}"
+        implementation "com.google.android.gms:play-services-basement:${mozconfig.substs.ANDROID_GOOGLE_PLAY_SERVICES_VERSION}"
+        implementation "com.google.android.gms:play-services-base:${mozconfig.substs.ANDROID_GOOGLE_PLAY_SERVICES_VERSION}"
+        implementation "com.google.android.gms:play-services-gcm:${mozconfig.substs.ANDROID_GOOGLE_PLAY_SERVICES_VERSION}"
+        implementation "com.google.android.gms:play-services-measurement:${mozconfig.substs.ANDROID_GOOGLE_PLAY_SERVICES_VERSION}"
     }
 
-    // Include LeakCanary in most gradle based builds. LeakCanary adds about 5k methods, so we disable
-    // it for the (non-proguarded, non-predex) localOld builds to allow space for other libraries.
-    // Gradle based tests include the no-op version.  Mach based builds only include the no-op version
-    // of this library.
-    // It doesn't seem like there is a non-trivial way to be conditional on 'localOld', so instead we explicitly
-    // define a version of leakcanary for every flavor:
-    localCompile 'com.squareup.leakcanary:leakcanary-android:1.4-beta1'
-    localOldCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.4-beta1'
-    officialCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.4-beta1'
-    officialCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.4-beta1'
-    testCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.4-beta1'
+    // Include LeakCanary in most gradle based builds.  Gradle based tests
+    // include the no-op version.  Mach based builds only include the no-op
+    // version of this library.
+    debugImplementation 'com.squareup.leakcanary:leakcanary-android:1.4-beta1'
+    releaseImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.4-beta1'
+    testImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.4-beta1'
 
-    // With a simple "compile", Gradle will always build these libraries in their default configuration
-    // (i.e. release), so we need to explicitly forward our own build configuration here (bug 1385695).
-    //
-    // Official builds compile a hacked up app:Official..Debug, but need the
-    // release versions of the dependencies, in order to not have debugging
-    // information.  It's not yet possible to specify just officialDebug, so we
-    // hack around it here.
-    if (mozconfig.substs.MOZILLA_OFFICIAL) {
-        debugCompile project(path: ':geckoview', configuration: "release")
-    } else {
-        debugCompile project(path: ':geckoview', configuration: "debug")
-    }
-    releaseCompile project(path: ':geckoview', configuration: "release")
+    implementation project(path: ':geckoview')
+    implementation project(path: ':thirdparty')
 
-    if (mozconfig.substs.MOZILLA_OFFICIAL) {
-        debugCompile project(path: ':thirdparty', configuration: "release")
-    } else {
-        debugCompile project(path: ':thirdparty', configuration: "debug")
-    }
-    releaseCompile project(path: ':thirdparty', configuration: "release")
-
-    testCompile 'junit:junit:4.12'
-    testCompile 'org.robolectric:robolectric:3.1.2'
-    testCompile 'org.simpleframework:simple-http:6.0.1'
-    testCompile 'org.mockito:mockito-core:1.10.19'
+    testImplementation 'junit:junit:4.12'
+    testImplementation 'org.robolectric:robolectric:3.5.1'
+    testImplementation 'org.simpleframework:simple-http:6.0.1'
+    testImplementation 'org.mockito:mockito-core:1.10.19'
 
     // Including the Robotium JAR directly can cause issues with dexing.
-    androidTestCompile 'com.jayway.android.robotium:robotium-solo:5.5.4'
+    androidTestImplementation 'com.jayway.android.robotium:robotium-solo:5.5.4'
 }
 
 // TODO: (bug 1261486): This impl is not robust -
 // we just wanted to land something.
 task checkstyle(type: Checkstyle) {
     configFile file("checkstyle.xml")
     // TODO: should use sourceSets from project instead of hard-coded str.
     source = ['../base/java/','../geckoview/src/main/java/']
     // TODO: This ignores our pre-processed resources.
     include '**/*.java'
     // TODO: classpath should probably be something.
     classpath = files()
 }
 
-task syncPreprocessedCode(type: Sync, dependsOn: rootProject.generateCodeAndResources) {
-    into("${project.buildDir}/generated/source/preprocessed_code")
-    from("${topobjdir}/mobile/android/base/generated/preprocessed")
-}
-
 // The localization system uses the moz.build preprocessor to interpolate a .dtd
 // file of XML entity definitions into an XML file of elements referencing those
 // entities.  (Each locale produces its own .dtd file, backstopped by the en-US
 // .dtd file in tree.)  Android Studio (and IntelliJ) don't handle these inline
 // entities smoothly.  This filter merely expands the entities in place, making
 // them appear properly throughout the IDE.  Be aware that this assumes that the
 // JVM's file.encoding is utf-8.  See comments in
 // mobile/android/mach_commands.py.
 class ExpandXMLEntitiesFilter extends FilterReader {
     ExpandXMLEntitiesFilter(Reader input) {
         // Extremely inefficient, but whatever.
         super(new StringReader(groovy.xml.XmlUtil.serialize(new XmlParser(false, false, true).parse(input))))
     }
 }
 
-task syncPreprocessedResources(type: Sync, dependsOn: rootProject.generateCodeAndResources) {
-    into("${project.buildDir}/generated/source/preprocessed_resources")
-    from("${topobjdir}/mobile/android/base/res")
-    filesMatching('**/strings.xml') {
-        filter(ExpandXMLEntitiesFilter)
-    }
-}
-
-// It's not easy -- see the backout in Bug 1242213 -- to change the <manifest>
-// package for Fennec.  Gradle has grown a mechanism to achieve what we want for
-// Fennec, however, with applicationId.  To use the same manifest as moz.build,
-// we replace the package with org.mozilla.gecko (the eventual package) here.
-task rewriteManifestPackage(type: Copy, dependsOn: rootProject.generateCodeAndResources) {
-    into("${project.buildDir}/generated/source/preprocessed_manifest")
-    from("${topobjdir}/mobile/android/base/AndroidManifest.xml")
-    filter { it.replaceFirst(/package=".*?"/, 'package="org.mozilla.gecko"') }
-}
-
 apply from: "${topsrcdir}/mobile/android/gradle/with_gecko_binaries.gradle"
 
 android.applicationVariants.all { variant ->
-    variant.preBuild.dependsOn rewriteManifestPackage
-    variant.preBuild.dependsOn syncPreprocessedCode
-    variant.preBuild.dependsOn syncPreprocessedResources
+    def syncPreprocessedJava = task("syncPreprocessedJavaFor${variant.name.capitalize()}", type: Sync) {
+        into("${project.buildDir}/moz.build/src/${variant.name}/java")
+        from("${topobjdir}/mobile/android/base/generated/preprocessed")
+        exclude('**/*.mkdir.done')
+    }
+    // This is an Android-Gradle plugin 3+-ism.  Culted from reading the source,
+    // searching for "registerJavaGeneratingTask", and finding
+    // https://github.com/GoogleCloudPlatform/endpoints-framework-gradle-plugin/commit/2f2b91476fb1c6647791e2c6fe531a47615a1e85.
+    // The added directory doesn't appear in the paths listed by the
+    // `sourceSets` task, for reasons unknown.
+    variant.registerJavaGeneratingTask(syncPreprocessedJava, syncPreprocessedJava.destinationDir)
+
+    def syncPreprocessedRes = task("syncPreprocessedResFor${variant.name.capitalize()}", type: Sync) {
+        into("${project.buildDir}/moz.build/src/${variant.name}/res")
+        from("${topobjdir}/mobile/android/base/res")
+        filesMatching('**/strings.xml') {
+            filter(ExpandXMLEntitiesFilter)
+        }
+        exclude('**/*.mkdir.done')
+    }
+    // This is an Android-Gradle plugin 3+-ism.  Determined by reading the
+    // source.  The added directory doesn't appear in the paths listed by the
+    // `sourceSets` task, for reasons unknown.
+    variant.registerGeneratedResFolders(project.files(syncPreprocessedRes.destinationDir).builtBy(syncPreprocessedRes))
 
-    // Official automation builds don't include Gecko binaries, since those binaries are not
-    // produced until after build time (at package time).  official Therefore, automation builds
-    // include the Gecko binaries into the APK at package time.  The "withGeckoBinaries" variant of
-    // the :geckoview project also does this.  (It does what it says on the tin!)  For notes on this
-    // approach, see mobile/android/gradle/with_gecko_binaries.gradle.
+    // It's not easy -- see the backout in Bug 1242213 -- to change the
+    // <manifest> package for Fennec.  Gradle has grown a mechanism to achieve
+    // what we want for Fennec, however, with applicationId.  To use the same
+    // manifest as moz.build, we replace the package with org.mozilla.gecko (the
+    // eventual package) here.
+    def rewriteManifestPackage = task("rewriteManifestPackageFor${variant.name.capitalize()}", type: Copy, dependsOn: rootProject.generateCodeAndResources) {
+        into("${project.buildDir}/moz.build/src/${variant.name}")
+        from("${topobjdir}/mobile/android/base/AndroidManifest.xml")
+        filter { it.replaceFirst(/package=".*?"/, 'package="org.mozilla.gecko"') }
+        exclude('**/*.mkdir.done')
+    }
+
+    // Every configuration needs the stub manifest at
+    // src/main/AndroidManifest.xml and the generated manifest.  We can't use
+    // the main sourceSet without losing the stub, so we cover all the
+    // configurations here.
+    android.sourceSets."${variant.name}".manifest.srcFile "${rewriteManifestPackage.destinationDir}/AndroidManifest.xml"
+    variant.preBuild.dependsOn rewriteManifestPackage
+
 
-    // Like 'local' or 'localOld'.
-    def audienceDimension = variant.productFlavors[0].name
+    // Local (read, not 'official') builds want to reflect developer changes to
+    // AndroidManifest.xml.in, strings.xml, and preprocessed Java code.  To do
+    // this, the Gradle build calls out to the moz.build system, which can be
+    // re-entrant.  Official builds are driven by the moz.build system and
+    // should never be re-entrant in this way.
+    if (!((variant.productFlavors*.name).contains('official'))) {
+        syncPreprocessedJava.dependsOn rootProject.generateCodeAndResources
+        syncPreprocessedRes.dependsOn rootProject.generateCodeAndResources
+        rewriteManifestPackage.dependsOn rootProject.generateCodeAndResources
+    }
 
-    // :app uses :geckoview:release and handles it's own Gecko binary inclusion,
-    // even though this would be most naturally done in the :geckoview project.
-    if (!audienceDimension.equals('official')) {
+    // When driven from moz.build via |mach build|, Gradle does not require or
+    // use Gecko binaries.  It's only |mach package| that packs the Gecko
+    // binaries into the resulting APK.  The "withoutGeckoBinaries" variants
+    // handle this.  When driven from Android Studio or Gradle, the
+    // "withGeckoBinaries" variants handle packing the Gecko binaries into the
+    // resulting APK (for on-device deployment).  They also update the Omnijars
+    // as necessary, smoothing out the edit-compile-test development cycle.
+    // They do what they say on the tin!
+    if ((variant.productFlavors*.name).contains('withGeckoBinaries')) {
         configureVariantWithGeckoBinaries(variant)
     }
 }
 
 android.applicationVariants.all { variant ->
-    configureVariantWithJNIWrappers(variant, "Fennec")
+    configureApplicationVariantWithJNIWrappers(variant, "Fennec")
 }
 
 if (gradle.startParameter.taskNames.any { it.endsWith('UnitTest') }) {
     // Approach cribbed from https://github.com/rwinch/jce-checker.
     int maxKeyLen = javax.crypto.Cipher.getMaxAllowedKeyLength("AES")
     if (maxKeyLen <= 128) {
         throw new GradleException(
             "Android unit tests require " +
@@ -411,17 +382,17 @@ android.applicationVariants.all { varian
         source = variant.javaCompile.source
         classpath = variant.javaCompile.classpath
 
         excludeFilter = file("findbugs-exclude.xml")
         dependsOn "assemble${variant.name.capitalize()}"
 
         reports {
             html.enabled = true // HTML reports for humans.
-            html.destination = "$project.buildDir/reports/findbugs/findbugs-${variant.name}-output.html"
+            html.destination = file("$project.buildDir/reports/findbugs/findbugs-${variant.name}-output.html")
             xml.enabled = false
         }
     }
 
     task("findbugsXml${variant.name.capitalize()}", type: FindBugs) {
         // TODO: figure out how to share the shared configuration.
         description "Analyze ${variant.name} code with findbugs (XML report)"
         group "Verification"
@@ -435,17 +406,17 @@ android.applicationVariants.all { varian
         source = variant.javaCompile.source
         classpath = variant.javaCompile.classpath
 
         excludeFilter = file("findbugs-exclude.xml")
         dependsOn "assemble${variant.name.capitalize()}"
 
         reports {
             xml.enabled = true // XML reports for machines.
-            xml.destination = "$project.buildDir/reports/findbugs/findbugs-${variant.name}-output.xml"
+            xml.destination = file("$project.buildDir/reports/findbugs/findbugs-${variant.name}-output.xml")
             html.enabled = false
         }
     }
 }
 
 // Bug 1353055 - Strip 'vars' debugging information to agree with moz.build.
 apply from: "${topsrcdir}/mobile/android/gradle/debug_level.gradle"
 android.applicationVariants.all configureVariantDebugLevel
@@ -461,18 +432,17 @@ android.applicationVariants.all { varian
     // Like 'local', 'localOld', or 'official'.
     def audienceDimension = variant.productFlavors[0].name
     if (!audienceDimension.equals('official')) {
         return
     }
 
     variant.outputs.each { output ->
         output.processManifest.doLast {
-            [output.processManifest.manifestOutputFile,
-             output.processManifest.instantRunManifestOutputFile,
+            [file("${manifestOutputDirectory}/AndroidManifest.xml"),
             ].each({ File manifestOutFile ->
                 if (manifestOutFile.exists()) {
                     def contents = manifestOutFile.getText('UTF-8')
 
                     // A non-validating, non-namespace aware XML processor.
                     def xml = new XmlSlurper(false, false).parseText(contents)
 
                     // First, reinstate our <activity-alias android:name=".App">.
--- a/mobile/android/app/lint.xml
+++ b/mobile/android/app/lint.xml
@@ -33,30 +33,28 @@
     <issue id="Instantiatable" severity="warning" />
     <issue id="LongLogTag" severity="warning" />
     <issue id="MissingPermission" severity="warning" />
     <issue id="OnClick" severity="warning" />
     <issue id="ReferenceType" severity="warning" />
     <issue id="ResourceAsColor" severity="warning" />
     <issue id="ResourceType" severity="warning" />
     <issue id="ValidFragment" severity="warning" />
-    <issue id="WrongConstant" severity="warning" />
 
     <!-- New Android-Gradle lint integration regressed this check. -->
     <issue id="MissingRegistered" severity="warning" />
 
     <!-- Fixes are in progress but we would like to block future candidates.
          The ** in the path are wildcards. We need these wildcards to not change our code structure.
          See: http://stackoverflow.com/questions/43994420/what-path-is-the-issue-ignore-path-element-in-lint-xml-relative-to -->
     <issue id="NewApi" severity="error">
         <ignore path="**/mobile/android/base/java/org/mozilla/gecko/activitystream/ActivityStreamPreference.java"/>
         <ignore path="**/mobile/android/base/java/org/mozilla/gecko/dlc/DownloadContentTelemetry.java"/>
         <ignore path="**/mobile/android/base/java/org/mozilla/gecko/preferences/LocaleListPreference.java"/>
         <ignore path="**/mobile/android/base/java/org/mozilla/gecko/media/MediaControlService.java"/>
-        <ignore path="**/mobile/android/base/java/org/mozilla/gecko/db/PerProfileDatabaseProvider.java"/>
         <ignore path="**/mobile/android/base/java/org/mozilla/gecko/PrintHelper.java"/>
         <ignore path="**/mobile/android/base/java/org/mozilla/gecko/animation/PropertyAnimator.java"/>
         <ignore path="**/mobile/android/base/java/org/mozilla/gecko/RemotePresentationService.java"/>
         <ignore path="**/mobile/android/base/java/org/mozilla/gecko/db/SharedBrowserDatabaseProvider.java"/>
         <ignore path="**/mobile/android/base/java/org/mozilla/gecko/tabs/TabPanelBackButton.java"/>
         <ignore path="**/mobile/android/base/java/org/mozilla/gecko/toolbar/ToolbarEditText.java"/>
         <ignore path="**/mobile/android/base/java/org/mozilla/gecko/util/ViewUtil.java"/>
         <ignore path="**/mobile/android/base/java/org/mozilla/gecko/IntentHelper.java"/>
--- a/mobile/android/app/src/main/res/drawable/ic_as_trending.xml
+++ b/mobile/android/app/src/main/res/drawable/ic_as_trending.xml
@@ -1,9 +1,9 @@
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:width="24dp"
         android:height="24dp"
         android:viewportWidth="12.0"
         android:viewportHeight="12.0">
     <path
         android:fillColor="@color/activity_stream_icon"
-        android:pathData="M4.97.151l-2.819,6.5A.25.25,0,0,0,2.381,7H4.029a.25.25,0,0,1,.225.359L2,12,9.4,5.437A.25.25,0,0,0,9.234,5H6.791a.25.25,0,0,1-.19-.412L10.15.412A.25.25,0,0,0,9.959,0H5.2A.25.25,0,0,0,4.97.151Z"/>
+        android:pathData="M4.97,0.151l-2.819,6.5A0.25,0.25,0,0,0,2.381,7H4.029a0.25,0.25,0,0,1,0.225,0.359L2,12,9.4,5.437A0.25,0.25,0,0,0,9.234,5H6.791a0.25,0.25,0,0,1,-0.19,-0.412L10.15,0.412A0.25,0.25,0,0,0,9.959,0H5.2A0.25,0.25,0,0,0,4.97,0.151Z"/>
 </vector>
--- a/mobile/android/app/src/main/res/layout/customtabs_action_bar_custom_view.xml
+++ b/mobile/android/app/src/main/res/layout/customtabs_action_bar_custom_view.xml
@@ -35,26 +35,25 @@
         android:animateLayoutChanges="true"
         android:gravity="center_vertical"
         android:orientation="vertical">
 
         <TextView
             android:id="@+id/custom_tabs_action_bar_title"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:lines="1"
+            android:singleLine="true"
             android:textColor="?android:textColorPrimary"
             android:textSize="14sp"
             tools:text="Mozilla.org"/>
 
         <TextView
             android:id="@+id/custom_tabs_action_bar_url"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:lines="1"
             android:singleLine="true"
             android:textColor="?android:textColorPrimary"
             android:textSize="10sp"
             android:ellipsize="middle"
             android:scrollHorizontally="true"
             tools:text="https://mozilla.org"/>
 
     </LinearLayout>
--- a/mobile/android/app/src/main/res/values-v11/themes.xml
+++ b/mobile/android/app/src/main/res/values-v11/themes.xml
@@ -10,25 +10,16 @@
         in other res/values-XXX/themes.xml.
     -->
     <style name="GeckoBase" parent="Theme.AppCompat.Light.DarkActionBar">
         <item name="android:windowContentOverlay">@null</item>
         <item name="windowActionBar">false</item>
         <item name="windowNoTitle">true</item>
     </style>
 
-    <style name="GeckoDialogBase" parent="@android:style/Theme.Holo.Light.Dialog">
-        <item name="android:windowContentOverlay">@null</item>
-        <item name="android:windowActionBar">false</item>
-        <item name="android:windowNoTitle">true</item>
-        <item name="android:windowBackground">@android:color/transparent</item>
-    </style>
-
-    <style name="GeckoTitleDialogBase" parent="@android:style/Theme.Holo.Light.Dialog" />
-
     <!--
         Activity based themes for API 11+. This theme completely replaces
         GeckoAppBase from res/values/themes.xml on API 11+ devices.
     -->
     <style name="GeckoAppBase" parent="Gecko">
         <item name="android:actionButtonStyle">@style/GeckoActionBar.Button</item>
         <item name="android:actionModeCopyDrawable">@drawable/ab_copy</item>
         <item name="android:actionModeCutDrawable">@drawable/ab_cut</item>
deleted file mode 100644
--- a/mobile/android/app/src/main/res/values-v13/search_styles.xml
+++ /dev/null
@@ -1,15 +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/. -->
-
-<resources>
-
-    <!-- Base application theme. -->
-    <style name="AppTheme" parent="@android:style/Theme.Holo.Light.NoActionBar">
-        <item name="android:windowBackground">@color/toolbar_grey</item>
-        <item name="android:colorBackground">@color/toolbar_grey</item>
-    </style>
-
-    <style name="SettingsTheme" parent="@android:style/Theme.Holo.Light"/>
-
-</resources>
deleted file mode 100644
--- a/mobile/android/app/src/main/res/values-v16/search_styles.xml
+++ /dev/null
@@ -1,19 +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/. -->
-
-<resources>
-
-    <style name="TextAppearance.EmptyView.Title" parent="@android:style/TextAppearance.Small">
-        <item name="android:textColor">@color/text_and_tabs_tray_grey</item>
-        <item name="android:textSize">20sp</item>
-        <item name="android:fontFamily">sans-serif-light</item>
-    </style>
-
-    <style name="TextAppearance.EmptyView.Message" parent="@android:style/TextAppearance.Small">
-        <item name="android:textColor">@color/placeholder_grey</item>
-        <item name="android:textSize">16sp</item>
-        <item name="android:lineSpacingExtra">4sp</item>
-    </style>
-
-</resources>
rename from mobile/android/base/resources/values-v17/themes.xml
rename to mobile/android/app/src/main/res/values-v17/themes.xml
--- a/mobile/android/app/src/main/res/values/themes.xml
+++ b/mobile/android/app/src/main/res/values/themes.xml
@@ -1,32 +1,26 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!-- 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/. -->
 
-<resources>
+<resources
+    xmlns:tools="http://schemas.android.com/tools">
 
     <!--
         Base application theme. This could be overridden by GeckoBaseTheme
         in other res/values-XXX/themes.xml.
     -->
     <style name="GeckoBase" parent="Theme.AppCompat.Light.DarkActionBar">
         <item name="windowNoTitle">true</item>
         <item name="windowActionBar">false</item>
         <item name="android:windowContentOverlay">@null</item>
     </style>
 
-    <style name="GeckoDialogBase" parent="@android:style/Theme.Dialog">
-        <item name="android:windowNoTitle">true</item>
-        <item name="android:windowContentOverlay">@null</item>
-    </style>
-
-    <style name="GeckoTitleDialogBase" parent="@android:style/Theme.Dialog" />
-
     <style name="Gecko.Preferences">
         <item name="windowActionBar">true</item>
         <item name="windowNoTitle">false</item>
         <item name="actionBarTheme">@style/ThemeOverlay.AppCompat.Dark.ActionBar</item>
         <item name="actionBarStyle">@style/PreferencesActionBar</item>
     </style>
 
     <!--
@@ -68,20 +62,16 @@
         <item name="android:textAppearanceMediumInverse">@style/TextAppearance.Medium.Inverse</item>
         <item name="android:textAppearanceSmallInverse">@style/TextAppearance.Small.Inverse</item>
 
         <item name="colorAccent">@color/action_accent</item>
 
         <item name="actionBarTheme">@style/GeckoActionBar</item>
     </style>
 
-    <style name="Gecko.Dialog" parent="GeckoDialogBase"/>
-
-    <style name="Gecko.TitleDialog" parent="GeckoTitleDialogBase"/>
-
     <!--
         Activity based themes, dependent on API level. This theme is replaced
         by GeckoAppBase from res/values-vXX/themes.xml on newer devices.
     -->
     <style name="GeckoAppBase" parent="Gecko">
         <item name="android:buttonStyle">@style/Widget.Button</item>
         <item name="android:dropDownItemStyle">@style/Widget.DropDownItem</item>
         <item name="android:editTextStyle">@style/Widget.EditText</item>
@@ -121,17 +111,18 @@
 
     <style name="GeckoCustomTabs" parent="Theme.AppCompat.Light.NoActionBar">
         <item name="menuItemActionBarStyle">@style/Widget.MenuItemActionBar</item>
         <item name="menuItemDefaultStyle">@style/Widget.MenuItemCustomTabs</item>
         <item name="windowActionModeOverlay">true</item>
     </style>
 
     <!-- Bookmark full-page dialog theme -->
-    <style name="Bookmark" parent="Theme.AppCompat.Light.DialogWhenLarge"/>
+    <style name="Bookmark" parent="Theme.AppCompat.Light.DialogWhenLarge"
+           tools:ignore="UnusedResources" />
     <style name="Bookmark.Gecko" parent="Gecko">
         <item name="toolbarStyle">@style/BookmarkToolbarStyle</item>
         <item name="colorAccent">@color/fennec_ui_accent</item>
         <item name="colorControlNormal">@color/disabled_grey</item>
 
         <item name="android:textColorHint">@color/tabs_tray_icon_grey</item>
     </style>
     <style name="BookmarkToolbarStyle.Base" parent="@style/Widget.AppCompat.Toolbar">
--- a/mobile/android/app/src/photon/res/values-v11/styles.xml
+++ b/mobile/android/app/src/photon/res/values-v11/styles.xml
@@ -1,15 +1,16 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <!-- 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/. -->
 
-<resources xmlns:android="http://schemas.android.com/apk/res/android">
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+           xmlns:tools="http://schemas.android.com/tools">
 
     <!--
         Only overriden styles for Honeycomb/Ice cream sandwich are specified here.
         Please refer to values/styles.xml for default styles.
     -->
 
     <!--
         Base application styles. This could be overridden in other res/values-XXX/themes.xml.
@@ -21,19 +22,16 @@
     <style name="Widget.BaseEditText" parent="android:style/Widget.Holo.Light.EditText" />
 
     <style name="Widget.BaseListView" parent="android:style/Widget.Holo.ListView" />
 
     <style name="Widget.BaseGridView" parent="android:style/Widget.Holo.GridView" />
 
     <style name="Widget.BaseTextView" parent="android:style/Widget.Holo.Light.TextView" />
 
-    <style name="Widget.ProgressBar.Horizontal" parent="android:style/Widget.Holo.ProgressBar.Horizontal" />
-
-
     <!--
         Application styles. All customizations that are not specific
         to a particular API level can go here.
     -->
     <style name="Widget.ListItem">
         <item name="android:textColor">@color/select_item_multichoice</item>
         <item name="android:minHeight">?android:attr/listPreferredItemHeight</item>
         <item name="android:textAppearance">?android:attr/textAppearanceLarge</item>
@@ -42,28 +40,16 @@
         <item name="android:paddingRight">7dip</item>
         <item name="android:checkMark">?android:attr/listChoiceIndicatorMultiple</item>
         <item name="android:ellipsize">marquee</item>
     </style>
 
     <!-- ActionBar -->
     <style name="ActionBar" parent="android:style/Widget.Holo.ActionBar" />
 
-    <!-- TabsLayout ActionBar -->
-    <style name="ActionBar.TabsLayout">
-        <item name="android:visibility">gone</item>
-    </style>
-
-    <!-- DropDown List View -->
-    <style name="DropDownListView" parent="@android:style/Widget.Holo.ListView.DropDown">
-        <item name="android:listSelector">@drawable/action_bar_button</item>
-        <item name="android:divider">@color/toolbar_divider_grey</item>
-        <item name="android:dividerHeight">@dimen/page_row_divider_height</item>
-    </style>
-
     <!-- Spinner DropDown Item -->
     <style name="Widget.DropDownItem.Spinner" parent="@android:style/Widget.Holo.Light.DropDownItem.Spinner">
         <item name="android:textColor">#FF000000</item>
     </style>
 
     <style name="Widget.Spinner" parent="android:style/Widget.Holo.Light.Spinner">
         <item name="android:minWidth">@dimen/doorhanger_input_width</item>
     </style>
@@ -103,14 +89,15 @@
         <item name="android:layout_marginTop">16dp</item>
         <item name="android:layout_marginBottom">16dp</item>
     </style>
 
     <style name="TabInput"></style>
 
     <style name="TabInput.TabWidget" parent="android:style/Widget.Holo.Light.TabWidget" />
 
-    <style name="TabInput.Tab" parent="android:style/Widget.Holo.Light.Tab">
+    <style name="TabInput.Tab" parent="android:style/Widget.Holo.Light.Tab"
+           tools:ignore="UnusedResources">
         <item name="android:minHeight">@dimen/menu_item_row_height</item>
         <item name="android:textAllCaps">true</item>
     </style>
 
 </resources>
--- a/mobile/android/app/src/photon/res/values-v16/styles.xml
+++ b/mobile/android/app/src/photon/res/values-v16/styles.xml
@@ -9,24 +9,16 @@
     <style name="TextAppearance.EmptyMessage" parent="TextAppearance.Large">
         <item name="android:fontFamily">sans-serif-light</item>
     </style>
 
     <style name="TextAppearance.Widget.Home.ItemTitle" parent="TextAppearance.Medium">
         <item name="android:fontFamily">sans-serif-light</item>
     </style>
 
-    <style name="TextAppearance.FirstrunTextLight">
-        <item name="android:fontFamily">sans-serif-light</item>
-    </style>
-
-    <style name="TextAppearance.FirstrunTextRegular">
-        <item name="android:fontFamily">sans-serif</item>
-    </style>
-
     <style name="TextAppearance.UrlBar.Title" parent="TextAppearance.Small">
         <item name="android:textSize">16sp</item>
     </style>
 
     <style name="TextAppearance.SearchSuggestion" parent="TextAppearance.Small">
         <item name="android:fontFamily">sans-serif-light</item>
     </style>
 </resources>
--- a/mobile/android/app/src/photon/res/values/styles.xml
+++ b/mobile/android/app/src/photon/res/values/styles.xml
@@ -20,18 +20,16 @@
     <style name="Widget.BaseEditText" parent="android:style/Widget.EditText"/>
 
     <style name="Widget.BaseListView" parent="android:style/Widget.ListView"/>
 
     <style name="Widget.BaseGridView" parent="android:style/Widget.GridView"/>
 
     <style name="Widget.BaseTextView" parent="android:style/Widget.TextView"/>
 
-    <style name="Widget.ProgressBar.Horizontal" parent="android:style/Widget.ProgressBar.Horizontal"/>
-
     <!--
         Application styles. All customizations that are not specific
         to a particular API level can go here.
     -->
     <style name="Widget.Button" parent="Widget.BaseButton">
         <item name="android:textAppearance">@style/TextAppearance.Widget.Button</item>
     </style>
 
@@ -60,20 +58,16 @@
 
     <style name="Widget.GridView" parent="Widget.BaseGridView">
         <item name="android:verticalSpacing">0dip</item>
         <item name="android:horizontalSpacing">0dip</item>
         <item name="android:cacheColorHint">@android:color/transparent</item>
         <item name="android:listSelector">@drawable/action_bar_button</item>
     </style>
 
-    <style name="Widget.Home.HomeList">
-        <item name="android:scrollbarStyle">outsideOverlay</item>
-    </style>
-
     <style name="Widget.ListItem">
         <item name="android:minHeight">?android:attr/listPreferredItemHeight</item>
         <item name="android:textAppearance">?android:attr/textAppearanceLargeInverse</item>
         <item name="android:gravity">center_vertical</item>
         <item name="android:paddingLeft">12dip</item>
         <item name="android:paddingStart">12dip</item>
         <item name="android:paddingRight">7dip</item>
         <item name="android:paddingEnd">7dip</item>
@@ -211,22 +205,16 @@
 
     <style name="Widget.BookmarksListView" parent="Widget.HomeListView"/>
 
     <style name="Widget.TopSitesThumbnailView">
       <item name="android:padding">0dip</item>
       <item name="android:scaleType">centerCrop</item>
     </style>
 
-    <style name="Widget.TopSitesGridItemPin">
-      <item name="android:minWidth">30dip</item>
-      <item name="android:minHeight">30dip</item>
-      <item name="android:padding">0dip</item>
-    </style>
-
     <style name="Widget.TopSitesGridItemTitle">
       <item name="android:textColor">@color/top_sites_grid_item_title</item>
       <item name="android:textSize">12sp</item>
       <item name="android:paddingTop">5dip</item>
       <item name="android:gravity">left|start</item>
     </style>
 
     <style name="Widget.HomeListView" parent="Widget.ListView">
@@ -290,17 +278,18 @@
         <item name="android:layout_weight">1</item>
         <item name="android:minHeight">48dp</item>
         <item name="android:textSize">14sp</item>
     </style>
 
     <!--
         We are overriding the snackbar message style to guarantee a consistent style across Android versions (bug 1217416).
     -->
-    <style name="TextAppearance.Design.Snackbar.Message" parent="android:TextAppearance" tools:override="true">
+    <style name="TextAppearance.Design.Snackbar.Message" parent="android:TextAppearance" tools:override="true"
+           tools:ignore="UnusedResources">
         <item name="android:textSize">@dimen/design_snackbar_text_size</item>
         <item name="android:textColor">@android:color/white</item>
     </style>
 
     <!--
         TextAppearance
         Note: Gecko uses light theme as default, while Android uses dark.
         If Android convention has to be followd, the list of colors specified 
@@ -365,17 +354,18 @@
         <item name="android:textStyle">italic</item>
     </style>
 
     <style name="TextAppearance.Micro">
         <item name="android:textSize">12sp</item>
         <item name="android:textColor">?android:attr/textColorTertiary</item>
     </style>
 
-    <style name="TextAppearance.Micro.Inverse">
+    <style name="TextAppearance.Micro.Inverse"
+           tools:ignore="UnusedResources">
         <item name="android:textColor">?android:attr/textColorTertiaryInverse</item>
         <item name="android:textColorHint">?android:attr/textColorHintInverse</item>
         <item name="android:textColorHighlight">@color/text_color_highlight_inverse</item>
         <item name="android:textColorLink">?android:attr/textColorLink</item>
     </style>
 
     <style name="TextAppearance.Widget" />
 
@@ -395,17 +385,18 @@
         <item name="android:textColor">@color/primary_text</item>
     </style>
 
     <style name="TextAppearance.Widget.HomePagerTabMenuStrip" parent="TextAppearance.Small">
         <item name="android:textColor">?android:attr/textColorHint</item>
         <item name="android:textSize">14sp</item>
     </style>
 
-    <style name="TextAppearance.Widget.Home" />
+    <style name="TextAppearance.Widget.Home"
+           tools:ignore="UnusedResources" />
 
     <style name="TextAppearance.Widget.Home.Header" parent="TextAppearance.Small">
         <item name="android:textColor">@color/disabled_grey</item>
         <item name="android:textSize">12sp</item>
     </style>
 
     <style name="TextAppearance.Widget.Home.ItemTitle" parent="TextAppearance">
         <item name="android:textSize">16sp</item>
@@ -431,17 +422,18 @@
     <style name="TextAppearance.DoorHanger.Medium.Bold">
         <item name="android:fontFamily">sans-serif-medium</item>
     </style>
 
     <style name="TextAppearance.DoorHanger.Medium.Light">
         <item name="android:fontFamily">sans-serif-light</item>
     </style>
 
-    <style name="TextAppearance.DoorHanger.Small">
+    <style name="TextAppearance.DoorHanger.Small"
+           tools:ignore="UnusedResources">
         <item name="android:textSize">14sp</item>
     </style>
 
     <style name="TextAppearance.UrlBar.Title" parent="TextAppearance.Small">
         <item name="android:textSize">16sp</item>
     </style>
 
     <style name="TextAppearance.SearchSuggestion" parent="TextAppearance.Small"/>
@@ -522,40 +514,31 @@
         <item name="android:layout_marginRight">4dp</item>
     </style>
 
     <style name="TabsListItemFavicon">
         <item name="android:layout_marginLeft">10dp</item>
         <item name="android:layout_marginRight">6dp</item>
     </style>
 
-    <style name="Widget.RemoteTabsItemView" parent="Widget.TwoLinePageRow"/>
-
     <style name="Widget.RemoteTabsClientView" parent="Widget.TwoLinePageRow">
         <item name="android:background">@color/about_page_header_grey</item>
     </style>
 
-    <style name="Widget.RemoteTabsListView" parent="Widget.HomeListView">
-        <item name="android:childDivider">@color/toolbar_divider_grey</item>
-    </style>
-
-    <style name="Widget.HistoryListView" parent="Widget.HomeListView">
-        <item name="android:childDivider">@color/toolbar_divider_grey</item>
-        <item name="android:drawSelectorOnTop">true</item>
-    </style>
-
     <!-- TabsLayout Row -->
-    <style name="TabLayoutItemTextAppearance">
+    <style name="TabLayoutItemTextAppearance"
+           tools:ignore="UnusedResources">
         <item name="android:textColor">#FFFFFFFF</item>
         <item name="android:singleLine">true</item>
         <item name="android:ellipsize">middle</item>
     </style>
 
     <!-- TabsLayout RemoteTabs Row Url -->
-    <style name="TabLayoutItemTextAppearance.Url">
+    <style name="TabLayoutItemTextAppearance.Url"
+           tools:ignore="UnusedResources">
         <item name="android:textColor">#FFA4A7A9</item>
     </style>
 
     <!-- Find bar -->
     <style name="FindBar">
         <item name="android:background">@color/text_and_tabs_tray_grey</item>
         <item name="android:paddingLeft">3dip</item>
         <item name="android:paddingStart">3dip</item>
@@ -574,18 +557,18 @@
         <item name="android:layout_marginRight">5dip</item>
         <item name="android:layout_marginEnd">5dip</item>
         <item name="android:scaleType">fitCenter</item>
         <item name="android:layout_centerVertical">true</item>
         <item name="android:background">@drawable/action_bar_button_inverse</item>
     </style>
 
     <style name="PopupAnimation">
-        <item name="@android:windowEnterAnimation">@anim/popup_show</item>
-        <item name="@android:windowExitAnimation">@anim/popup_hide</item>
+        <item name="android:windowEnterAnimation">@anim/popup_show</item>
+        <item name="android:windowExitAnimation">@anim/popup_hide</item>
     </style>
 
     <style name="ToastBase">
         <item name="android:background">@drawable/toast_background</item>
         <item name="android:layout_width">match_parent</item>
         <item name="android:layout_height">wrap_content</item>
         <item name="android:layout_alignParentBottom">true</item>
         <item name="android:layout_centerHorizontal">true</item>
@@ -732,17 +715,18 @@
 
     <style name="TabInput"></style>
 
     <style name="TabInput.TabWidget">
         <item name="android:divider">@drawable/divider_vertical</item>
         <item name="android:background">@drawable/tab_indicator_background</item>
     </style>
 
-    <style name="TabInput.Tab">
+    <style name="TabInput.Tab"
+           tools:ignore="UnusedResources">
         <item name="android:background">@drawable/tabs_strip_indicator</item>
         <item name="android:gravity">center</item>
         <item name="android:minHeight">@dimen/menu_item_row_height</item>
     </style>
 
     <style name="TextAppearance.FirstrunLight"/>
     <style name="TextAppearance.FirstrunRegular"/>
 
@@ -793,17 +777,18 @@
     </style>
 
     <style name="RemoteTabsPanelItem.TextAppearance.Header">
         <item name="android:textColor">@color/placeholder_active_grey</item>
         <item name="android:textSize">20sp</item>
         <item name="android:layout_marginBottom">8dp</item>
     </style>
 
-    <style name="RemoteTabsPanelItem.TextAppearance.Linkified">
+    <style name="RemoteTabsPanelItem.TextAppearance.Linkified"
+           tools:ignore="UnusedResources">
         <item name="android:clickable">true</item>
         <item name="android:focusable">true</item>
         <item name="android:textColor">#0092DB</item>
     </style>
 
     <style name="RemoteTabsPanelItem.Button">
         <item name="android:background">@drawable/remote_tabs_setup_button_background</item>
         <item name="android:textColor">#FFFFFF</item>
@@ -815,28 +800,27 @@
         <item name="android:paddingStart">8dp</item>
         <item name="android:paddingRight">8dp</item>
         <item name="android:paddingEnd">8dp</item>
 
         <!-- AppCompat sets Button text to all caps so we override that here. -->
         <item name="textAllCaps">false</item>
     </style>
 
-    <style name="TabQueueActivity" parent="android:style/Theme.NoDisplay" />
-
     <style name="ActivityStreamContextMenuText">
         <item name="android:textSize">16sp</item>
     </style>
 
     <!-- We use this style to provide our own divider that has an inset on the left side -->
     <style name="ActivityStreamContextMenuStyle">
         <item name="android:listDivider">@drawable/as_contextmenu_divider</item>
     </style>
 
-    <style name="ActivityStreamButton" parent="Widget.AppCompat.Button.Colored">
+    <style name="ActivityStreamButton" parent="Widget.AppCompat.Button.Colored"
+           tools:ignore="UnusedResources">
         <item name="colorButtonNormal">@color/link_blue</item>
         <item name="android:textColor">@android:color/white</item>
     </style>
 
     <!-- centerInside will downscale larger icons to fit or center smaller favicons and allow us to draw a colored
          border around them. When changing these values, consider favicons downloaded from the internet and
          those provided by suggested sites, including suggested sites from distributions. -->
     <style name="ActivityStreamFaviconView">
--- a/mobile/android/app/src/test/java/org/mozilla/gecko/GlobalPageMetadataTest.java
+++ b/mobile/android/app/src/test/java/org/mozilla/gecko/GlobalPageMetadataTest.java
@@ -1,42 +1,39 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 package org.mozilla.gecko;
 
+import android.content.ContentProvider;
 import android.content.ContentProviderClient;
 import android.content.ContentValues;
 import android.database.Cursor;
 import android.os.RemoteException;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mozilla.gecko.background.db.DelegatingTestContentProvider;
 import org.mozilla.gecko.background.testhelpers.TestRunner;
 import org.mozilla.gecko.db.BrowserContract;
 import org.mozilla.gecko.db.BrowserContract.PageMetadata;
 import org.mozilla.gecko.db.BrowserDB;
-import org.mozilla.gecko.db.BrowserProvider;
 import org.mozilla.gecko.db.LocalBrowserDB;
 import org.robolectric.shadows.ShadowContentResolver;
 
 import static org.junit.Assert.*;
 
 @RunWith(TestRunner.class)
 public class GlobalPageMetadataTest {
     @Test
     public void testQueueing() throws Exception {
         BrowserDB db = new LocalBrowserDB("default");
 
-        BrowserProvider provider = new BrowserProvider();
+        final ContentProvider provider = DelegatingTestContentProvider.createDelegatingBrowserProvider();
         try {
-            provider.onCreate();
-            ShadowContentResolver.registerProvider(BrowserContract.AUTHORITY, new DelegatingTestContentProvider(provider));
-
             ShadowContentResolver cr = new ShadowContentResolver();
             ContentProviderClient pageMetadataClient = cr.acquireContentProviderClient(PageMetadata.CONTENT_URI);
 
             assertEquals(0, GlobalPageMetadata.getInstance().getMetadataQueueSize());
 
             // There's not history record for this uri, so test that queueing works.
             GlobalPageMetadata.getInstance().doAddOrQueue(db, pageMetadataClient, "https://mozilla.org", false, "{type: 'article'}");
 
@@ -59,21 +56,18 @@ public class GlobalPageMetadataTest {
 
     @Test
     public void testInsertingMetadata() throws Exception {
         BrowserDB db = new LocalBrowserDB("default");
 
         // Start listening for events.
         GlobalPageMetadata.getInstance().init();
 
-        BrowserProvider provider = new BrowserProvider();
+        final ContentProvider provider = DelegatingTestContentProvider.createDelegatingBrowserProvider();
         try {
-            provider.onCreate();
-            ShadowContentResolver.registerProvider(BrowserContract.AUTHORITY, new DelegatingTestContentProvider(provider));
-
             ShadowContentResolver cr = new ShadowContentResolver();
             ContentProviderClient historyClient = cr.acquireContentProviderClient(BrowserContract.History.CONTENT_URI);
             ContentProviderClient pageMetadataClient = cr.acquireContentProviderClient(PageMetadata.CONTENT_URI);
 
             // Insert required history item...
             ContentValues cv = new ContentValues();
             cv.put(BrowserContract.History.GUID, "guid1");
             cv.put(BrowserContract.History.URL, "https://mozilla.org");
@@ -166,9 +160,9 @@ public class GlobalPageMetadataTest {
 
         assertNotNull(cursor);
         try {
             assertEquals(expected, cursor.getCount());
         } finally {
             cursor.close();
         }
     }
-}
\ No newline at end of file
+}
--- a/mobile/android/app/src/test/java/org/mozilla/gecko/icons/loader/TestLegacyLoader.java
+++ b/mobile/android/app/src/test/java/org/mozilla/gecko/icons/loader/TestLegacyLoader.java
@@ -1,36 +1,28 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 package org.mozilla.gecko.icons.loader;
 
+import android.content.ContentProvider;
 import android.graphics.Bitmap;
 
 import org.junit.Assert;
-import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mozilla.gecko.GeckoProfile;
 import org.mozilla.gecko.background.db.DelegatingTestContentProvider;
 import org.mozilla.gecko.background.testhelpers.TestRunner;
-import org.mozilla.gecko.db.BrowserContract;
-import org.mozilla.gecko.db.BrowserDB;
-import org.mozilla.gecko.db.BrowserProvider;
 import org.mozilla.gecko.icons.IconDescriptor;
 import org.mozilla.gecko.icons.IconRequest;
 import org.mozilla.gecko.icons.IconResponse;
 import org.mozilla.gecko.icons.Icons;
 import org.robolectric.RuntimeEnvironment;
-import org.robolectric.shadows.ShadowContentResolver;
 
-import java.lang.reflect.Field;
-import java.lang.reflect.Modifier;
 import java.util.Iterator;
-import java.util.concurrent.ConcurrentHashMap;
 
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 
 @RunWith(TestRunner.class)
@@ -41,33 +33,31 @@ public class TestLegacyLoader {
     private static final String TEST_ICON_URL_3 = "https://example.net/icon/favicon.ico";
 
     @Test
     public void testDatabaseIsQueriesForNormalRequestsWithNetworkSkipped() {
         // We're going to query BrowserProvider via LegacyLoader, and will access a database.
         // We need to ensure we close our db connection properly.
         // This is the only test in this class that actually accesses a database. If that changes,
         // move BrowserProvider registration into a @Before method, and provider.shutdown into @After.
-        final BrowserProvider provider = new BrowserProvider();
-        provider.onCreate();
-        ShadowContentResolver.registerProvider(BrowserContract.AUTHORITY, new DelegatingTestContentProvider(provider));
+        final ContentProvider provider = DelegatingTestContentProvider.createDelegatingBrowserProvider();
         try {
             final IconRequest request = Icons.with(RuntimeEnvironment.application)
                     .pageUrl(TEST_PAGE_URL)
                     .icon(IconDescriptor.createGenericIcon(TEST_ICON_URL))
                     .skipNetwork()
                     .build();
 
             final LegacyLoader loader = spy(new LegacyLoader());
             final IconResponse response = loader.load(request);
 
             verify(loader).loadBitmapFromDatabase(request);
             Assert.assertNull(response);
-        // Close any open db connections.
         } finally {
+            // Close any open db connections.
             provider.shutdown();
         }
     }
 
     @Test
     public void testNothingIsLoadedIfNetworkIsNotSkipped() {
         final IconRequest request = Icons.with(RuntimeEnvironment.application)
                 .pageUrl(TEST_PAGE_URL)
--- a/mobile/android/app/src/test/java/org/mozilla/gecko/icons/preparation/TestLookupIconUrl.java
+++ b/mobile/android/app/src/test/java/org/mozilla/gecko/icons/preparation/TestLookupIconUrl.java
@@ -23,16 +23,17 @@ public class TestLookupIconUrl {
     private static final String TEST_ICON_URL_2 = "http://example.org/favicon.ico";
     private static final String TEST_ICON_URL_3 = "http://example.com/favicon.ico";
     private static final String TEST_ICON_URL_4 = "http://example.net/favicon.ico";
 
 
     @Before
     public void setUp() {
         MemoryStorage.get().evictAll();
+        DiskStorage.get(RuntimeEnvironment.application).evictAll();
     }
 
     @Test
     public void testNoIconUrlIsAddedByDefault() {
         final IconRequest request = Icons.with(RuntimeEnvironment.application)
                 .pageUrl(TEST_PAGE_URL)
                 .build();
 
--- a/mobile/android/app/src/test/java/org/mozilla/gecko/util/NetworkUtilsTest.java
+++ b/mobile/android/app/src/test/java/org/mozilla/gecko/util/NetworkUtilsTest.java
@@ -7,36 +7,40 @@ import android.content.Context;
 import android.net.ConnectivityManager;
 import android.net.NetworkInfo;
 import android.telephony.TelephonyManager;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mozilla.gecko.background.testhelpers.TestRunner;
-import org.mozilla.gecko.util.NetworkUtils.*;
+import org.mozilla.gecko.util.NetworkUtils.ConnectionSubType;
+import org.mozilla.gecko.util.NetworkUtils.ConnectionType;
+import org.mozilla.gecko.util.NetworkUtils.NetworkStatus;
 import org.robolectric.RuntimeEnvironment;
-import org.robolectric.internal.ShadowExtractor;
+import org.robolectric.shadow.api.Shadow;
 import org.robolectric.shadows.ShadowConnectivityManager;
 import org.robolectric.shadows.ShadowNetworkInfo;
 
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 
 @RunWith(TestRunner.class)
 public class NetworkUtilsTest {
     private ConnectivityManager connectivityManager;
     private ShadowConnectivityManager shadowConnectivityManager;
 
     @Before
     public void setUp() {
         connectivityManager = (ConnectivityManager) RuntimeEnvironment.application.getSystemService(Context.CONNECTIVITY_SERVICE);
 
         // Not using Shadows.shadowOf(connectivityManager) because of Robolectric bug when using API23+
         // See: https://github.com/robolectric/robolectric/issues/1862
-        shadowConnectivityManager = (ShadowConnectivityManager) ShadowExtractor.extract(connectivityManager);
+        shadowConnectivityManager = (ShadowConnectivityManager) Shadow.extract(connectivityManager);
     }
 
     @Test
     public void testIsConnected() throws Exception {
         assertFalse(NetworkUtils.isConnected((ConnectivityManager) null));
 
         shadowConnectivityManager.setActiveNetworkInfo(null);
         assertFalse(NetworkUtils.isConnected(connectivityManager));
@@ -177,9 +181,9 @@ public class NetworkUtilsTest {
         );
         assertEquals(NetworkStatus.DOWN, NetworkUtils.getNetworkStatus(connectivityManager));
 
         shadowConnectivityManager.setActiveNetworkInfo(
                 ShadowNetworkInfo.newInstance(NetworkInfo.DetailedState.CONNECTED, ConnectivityManager.TYPE_MOBILE, 0, true, true)
         );
         assertEquals(NetworkStatus.UP, NetworkUtils.getNetworkStatus(connectivityManager));
     }
-}
\ No newline at end of file
+}
--- a/mobile/android/app/src/test/resources/robolectric.properties
+++ b/mobile/android/app/src/test/resources/robolectric.properties
@@ -1,3 +1,3 @@
-sdk=21
+sdk=23
 constants=org.mozilla.gecko.BuildConfig
 packageName=org.mozilla.gecko
--- a/mobile/android/base/AndroidManifest.xml.in
+++ b/mobile/android/base/AndroidManifest.xml.in
@@ -1,11 +1,12 @@
 #filter substitution
 <?xml version="1.0" encoding="utf-8"?>
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+      xmlns:tools="http://schemas.android.com/tools"
       package="@ANDROID_PACKAGE_NAME@"
       android:installLocation="internalOnly"
       android:versionCode="@ANDROID_VERSION_CODE@"
       android:versionName="@MOZ_APP_VERSION@"
 #ifdef MOZ_ANDROID_SHARED_ID
       android:sharedUserId="@MOZ_ANDROID_SHARED_ID@"
 #endif
       >
@@ -128,17 +129,17 @@
                 <category android:name="android.intent.category.DEFAULT" />
             </intent-filter>
 
             <intent-filter>
                 <action android:name="org.mozilla.gecko.UPDATE"/>
                 <category android:name="android.intent.category.DEFAULT" />
             </intent-filter>
 
-            <intent-filter>
+            <intent-filter tools:ignore="AppLinkUrlError">
                 <action android:name="android.intent.action.WEB_SEARCH" />
                 <category android:name="android.intent.category.DEFAULT" />
                 <category android:name="android.intent.category.BROWSABLE" />
                 <data android:scheme="" />
                 <data android:scheme="http" />
                 <data android:scheme="https" />
             </intent-filter>
 
@@ -154,27 +155,27 @@
                  used, so we use integer resources instead of drawables, because
                  setting a drawable referenced to 0 results in errors when used
                  as a real drawable resource somewhere else. -->
             <meta-data
                 android:name="com.android.systemui.action_assist_icon"
                 android:resource="@integer/assist_launch_icon_res"/>
 
             <!-- For XPI installs from websites and the download manager. -->
-            <intent-filter>
+            <intent-filter tools:ignore="AppLinkUrlError">
                 <action android:name="android.intent.action.VIEW" />
                 <category android:name="android.intent.category.DEFAULT" />
                 <data android:scheme="file" />
                 <data android:scheme="http" />
                 <data android:scheme="https" />
                 <data android:mimeType="application/x-xpinstall" />
             </intent-filter>
 
             <!-- For XPI installs from file: URLs. -->
-            <intent-filter>
+            <intent-filter tools:ignore="AppLinkUrlError">
                 <action android:name="android.intent.action.VIEW" />
                 <category android:name="android.intent.category.DEFAULT" />
                 <data android:host="" />
                 <data android:scheme="file" />
                 <data android:pathPattern=".*\\.xpi" />
             </intent-filter>
 
 #ifdef MOZ_ANDROID_BEAM
--- a/mobile/android/base/Makefile.in
+++ b/mobile/android/base/Makefile.in
@@ -22,16 +22,18 @@ GARBAGE += \
   FennecJNIWrappers.cpp \
   FennecJNIWrappers.h \
   $(NULL)
 
 GARBAGE_DIRS += classes db jars res sync services generated
 
 gradle_dir := $(topobjdir)/gradle/build/mobile/android
 
+ifndef MOZ_BUILD_MOBILE_ANDROID_WITH_GRADLE
+
 # The bootclasspath is functionally identical to the classpath, but allows the
 # classes given to redefine classes in core packages, such as java.lang.
 # android.jar is here as it provides Android's definition of the Java Standard
 # Library. The compatability lib here tweaks a few of the core classes to paint
 # over changes in behaviour between versions.
 JAVA_BOOTCLASSPATH := \
     $(ANDROID_SDK)/android.jar \
     $(NULL)
@@ -138,17 +140,16 @@ endif
 # java_bundled_libs.  See the note above.
 
 # uniq purloined from http://stackoverflow.com/a/16151140.
 uniq = $(if $1,$(firstword $1) $(call uniq,$(filter-out $(firstword $1),$1)))
 
 java_bundled_libs := $(call uniq,$(java_bundled_libs))
 java_bundled_libs := $(subst $(NULL) ,:,$(strip $(java_bundled_libs)))
 
-ifndef MOZ_BUILD_MOBILE_ANDROID_WITH_GRADLE
 GECKOVIEW_JARS = \
   constants.jar \
   gecko-R.jar \
   gecko-mozglue.jar \
   gecko-util.jar \
   gecko-view.jar \
   sync-thirdparty.jar \
   $(NULL)
@@ -170,26 +171,16 @@ FENNEC_JARS = \
   gecko-thirdparty.jar \
   services.jar \
   $(NULL)
 
 ifdef MOZ_ANDROID_MLS_STUMBLER
 FENNEC_JARS += ../stumbler/stumbler.jar
 endif
 
-else # MOZ_BUILD_MOBILE_ANDROID_WITH_GRADLE
-
-GECKOVIEW_JARS := $(gradle_dir)/geckoview/intermediates/bundles/debug/classes.jar
-FENNEC_JARS := $(gradle_dir)/app/intermediates/packaged/officialPhoton/debug/classes.jar
-
-$(GECKOVIEW_JARS): .gradle.deps
-$(FENNEC_JARS): .gradle.deps
-
-endif # MOZ_BUILD_MOBILE_ANDROID_WITH_GRADLE
-
 geckoview_jars_classpath := $(subst $(NULL) ,:,$(strip $(GECKOVIEW_JARS)))
 
 # All the jars we're compiling from source. (not to be confused with
 # java_bundled_libs, which holds the jars which we're including as binaries).
 ALL_JARS = \
   $(GECKOVIEW_JARS) \
   $(FENNEC_JARS) \
   $(NULL)
@@ -227,37 +218,39 @@ library_jars := \
 # MOZ_ANDROID_MMA requires MOZ_INSTALL_TRACKING, so we don't need a
 # separate clause for MMA (Leanplum) support.
 ifdef MOZ_INSTALL_TRACKING
 library_jars += $(ANDROID_SDK)/optional/org.apache.http.legacy.jar
 endif # MOZ_INSTALL_TRACKING
 
 library_jars := $(subst $(NULL) ,:,$(strip $(library_jars)))
 
+endif # MOZ_BUILD_MOBILE_ANDROID_WITH_GRADLE
+
 ifdef MOZ_BUILD_MOBILE_ANDROID_WITH_GRADLE
 define gradle_command
 $(1): $(2)
 	@$$(TOUCH) $$@
 	$$(topsrcdir)/mach android assemble-app
 endef
 
 # .gradle.deps: .aapt.deps FORCE
 $(eval $(call gradle_command,.gradle.deps,.aapt.deps FORCE))
 
 classes.dex: .gradle.deps
 	$(REPORT_BUILD)
-	cp $(gradle_dir)/app/intermediates/transforms/dex/officialPhoton/debug/folders/1000/1f/main/classes.dex $@
+	cp $(gradle_dir)/app/intermediates/transforms/dexMerger/officialWithoutGeckoBinariesNoMinApiPhoton/debug/0/classes.dex classes.dex
 
 GeneratedJNIWrappers.cpp GeneratedJNIWrappers.h GeneratedJNINatives.h : .gradle.deps
 	$(REPORT_BUILD)
 
 FennecJNIWrappers.cpp FennecJNIWrappers.h FennecJNINatives.h: .gradle.deps
 	$(REPORT_BUILD)
 
-else
+else # MOZ_BUILD_MOBILE_ANDROID_WITH_GRADLE
 classes.dex: .proguard.deps
 	$(REPORT_BUILD)
 	$(DX) --dex --output=classes.dex --force-jumbo jars-proguarded
 
 ifdef MOZ_DISABLE_PROGUARD
   PROGUARD_PASSES=0
 else
   ifdef MOZ_DEBUG
@@ -268,29 +261,16 @@ else
     else
       PROGUARD_PASSES=6
     endif
   endif
 endif
 
 proguard_config_dir=$(topsrcdir)/mobile/android/config/proguard
 
-# This stanza ensures that the set of GeckoView classes does not depend on too
-# much of Fennec, where "too much" is defined as the set of potentially
-# non-GeckoView classes that GeckoView already depended on at a certain point in
-# time.  The idea is to set a high-water mark that is not to be crossed.
-classycle_jar := $(topsrcdir)/mobile/android/build/classycle/classycle-1.4.1.jar
-.geckoview.deps: geckoview.ddf $(classycle_jar) $(ALL_JARS)
-	$(JAVA) -cp $(classycle_jar) \
-		classycle.dependency.DependencyChecker \
-		-mergeInnerClasses \
-		-dependencies=@$< \
-		$(ALL_JARS)
-	@$(TOUCH) $@
-
 # First, we delete debugging information from libraries. Having line-number
 # information for libraries for which we lack the source isn't useful, so this
 # saves us a bit of space. Importantly, Proguard has a bug causing it to
 # sometimes corrupt this information if present (which it does for some of the
 # included libraries). This corruption prevents dex from completing, so we need
 # to get rid of it.  This prevents us from seeing line numbers in stack traces
 # for stack frames inside libraries.
 #
@@ -307,17 +287,17 @@ classycle_jar := $(topsrcdir)/mobile/and
 		-injars $(subst ::,:,$(java_bundled_libs))\
 		-outjars bundled-jars-nodebug \
 		-libraryjars $(library_jars):gecko-R.jar
 
 # We touch the target file before invoking Proguard so that Proguard's
 # outputs are fresher than the target, preventing a subsequent
 # invocation from thinking Proguard's outputs are stale.  This is safe
 # because Make removes the target file if any recipe command fails.
-.proguard.deps: .geckoview.deps .bundled.proguard.deps $(ALL_JARS) $(proguard_config_dir)/proguard.cfg $(PROGUARD_JAR)
+.proguard.deps: .bundled.proguard.deps $(ALL_JARS) $(proguard_config_dir)/proguard.cfg $(PROGUARD_JAR)
 	$(REPORT_BUILD)
 	@$(TOUCH) $@
 	$(JAVA) \
 		-Xmx512m -Xms128m \
 		-jar $(PROGUARD_JAR) \
 		@$(proguard_config_dir)/proguard.cfg \
 		-optimizationpasses $(PROGUARD_PASSES) \
 		-injars $(subst ::,:,$(all_jars_classpath)):bundled-jars-nodebug \
@@ -499,17 +479,17 @@ ifdef MOZ_BUILD_MOBILE_ANDROID_WITH_GRAD
 # strings.xml.
 
 # .gradle.nodeps: AndroidManifest.xml generated/preprocessed/org/mozilla/gecko/AppConstants.java ... FORCE
 $(eval $(call gradle_command,.gradle.nodeps,AndroidManifest.xml $(constants_PP_JAVAFILES) FORCE))
 
 .aapt.nodeps: .gradle.nodeps FORCE
 	@$(TOUCH) $@
 	cp $(GRADLE_ANDROID_APP_APK) gecko-nodeps.ap_
-	cp $(gradle_dir)/app/intermediates/transforms/dex/officialPhoton/debug/folders/1000/1f/main/classes.dex classes.dex
+	cp $(gradle_dir)/app/intermediates/transforms/dexMerger/officialWithoutGeckoBinariesNoMinApiPhoton/debug/0/classes.dex classes.dex
 else
 # .aapt.nodeps: AndroidManifest.xml FORCE
 $(eval $(call aapt_command,.aapt.nodeps,AndroidManifest.xml FORCE,gecko-nodeps.ap_,gecko-nodeps/,gecko-nodeps/))
 endif
 
 # Override the Java settings with some specific android settings
 include $(topsrcdir)/config/android-common.mk
 
deleted file mode 100644
--- a/mobile/android/base/geckoview.ddf
+++ /dev/null
@@ -1,74 +0,0 @@
-# This is a Classycle dependency definition file that asserts that the contents
-# of the GeckoView library (Classycle set [lib]) is a dependency (but does not
-# depend) on Fennec (Classycle set [main]).  The additional Classycle set
-# [middle] consists of classes referenced by GeckoView that probably should not
-# be referenced.  We want this middle set to shrink over time.
-
-show allResults
-
-[lib] = \
-  org.mozilla.gecko.gfx.* \
-  org.mozilla.gecko.mozglue.* \
-  org.mozilla.gecko.sqlite.* \
-  org.mozilla.gecko.util.* \
-  org.mozilla.gecko.AndroidGamepadManager \
-  org.mozilla.gecko.AppConstants \
-  org.mozilla.gecko.ContextGetter \
-  org.mozilla.gecko.CrashHandler \
-  org.mozilla.gecko.EventDispatcher \
-  org.mozilla.gecko.GeckoAccessibility \
-  org.mozilla.gecko.GeckoAppShell \
-  org.mozilla.gecko.GeckoBatteryManager \
-  org.mozilla.gecko.GeckoEditable \
-  org.mozilla.gecko.GeckoEditableClient \
-  org.mozilla.gecko.GeckoEditableListener \
-  org.mozilla.gecko.GeckoEvent \
-  org.mozilla.gecko.GeckoInputConnection \
-  org.mozilla.gecko.GeckoJavaSampler \
-  org.mozilla.gecko.GeckoNetworkManager \
-  org.mozilla.gecko.GeckoProfile \
-  org.mozilla.gecko.GeckoScreenOrientation \
-  org.mozilla.gecko.GeckoSharedPrefs \
-  org.mozilla.gecko.GeckoThread \
-  org.mozilla.gecko.GeckoView \
-  org.mozilla.gecko.GlobalHistory \
-  org.mozilla.gecko.InputMethods \
-  org.mozilla.gecko.NSSBridge \
-  org.mozilla.gecko.NotificationClient \
-  org.mozilla.gecko.NotificationHandler \
-  org.mozilla.gecko.PrefsHelper \
-  org.mozilla.gecko.SysInfo \
-  org.mozilla.gecko.TouchEventInterceptor \
-  org.mozilla.gecko.ZoomConstraints
-
-[middle] = \
-  org.mozilla.gecko.prompts.* \
-  org.mozilla.gecko.FormAssistPopup \
-  org.mozilla.gecko.GeckoActivity \
-  org.mozilla.gecko.GeckoApp \
-  org.mozilla.gecko.GeckoProfileDirectories \
-  org.mozilla.gecko.GuestSession \
-  org.mozilla.gecko.R \
-  org.mozilla.gecko.Tab \
-  org.mozilla.gecko.Tabs \
-  org.mozilla.gecko.Telemetry \
-  org.mozilla.gecko.TelemetryContract \
-  org.mozilla.gecko.ThumbnailHelper \
-  org.mozilla.gecko.db.BrowserDB \
-  org.mozilla.gecko.db.LocalBrowserDB \
-  org.mozilla.gecko.distribution.Distribution \
-  org.mozilla.gecko.icons.*
-
-[main] = org.mozilla.gecko.* excluding [lib] [middle]
-
-check sets [lib] [middle] [main]
-
-# Bug 1107134: it appears that Classycle can be fooled if the Java
-# compiler inlines a constant from [main] into [lib].  That is, [main]
-# really does depend on [lib] but Classycle only sees the dependency
-# with some javac versions.  For now, disable the check.  Yes, this
-# processing is useless without this check.
-# check [lib] directlyIndependentOf [main]
-
-# This fails; if this passed, GeckoView would be ready to extract from Fennec.
-# check [lib] independentOf [middle]
--- a/mobile/android/base/java/org/mozilla/gecko/CrashReporter.java
+++ b/mobile/android/base/java/org/mozilla/gecko/CrashReporter.java
@@ -41,17 +41,19 @@ import android.os.Handler;
 import android.support.v7.app.AppCompatActivity;
 import android.text.TextUtils;
 import android.util.Log;
 import android.view.View;
 import android.widget.CheckBox;
 import android.widget.CompoundButton;
 import android.widget.EditText;
 
-@SuppressLint("Registered") // This activity is only registered in the manifest if MOZ_CRASHREPORTER is set
+// Registered: This activity is only registered in the manifest if MOZ_CRASHREPORTER is set.
+// CutPasteId: This lint is not worth fixing.  To fix it, cache all the findViewById results.
+@SuppressLint("Registered,CutPasteId")
 public class CrashReporter extends AppCompatActivity
 {
     private static final String LOGTAG = "GeckoCrashReporter";
 
     private static final String PASSED_MINI_DUMP_KEY = "minidumpPath";
     private static final String PASSED_MINI_DUMP_SUCCESS_KEY = "minidumpSuccess";
     private static final String MINI_DUMP_PATH_KEY = "upload_file_minidump";
     private static final String PAGE_URL_KEY = "URL";
--- a/mobile/android/base/java/org/mozilla/gecko/activitystream/ActivityStreamTelemetry.java
+++ b/mobile/android/base/java/org/mozilla/gecko/activitystream/ActivityStreamTelemetry.java
@@ -1,15 +1,16 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
  * 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/. */
 
 package org.mozilla.gecko.activitystream;
 
+import android.annotation.SuppressLint;
 import android.content.Context;
 import android.content.SharedPreferences;
 import android.content.res.Resources;
 import android.support.annotation.NonNull;
 
 import org.json.JSONArray;
 import org.json.JSONException;
 import org.json.JSONObject;
@@ -211,18 +212,17 @@ public class ActivityStreamTelemetry {
                     case BrowserContract.TopSites.TYPE_SUGGESTED:
                         this.set(Contract.SOURCE_SUBTYPE, Contract.SUBTYPE_SUGGESTED);
                         break;
                     case BrowserContract.TopSites.TYPE_TOP:
                         this.set(Contract.SOURCE_SUBTYPE, Contract.SUBTYPE_TOP);
                         break;
                     // While we also have a "blank" type, it is not used by Activity Stream.
                     case BrowserContract.TopSites.TYPE_BLANK:
-                    default:
-                        throw new IllegalStateException("Unknown top site type: " + topSite.getType());
+                        throw new IllegalStateException("Unknown top site type :" + (int) topSite.getType());
                 }
 
                 return this;
             }
 
             public String build() {
                 return data.toString();
             }
--- a/mobile/android/base/java/org/mozilla/gecko/activitystream/homepanel/model/Highlight.java
+++ b/mobile/android/base/java/org/mozilla/gecko/activitystream/homepanel/model/Highlight.java
@@ -221,9 +221,10 @@ public class Highlight implements Webpag
 
     @Override
     public long getUniqueId() {
         return historyId;
     }
 
     // The Highlights cursor automatically notifies of data changes, so nothing needs to be done here.
     @Override
-    public void onStateCommitted() {}}
+    public void onStateCommitted() {}
+}
--- a/mobile/android/base/java/org/mozilla/gecko/customtabs/ActionBarPresenter.java
+++ b/mobile/android/base/java/org/mozilla/gecko/customtabs/ActionBarPresenter.java
@@ -29,17 +29,16 @@ import android.widget.ImageView;
 import android.widget.TextView;
 
 import org.mozilla.gecko.GeckoView;
 import org.mozilla.gecko.GeckoSession.ProgressListener.SecurityInformation;
 import org.mozilla.gecko.R;
 import org.mozilla.gecko.SiteIdentity;
 import org.mozilla.gecko.Tab;
 import org.mozilla.gecko.toolbar.SecurityModeUtil;
-import org.mozilla.gecko.toolbar.CustomTabsSecurityPopup;
 import org.mozilla.gecko.util.ColorUtil;
 
 /**
  * This class is used to maintain appearance of ActionBar of CustomTabsActivity, includes background
  * color, custom-view and so on.
  */
 public class ActionBarPresenter {
 
--- a/mobile/android/base/java/org/mozilla/gecko/customtabs/CustomTabsSecurityPopup.java
+++ b/mobile/android/base/java/org/mozilla/gecko/customtabs/CustomTabsSecurityPopup.java
@@ -1,13 +1,13 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-package org.mozilla.gecko.toolbar;
+package org.mozilla.gecko.customtabs;
 
 import android.content.ClipData;
 import android.content.ClipboardManager;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.support.design.widget.Snackbar;
--- a/mobile/android/base/java/org/mozilla/gecko/db/AbstractTransactionalProvider.java
+++ b/mobile/android/base/java/org/mozilla/gecko/db/AbstractTransactionalProvider.java
@@ -37,18 +37,16 @@ import java.util.Arrays;
  * primarily to avoid the pattern of a transaction being begun, a read occurring,
  * and then a write being necessary. This lock upgrade can result in SQLITE_BUSY,
  * which we don't handle well. Better to avoid starting a transaction too soon!
  *
  * You are probably interested in some subclasses:
  *
  * * {@link AbstractPerProfileDatabaseProvider} provides a simple abstraction for
  *   querying databases that are stored in the user's profile directory.
- * * {@link PerProfileDatabaseProvider} is a simple version that only allows a
- *   single ContentProvider to access each per-profile database.
  * * {@link SharedBrowserDatabaseProvider} is an example of a per-profile provider
  *   that allows for multiple providers to safely work with the same databases.
  */
 @SuppressWarnings("javadoc")
 public abstract class AbstractTransactionalProvider extends ContentProvider {
     private static final String LOGTAG = "GeckoTransProvider";
 
     private static final boolean logDebug = Log.isLoggable(LOGTAG, Log.DEBUG);
@@ -129,17 +127,17 @@ public abstract class AbstractTransactio
             db.setTransactionSuccessful();
         }
     }
 
     /**
      * If we're not in a batch, but we are in a write transaction,
      * end it.
      *
-     * @see PerProfileDatabaseProvider#markWriteSuccessful(SQLiteDatabase)
+     * @see AbstractTransactionalProvider#markWriteSuccessful(SQLiteDatabase)
      */
     protected void endWrite(final SQLiteDatabase db) {
         if (isInBatch()) {
             trace("Not ending write: inside batch operation.");
             return;
         }
 
         if (db.inTransaction()) {
--- a/mobile/android/base/java/org/mozilla/gecko/db/LocalBrowserDB.java
+++ b/mobile/android/base/java/org/mozilla/gecko/db/LocalBrowserDB.java
@@ -301,17 +301,21 @@ public class LocalBrowserDB extends Brow
                 // For now, each name is expected to be unique, and duplicate
                 // icons will be duplicated in the DB. See Bug 1040806 Comment 8.
                 if (iconValue != null) {
                     final int faviconID = faviconIDs.get(name);
                     iconValue.put("_id", faviconID);
                     bookmarkValue.put(Bookmarks.FAVICON_ID, faviconID);
                     faviconValues.add(iconValue);
                 }
-            } catch (IllegalAccessException | IllegalArgumentException | NoSuchFieldException e) {
+            } catch (IllegalAccessException e) {
+                Log.wtf(LOGTAG, "Reflection failure.", e);
+            } catch (IllegalArgumentException e) {
+                Log.wtf(LOGTAG, "Reflection failure.", e);
+            } catch (NoSuchFieldException e) {
                 Log.wtf(LOGTAG, "Reflection failure.", e);
             }
         }
 
         if (!faviconValues.isEmpty()) {
             try {
                 cr.bulkInsert(mFaviconsUriWithProfile, faviconValues.toArray(new ContentValues[faviconValues.size()]));
             } catch (Exception e) {
@@ -497,17 +501,23 @@ public class LocalBrowserDB extends Brow
         try {
             Class<?> drawablesClass = R.raw.class;
 
             // Look for a favicon with the id R.raw.bookmarkdefaults_favicon_*.
             Field faviconField = drawablesClass.getField(name.replace("_title_", "_favicon_"));
             faviconField.setAccessible(true);
 
             return faviconField.getInt(null);
-        } catch (IllegalAccessException | NoSuchFieldException e) {
+        } catch (IllegalAccessException e) {
+            // We'll end up here for any default bookmark that doesn't have a favicon in
+            // resources/raw/ (i.e., about:firefox). When this happens, the Favicons service will
+            // fall back to the default branding icon for about pages. Non-about pages should always
+            // specify an icon; otherwise, the placeholder globe favicon will be used.
+            Log.d(LOGTAG, "No raw favicon resource found for " + name);
+        } catch (NoSuchFieldException e) {
             // We'll end up here for any default bookmark that doesn't have a favicon in
             // resources/raw/ (i.e., about:firefox). When this happens, the Favicons service will
             // fall back to the default branding icon for about pages. Non-about pages should always
             // specify an icon; otherwise, the placeholder globe favicon will be used.
             Log.d(LOGTAG, "No raw favicon resource found for " + name);
         }
 
         Log.e(LOGTAG, "Failed to find favicon resource ID for " + name);
deleted file mode 100644
--- a/mobile/android/base/java/org/mozilla/gecko/db/PerProfileDatabaseProvider.java
+++ /dev/null
@@ -1,55 +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/. */
-
-package org.mozilla.gecko.db;
-
-import org.mozilla.gecko.AppConstants.Versions;
-import org.mozilla.gecko.db.PerProfileDatabases.DatabaseHelperFactory;
-
-import android.content.Context;
-import android.database.sqlite.SQLiteOpenHelper;
-
-/**
- * Abstract class containing methods needed to make a SQLite-based content
- * provider with a database helper of type T, where one database helper is
- * held per profile.
- */
-public abstract class PerProfileDatabaseProvider<T extends SQLiteOpenHelper> extends AbstractPerProfileDatabaseProvider {
-    private PerProfileDatabases<T> databases;
-
-    @Override
-    protected PerProfileDatabases<T> getDatabases() {
-        return databases;
-    }
-
-    protected abstract String getDatabaseName();
-
-    /**
-     * Creates and returns an instance of the appropriate DB helper.
-     *
-     * @param  context       to use to create the database helper
-     * @param  databasePath  path to the DB file
-     * @return               instance of the database helper
-     */
-    protected abstract T createDatabaseHelper(Context context, String databasePath);
-
-    @Override
-    public boolean onCreate() {
-        synchronized (this) {
-            databases = new PerProfileDatabases<T>(
-                getContext(), getDatabaseName(), new DatabaseHelperFactory<T>() {
-                    @Override
-                    public T makeDatabaseHelper(Context context, String databasePath) {
-                        final T helper = createDatabaseHelper(context, databasePath);
-                        if (Versions.feature16Plus) {
-                            helper.setWriteAheadLoggingEnabled(true);
-                        }
-                        return helper;
-                    }
-                });
-        }
-
-        return true;
-    }
-}
--- a/mobile/android/base/java/org/mozilla/gecko/dlc/BaseAction.java
+++ b/mobile/android/base/java/org/mozilla/gecko/dlc/BaseAction.java
@@ -1,15 +1,16 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
  * 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/. */
 
 package org.mozilla.gecko.dlc;
 
+import android.annotation.SuppressLint;
 import android.content.Context;
 import android.support.annotation.IntDef;
 import android.util.Log;
 
 import org.mozilla.gecko.AppConstants;
 import org.mozilla.gecko.background.nativecode.NativeCrypto;
 import org.mozilla.gecko.dlc.catalog.DownloadContent;
 import org.mozilla.gecko.dlc.catalog.DownloadContentCatalog;
@@ -95,17 +96,17 @@ public abstract class BaseAction {
     protected File getDestinationFile(Context context, DownloadContent content)
             throws UnrecoverableDownloadContentException, RecoverableDownloadContentException {
         File destinationDirectory;
         if (content.isFont()) {
             destinationDirectory = new File(context.getApplicationInfo().dataDir, "fonts");
         } else if (content.isHyphenationDictionary()) {
             destinationDirectory = new File(context.getApplicationInfo().dataDir, "hyphenation");
         } else {
-            throw new UnrecoverableDownloadContentException("Can't determine destination for kind: " + content.getKind());
+            throw new UnrecoverableDownloadContentException("Can't determine destination for kind: " + (String) content.getKind());
         }
 
         if (!destinationDirectory.exists() && !destinationDirectory.mkdirs()) {
             throw new RecoverableDownloadContentException(RecoverableDownloadContentException.DISK_IO,
                     "Destination directory does not exist and cannot be created");
         }
 
         return new File(destinationDirectory, content.getFilename());
--- a/mobile/android/base/java/org/mozilla/gecko/dlc/DownloadAction.java
+++ b/mobile/android/base/java/org/mozilla/gecko/dlc/DownloadAction.java
@@ -1,15 +1,16 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
  * 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/. */
 
 package org.mozilla.gecko.dlc;
 
+import android.annotation.SuppressLint;
 import android.content.Context;
 import android.net.ConnectivityManager;
 import android.net.NetworkInfo;
 import android.support.v4.net.ConnectivityManagerCompat;
 import android.util.Log;
 
 import org.mozilla.gecko.dlc.catalog.DownloadContent;
 import org.mozilla.gecko.dlc.catalog.DownloadContentCatalog;
@@ -101,17 +102,17 @@ public class DownloadAction extends Base
                 if (!verify(temporaryFile, content.getDownloadChecksum())) {
                     Log.w(LOGTAG, "Wrong checksum after download, content=" + content.getId());
                     temporaryFile.delete();
                     DownloadContentTelemetry.eventDownloadFailure(content, DownloadContentTelemetry.ERROR_CHECKSUM);
                     continue;
                 }
 
                 if (!content.isAssetArchive()) {
-                    Log.e(LOGTAG, "Downloaded content is not of type 'asset-archive': " + content.getType());
+                    Log.e(LOGTAG, "Downloaded content is not of type 'asset-archive': " + (String) content.getType());
                     temporaryFile.delete();
                     DownloadContentTelemetry.eventDownloadFailure(content, DownloadContentTelemetry.ERROR_LOGIC);
                     continue;
                 }
 
                 extract(temporaryFile, destinationFile, content.getChecksum());
 
                 catalog.markAsDownloaded(content);
deleted file mode 100644
--- a/mobile/android/base/java/org/mozilla/gecko/home/HomeExpandableListView.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
- * 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/. */
-
-package org.mozilla.gecko.home;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.ContextMenu.ContextMenuInfo;
-import android.view.View;
-import android.widget.AdapterView;
-import android.widget.AdapterView.OnItemLongClickListener;
-import android.widget.ExpandableListView;
-
-/**
- * <code>HomeExpandableListView</code> is a custom extension of
- * <code>ExpandableListView<code>, that packs a <code>HomeContextMenuInfo</code>
- * when any of its rows is long pressed.
- * <p>
- * This is the <code>ExpandableListView</code> equivalent of
- * <code>HomeListView</code>.
- */
-public class HomeExpandableListView extends ExpandableListView
-                                    implements OnItemLongClickListener {
-
-    // ContextMenuInfo associated with the currently long pressed list item.
-    private HomeContextMenuInfo mContextMenuInfo;
-
-    // ContextMenuInfo factory.
-    private HomeContextMenuInfo.ExpandableFactory mContextMenuInfoFactory;
-
-    public HomeExpandableListView(Context context) {
-        this(context, null);
-    }
-
-    public HomeExpandableListView(Context context, AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public HomeExpandableListView(Context context, AttributeSet attrs, int defStyle) {
-        super(context, attrs, defStyle);
-
-        setOnItemLongClickListener(this);
-    }
-
-    @Override
-    public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
-        if (mContextMenuInfoFactory == null) {
-            return false;
-        }
-
-        // HomeExpandableListView items can correspond to groups and children.
-        // The factory can determine whether to add context menu for either,
-        // both, or none by unpacking the given position.
-        mContextMenuInfo = mContextMenuInfoFactory.makeInfoForAdapter(view, position, id, getExpandableListAdapter());
-        return showContextMenuForChild(HomeExpandableListView.this);
-    }
-
-    @Override
-    public ContextMenuInfo getContextMenuInfo() {
-        return mContextMenuInfo;
-    }
-
-    public void setContextMenuInfoFactory(final HomeContextMenuInfo.ExpandableFactory factory) {
-        mContextMenuInfoFactory = factory;
-    }
-}
--- a/mobile/android/base/java/org/mozilla/gecko/updater/UpdateService.java
+++ b/mobile/android/base/java/org/mozilla/gecko/updater/UpdateService.java
@@ -289,22 +289,24 @@ public class UpdateService extends Inten
         Permissions.from(this)
                 .withPermissions(Manifest.permission.WRITE_EXTERNAL_STORAGE)
                 .doNotPrompt()
                 .andFallback(new Runnable() {
                     @Override
                     public void run() {
                         showPermissionNotification();
                         sendCheckUpdateResult(CheckUpdateResult.NOT_AVAILABLE);
-                    }})
+                    }
+                })
                 .run(new Runnable() {
                     @Override
                     public void run() {
                         startDownload(info, flags);
-                    }});
+                    }
+                });
     }
 
     private void startDownload(UpdateInfo info, int flags) {
         AutoDownloadPolicy policy = getAutoDownloadPolicy();
 
         // We only start a download automatically if one of following criteria are met:
         //
         // - We have a FORCE_DOWNLOAD flag passed in
--- a/mobile/android/base/java/org/mozilla/gecko/util/UnusedResourcesUtil.java
+++ b/mobile/android/base/java/org/mozilla/gecko/util/UnusedResourcesUtil.java
@@ -96,9 +96,13 @@ final class UnusedResourcesUtil {
     // not needed while Activity Stream is part of the HomePager
     public static final int[] TEMPORARY_UNUSED_ACTIVITY_STREAM = {
             R.string.activity_stream_topsites
     };
 
     public static final int[] USED_IN_PAGE_ACTION = {
             R.drawable.add_to_homescreen
     };
+
+    public static final int[] USED_IN_LEANPLUM_EXPANDABLE_LIST_ACTIVITY = {
+            R.style.Widget_ExpandableListView,
+    };
 }
--- a/mobile/android/base/moz.build
+++ b/mobile/android/base/moz.build
@@ -17,19 +17,16 @@ with Files('adjust-sdk-sandbox.token'):
     BUG_COMPONENT = ('Firefox for Android', 'Build Config & IDE Support')
 
 with Files('pocket-api-sandbox.token'):
     BUG_COMPONENT = ('Firefox for Android', 'Build Config & IDE Support')
 
 with Files('android-services.mozbuild'):
     BUG_COMPONENT = ('Android Background Services', 'Android Sync')
 
-with Files('geckoview.ddf'):
-    BUG_COMPONENT = ('Firefox for Android', 'GeckoView')
-
 with Files('crashreporter/**'):
     BUG_COMPONENT = ('Firefox for Android', 'General')
 
 with Files('java/**'):
     BUG_COMPONENT = ('Firefox for Android', 'General')
 
 with Files('java/org/mozilla/gecko/activitystream/**'):
     BUG_COMPONENT = ('Firefox for Android', 'Awesomescreen')
@@ -563,17 +560,16 @@ gbjar.sources += ['java/org/mozilla/geck
     'db/HomeProvider.java',
     'db/LocalBrowserDB.java',
     'db/LocalSearches.java',
     'db/LocalTabsAccessor.java',
     'db/LocalUrlAnnotations.java',
     'db/LocalURLMetadata.java',
     'db/LoginsProvider.java',
     'db/PasswordsProvider.java',
-    'db/PerProfileDatabaseProvider.java',
     'db/PerProfileDatabases.java',
     'db/RemoteClient.java',
     'db/RemoteTab.java',
     'db/Searches.java',
     'db/SearchHistoryProvider.java',
     'db/SharedBrowserDatabaseProvider.java',
     'db/SQLiteBridgeContentProvider.java',
     'db/SuggestedSites.java',
@@ -661,17 +657,16 @@ gbjar.sources += ['java/org/mozilla/geck
     'home/FramePanelLayout.java',
     'home/HistorySectionsHelper.java',
     'home/HomeAdapter.java',
     'home/HomeBanner.java',
     'home/HomeConfig.java',
     'home/HomeConfigLoader.java',
     'home/HomeConfigPrefsBackend.java',
     'home/HomeContextMenuInfo.java',
-    'home/HomeExpandableListView.java',
     'home/HomeFragment.java',
     'home/HomeListView.java',
     'home/HomePager.java',
     'home/HomePanelsManager.java',
     'home/HomeScreen.java',
     'home/ImageLoader.java',
     'home/MultiTypeCursorAdapter.java',
     'home/PanelAuthCache.java',
@@ -1160,17 +1155,17 @@ if CONFIG['MOZ_INSTALL_TRACKING']:
 gbjar.extra_jars += [CONFIG['ANDROID_APPCOMPAT_V7_AAR_LIB']]
 gbjar.extra_jars += [CONFIG['ANDROID_SUPPORT_VECTOR_DRAWABLE_AAR_LIB']]
 gbjar.extra_jars += [CONFIG['ANDROID_ANIMATED_VECTOR_DRAWABLE_AAR_LIB']]
 gbjar.extra_jars += [CONFIG['ANDROID_CARDVIEW_V7_AAR_LIB']]
 gbjar.extra_jars += [CONFIG['ANDROID_DESIGN_AAR_LIB']]
 gbjar.extra_jars += [CONFIG['ANDROID_RECYCLERVIEW_V7_AAR_LIB']]
 gbjar.extra_jars += [CONFIG['ANDROID_CUSTOMTABS_AAR_LIB']]
 
-gbjar.javac_flags += ['-Xlint:all,-deprecation,-fallthrough', '-J-Xmx512m', '-J-Xms128m']
+gbjar.javac_flags += ['-Xlint:all,-deprecation,-fallthrough,-cast', '-J-Xmx512m', '-J-Xms128m']
 
 # gecko-thirdparty is a good place to put small independent libraries
 gtjar = add_java_jar('gecko-thirdparty')
 gtjar.sources += [ thirdparty_source_dir + f for f in [
     'com/booking/rtlviewpager/PagerAdapterWrapper.java',
     'com/booking/rtlviewpager/RtlViewPager.java',
     'com/jakewharton/disklrucache/DiskLruCache.java',
     'com/jakewharton/disklrucache/StrictLineReader.java',
deleted file mode 100644
--- a/mobile/android/build/classycle/LICENSE.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-- Redistributions of source code must retain the above copyright notice,
-  this list of conditions and the following disclaimer.
-- Redistributions in binary form must reproduce the above copyright notice,
-  this list of conditions and the following disclaimer in the documentation
-  and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
-CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
-EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
deleted file mode 100644
index bc8f2ddaac38df5e5eb22e2033546e04aa0d656f..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
new file mode 100644
--- /dev/null
+++ b/mobile/android/docs/gradle.rst
@@ -0,0 +1,101 @@
+.. -*- Mode: rst; fill-column: 80; -*-
+
+=================================
+ The Fennec Gradle configuration
+=================================
+
+The Fennec Gradle configuration has three major facets:
+
+1. separation into Gradle projects;
+2. Android-Gradle build configurations using `flavorDimensions`;
+3. integration into the larger `moz.build` build system.
+
+Separation into Gradle projects
+===============================
+
+The Fennec source code is separated into multiple Gradle projects.  Right now,
+there are only a few: `:app`, `:geckoview`, `:thirdparty`, etc.  Over time, pieces
+of the Fennec source code will be extracted into separate, more-or-less
+stand-alone Gradle projects (e.g., `:services`, `:stumbler`, `:media`) and use
+modern techniques such as dependency injection to configure themselves at
+runtime.
+
+The `:omnijar` project is special and exists only to support integration with
+Android Studio.
+
+The details of the Gradle projects are reflected in the root `settings.gradle`
+and the `**/build.gradle` files throughout the tree.
+
+Android-Gradle build configurations
+===================================
+
+The Fennec `:app` project uses the Android-Gradle build plugin
+`flavorDimensions` feature set to support many different configurations.  The
+Gradle integration must support many often conflicting requirements; the flavor
+dimensions chosen support these requirements.
+
+Version 3.0+ of the Android-Gradle build plugin improves support for "variant
+dependencies".  This makes it easier for a consuming application (for us,
+`:app`) to use the appropriate configuration of consumed libraries (for us,
+`:geckoview`).  This allows us to simplify the logic around packaging the Gecko
+libraries and Omnijar.
+
+The details of the Android-Gradle build configurations are reflected
+`**/build.gradle` files throughout the tree, in the
+`mobile/android/gradle/*.gradle` files, and in the configuration baked into
+`mobile/android/gradle.configure`.
+
+The notable flavor dimensions are:
+
+audience
+--------
+
+The `audience` flavor dimension determines who the build is for.  "local"
+audiences are developers: they should get extra logging and as much support for
+building Fennec as possible.  In particular, "local" audiences get support for
+modifying the Android manifest and regenerating the pre-processed `strings.xml`
+files while building with Gradle from within Android Studio.
+
+"official" audiences are end users: they should get Mozilla's official branding
+and have security-sensitive developer features disabled.  The "official"
+audience corresponds roughly to the `MOZILLA_OFFICIAL=1` build setting.
+
+**Builds shipped to the Google Play Store are always for "official" audiences.**
+
+geckoBinaries
+-------------
+
+For deep historical reasons, Mozilla's build system has multiple stages, the
+most important of which are the build stage and the package stage.  During the
+build stage, the Gecko compiled libraries (e.g., `libxul.so`) and the Omnijar
+have not yet been built.  These libraries are only available during the package
+stage.  Gradle builds always want to include the Gecko libraries and the
+Omnijar.
+
+To accommodate the different stages, the build stage always invokes
+"withoutGeckoBinaries" Gradle configurations. These configurations don't expect
+or use the Gecko libraries or Omnijar.  At the moment, the package stage also
+invokes "withoutGeckoBinaries", but in the future, the package stage will invoke
+"withGeckoBinaries" Gradle configurations to simplify the packaging of libraries
+and the omnijar.
+
+**Local developers almost always want to build "withGeckoBinaries", so that the
+APK files produced can be run on device.**
+
+minApi
+------
+
+At various times in the past, Fennec has supported APK splits, producing APKs
+that support only specific Android versions.  While this is not used at this
+time, there are certain developer options (i.e., options that should only apply
+to "local" audiences) that *also* depend on the target Android version.  This
+flavor dimension allows to opt in to those options, improving the speed of
+development.
+
+Integration into the larger `moz.build` build system
+====================================================
+
+The details of the Gradle integration into the larger `moz.build` system are
+mostly captured in configuration baked into `mobile/android/gradle.configure`.
+This configuration is reflected in the Android-specific `mach android *`
+commands defined in `mobile/android/mach_commands.py`.
--- a/mobile/android/docs/index.rst
+++ b/mobile/android/docs/index.rst
@@ -15,15 +15,16 @@ Contents:
    uitelemetry
    activitystreamtelemetry
    downloadcontenttelemetry
    adjust
    mma
    defaultdomains
    shutdown
    push
+   gradle
 
 Indices and tables
 ==================
 
 * :ref:`genindex`
 * :ref:`modindex`
 * :ref:`search`
--- a/mobile/android/geckoview/build.gradle
+++ b/mobile/android/geckoview/build.gradle
@@ -1,12 +1,14 @@
 buildDir "${topobjdir}/gradle/build/mobile/android/geckoview"
 
 apply plugin: 'com.android.library'
 
+apply from: "${topsrcdir}/mobile/android/gradle/product_flavors.gradle"
+
 // This converts MOZ_APP_VERSION into an integer
 // version code.
 //
 // We take something like 58.1.2a1 and come out with 5800102
 // This gives us 3 digits for the major number, and 2 digits
 // each for the minor and build number. Beta and Release
 def computeVersionCode() {
     String appVersion = mozconfig.substs.MOZ_APP_VERSION
@@ -33,22 +35,18 @@ def computeVersionCode() {
         code += Integer.parseInt(parts[2])
     }
 
     return code;
 }
 
 android {
     compileSdkVersion project.ext.compileSdkVersion
-    buildToolsVersion project.ext.buildToolsVersion
 
     defaultConfig {
-        defaultPublishConfig 'release'
-        publishNonDefault true
-
         targetSdkVersion project.ext.targetSdkVersion
         minSdkVersion project.ext.minSdkVersion
         manifestPlaceholders = project.ext.manifestPlaceholders
 
         versionCode computeVersionCode()
         versionName "${mozconfig.substs.MOZ_APP_VERSION}-${mozconfig.substs.MOZ_UPDATE_CHANNEL}"
         consumerProguardFiles 'proguard-rules.txt'
 
@@ -98,24 +96,18 @@ android {
 
         // Official corresponds, roughly, to whether this build is performed on
         // Mozilla's continuous integration infrastructure. You should disable
         // developer-only functionality when this flag is set.
         // This makes no sense for GeckoView and should be removed as soon as possible.
         buildConfigField 'boolean', 'MOZILLA_OFFICIAL', mozconfig.substs.MOZILLA_OFFICIAL ? 'true' : 'false';
     }
 
-    buildTypes {
-        withGeckoBinaries {
-            initWith release
-        }
-        withoutGeckoBinaries { // For clarity and consistency throughout the tree.
-            initWith release
-        }
-    }
+    project.configureProductFlavors.delegate = it
+    project.configureProductFlavors()
 
     compileOptions {
         sourceCompatibility JavaVersion.VERSION_1_7
         targetCompatibility JavaVersion.VERSION_1_7
     }
 
     dexOptions {
         javaMaxHeapSize "2g"
@@ -149,31 +141,26 @@ android {
 
             assets {
             }
         }
     }
 }
 
 dependencies {
-    compile "com.android.support:support-v4:${mozconfig.substs.ANDROID_SUPPORT_LIBRARY_VERSION}"
-    compile "com.android.support:palette-v7:${mozconfig.substs.ANDROID_SUPPORT_LIBRARY_VERSION}"
+    implementation "com.android.support:support-v4:${mozconfig.substs.ANDROID_SUPPORT_LIBRARY_VERSION}"
+    implementation "com.android.support:palette-v7:${mozconfig.substs.ANDROID_SUPPORT_LIBRARY_VERSION}"
 }
 
 apply from: "${topsrcdir}/mobile/android/gradle/with_gecko_binaries.gradle"
 
 android.libraryVariants.all { variant ->
-    // Like 'debug', 'release', or 'withGeckoBinaries'.
-    def buildType = variant.buildType.name
-
-    // It would be most natural for :geckoview to always include the Gecko
-    // binaries, but that's difficult; see the notes in
-    // mobile/android/gradle/with_gecko_binaries.gradle.  Instead :app uses
-    // :geckoview:release and handles it's own Gecko binary inclusion.
-    if (buildType.equals('withGeckoBinaries')) {
+    // See the notes in mobile/android/app/build.gradle for details on including
+    // Gecko binaries and the Omnijar.
+    if ((variant.productFlavors*.name).contains('withGeckoBinaries')) {
         configureVariantWithGeckoBinaries(variant)
     }
 
     // Javadoc and Sources JAR configuration cribbed from
     // https://github.com/mapbox/mapbox-gl-native/blob/d169ea55c1cfa85cd8bf19f94c5f023569f71810/platform/android/MapboxGLAndroidSDK/build.gradle#L85
     // informed by
     // https://code.tutsplus.com/tutorials/creating-and-publishing-an-android-library--cms-24582,
     // and amended from numerous Stackoverflow posts.
@@ -197,31 +184,31 @@ android.libraryVariants.all { variant ->
         options.source = 7
 
         options.docTitle = "GeckoView ${mozconfig.substs.MOZ_APP_VERSION} API"
         options.header = "GeckoView ${mozconfig.substs.MOZ_APP_VERSION} API"
         options.addStringOption('noindex');
         options.addStringOption('noqualifier', 'java.lang');
     }
 
-    task "javadocJar${name.capitalize()}"(type: Jar, dependsOn: javadoc) {
+    def javadocJar = task("javadocJar${name.capitalize()}", type: Jar, dependsOn: javadoc) {
         classifier = 'javadoc'
         from javadoc.destinationDir
     }
 
-    task "sourcesJar${name.capitalize()}"(type: Jar) {
+    def sourcesJar = task("sourcesJar${name.capitalize()}", type: Jar) {
         classifier 'sources'
         description = "Generate Javadoc for build variant $name"
         destinationDir = new File(destinationDir, variant.baseName)
         from files(variant.javaCompile.source)
     }
 }
 
 android.libraryVariants.all { variant ->
-    configureVariantWithJNIWrappers(variant, "Generated")
+    configureLibraryVariantWithJNIWrappers(variant, "Generated")
 }
 
 apply plugin: 'maven'
  
 uploadArchives {
     repositories.mavenDeployer {
         pom.groupId = 'org.mozilla'
         pom.artifactId = "geckoview-${mozconfig.substs.MOZ_UPDATE_CHANNEL}-${mozconfig.substs.ANDROID_CPU_ARCH}"
@@ -240,32 +227,32 @@ uploadArchives {
 }
 
 // This is all related to the withGeckoBinaries approach; see
 // mobile/android/gradle/with_gecko_binaries.gradle.
 afterEvaluate {
     // The bundle tasks are only present when the particular configuration is
     // being built, so this task might not exist.  (This is due to the way the
     // Android Gradle plugin defines things during configuration.)
-    def bundleWithGeckoBinaries = tasks.findByName('bundleWithGeckoBinaries')
+    def bundleWithGeckoBinaries = tasks.findByName('bundleOfficialWithGeckoBinariesNoMinApiRelease')
     if (!bundleWithGeckoBinaries) {
         return
     }
 
     // Remove default configuration, which is the release configuration, when
     // we're actually building withGeckoBinaries.  This makes `gradle install`
     // install the withGeckoBinaries artifacts, not the release artifacts (which
     // are withoutGeckoBinaries and not suitable for distribution.)
     def Configuration archivesConfig = project.getConfigurations().getByName('archives')
     archivesConfig.artifacts.removeAll { it.extension.equals('aar') }
 
     artifacts {
         // Instead of default (release) configuration, publish one with Gecko binaries.
-        archives bundleWithGeckoBinaries
+        archives bundleOfficialWithGeckoBinariesNoMinApiRelease
         // Javadoc and sources for developer ergononomics.
-        archives javadocJarWithGeckoBinaries
-        archives sourcesJarWithGeckoBinaries
+        archives javadocJarOfficialWithGeckoBinariesNoMinApiRelease
+        archives sourcesJarOfficialWithGeckoBinariesNoMinApiRelease
     }
 }
 
 // Bug 1353055 - Strip 'vars' debugging information to agree with moz.build.
 apply from: "${topsrcdir}/mobile/android/gradle/debug_level.gradle"
 android.libraryVariants.all configureVariantDebugLevel
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/GeckoHlsPlayer.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/GeckoHlsPlayer.java
@@ -59,17 +59,17 @@ public class GeckoHlsPlayer implements B
      *  Gecko media pipleine (in cpp). Once HLSDemuxer is created later, we
      *  need to bridge this HLSResource to the created demuxer. And they share
      *  the same GeckoHlsPlayer.
      *  mPlayerId is a token used for Gecko media pipeline to obtain corresponding player.
      */
     private final int mPlayerId;
     private boolean mExoplayerSuspended = false;
 
-    private enum MediaDecoderPlayState{
+    private enum MediaDecoderPlayState {
         PLAY_STATE_PREPARING,
         PLAY_STATE_PAUSED,
         PLAY_STATE_PLAYING
     }
     // Default value is PLAY_STATE_PREPARING and it will be set to PLAY_STATE_PLAYING
     // once HTMLMediaElement calls PlayInternal().
     private MediaDecoderPlayState mMediaDecoderPlayState = MediaDecoderPlayState.PLAY_STATE_PREPARING;
     private DataSource.Factory mMediaDataSourceFactory;
--- a/mobile/android/geckoview_example/build.gradle
+++ b/mobile/android/geckoview_example/build.gradle
@@ -1,68 +1,44 @@
 buildDir "${topobjdir}/gradle/build/mobile/android/geckoview_example"
 
 apply plugin: 'com.android.application'
 
+apply from: "${topsrcdir}/mobile/android/gradle/product_flavors.gradle"
+
 android {
     compileSdkVersion project.ext.compileSdkVersion
-    buildToolsVersion project.ext.buildToolsVersion
 
     defaultConfig {
         targetSdkVersion project.ext.targetSdkVersion
         minSdkVersion project.ext.minSdkVersion
         manifestPlaceholders = project.ext.manifestPlaceholders
 
         applicationId "org.mozilla.geckoview_example"
         versionCode 1
         versionName "1.0"
         testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
     }
 
-    // This is extremely frustrating, but the only way to do it automation for
-    // now.  Without this, we only get a "debugAndroidTest" configuration; we
-    // have no "withoutGeckoBinariesAndroidTest" configuration.
-    testBuildType "withoutGeckoBinaries"
     buildTypes {
         release {
             minifyEnabled false
             proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
         }
-        withGeckoBinaries { // For consistency with :geckoview project in Task Cluster invocations.
-            initWith debug
-        }
-        withoutGeckoBinaries { // Logical negation of withGeckoBinaries.
-            initWith debug
-        }
     }
+
+    project.configureProductFlavors.delegate = it
+    project.configureProductFlavors()
 }
 
 dependencies {
-    testCompile 'junit:junit:4.12'
+    testImplementation 'junit:junit:4.12'
 
-    compile 'com.android.support:support-annotations:23.4.0'
+    implementation 'com.android.support:support-annotations:23.4.0'
 
-    androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2'
-    androidTestCompile 'com.android.support.test:runner:0.5'
+    androidTestImplementation 'com.android.support.test.espresso:espresso-core:2.2.2'
+    androidTestImplementation 'com.android.support.test:runner:0.5'
     // Not defining this library again results in test-app assuming 23.1.1, and the following errors:
     // "Conflict with dependency 'com.android.support:support-annotations'. Resolved versions for app (23.4.0) and test app (23.1.1) differ."
-    androidTestCompile 'com.android.support:support-annotations:23.4.0'
-
-    debugCompile project(path: ':geckoview', configuration: "debug")
-    releaseCompile project(path: ':geckoview', configuration: "release")
-    withGeckoBinariesCompile project(path: ':geckoview', configuration: "withGeckoBinaries")
-    withoutGeckoBinariesCompile project(path: ':geckoview', configuration: "withoutGeckoBinaries")
-}
-
-apply from: "${topsrcdir}/mobile/android/gradle/with_gecko_binaries.gradle"
+    androidTestImplementation 'com.android.support:support-annotations:23.4.0'
 
-android.applicationVariants.all { variant ->
-    // Like 'debug', 'release', or 'withoutGeckoBinaries'.
-    def buildType = variant.buildType.name
-
-    // It would be most natural for :geckoview to always include the Gecko
-    // binaries, but that's difficult; see the notes in
-    // mobile/android/gradle/with_gecko_binaries.gradle.  Instead we handle our
-    // own Gecko binary inclusion.
-    if (!buildType.equals('withoutGeckoBinaries')) {
-        configureVariantWithGeckoBinaries(variant)
-    }
+    implementation project(path: ':geckoview')
 }
--- a/mobile/android/gradle.configure
+++ b/mobile/android/gradle.configure
@@ -41,30 +41,33 @@ set_config('GRADLE', gradle)
 def gradle_android_build_config():
     def capitalize(s):
         # str.capitalize lower cases trailing letters.
         if s:
             return s[0].upper() + s[1:]
         else:
             return s
 
-    # It's not really possible to abstract the GeckoView details just yet; post
-    # Android-Gradle plugin 3.0+, the configurations can be more sensible and
-    # we'll do this work.
     def variant(productFlavors, buildType):
         return namespace(
             productFlavors=productFlavors,
             buildType=buildType,
             # Like 'OfficialWithoutGeckoBinariesPhotonDebug'
             name = ''.join(capitalize(t) for t in chain(productFlavors, (buildType, )))
         )
 
     return namespace(
         app=namespace(
-            variant=variant(('official', 'photon'), 'debug'),
+            variant=variant(('official', 'withoutGeckoBinaries', 'noMinApi', 'photon'), 'debug'),
+        ),
+        geckoview=namespace(
+            variant=variant(('official', 'withGeckoBinaries', 'noMinApi'), 'release'),
+        ),
+        geckoview_example=namespace(
+            variant=variant(('official', 'withGeckoBinaries', 'noMinApi'), 'debug'),
         ),
     )
 
 
 @depends(gradle_android_build_config)
 def gradle_android_app_variant_name(build_config):
     '''Like "officialPhotonDebug".'''
     def uncapitalize(s):
@@ -77,34 +80,59 @@ def gradle_android_app_variant_name(buil
 
 set_config('GRADLE_ANDROID_APP_VARIANT_NAME', gradle_android_app_variant_name)
 
 
 @depends(gradle_android_build_config)
 def gradle_android_app_tasks(build_config):
     '''Gradle tasks run by |mach android assemble-app|.'''
     return [
-        'geckoview:generateJNIWrappersForGeneratedRelease',
+        'geckoview:generateJNIWrappersForGenerated{geckoview.variant.name}'.format(geckoview=build_config.geckoview),
         'app:generateJNIWrappersForFennec{app.variant.name}'.format(app=build_config.app),
         'app:assemble{app.variant.name}'.format(app=build_config.app),
         'app:assemble{app.variant.name}AndroidTest'.format(app=build_config.app),
     ]
 
 set_config('GRADLE_ANDROID_APP_TASKS', gradle_android_app_tasks)
 
 
 @depends(gradle_android_build_config, check_build_environment)
+@imports(_from='itertools', _import='imap')
 def gradle_android_app_apks(build_config, build_env):
     '''Paths to APK files produced by |mach android assemble-app|.'''
-    flavor = '-'.join(build_config.app.variant.productFlavors)
-    buildType = build_config.app.variant.buildType
-    f = '{}/gradle/build/mobile/android/app/outputs/apk/app-{}-{}.apk'
-    g = '{}/gradle/build/mobile/android/app/outputs/apk/app-{}-{}-androidTest.apk'
-    return namespace(app_apk=f.format(build_env.topobjdir, flavor, buildType),
-                     app_androidTest_apk=g.format(build_env.topobjdir, flavor, buildType))
+    def capitalize(s):
+        # str.capitalize lower cases trailing letters.
+        if s:
+            return s[0].upper() + s[1:]
+        else:
+            return s
+
+    def uncapitalize(s):
+        if s:
+            return s[0].lower() + s[1:]
+        else:
+            return s
+
+    # Like 'officialPhoton'.
+    productFlavor = uncapitalize(''.join(imap(capitalize, build_config.app.variant.productFlavors)))
+    # Like 'official-photon'.
+    product_flavor = '-'.join(build_config.app.variant.productFlavors)
+
+    substs = {
+        'topobjdir': build_env.topobjdir,
+        'productFlavor': productFlavor,
+        'product_flavor': product_flavor,
+        'buildType': build_config.app.variant.buildType,
+    }
+
+    f = '{topobjdir}/gradle/build/mobile/android/app/outputs/apk/{productFlavor}/{buildType}/app-{product_flavor}-{buildType}.apk'
+    g = '{topobjdir}/gradle/build/mobile/android/app/outputs/apk/androidTest/{productFlavor}/{buildType}/app-{product_flavor}-{buildType}-androidTest.apk'
+
+    return namespace(app_apk=f.format(**substs),
+                     app_androidTest_apk=g.format(**substs))
 
 set_config('GRADLE_ANDROID_APP_APK', gradle_android_app_apks.app_apk)
 set_config('GRADLE_ANDROID_APP_ANDROIDTEST_APK', gradle_android_app_apks.app_androidTest_apk)
 
 
 @depends(gradle_android_build_config)
 def gradle_android_test_tasks(build_config):
     '''Gradle tasks run by |mach android test|.'''
@@ -141,23 +169,23 @@ def gradle_android_findbugs_tasks(build_
     return [
         'app:findbugsXml{app.variant.name}'.format(app=build_config.app),
         'app:findbugsHtml{app.variant.name}'.format(app=build_config.app),
     ]
 
 set_config('GRADLE_ANDROID_FINDBUGS_TASKS', gradle_android_findbugs_tasks)
 
 
-@dependable
-def gradle_android_archive_geckoview_tasks():
+@depends(gradle_android_build_config)
+def gradle_android_archive_geckoview_tasks(build_config):
     '''Gradle tasks run by |mach android archive-geckoview|.'''
     return [
-        'geckoview:assembleWithGeckoBinaries',
-        'geckoview_example:assembleWithGeckoBinaries',
-        'geckoview_example:assembleWithGeckoBinariesAndroidTest',
+        'geckoview:assemble{geckoview.variant.name}'.format(geckoview=build_config.geckoview),
+        'geckoview_example:assemble{geckoview_example.variant.name}'.format(geckoview_example=build_config.geckoview_example),
+        'geckoview_example:assemble{geckoview_example.variant.name}AndroidTest'.format(geckoview_example=build_config.geckoview_example),
         'geckoview:uploadArchives',
     ]
 
 set_config('GRADLE_ANDROID_ARCHIVE_GECKOVIEW_TASKS', gradle_android_archive_geckoview_tasks)
 
 
 @depends(
     gradle_android_app_tasks,
--- a/mobile/android/gradle/debug_level.gradle
+++ b/mobile/android/gradle/debug_level.gradle
@@ -1,20 +1,17 @@
 /* -*- Mode: Groovy; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
  * 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/. */
 
 // Bug 1353055 - Strip 'vars' debugging information to agree with moz.build.
 ext.configureVariantDebugLevel = { variant ->
-    // Like 'debug', 'release', or 'withGeckoBinaries'.
+    // Like 'debug' or 'release'.
     def buildType = variant.buildType.name
 
-    // For :app, like 'local', 'localOld', or 'official'.  For other projects, null.
-    def audienceDimension = variant.productFlavors[0]?.name
-
     // The default is 'lines,source,vars', which includes debugging information
     // that is quite large: roughly 500kb for Fennec.  Therefore we remove
     // 'vars' unless we're producing a debug build, where it is useful.
-    if (!'debug'.equals(buildType) || 'official'.equals(audienceDimension)) {
+    if (!'debug'.equals(buildType) || (variant.productFlavors*.name).contains('official')) {
         variant.javaCompile.options.debugOptions.debugLevel = 'lines,source'
     }
 }
new file mode 100644
--- /dev/null
+++ b/mobile/android/gradle/product_flavors.gradle
@@ -0,0 +1,48 @@
+/* -*- Mode: Groovy; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
+ * 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/. */
+
+ext.configureProductFlavors = {
+    flavorDimensions "audience", "geckoBinaries", "minApi"
+    productFlavors {
+        local {
+            dimension "audience"
+        }
+
+        // Automation builds.  We use "official" rather than "automation" to drive these builds down
+        // the list of configurations that Android Studio offers, thereby making it _not_ the
+        // default.  This avoids a common issue with "omni.ja" not being packed into the default APK
+        // built and deployed by Android Studio.
+        official {
+             dimension "audience"
+        }
+
+        withGeckoBinaries {
+            dimension "geckoBinaries"
+        }
+
+        withoutGeckoBinaries {
+            dimension "geckoBinaries"
+        }
+
+        // For API 21+ - with pre-dexing, this will be faster for local development.
+        minApi21 {
+            dimension "minApi"
+
+            // For pre-dexing, setting `minSdkVersion 21` allows the Android gradle plugin to
+            // pre-DEX each module and produce an APK that can be tested on
+            // Android Lollipop without time consuming DEX merging processes.
+            minSdkVersion 21
+            dexOptions {
+                preDexLibraries true
+            }
+        }
+
+        // For API < 21 - does not support pre-dexing because local development
+        // is slow in that case.
+        noMinApi {
+            dimension "minApi"
+        }
+    }
+}
--- a/mobile/android/gradle/with_gecko_binaries.gradle
+++ b/mobile/android/gradle/with_gecko_binaries.gradle
@@ -1,51 +1,27 @@
-/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
+/* -*- Mode: Groovy; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
  * 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/. */
 
-// We run fairly hard into a fundamental limitation of the Android Gradle
-// plugin.  There are many bugs filed about this, but
-// https://code.google.com/p/android/issues/detail?id=216978#c6 is a reason one.
-// The issue is that we need fine-grained control over when to include Gecko's
-// binary libraries into the GeckoView AAR and the Fennec APK, and that's hard
-// to achieve.  In particular:
-//
-// * :app:official* wants :geckoview to not include Gecko binaries (official
-// *  automation build, before package)
-//
-// * :geckoview:withLibraries wants :geckoview to include Gecko binaries
-// * (automation build, after package)
-//
-// * non-:app:official* wants :geckoview to include Gecko binaries (local
-// * build, always after package)
-//
-// publishNonDefault (see
-// http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Library-Publication)
-// is intended to address this, but doesn't handle our case.  That option always
-// builds *all* configurations, which fails when the required Gecko binaries
-// don't exist (automation build, before package).  So instead, we make both
-// :app and :geckoview both know how to include the Gecko binaries, and use a
-// non-default, non-published :geckoview:withGeckoBinaries configuration to
-// handle automation's needs.  Simple, right?
-
 // The omnijar inputs are listed as resource directory inputs to a dummy JAR.
 // That arrangement labels them nicely in IntelliJ.  See the comment in the
 // :omnijar project for more context.
 evaluationDependsOn(':omnijar')
 
-task buildOmnijar(type:Exec) {
+task buildOmnijars(type:Exec) {
     dependsOn rootProject.generateCodeAndResources
 
     // See comment in :omnijar project regarding interface mismatches here.
     inputs.file(project(':omnijar').sourceSets.main.resources.srcDirs).skipWhenEmpty() 
 
-    // Produce a single output file.
+    // Produce both the Fennec and the GeckoView omnijars.
     outputs.file "${topobjdir}/dist/fennec/assets/omni.ja"
+    outputs.file "${topobjdir}/dist/geckoview/assets/omni.ja"
 
     workingDir "${topobjdir}"
 
     commandLine mozconfig.substs.GMAKE
     args '-C'
     args "${topobjdir}/mobile/android/base"
     args 'gradle-omnijar'
 
@@ -55,134 +31,154 @@ task buildOmnijar(type:Exec) {
     errorOutput = standardOutput
     doLast {
         if (execResult.exitValue != 0) {
             throw new GradleException("Process '${commandLine}' finished with non-zero exit value ${execResult.exitValue}:\n\n${standardOutput.toString()}")
         }
     }
 }
 
-task syncOmnijarFromDistDir(type: Sync) {
-    // :app needs the full Fennec omni.ja, whereas other projects need the GeckoView-specific omni.ja.
+ext.configureVariantWithGeckoBinaries = { variant ->
+    // :app needs the full Fennec omni.ja, whereas other projects need the
+    // GeckoView-specific omni.ja.
     def omnijar_dir = "app".equals(project.name) ? "fennec" : "geckoview"
-    into("${project.buildDir}/generated/omnijar")
-    from("${topobjdir}/dist/${omnijar_dir}/omni.ja",
-         "${topobjdir}/dist/${omnijar_dir}/assets/omni.ja") {
-        // Throw an exception if we find multiple, potentially conflicting omni.ja files.
-        duplicatesStrategy 'fail'
-    }
-}
+    def distDir = "${topobjdir}/dist/${omnijar_dir}"
 
-task checkLibsExistInDistDir {
-    doLast {
-        if (syncLibsFromDistDir.source.empty) {
-            throw new GradleException("Required JNI libraries not found in ${topobjdir}/dist/fennec/lib.  Have you built and packaged?")
+    def syncOmnijarFromDistDir = task("syncOmnijarFromDistDirFor${variant.name.capitalize()}", type: Sync) {
+        doFirst {
+            if (source.empty) {
+                throw new GradleException("Required omnijar not found in ${source.asPath}.  Have you built and packaged?")
+            }
+        }
+
+        into("${project.buildDir}/moz.build/src/${variant.name}/omnijar")
+        from("${distDir}/omni.ja",
+             "${distDir}/assets/omni.ja") {
+            // Throw an exception if we find multiple, potentially conflicting omni.ja files.
+            duplicatesStrategy 'fail'
         }
     }
-}
+
+    def syncLibsFromDistDir = task("syncLibsFromDistDirFor${variant.name.capitalize()}", type: Sync) {
+        doFirst {
+            if (source.empty) {
+                throw new GradleException("Required JNI libraries not found in ${source.asPath}.  Have you built and packaged?")
+            }
+        }
 
-task syncLibsFromDistDir(type: Sync, dependsOn: checkLibsExistInDistDir) {
-    into("${project.buildDir}/generated/jniLibs")
-    from("${topobjdir}/dist/fennec/lib")
-}
+        into("${project.buildDir}/moz.build/src/${variant.name}/jniLibs")
+        from("${distDir}/lib")
+    }
 
-task checkAssetsExistInDistDir {
-    doLast {
-        if (syncAssetsFromDistDir.source.empty) {
-            throw new GradleException("Required assets not found in ${topobjdir}/dist/fennec/assets.  Have you built and packaged?")
+    def syncAssetsFromDistDir = task("syncAssetsFromDistDirFor${variant.name.capitalize()}", type: Sync) {
+        doFirst {
+            if (source.empty) {
+                throw new GradleException("Required assets not found in ${source.asPath}.  Have you built and packaged?")
+            }
+        }
+
+        into("${project.buildDir}/moz.build/src/${variant.name}/assets")
+        from("${distDir}/assets") {
+            exclude 'omni.ja'
         }
     }
-}
+
+    // Local (read, not 'official') builds want to reflect developer changes to
+    // the Omnijar sources.  To do this, the Gradle build calls out to the
+    // moz.build system, which can be re-entrant.  Official builds are driven by
+    // the moz.build system and should never be re-entrant in this way.
+    if (!((variant.productFlavors*.name).contains('official'))) {
+        syncOmnijarFromDistDir.dependsOn buildOmnijars
+    }
 
-task syncAssetsFromDistDir(type: Sync, dependsOn: checkAssetsExistInDistDir) {
-    into("${project.buildDir}/generated/assets")
-    from("${topobjdir}/dist/fennec/assets") {
-        exclude 'omni.ja'
+    def assetGenTask = tasks.findByName("generate${variant.name.capitalize()}Assets")
+    if ((variant.productFlavors*.name).contains('withGeckoBinaries')) {
+        assetGenTask.dependsOn syncOmnijarFromDistDir
+        assetGenTask.dependsOn syncLibsFromDistDir
+        assetGenTask.dependsOn syncAssetsFromDistDir
+
+        android.sourceSets."${variant.name}".assets.srcDir syncOmnijarFromDistDir.destinationDir
+        android.sourceSets."${variant.name}".assets.srcDir syncAssetsFromDistDir.destinationDir
+        android.sourceSets."${variant.name}".jniLibs.srcDir syncLibsFromDistDir.destinationDir
     }
 }
 
-ext.configureVariantWithGeckoBinaries = { variant ->
-    // Like 'localPhoton' or 'localOldPhoton'; may be null.
-    def productFlavor = ""
-    def productFlavorNames = variant.productFlavors.collect { it.name.capitalize() }
-    if (!productFlavorNames.isEmpty()) {
-        productFlavor = productFlavorNames.join()
-        // Groovy's `uncapitilize` is not yet available.
-        def c = productFlavor.toCharArray()
-        c[0] = Character.toLowerCase(c[0])
-        productFlavor = new String(c)
-    }
-
-    // Like 'debug' or 'release'.
-    def buildType = variant.buildType.name
-
-    syncOmnijarFromDistDir.dependsOn buildOmnijar
-    def generateAssetsTask = tasks.findByName("generate${productFlavor.capitalize()}${buildType.capitalize()}Assets")
-    generateAssetsTask.dependsOn syncOmnijarFromDistDir
-    generateAssetsTask.dependsOn syncLibsFromDistDir
-    generateAssetsTask.dependsOn syncAssetsFromDistDir
-
-    def sourceSet = productFlavor ? "${productFlavor}${buildType.capitalize()}" : buildType
-    android.sourceSets."${sourceSet}".assets.srcDir syncOmnijarFromDistDir.destinationDir
-    android.sourceSets."${sourceSet}".assets.srcDir syncAssetsFromDistDir.destinationDir
-    android.sourceSets."${sourceSet}".jniLibs.srcDir syncLibsFromDistDir.destinationDir
-}
-
-ext.configureVariantWithJNIWrappers = { variant, module ->
-    def jarTask
-    if (module == 'Generated') {
-        jarTask = tasks["package${variant.name.capitalize()}JarArtifact"]
-    } else {
-        jarTask = tasks["jar${variant.name.capitalize()}Classes"]
-    }
-
-    if (jarTask.outputs.files.size() != 1) {
-        throw new GradleException("Jar task output multiple files other than one single jar")
-    }
-
-    // At configuration time, the classpath of dependencies with internal_impl
-    // JAR files may not be correct.  This manifests in
+ext.configureLibraryVariantWithJNIWrappers = { variant, module ->
+    // Library variants have two essentially independent transform* tasks:
+    //
+    // - ...WithSyncLibJars... is used by assemble* and bundle*
+    // - ...WithPrepareIntermediateJars... is used by consuming applications.
     //
-    // 'Exception in thread "main" java.lang.NoClassDefFoundError: android/support/v4/app/ActivityCompatApi23$RequestPermissionsRequestCodeValidator'
-    //
-    // when running |mach gradle clean app:generateJNI...|.  We work around this
-    // by configuring the classpath at evaluation-time, not configuration-time.
-    //
-    // The specific dependency on the `prepareDependencies` task may not be
-    // necessary, but commits like
-    // https://github.com/evant/gradle-retrolambda/commit/15108c65ee43be499a1359d9d4f88b0851d46769
-    // suggest that it is.  It certainly doesn't hurt.
-    def prepareDependenciesTask = tasks.getByName("prepare${variant.name.capitalize()}Dependencies")
+    // It's not really possible to insert something immediately _after_
+    // ...WithPrepareIntermediateJars..., so we make the consuming moz.build
+    // system invoke this target directly, and force the
+    // ...WithPrepareIntermediateJars... dependency.  The real consumer of the
+    // JNI wrappers is the moz.build system, which always builds geckoview to
+    // consume from Fennec, so that dependency likely adds less to the build time.
+    def jarTask = tasks["transformClassesAndResourcesWithPrepareIntermediateJarsFor${variant.name.capitalize()}"]
+    def output = jarTask.outputs.files.find({ it.absolutePath.contains('/classes.jar') })
 
     def wrapperTask
     if (System.env.IS_LANGUAGE_REPACK == '1') {
         // Single-locale l10n repacks set `IS_LANGUAGE_REPACK=1` and don't
         // really have a build environment.
         wrapperTask = task("generateJNIWrappersFor${module}${variant.name.capitalize()}")
     } else {
         wrapperTask = task("generateJNIWrappersFor${module}${variant.name.capitalize()}", type: JavaExec) {
             classpath "${topobjdir}/build/annotationProcessors/annotationProcessors.jar"
-    
+        
             // Configure the classpath at evaluation-time, not at
             // configuration-time: see above comment.
             doFirst {
                 classpath variant.javaCompile.classpath
                 // Include android.jar.
                 classpath variant.javaCompile.options.bootClasspath
             }
     
             main = 'org.mozilla.gecko.annotationProcessors.AnnotationProcessor'
             args module
-            args jarTask.outputs.files.iterator().next()
-    
+            args output
+            
             workingDir "${topobjdir}/mobile/android/base"
-    
+            
             dependsOn jarTask
-            dependsOn prepareDependenciesTask
         }
     }
 
     if (module == 'Generated') {
         tasks["bundle${variant.name.capitalize()}"].dependsOn wrapperTask
     } else {
         tasks["assemble${variant.name.capitalize()}"].dependsOn wrapperTask
     }
 }
+
+ext.configureApplicationVariantWithJNIWrappers = { variant, module ->
+    def jarTask = tasks["bundleAppClasses${variant.name.capitalize()}"]
+    def output = jarTask.outputs.files.find({ it.absolutePath.contains('/classes.jar') })
+
+    def wrapperTask
+    if (System.env.IS_LANGUAGE_REPACK == '1') {
+        // Single-locale l10n repacks set `IS_LANGUAGE_REPACK=1` and don't
+        // really have a build environment.
+        wrapperTask = task("generateJNIWrappersFor${module}${variant.name.capitalize()}")
+    } else {
+        wrapperTask = task("generateJNIWrappersFor${module}${variant.name.capitalize()}", type: JavaExec) {
+            classpath "${topobjdir}/build/annotationProcessors/annotationProcessors.jar"
+        
+            // Configure the classpath at evaluation-time, not at
+            // configuration-time: see above comment.
+            doFirst {
+                classpath variant.javaCompile.classpath
+                // Include android.jar.
+                classpath variant.javaCompile.options.bootClasspath
+            }
+        
+            main = 'org.mozilla.gecko.annotationProcessors.AnnotationProcessor'
+            args module
+            args output
+        
+            workingDir "${topobjdir}/mobile/android/base"
+    
+            // This forces bundling, which isn't usually part of the assemble* process.
+            dependsOn jarTask
+        }
+    }
+}
--- a/mobile/android/installer/package-manifest.in
+++ b/mobile/android/installer/package-manifest.in
@@ -136,21 +136,19 @@
 @BINPATH@/components/dom_power.xpt
 #ifdef MOZ_ANDROID_GCM
 @BINPATH@/components/dom_push.xpt
 #endif
 @BINPATH@/components/dom_quota.xpt
 @BINPATH@/components/dom_range.xpt
 @BINPATH@/components/dom_security.xpt
 @BINPATH@/components/dom_sidebar.xpt
-@BINPATH@/components/dom_mobilemessage.xpt
 @BINPATH@/components/dom_storage.xpt
 @BINPATH@/components/dom_system.xpt
 @BINPATH@/components/dom_traversal.xpt
-@BINPATH@/components/dom_tv.xpt
 #ifdef MOZ_WEBSPEECH
 @BINPATH@/components/dom_webspeechrecognition.xpt
 #endif
 @BINPATH@/components/dom_xbl.xpt
 @BINPATH@/components/dom_xhr.xpt
 @BINPATH@/components/dom_xpath.xpt
 @BINPATH@/components/dom_xul.xpt
 @BINPATH@/components/dom_presentation.xpt
@@ -254,20 +252,16 @@
 @BINPATH@/components/xpconnect.xpt
 @BINPATH@/components/xulapp.xpt
 @BINPATH@/components/xul.xpt
 @BINPATH@/components/zipwriter.xpt
 
 ; JavaScript components
 @BINPATH@/components/ConsoleAPI.manifest
 @BINPATH@/components/ConsoleAPIStorage.js
-@BINPATH@/components/ContactManager.js
-@BINPATH@/components/ContactManager.manifest
-@BINPATH@/components/PhoneNumberService.js
-@BINPATH@/components/PhoneNumberService.manifest
 @BINPATH@/components/NotificationStorage.js
 @BINPATH@/components/NotificationStorage.manifest
 #ifdef MOZ_ANDROID_GCM
 @BINPATH@/components/Push.js
 @BINPATH@/components/Push.manifest
 @BINPATH@/components/PushComponents.js
 #endif
 @BINPATH@/components/BrowserElementParent.manifest
@@ -397,19 +391,16 @@
 @BINPATH@/components/BuiltinProviders.manifest
 @BINPATH@/components/PresentationControlService.js
 @BINPATH@/components/PresentationNetworkHelper.js
 @BINPATH@/components/PresentationNetworkHelper.manifest
 @BINPATH@/components/PresentationDataChannelSessionTransport.js
 @BINPATH@/components/PresentationDataChannelSessionTransport.manifest
 @BINPATH@/components/AndroidCastDeviceProvider.manifest
 @BINPATH@/components/AndroidCastDeviceProvider.js
-
-@BINPATH@/components/TVSimulatorService.js
-@BINPATH@/components/TVSimulatorService.manifest
 #endif
 
 @BINPATH@/components/mozIntl.manifest
 @BINPATH@/components/mozIntl.js
 
 ; Modules
 @BINPATH@/modules/*
 
--- a/mobile/android/mach_commands.py
+++ b/mobile/android/mach_commands.py
@@ -409,17 +409,19 @@ class MachCommands(MachCommandBase):
             # Avoid logging the command
             self.log_manager.terminal_handler.setLevel(logging.CRITICAL)
 
         # In automation, JAVA_HOME is set via mozconfig, which needs
         # to be specially handled in each mach command. This turns
         # $JAVA_HOME/bin/java into $JAVA_HOME.
         java_home = os.path.dirname(os.path.dirname(self.substs['JAVA']))
 
-        gradle_flags = shell_split(self.substs.get('GRADLE_FLAGS', ''))
+        gradle_flags = self.substs.get('GRADLE_FLAGS', '') or \
+                       os.environ.get('GRADLE_FLAGS', '')
+        gradle_flags = shell_split(gradle_flags)
 
         # We force the Gradle JVM to run with the UTF-8 encoding, since we
         # filter strings.xml, which is really UTF-8; the ellipsis character is
         # replaced with ??? in some encodings (including ASCII).  It's not yet
         # possible to filter with encodings in Gradle
         # (https://github.com/gradle/gradle/pull/520) and it's challenging to
         # do our filtering with Gradle's Ant support.  Moreover, all of the
         # Android tools expect UTF-8: see
--- a/mobile/android/moz.build
+++ b/mobile/android/moz.build
@@ -6,19 +6,16 @@
 
 with Files('**'):
     BUG_COMPONENT = ('Firefox for Android', 'Build Config & IDE Support')
     SCHEDULES.exclusive = ['android']
 
 with Files('branding/**'):
     BUG_COMPONENT = ('Firefox for Android', 'General')
 
-with Files('build/**'):
-    BUG_COMPONENT = ('Firefox for Android', 'Build Config & IDE Support')
-
 with Files('config/**'):
     BUG_COMPONENT = ('Firefox for Android', 'Build Config & IDE Support')
 
 with Files('docs/**'):
     BUG_COMPONENT = ('Firefox for Android', 'General')
 
 with Files('geckoview/**'):
     BUG_COMPONENT = ('Firefox for Android', 'GeckoView')
--- a/mobile/android/services/src/test/java/org/mozilla/gecko/background/db/DelegatingTestContentProvider.java
+++ b/mobile/android/services/src/test/java/org/mozilla/gecko/background/db/DelegatingTestContentProvider.java
@@ -3,41 +3,84 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.background.db;
 
 import android.content.ContentProvider;
 import android.content.ContentProviderOperation;
 import android.content.ContentProviderResult;
 import android.content.ContentValues;
+import android.content.Context;
 import android.content.OperationApplicationException;
+import android.content.pm.ProviderInfo;
 import android.database.Cursor;
 import android.net.Uri;
 import android.os.Bundle;
 import android.support.annotation.Nullable;
 
 import org.mozilla.gecko.db.BrowserContract;
+import org.mozilla.gecko.db.BrowserProvider;
+import org.mozilla.gecko.db.TabsProvider;
+import org.robolectric.android.controller.ContentProviderController;
+import org.robolectric.util.ReflectionHelpers;
 
 import java.util.ArrayList;
 
 /**
  * Wrap a ContentProvider, appending &test=1 to all queries.
  */
 public class DelegatingTestContentProvider extends ContentProvider {
-    protected final ContentProvider mTargetProvider;
+    protected ContentProvider mTargetProvider;
 
     protected static Uri appendUriParam(Uri uri, String param, String value) {
         return uri.buildUpon().appendQueryParameter(param, value).build();
     }
 
+    /**
+     * Create and register a new <tt>BrowserProvider</tt> that has test delegation.
+     * <p>
+     * Robolectric doesn't make it easy to parameterize a created
+     * <tt>ContentProvider</tt>, so we modify a built-in helper to do it.
+     * @return delegated <tt>ContentProvider</tt>.
+     */
+    public static ContentProvider createDelegatingBrowserProvider() {
+        final ContentProviderController<DelegatingTestContentProvider> contentProviderController
+                = ContentProviderController.of(ReflectionHelpers.callConstructor(DelegatingTestContentProvider.class,
+                ReflectionHelpers.ClassParameter.from(ContentProvider.class, new BrowserProvider())));
+        return contentProviderController.create(BrowserContract.AUTHORITY).get();
+    }
+
+    /**
+     * Create and register a new <tt>TabsProvider</tt> that has test delegation.
+     * <p>
+     * Robolectric doesn't make it easy to parameterize a created
+     * <tt>ContentProvider</tt>, so we modify a built-in helper to do it.
+     * @return delegated <tt>ContentProvider</tt>.
+     */
+    public static ContentProvider createDelegatingTabsProvider() {
+        final ContentProviderController<DelegatingTestContentProvider> contentProviderController
+                = ContentProviderController.of(ReflectionHelpers.callConstructor(DelegatingTestContentProvider.class,
+                ReflectionHelpers.ClassParameter.from(ContentProvider.class, new TabsProvider())));
+        return contentProviderController.create(BrowserContract.TABS_AUTHORITY).get();
+    }
+
     public DelegatingTestContentProvider(ContentProvider targetProvider) {
         super();
         mTargetProvider = targetProvider;
     }
 
+    public void attachInfo(Context context, ProviderInfo info) {
+        // With newer Robolectric versions, we must create the target provider
+        // before calling into super.  If we don't do this, the target
+        // provider's onCreate() will witness a null getContext(), which the
+        // Android documentation guarantees never happens on device.
+        mTargetProvider.attachInfo(context, null);
+        super.attachInfo(context, info);
+    }
+
     private Uri appendTestParam(Uri uri) {
         return appendUriParam(uri, BrowserContract.PARAM_IS_TEST, "1");
     }
 
     @Override
     public boolean onCreate() {
         return mTargetProvider.onCreate();
     }
@@ -83,12 +126,16 @@ public class DelegatingTestContentProvid
     }
 
     @Nullable
     @Override
     public Bundle call(String method, String arg, Bundle extras) {
         return mTargetProvider.call(method, arg, extras);
     }
 
+    public void shutdown() {
+        mTargetProvider.shutdown();
+    }
+
     public ContentProvider getTargetProvider() {
         return mTargetProvider;
     }
 }
--- a/mobile/android/services/src/test/java/org/mozilla/gecko/background/db/TestTabsProvider.java
+++ b/mobile/android/services/src/test/java/org/mozilla/gecko/background/db/TestTabsProvider.java
@@ -1,28 +1,28 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 package org.mozilla.gecko.background.db;
 
+import android.content.ContentProvider;
 import android.content.ContentProviderClient;
 import android.content.ContentValues;
 import android.database.Cursor;
 import android.net.Uri;
 import android.os.RemoteException;
 
 import org.json.simple.JSONArray;
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mozilla.gecko.background.testhelpers.TestRunner;
 import org.mozilla.gecko.db.BrowserContract;
-import org.mozilla.gecko.db.TabsProvider;
 import org.mozilla.gecko.sync.repositories.android.BrowserContractHelpers;
 import org.mozilla.gecko.sync.repositories.android.FennecTabsRepository;
 import org.mozilla.gecko.sync.repositories.domain.TabsRecord;
 import org.robolectric.shadows.ShadowContentResolver;
 
 @RunWith(TestRunner.class)
 public class TestTabsProvider {
     public static final String TEST_CLIENT_GUID = "test guid"; // Real GUIDs never contain spaces.
@@ -30,23 +30,21 @@ public class TestTabsProvider {
 
     public static final String CLIENTS_GUID_IS = BrowserContract.Clients.GUID + " = ?";
     public static final String TABS_CLIENT_GUID_IS = BrowserContract.Tabs.CLIENT_GUID + " = ?";
 
     protected Tab testTab1;
     protected Tab testTab2;
     protected Tab testTab3;
 
-    protected TabsProvider provider;
+    protected ContentProvider provider;
 
     @Before
     public void setUp() {
-        provider = new TabsProvider();
-        provider.onCreate();
-        ShadowContentResolver.registerProvider(BrowserContract.TABS_AUTHORITY, new DelegatingTestContentProvider(provider));
+        provider = DelegatingTestContentProvider.createDelegatingTabsProvider();
     }
 
     @After
     public void tearDown() throws Exception {
         provider.shutdown();
         provider = null;
     }
 
--- a/mobile/android/services/src/test/java/org/mozilla/gecko/background/testhelpers/MockGlobalSession.java
+++ b/mobile/android/services/src/test/java/org/mozilla/gecko/background/testhelpers/MockGlobalSession.java
@@ -8,30 +8,32 @@ import org.mozilla.gecko.sync.NonObjectJ
 import org.mozilla.gecko.sync.SyncConfiguration;
 import org.mozilla.gecko.sync.SyncConfigurationException;
 import org.mozilla.gecko.sync.crypto.KeyBundle;
 import org.mozilla.gecko.sync.delegates.GlobalSessionCallback;
 import org.mozilla.gecko.sync.net.BasicAuthHeaderProvider;
 import org.mozilla.gecko.sync.stage.CompletedStage;
 import org.mozilla.gecko.sync.stage.GlobalSyncStage;
 import org.mozilla.gecko.sync.stage.GlobalSyncStage.Stage;
+import org.robolectric.Robolectric;
+import org.robolectric.RuntimeEnvironment;
 
 import java.io.IOException;
 import java.util.HashMap;
 
 
 public class MockGlobalSession extends MockPrefsGlobalSession {
 
   public MockGlobalSession(String username, String password, KeyBundle keyBundle, GlobalSessionCallback callback) throws SyncConfigurationException, IllegalArgumentException, NonObjectJSONException, IOException {
     this(new SyncConfiguration(username, new BasicAuthHeaderProvider(username, password), new MockSharedPreferences(), keyBundle), callback);
   }
 
   public MockGlobalSession(SyncConfiguration config, GlobalSessionCallback callback)
           throws SyncConfigurationException, IllegalArgumentException, IOException, NonObjectJSONException {
-    super(config, callback, null, null);
+    super(config, callback, RuntimeEnvironment.application, null);
   }
 
   @Override
   public boolean isEngineRemotelyEnabled(String engine, EngineSettings engineSettings) {
     return false;
   }
 
   @Override
--- a/mobile/android/services/src/test/java/org/mozilla/gecko/background/testhelpers/MockPrefsGlobalSession.java
+++ b/mobile/android/services/src/test/java/org/mozilla/gecko/background/testhelpers/MockPrefsGlobalSession.java
@@ -48,14 +48,9 @@ public class MockPrefsGlobalSession exte
       ClientsDataDelegate clientsDelegate)
       throws SyncConfigurationException, IllegalArgumentException, IOException, NonObjectJSONException {
 
     final SharedPreferences prefs = new MockSharedPreferences();
     final SyncConfiguration config = new SyncConfiguration(username, authHeaderProvider, prefs);
     config.syncKeyBundle = syncKeyBundle;
     return new MockPrefsGlobalSession(config, callback, context, clientsDelegate);
   }
-
-  @Override
-  public Context getContext() {
-    return null;
-  }
 }
--- a/mobile/android/services/src/test/java/org/mozilla/gecko/db/BrowserProviderBookmarksTest.java
+++ b/mobile/android/services/src/test/java/org/mozilla/gecko/db/BrowserProviderBookmarksTest.java
@@ -1,33 +1,33 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 package org.mozilla.gecko.db;
 
+import android.content.ContentProvider;
 import android.content.ContentProviderClient;
 import android.content.ContentUris;
 import android.content.ContentValues;
 import android.database.Cursor;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.RemoteException;
 
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mozilla.gecko.background.db.DelegatingTestContentProvider;
 import org.mozilla.gecko.background.testhelpers.TestRunner;
+import org.mozilla.gecko.db.BrowserContract.Bookmarks;
 import org.mozilla.gecko.sync.Utils;
 import org.mozilla.gecko.sync.repositories.android.BrowserContractHelpers;
 import org.robolectric.shadows.ShadowContentResolver;
 
-import org.mozilla.gecko.db.BrowserContract.Bookmarks;
-
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Random;
 import java.util.UUID;
 import java.util.concurrent.ConcurrentHashMap;
 
 import static org.junit.Assert.assertEquals;
@@ -36,35 +36,34 @@ import static org.junit.Assert.assertNot
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import static org.mozilla.gecko.db.BrowserProviderGeneralTest.INVALID_TIMESTAMP;
 import static org.mozilla.gecko.db.BrowserProviderGeneralTest.assertVersionsForSelection;
 import static org.mozilla.gecko.db.BrowserProviderGeneralTest.bookmarksTestSyncUri;
 import static org.mozilla.gecko.db.BrowserProviderGeneralTest.bookmarksTestUri;
-import static org.mozilla.gecko.db.BrowserProviderGeneralTest.getBookmarksTestSyncIncrementLocalVersionUri;
 import static org.mozilla.gecko.db.BrowserProviderGeneralTest.getBookmarkIdFromGuid;
+import static org.mozilla.gecko.db.BrowserProviderGeneralTest
+        .getBookmarksTestSyncIncrementLocalVersionUri;
 import static org.mozilla.gecko.db.BrowserProviderGeneralTest.insertBookmark;
 import static org.mozilla.gecko.db.BrowserProviderGeneralTest.withDeleted;
 import static org.mozilla.gecko.db.BrowserProviderGeneralTest.withSync;
 
 /**
  * Testing direct interactions with bookmarks through BrowserProvider
  */
 @RunWith(TestRunner.class)
 public class BrowserProviderBookmarksTest {
     private ContentProviderClient bookmarksClient;
-    private BrowserProvider provider;
+    private ContentProvider provider;
 
     @Before
     public void setUp() throws Exception {
-        provider = new BrowserProvider();
-        provider.onCreate();
-        ShadowContentResolver.registerProvider(BrowserContract.AUTHORITY, new DelegatingTestContentProvider(provider));
+        provider = DelegatingTestContentProvider.createDelegatingBrowserProvider();
 
         ShadowContentResolver contentResolver = new ShadowContentResolver();
         bookmarksClient = contentResolver.acquireContentProviderClient(BrowserContractHelpers.BOOKMARKS_CONTENT_URI);
     }
 
     @After
     public void tearDown() {
         bookmarksClient.release();
--- a/mobile/android/services/src/test/java/org/mozilla/gecko/db/BrowserProviderGeneralTest.java
+++ b/mobile/android/services/src/test/java/org/mozilla/gecko/db/BrowserProviderGeneralTest.java
@@ -1,20 +1,20 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 package org.mozilla.gecko.db;
 
+import android.content.ContentProvider;
 import android.content.ContentProviderClient;
 import android.content.ContentValues;
 import android.database.Cursor;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.RemoteException;
-import android.provider.Browser;
 
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mozilla.gecko.background.db.DelegatingTestContentProvider;
 import org.mozilla.gecko.background.testhelpers.TestRunner;
 import org.mozilla.gecko.sync.repositories.android.BrowserContractHelpers;
@@ -36,25 +36,22 @@ public class BrowserProviderGeneralTest 
     final static Uri bookmarksTestSyncUri = withSync(bookmarksTestUri);
     final static Uri getBookmarksTestSyncIncrementLocalVersionUri = bookmarksTestSyncUri
             .buildUpon()
             .appendQueryParameter(BrowserContract.PARAM_INCREMENT_LOCAL_VERSION_FROM_SYNC, "true")
             .build();
 
     private static final long INVALID_ID = -1;
 
-    private BrowserProvider provider;
+    private ContentProvider provider;
     private ContentProviderClient browserClient;
 
     @Before
     public void setUp() throws Exception {
-        provider = new BrowserProvider();
-        provider.onCreate();
-
-        ShadowContentResolver.registerProvider(BrowserContract.AUTHORITY, new DelegatingTestContentProvider(provider));
+        provider = DelegatingTestContentProvider.createDelegatingBrowserProvider();
 
         ShadowContentResolver contentResolver = new ShadowContentResolver();
         browserClient = contentResolver.acquireContentProviderClient(BrowserContractHelpers.BOOKMARKS_CONTENT_URI);
     }
 
     @After
     public void tearDown() throws Exception {
         browserClient.release();
--- a/mobile/android/services/src/test/java/org/mozilla/gecko/db/BrowserProviderHistoryVisitsTestBase.java
+++ b/mobile/android/services/src/test/java/org/mozilla/gecko/db/BrowserProviderHistoryVisitsTestBase.java
@@ -1,39 +1,36 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 package org.mozilla.gecko.db;
 
+import android.content.ContentProvider;
 import android.content.ContentProviderClient;
 import android.content.ContentValues;
 import android.net.Uri;
 import android.os.RemoteException;
 
 import org.junit.After;
 import org.junit.Before;
 import org.mozilla.gecko.background.db.DelegatingTestContentProvider;
 import org.mozilla.gecko.sync.repositories.android.BrowserContractHelpers;
 import org.robolectric.shadows.ShadowContentResolver;
 
-import java.util.UUID;
-
 public class BrowserProviderHistoryVisitsTestBase {
     /* package-private */ ShadowContentResolver contentResolver;
     /* package-private */ ContentProviderClient historyClient;
     /* package-private */ ContentProviderClient visitsClient;
     /* package-private */ Uri historyTestUri;
     /* package-private */ Uri visitsTestUri;
-    /* package-private */ BrowserProvider provider;
+    /* package-private */ ContentProvider provider;
 
     @Before
     public void setUp() throws Exception {
-        provider = new BrowserProvider();
-        provider.onCreate();
-        ShadowContentResolver.registerProvider(BrowserContract.AUTHORITY, new DelegatingTestContentProvider(provider));
+        provider = DelegatingTestContentProvider.createDelegatingBrowserProvider();
 
         contentResolver = new ShadowContentResolver();
         historyClient = contentResolver.acquireContentProviderClient(BrowserContractHelpers.HISTORY_CONTENT_URI);
         visitsClient = contentResolver.acquireContentProviderClient(BrowserContractHelpers.VISITS_CONTENT_URI);
 
         historyTestUri = testUri(BrowserContract.History.CONTENT_URI);
         visitsTestUri = testUri(BrowserContract.Visits.CONTENT_URI);
     }
--- a/mobile/android/services/src/test/java/org/mozilla/gecko/db/LocalBrowserDBTest.java
+++ b/mobile/android/services/src/test/java/org/mozilla/gecko/db/LocalBrowserDBTest.java
@@ -1,14 +1,15 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 package org.mozilla.gecko.db;
 
 import android.annotation.SuppressLint;
+import android.content.ContentProvider;
 import android.content.ContentProviderClient;
 import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.content.Context;
 import android.database.Cursor;
 import android.net.Uri;
 import android.os.RemoteException;
 import android.support.annotation.Nullable;
@@ -39,25 +40,23 @@ public class LocalBrowserDBTest {
     private static final String BOOKMARK_TITLE = "mozilla";
 
     private static final String UPDATE_URL = "https://bugzilla.mozilla.org";
     private static final String UPDATE_TITLE = "bugzilla";
 
     private static final String FOLDER_NAME = "folder1";
 
     private Context context;
-    private BrowserProvider provider;
+    private ContentProvider provider;
     private ContentProviderClient bookmarkClient;
 
     @Before
     public void setUp() throws Exception {
         context = RuntimeEnvironment.application;
-        provider = new BrowserProvider();
-        provider.onCreate();
-        ShadowContentResolver.registerProvider(BrowserContract.AUTHORITY, new DelegatingTestContentProvider(provider));
+        provider = DelegatingTestContentProvider.createDelegatingBrowserProvider();
 
         ShadowContentResolver contentResolver = new ShadowContentResolver();
         bookmarkClient = contentResolver.acquireContentProviderClient(BrowserContractHelpers.BOOKMARKS_CONTENT_URI);
     }
 
     @After
     public void tearDown() {
         bookmarkClient.release();
--- a/mobile/android/services/src/test/java/org/mozilla/gecko/fxa/devices/TestFxAccountDeviceListUpdater.java
+++ b/mobile/android/services/src/test/java/org/mozilla/gecko/fxa/devices/TestFxAccountDeviceListUpdater.java
@@ -1,13 +1,14 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 package org.mozilla.gecko.fxa.devices;
 
+import android.content.ContentProvider;
 import android.content.ContentProviderClient;
 import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.database.Cursor;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.RemoteException;
 
@@ -16,17 +17,16 @@ import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.mozilla.gecko.background.db.DelegatingTestContentProvider;
 import org.mozilla.gecko.background.fxa.FxAccountClient;
 import org.mozilla.gecko.background.testhelpers.TestRunner;
 import org.mozilla.gecko.db.BrowserContract;
-import org.mozilla.gecko.db.BrowserProvider;
 import org.mozilla.gecko.fxa.authenticator.AndroidFxAccount;
 import org.mozilla.gecko.fxa.login.State;
 import org.robolectric.shadows.ShadowContentResolver;
 
 import java.util.List;
 import java.util.UUID;
 
 import static java.util.Objects.deepEquals;
@@ -114,22 +114,19 @@ public class TestFxAccountDeviceListUpda
         assertTrue(firstDevice.getAsLong(BrowserContract.RemoteDevices.DATE_MODIFIED) < timeBeforeCall + 10000);
         assertEquals(firstDevice.getAsString(BrowserContract.RemoteDevices.NAME), device.name);
     }
 
     @Test
     public void testBrowserProvider() {
         Uri uri = testUri(BrowserContract.RemoteDevices.CONTENT_URI);
 
-        BrowserProvider provider = new BrowserProvider();
+        final ContentProvider provider = DelegatingTestContentProvider.createDelegatingBrowserProvider();
         Cursor c = null;
         try {
-            provider.onCreate();
-            ShadowContentResolver.registerProvider(BrowserContract.AUTHORITY, new DelegatingTestContentProvider(provider));
-
             final ShadowContentResolver cr = new ShadowContentResolver();
             ContentProviderClient remoteDevicesClient = cr.acquireContentProviderClient(BrowserContract.RemoteDevices.CONTENT_URI);
 
             // First let's insert a client for initial state.
 
             Bundle bundle = new Bundle();
             ContentValues device1 = createMockRemoteClientValues("device1");
             bundle.putParcelableArray(BrowserContract.METHOD_PARAM_DATA, new ContentValues[] { device1 });
--- a/mobile/android/services/src/test/java/org/mozilla/gecko/sync/repositories/android/VisitsHelperTest.java
+++ b/mobile/android/services/src/test/java/org/mozilla/gecko/sync/repositories/android/VisitsHelperTest.java
@@ -1,27 +1,27 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 package org.mozilla.gecko.sync.repositories.android;
 
+import android.content.ContentProvider;
 import android.content.ContentProviderClient;
 import android.content.ContentValues;
 import android.net.Uri;
 
 import junit.framework.Assert;
 
 import org.json.simple.JSONArray;
 import org.json.simple.JSONObject;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mozilla.gecko.background.db.DelegatingTestContentProvider;
 import org.mozilla.gecko.background.testhelpers.TestRunner;
 import org.mozilla.gecko.db.BrowserContract;
-import org.mozilla.gecko.db.BrowserProvider;
 import org.robolectric.shadows.ShadowContentResolver;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
 @RunWith(TestRunner.class)
 public class VisitsHelperTest {
     @Test
@@ -51,21 +51,18 @@ public class VisitsHelperTest {
         Assert.assertEquals(Long.valueOf(date + 1000), cv2.getAsLong(BrowserContract.Visits.DATE_VISITED));
     }
 
     @Test
     public void testGetRecentHistoryVisitsForGUID() throws Exception {
         Uri historyTestUri = testUri(BrowserContract.History.CONTENT_URI);
         Uri visitsTestUri = testUri(BrowserContract.Visits.CONTENT_URI);
 
-        BrowserProvider provider = new BrowserProvider();
+        final ContentProvider provider = DelegatingTestContentProvider.createDelegatingBrowserProvider();
         try {
-            provider.onCreate();
-            ShadowContentResolver.registerProvider(BrowserContract.AUTHORITY, new DelegatingTestContentProvider(provider));
-
             final ShadowContentResolver cr = new ShadowContentResolver();
             ContentProviderClient historyClient = cr.acquireContentProviderClient(BrowserContractHelpers.HISTORY_CONTENT_URI);
             ContentProviderClient visitsClient = cr.acquireContentProviderClient(BrowserContractHelpers.VISITS_CONTENT_URI);
 
             ContentValues historyItem = new ContentValues();
             historyItem.put(BrowserContract.History.URL, "https://www.mozilla.org");
             historyItem.put(BrowserContract.History.GUID, "testGUID");
             historyClient.insert(historyTestUri, historyItem);
--- a/mobile/android/thirdparty/build.gradle
+++ b/mobile/android/thirdparty/build.gradle
@@ -1,20 +1,16 @@
 buildDir "${topobjdir}/gradle/build/mobile/android/thirdparty"
 
 apply plugin: 'com.android.library'
 
 android {
     compileSdkVersion project.ext.compileSdkVersion
-    buildToolsVersion project.ext.buildToolsVersion
 
     defaultConfig {
-        defaultPublishConfig 'release'
-        publishNonDefault true
-
         targetSdkVersion project.ext.targetSdkVersion
         minSdkVersion project.ext.minSdkVersion
         manifestPlaceholders = project.ext.manifestPlaceholders
     }
 
     compileOptions {
         sourceCompatibility JavaVersion.VERSION_1_7
         targetCompatibility JavaVersion.VERSION_1_7
@@ -42,21 +38,21 @@ android {
                 // here is only the no-op library for mach-based builds.
                 exclude 'com/squareup/leakcanary/**'
             }
         }
     }
 }
 
 dependencies {
-    compile "com.android.support:support-v4:${mozconfig.substs.ANDROID_SUPPORT_LIBRARY_VERSION}"
+    implementation "com.android.support:support-v4:${mozconfig.substs.ANDROID_SUPPORT_LIBRARY_VERSION}"
     if (mozconfig.substs.MOZ_ANDROID_MMA) {
-        compile "com.android.support:appcompat-v7:${mozconfig.substs.ANDROID_SUPPORT_LIBRARY_VERSION}"
-        compile "com.android.support:support-annotations:${mozconfig.substs.ANDROID_GOOGLE_PLAY_SERVICES_VERSION}"
-        compile "com.google.android.gms:play-services-gcm:${mozconfig.substs.ANDROID_GOOGLE_PLAY_SERVICES_VERSION}"
+        implementation "com.android.support:appcompat-v7:${mozconfig.substs.ANDROID_SUPPORT_LIBRARY_VERSION}"
+        implementation "com.android.support:support-annotations:${mozconfig.substs.ANDROID_GOOGLE_PLAY_SERVICES_VERSION}"
+        implementation "com.google.android.gms:play-services-gcm:${mozconfig.substs.ANDROID_GOOGLE_PLAY_SERVICES_VERSION}"
     }
 }
 
 apply plugin: 'idea'
 
 idea {
     module {
         // This is cosmetic.  See the excludes in the root project.
--- a/netwerk/base/nsINetUtil.idl
+++ b/netwerk/base/nsINetUtil.idl
@@ -78,23 +78,16 @@ interface nsINetUtil : nsISupports
   /**
    * Take aURI and produce an immutable version of it for the caller.  If aURI
    * is immutable this will be aURI itself; otherwise this will be a clone,
    * marked immutable if possible.  Passing null to this method is allowed; in
    * that case it will return null.
    */
   nsIURI toImmutableURI(in nsIURI aURI);
 
-  /**
-   * Create a simple nested URI using the result of
-   * toImmutableURI on the passed-in aURI which may not be null.
-   * Note: The return URI will not have had its spec set yet.
-   */
-  nsIURI newSimpleNestedURI(in nsIURI aURI);
-
   /** Escape every character with its %XX-escaped equivalent */
   const unsigned long ESCAPE_ALL = 0;
 
   /** Leave alphanumeric characters intact and %XX-escape all others */
   const unsigned long ESCAPE_XALPHAS = 1;
 
   /** Leave alphanumeric characters intact, convert spaces to '+',
       %XX-escape all others */
--- a/netwerk/base/nsIOService.cpp
+++ b/netwerk/base/nsIOService.cpp
@@ -1570,29 +1570,16 @@ nsIOService::ToImmutableURI(nsIURI* uri,
     nsresult rv = NS_EnsureSafeToReturn(uri, result);
     NS_ENSURE_SUCCESS(rv, rv);
 
     NS_TryToSetImmutable(*result);
     return NS_OK;
 }
 
 NS_IMETHODIMP
-nsIOService::NewSimpleNestedURI(nsIURI* aURI, nsIURI** aResult)
-{
-    NS_ENSURE_ARG(aURI);
-
-    nsCOMPtr<nsIURI> safeURI;
-    nsresult rv = NS_EnsureSafeToReturn(aURI, getter_AddRefs(safeURI));
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    NS_IF_ADDREF(*aResult = new nsSimpleNestedURI(safeURI));
-    return *aResult ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
-}
-
-NS_IMETHODIMP
 nsIOService::SetManageOfflineStatus(bool aManage)
 {
     LOG(("nsIOService::SetManageOfflineStatus aManage=%d\n", aManage));
     mManageLinkStatus = aManage;
 
     // When detection is not activated, the default connectivity state is true.
     if (!mManageLinkStatus) {
         SetConnectivityInternal(true);
--- a/old-configure.in
+++ b/old-configure.in
@@ -2128,17 +2128,17 @@ AC_SUBST(MOZ_MULET)
 
 dnl ========================================================
 dnl Ensure Android SDK and build-tools versions depending on
 dnl mobile target.
 dnl ========================================================
 
 case "$MOZ_BUILD_APP" in
 mobile/android)
-    MOZ_ANDROID_SDK(23, 23, 25.0.3, 26.0.0 26.0.0-dev 25.3.2 25.3.1)
+    MOZ_ANDROID_SDK(23, 23, 26.0.2, 26.0.0 26.0.0-dev 25.3.2 25.3.1)
     ;;
 esac
 
 dnl ========================================================
 dnl =
 dnl = Toolkit Options
 dnl =
 dnl ========================================================
--- a/python/mozboot/mozboot/android-packages.txt
+++ b/python/mozboot/mozboot/android-packages.txt
@@ -1,6 +1,6 @@
 platform-tools
-build-tools;25.0.3
+build-tools;26.0.2
 platforms;android-23
 extras;android;m2repository
 extras;google;m2repository
 emulator
--- a/python/mozbuild/mozbuild/config_status.py
+++ b/python/mozbuild/mozbuild/config_status.py
@@ -33,23 +33,20 @@ from mozbuild.backend import (
 log_manager = LoggingManager()
 
 
 ANDROID_IDE_ADVERTISEMENT = '''
 =============
 ADVERTISEMENT
 
 You are building Firefox for Android. After your build completes, you can open
-the top source directory in IntelliJ or Android Studio directly and build using
-Gradle.  See the documentation at
+the top source directory in Android Studio directly and build using Gradle.
+See the documentation at
 
 https://developer.mozilla.org/en-US/docs/Simple_Firefox_for_Android_build
-
-PLEASE BE AWARE THAT GRADLE AND INTELLIJ/ANDROID STUDIO SUPPORT IS EXPERIMENTAL.
-You should verify any changes using |mach build|.
 =============
 '''.strip()
 
 VISUAL_STUDIO_ADVERTISEMENT = '''
 ===============================
 Visual Studio Support Available
 
 You are building Firefox on Windows. You can generate Visual Studio
--- a/security/manager/ssl/StaticHPKPins.h
+++ b/security/manager/ssl/StaticHPKPins.h
@@ -1156,9 +1156,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 = 483;
 
 static const int32_t kUnknownId = -1;
 
-static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1524423617990000);
+static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1524509866086000);
--- a/security/manager/ssl/nsSTSPreloadList.errors
+++ b/security/manager/ssl/nsSTSPreloadList.errors
@@ -1,15 +1,16 @@
 00220022.net: could not connect to host
 01100010011001010111001101110100.com: could not connect to host
 06se.com: could not connect to host
 07733.win: could not connect to host
 0day.su: could not connect to host
 0i0.nl: could not connect to host
 0vi.org: could not connect to host
+0x52.org: could not connect to host
 10gb.io: could not connect to host
 135vv.com: could not connect to host
 13826145000.com: could not connect to host
 166166.com: could not connect to host
 1nian.vip: could not connect to host
 1q365a.com: could not connect to host
 24hrs.shopping: could not connect to host
 28spots.net: could not connect to host
@@ -47,35 +48,34 @@ abolition.co: could not connect to host
 accwing.com: could not connect to host
 acgaudio.com: could not connect to host
 achterhoekseveiligheidsbeurs.nl: could not connect to host
 acrossgw.com: could not connect to host
 ad-disruptio.fr: could not connect to host
 adamdixon.co.uk: could not connect to host
 adec-emsa.ae: could not connect to host
 adult.properties: could not connect to host
-adventureally.com: could not connect to host
 aevpn.org: could not connect to host
 affily.io: could not connect to host
 afterstack.net: could not connect to host
 agilebits.net: could not connect to host
+ahwah.net: could not connect to host
 aiicy.org: could not connect to host
 aim-consultants.com: could not connect to host
-aivd.lol: could not connect to host
 akiba-server.info: could not connect to host
 akita-stream.com: could not connect to host
+akoch.net: could not connect to host
 akoww.de: could not connect to host
 akul.co.in: could not connect to host
 al-f.net: could not connect to host
 alasta.info: could not connect to host
 alauda-home.de: could not connect to host
 alcatraz.online: could not connect to host
 alcnutrition.com: could not connect to host
 alexandernorth.ch: could not connect to host
-alexandros.io: could not connect to host
 alexei.su: could not connect to host
 alexey-shamara.ru: could not connect to host
 alexmol.tk: could not connect to host
 alexperry.io: could not connect to host
 alilialili.ga: could not connect to host
 alldm.ru: could not connect to host
 allscammers.exposed: could not connect to host
 altahrim.net: could not connect to host
@@ -95,24 +95,26 @@ andrewdaws.info: could not connect to ho
 andrewdaws.me: could not connect to host
 andrewdaws.tv: could not connect to host
 andrewrdaws.com: could not connect to host
 andronika.net: could not connect to host
 angrydragonproductions.com: could not connect to host
 annetaan.fi: could not connect to host
 annonasoftware.com: could not connect to host
 anongoth.pl: could not connect to host
+answers-online.ru: could not connect to host
 antimatiere.space: could not connect to host
 anttitenhunen.com: could not connect to host
 anyways.at: could not connect to host
 aojiao.org: could not connect to host
 apkoyunlar.club: could not connect to host
 apparels24.com: could not connect to host
 appdrinks.com: could not connect to host
 apple.ax: could not connect to host
+arbitrarion.com: could not connect to host
 area3.org: could not connect to host
 arenlor.com: could not connect to host
 arenlor.info: could not connect to host
 arenns.com: could not connect to host
 arent.kz: could not connect to host
 argh.io: could not connect to host
 arksan.com.tr: could not connect to host
 armenians.online: could not connect to host
@@ -151,28 +153,26 @@ avonlearningcampus.com: could not connec
 awan.tech: could not connect to host
 awf0.xyz: could not connect to host
 axel-fischer.science: could not connect to host
 azabani.com: could not connect to host
 b8a.me: could not connect to host
 babelfisch.eu: could not connect to host
 bad.pet: could not connect to host
 bageez.us: could not connect to host
-bailbondsaffordable.com: could not connect to host
 baiyangliu.com: could not connect to host
 baka.network: could not connect to host
-baldur.cc: could not connect to host
 balonmano.co: could not connect to host
 bandally.net: could not connect to host
 bandarifamily.com: could not connect to host
 bannisbierblog.de: could not connect to host
-barbate.fr: could not connect to host
 barracuda.blog: could not connect to host
 barreaudenice.com: could not connect to host
 batfoundry.com: could not connect to host
+bbb1991.me: could not connect to host
 bbdos.ru: could not connect to host
 bbnx.net: could not connect to host
 bdsmxxxpics.com: could not connect to host
 bdvg.org: could not connect to host
 beamitapp.com: could not connect to host
 bearden.io: could not connect to host
 beasel.biz: could not connect to host
 bellavistaoutdoor.com: could not connect to host
@@ -202,17 +202,16 @@ bitcoin-daijin.com: could not connect to
 bitcoinjpn.com: could not connect to host
 bitmaincare.com.ua: could not connect to host
 bitmaincare.ru: could not connect to host
 bitmessage.ch: could not connect to host
 bityes.org: could not connect to host
 bizeau.ch: could not connect to host
 bjgongyi.com: could not connect to host
 bjtxl.cn: could not connect to host
-black-khat.com: could not connect to host
 blackdiam.net: could not connect to host
 blantik.net: could not connect to host
 blazeit.io: could not connect to host
 blindaryproduction.tk: could not connect to host
 blinkenlight.co.uk: could not connect to host
 blinkenlight.com.au: could not connect to host
 blog.gparent.org: could not connect to host
 blokuhaka.fr: could not connect to host
@@ -228,55 +227,55 @@ bqcp.net: could not connect to host
 brage.info: could not connect to host
 braintensive.com: could not connect to host
 brandontaylor-black.com: could not connect to host
 breathingblanket.com: could not connect to host
 briangarcia.ga: could not connect to host
 brianpcurran.com: could not connect to host
 brightonchilli.org.uk: could not connect to host
 brio-ukraine.store: could not connect to host
-brooke-fan.com: could not connect to host
 brookframework.org: could not connect to host
 brrr.fr: could not connect to host
 bryanshearer.accountant: could not connect to host
 brynnan.nl: could not connect to host
 bsalyzer.com: could not connect to host
 bsktweetup.info: could not connect to host
 bslim-e-boutique.com: could not connect to host
 bsuess.de: could not connect to host
-budgetlovers.nl: could not connect to host
 bugginslab.co.uk: could not connect to host
 bugsmashed.com: could not connect to host
 buka.jp: could not connect to host
 businessfurs.info: could not connect to host
 businesshub.cz: could not connect to host
 businessmodeler.se: could not connect to host
 buyingsellingflorida.com: could not connect to host
 buyshoe.org: could not connect to host
 bvexplained.co.uk: could not connect to host
 by1898.com: could not connect to host
 byji.com: could not connect to host
 bypass.kr: could not connect to host
 byteshift.ca: could not connect to host
 cafesg.net: could not connect to host
 caipai.fm: could not connect to host
 calculatoaresecondhand.xyz: could not connect to host
+caldecotevillagehall.co.uk: could not connect to host
 callabs.net: could not connect to host
 callsigns.ca: could not connect to host
 camda.online: could not connect to host
 campingcarlovers.com: could not connect to host
 canarymod.net: could not connect to host
 cancelmyprofile.com: could not connect to host
 caps.is: could not connect to host
 capturethepen.co.uk: could not connect to host
 cardloan-manual.net: could not connect to host
 cardse.net: could not connect to host
 carloshmm.stream: could not connect to host
 carlovanwyk.com: could not connect to host
 casinoreal.com: could not connect to host
+catsmagic.pp.ua: could not connect to host
 caughtredhanded.co.nz: could not connect to host
 cctld.com: could not connect to host
 cdnk39.com: could not connect to host
 cee.io: could not connect to host
 cegfw.com: could not connect to host
 celuliteonline.com: could not connect to host
 cencalvia.org: could not connect to host
 centos.pub: could not connect to host
@@ -318,77 +317,83 @@ cnlic.com: could not connect to host
 cnwage.com: could not connect to host
 cnwarn.com: could not connect to host
 co-yutaka.com: could not connect to host
 cobaltlp.com: could not connect to host
 coccolebenessere.it: could not connect to host
 coco-cool.fr: could not connect to host
 codenlife.xyz: could not connect to host
 codercross.com: could not connect to host
+codercy.com: could not connect to host
 codewiz.xyz: could not connect to host
 cogumelosmagicos.org: could not connect to host
 colleencornez.com: could not connect to host
 collins.kg: could not connect to host
 combatshield.cz: could not connect to host
 complt.xyz: could not connect to host
 comprehensiveihc.com: could not connect to host
+computerassistance.co.uk: could not connect to host
 conception.sk: could not connect to host
 conniesacademy.com: could not connect to host
 conrad.am: could not connect to host
 construct-trust.com: could not connect to host
 conve.eu: could not connect to host
 corecdn.org: could not connect to host
 corinnanese.de: could not connect to host
 correct.horse: could not connect to host
 cosmeticosdelivery.com.br: could not connect to host
 cosplayer.com: could not connect to host
 coumoul.fr: could not connect to host
 cpaneltips.com: could not connect to host
 crackpfer.de: could not connect to host
 crackslut.eu: could not connect to host
 creative-wave.fr: could not connect to host
 creativecommonscatpictures.com: could not connect to host
+crestasantos.com: could not connect to host
 cristianhares.com: could not connect to host
 criticalaim.com: could not connect to host
 crox.co: could not connect to host
 cryptopartynewcastle.org: could not connect to host
 crystalmachine.net: could not connect to host
+cselzer.com: could not connect to host
 csgo77.com: could not connect to host
 cspeti.hu: could not connect to host
 ctj.im: could not connect to host
 cunha.be: could not connect to host
 cuonic.com: could not connect to host
+curacao-license.com: could not connect to host
 customfilmworks.com: could not connect to host
 cyber-computer.club: could not connect to host
 cyberpeace.nl: could not connect to host
 cyberstatus.de: could not connect to host
 cypherpunk.ws: could not connect to host
 czlx.co: could not connect to host
 d-bood.site: could not connect to host
 d8studio.net: could not connect to host
-dahlberg.cologne: could not connect to host
 daltonedwards.me: could not connect to host
 dam74.com.ar: could not connect to host
 daniel-stahl.net: could not connect to host
 danielthompson.info: could not connect to host
+dannyrohde.de: could not connect to host
 danpiel.net: could not connect to host
 darkdestiny.ch: could not connect to host
 darlo.co.uk: could not connect to host
 data-detox.com: could not connect to host
 datacool.tk: could not connect to host
 datorb.com: could not connect to host
 davidscherzer.at: could not connect to host
 davidstuff.net: could not connect to host
 davros.eu: could not connect to host
 davros.ru: could not connect to host
 dawnson.is: could not connect to host
 day.vip: could not connect to host
 days.one: could not connect to host
 dbcom.ru: could not connect to host
 dbox.ga: could not connect to host
+dcc.moe: could not connect to host
 dden.website: could not connect to host
 dden.xyz: could not connect to host
 de-servers.de: could not connect to host
 decoyrouting.com: could not connect to host
 deepcreampie.com: could not connect to host
 deepsouthsounds.com: could not connect to host
 deloittequant.com: could not connect to host
 derchris.me: could not connect to host
@@ -407,34 +412,31 @@ devkid.net: could not connect to host
 devops.moe: could not connect to host
 dhl-smart.ch: could not connect to host
 dhub.xyz: could not connect to host
 dhuy.net: could not connect to host
 diceduels.com: could not connect to host
 dicgaming.net: could not connect to host
 dick.red: could not connect to host
 didierlaumen.be: could not connect to host
-didikhari.web.id: could not connect to host
 diemogebhardt.com: could not connect to host
 dieser.me: could not connect to host
 digihyp.ch: could not connect to host
 digioccumss.ddns.net: could not connect to host
 digitalhurricane.io: could not connect to host
-digitalrxcloud.com: could not connect to host
 diguass.us: could not connect to host
 dijks.com: could not connect to host
 dirtycat.ru: could not connect to host
 disability.gov: could not connect to host
 disadattamentolavorativo.it: could not connect to host
 disco-crazy-world.de: could not connect to host
 discoveryballoon.org: could not connect to host
 distinctivephotography.com.au: could not connect to host
 ditch.ch: could not connect to host
 dixmag.com: could not connect to host
-dlld.com: could not connect to host
 dlouwrink.nl: could not connect to host
 dlyl888.com: could not connect to host
 dnscrypt.org: could not connect to host
 dobrisan.ro: could not connect to host
 dogcratereview.info: could not connect to host
 dojifish.space: could not connect to host
 dolphin-hosting.com: could not connect to host
 domengrad.ru: could not connect to host
@@ -456,27 +458,27 @@ droomhuis-in-zuid-holland-kopen.nl: coul
 drunkscifi.com: could not connect to host
 duan.li: could not connect to host
 dubrovskiy.net: could not connect to host
 dubrovskiy.pro: could not connect to host
 duch.cloud: could not connect to host
 duelsow.eu: could not connect to host
 duesee.org: could not connect to host
 duks.com.br: could not connect to host
-dullapp.com: could not connect to host
 duo.money: could not connect to host
 durangoenergyllc.com: could not connect to host
 dwnld.me: could not connect to host
 e-mak.eu: could not connect to host
 e-wishlist.net: could not connect to host
 eatfitoutlet.com.br: could not connect to host
 eatry.io: could not connect to host
-ecodigital.social: could not connect to host
 ectora.com: could not connect to host
 edgecustomersportal.com: could not connect to host
+edlinus.cn: 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]
 edusantorini.com: could not connect to host
 eeb98.com: could not connect to host
 ehuber.info: could not connect to host
 einsatzstiefel.info: could not connect to host
 ekobudisantoso.net: could not connect to host
 elbetech.net: could not connect to host
 elektronring.com: could not connect to host
 elenorsmadness.org: could not connect to host
@@ -486,32 +488,34 @@ elisabeth-strunz.de: could not connect t
 elonbase.com: could not connect to host
 elsword.moe: could not connect to host
 eltransportquevolem.org: could not connect to host
 emilyjohnson.ga: could not connect to host
 emrenovation.com: could not connect to host
 endspamwith.us: could not connect to host
 enfoqueseguro.com: could not connect to host
 envygeeks.io: could not connect to host
-epulsar.ru: could not connect to host
 er-music.com: could not connect to host
 eriser.fr: could not connect to host
 erspro.net: could not connect to host
 erwinwensveen.nl: could not connect to host
 ethiobaba.com: could not connect to host
 euexia.fr: could not connect to host
 eurostrategy.vn.ua: could not connect to host
 ev-zertifikate.de: could not connect to host
 evankurniawan.com: could not connect to host
 eveshaiwu.com: could not connect to host
 evileden.com: could not connect to host
 exceptionalservices.us: could not connect to host
 exo.do: could not connect to host
+exploravacations.in: could not connect to host
+extensiblewebmanifesto.org: could not connect to host
+extensiblewebreportcard.org: could not connect to host
+extensiblewebsummit.org: could not connect to host
 exteriorservices.io: could not connect to host
-extranetpuc.com.br: could not connect to host
 eytosh.net: could not connect to host
 f8842.com: could not connect to host
 faber.org.ru: could not connect to host
 fabian-kluge.de: could not connect to host
 facebook.ax: could not connect to host
 facilitrak.com: could not connect to host
 factureenlinea.com: could not connect to host
 fafatiger.com: could not connect to host
@@ -529,32 +533,36 @@ fastbackmbg.be: could not connect to hos
 faxreader.net: could not connect to host
 fed51.com: could not connect to host
 feedstringer.com: could not connect to host
 feirlane.org: could not connect to host
 fengyadi.com: could not connect to host
 fensterbau-mutscheller.de: could not connect to host
 feras-alhajjaji.com: could not connect to host
 fetclips.se: could not connect to host
-fhg90.com: could not connect to host
 ficklenote.net: could not connect to host
+fierman.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]
+fierman.net: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 119"  data: no]
+fierman.us: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 119"  data: no]
 fifieldtech.com: could not connect to host
+figuurzagers.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]
 fileio.io: could not connect to host
 findmybottleshop.com.au: could not connect to host
 finstererlebnis.de: could not connect to host
 firebaseio.com: could not connect to host
 firexarxa.de: could not connect to host
 fix-the-timeline.com: could not connect to host
 fix-the-timeline.org: could not connect to host
 fixmyglitch.com: could not connect to host
 fixthetimeline.com: could not connect to host
 fixthetimeline.org: could not connect to host
-floriantanner.ch: could not connect to host
+flopy.club: could not connect to host
 flow.su: could not connect to host
 flugplatz-edvc.de: could not connect to host
+fly.moe: could not connect to host
 flygpost.com: could not connect to host
 flyingdoggy.net: could not connect to host
 focalforest.com: could not connect to host
 folioapp.io: could not connect to host
 forcamp.ga: could not connect to host
 forschbach-janssen.de: could not connect to host
 forsyththeatre.com: could not connect to host
 fortuna-loessnitz.de: could not connect to host
@@ -562,16 +570,17 @@ foshanshequ.com: could not connect to ho
 fossewayflowers.co.uk: could not connect to host
 fossewayflowers.com: could not connect to host
 foudufafa.de: could not connect to host
 foxyslut.com: could not connect to host
 fragnic.com: could not connect to host
 franckyz.com: could not connect to host
 fransallen.com: could not connect to host
 franzt.ovh: could not connect to host
+frebib.net: could not connect to host
 fredliang.cn: could not connect to host
 fredtec.ru: could not connect to host
 freejidi.com: could not connect to host
 freelansir.com: could not connect to host
 freeshkre.li: could not connect to host
 freesounding.ru: could not connect to host
 freshcode.nl: could not connect to host
 frickenate.com: could not connect to host
@@ -611,18 +620,18 @@ game-gentle.com: could not connect to ho
 gameswitchers.uk: could not connect to host
 gametium.com: could not connect to host
 gametium.es: could not connect to host
 gasbarkenora.com: could not connect to host
 gasnews.net: could not connect to host
 gautham.it: could not connect to host
 gautham.pro: could not connect to host
 gaygeeks.de: could not connect to host
+gc.net: could not connect to host
 gchoic.com: could not connect to host
-gchq.wtf: could not connect to host
 gdb-tutorial.net: could not connect to host
 gdevpenze.ru: could not connect to host
 gdhzcgs.com: could not connect to host
 gdz-otvety.com: could not connect to host
 ge1.me: could not connect to host
 gehrke.nrw: could not connect to host
 geigr.de: could not connect to host
 generationnext.pl: could not connect to host
@@ -640,58 +649,56 @@ getgeek.io: could not connect to host
 getgeek.no: could not connect to host
 getgeek.nu: could not connect to host
 getgeek.pl: 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
 gglks.com: could not connect to host
 ggss.cf: could not connect to host
-giftking.nl: could not connect to host
 gifzilla.net: could not connect to host
 gina-architektur.design: could not connect to host
 git.co: could not connect to host
 glasner.photo: could not connect to host
 glutenfreelife.co.nz: could not connect to host
 gm-assicurazioni.it: could not connect to host
 gmantra.org: could not connect to host
 gmanukyan.com: could not connect to host
-gmind.ovh: could not connect to host
 gnom.me: could not connect to host
 gnosticjade.net: could not connect to host
 godrealms.com: could not connect to host
 goiaspropaganda.com.br: could not connect to host
+gongjuhao.com: could not connect to host
 google: could not connect to host
 google.ax: could not connect to host
 goranrango.ch: could not connect to host
 gottfridsberg.org: could not connect to host
 gozadentro.com: could not connect to host
 gradsm-ci.net: could not connect to host
 granth.io: could not connect to host
 graphire.io: could not connect to host
 gratisonlinesex.com: could not connect to host
 greg.red: could not connect to host
+greggsfoundation.org.uk: could not connect to host
 gregmartyn.com: could not connect to host
 greuel.online: could not connect to host
 gritte.net: could not connect to host
 grossmisconduct.news: could not connect to host
 gugaltika-ipb.org: could not connect to host
 gus.moe: could not connect to host
 gvchannel.xyz: could not connect to host
 gvt2.com: could not connect to host
 gvt3.com: could not connect to host
 h2cdn.cloud: could not connect to host
 h3artbl33d.nl: could not connect to host
-h3x.jp: could not connect to host
-h3z.jp: could not connect to host
 habeo.si: could not connect to host
-hackthissite.org: could not connect to host
 hakugin.me: could not connect to host
 halcyonsbastion.com: could not connect to host
 halkyon.net: could not connect to host
+hang333.pw: could not connect to host
 hapijs.cn: could not connect to host
 harrypottereditor.net: could not connect to host
 hasabig.wang: could not connect to host
 hasalittle.wang: could not connect to host
 hashplex.com: could not connect to host
 haze.network: could not connect to host
 hbbet.com: could not connect to host
 hbvip.com: could not connect to host
@@ -729,28 +736,28 @@ homesandal.com: could not connect to hos
 homoglyph.net: could not connect to host
 hoodoo.io: could not connect to host
 hoodoo.tech: could not connect to host
 horvathd.eu: could not connect to host
 hosted-oswa.org: could not connect to host
 hotelmadhuwanvihar.com: could not connect to host
 howardtyson.com: could not connect to host
 hozinga.de: could not connect to host
+hp-work.net: could not connect to host
 hr98.tk: could not connect to host
 hserver.top: could not connect to host
 hudingyuan.cn: could not connect to host
 huiser.nl: could not connect to host
 hukkatavara.com: could not connect to host
 hunger.im: could not connect to host
 huwjones.me: could not connect to host
 huzurmetal.net: could not connect to host
 hydrante.ch: could not connect to host
 hypotheques24.ch: could not connect to host
 iadttaveras.com: could not connect to host
-ibron.co: could not connect to host
 icebound.cc: could not connect to host
 iceloch.com: could not connect to host
 ictpro.info: could not connect to host
 icusignature.com: could not connect to host
 idcrane.com: could not connect to host
 ideadozz.hu: could not connect to host
 idemo.in: could not connect to host
 idol-bikes.ru: could not connect to host
@@ -758,29 +765,28 @@ idtechnowizard.com: could not connect to
 iemb.cf: could not connect to host
 ifoss.me: could not connect to host
 ifxnet.com: could not connect to host
 ikenmeyer.com: could not connect to host
 ikenmeyer.eu: could not connect to host
 ikzoekeengoedkopeauto.nl: could not connect to host
 ileat.com: could not connect to host
 img.ovh: could not connect to host
+imgencrypt.com: could not connect to host
 imlinan.cn: could not connect to host
 imlinan.info: could not connect to host
 imlinan.net: could not connect to host
 immersionwealth.com: could not connect to host
 imperdintechnologies.com: could not connect to host
-impulse-clan.de: could not connect to host
 increasetestosteronelevels.org: could not connect to host
 indybay.org: could not connect to host
 inexpensivecomputers.net: could not connect to host
 informatik.zone: could not connect to host
 infoworm.org: could not connect to host
 injust.me: could not connect to host
-innovativeideaz.org: could not connect to host
 inondation.ch: could not connect to host
 inscript.pl: could not connect to host
 insouciant.org: could not connect to host
 instaquiz.ru: could not connect to host
 instasex.ch: could not connect to host
 intelldynamics.com: could not connect to host
 interviewpipeline.co.uk: could not connect to host
 investorloanshub.com: could not connect to host
@@ -794,19 +800,17 @@ itad.top: could not connect to host
 itpro-mg.de: could not connect to host
 its-schindler.de: could not connect to host
 itsatrap.nl: could not connect to host
 ivanilla.org: could not connect to host
 ivanpolchenko.com: could not connect to host
 j0ng.xyz: could not connect to host
 jaimechanaga.com: could not connect to host
 jaion.ml: could not connect to host
-jaketremper.com: could not connect to host
 jakincode.army: could not connect to host
-jaksch.biz: could not connect to host
 jaksel.id: could not connect to host
 jamesheald.com: could not connect to host
 janssen.fm: could not connect to host
 japan4you.org: could not connect to host
 jaredfraser.com: could not connect to host
 javascriptlab.fr: could not connect to host
 jccars-occasions.be: could not connect to host
 jccrew.org: could not connect to host
@@ -826,63 +830,65 @@ joecod.es: could not connect to host
 joetyson.io: could not connect to host
 johngo.tk: could not connect to host
 jonathansanchez.pro: could not connect to host
 jooto.com: could not connect to host
 jordanhamilton.me: could not connect to host
 js88.sg: could not connect to host
 jsc7776.com: could not connect to host
 jsjyhzy.cc: could not connect to host
+juan23.edu.uy: could not connect to host
 juliaoantiguidades.com.br: could not connect to host
 juliawebber.co.za: could not connect to host
 jumbopan.com: could not connect to host
 jumbopan.net: could not connect to host
 just-pools.co.za: could not connect to host
 justinharrison.ca: could not connect to host
 justzz.xyz: could not connect to host
 juventusmania1897.com: could not connect to host
 k33k00.com: could not connect to host
 kaasbijwijn.nl: could not connect to host
-kabus.org: could not connect to host
 kaibol.com: could not connect to host
 kaika-facilitymanagement.de: could not connect to host
+kaloix.de: could not connect to host
 kamitech.ch: could not connect to host
 kanganer.com: could not connect to host
 kangzaber.com: could not connect to host
 kapo.info: could not connect to host
 karamna.com: could not connect to host
 karanlyons.com: could not connect to host
 karlic.net: could not connect to host
 karuneshjohri.com: could not connect to host
 katzen.me: could not connect to host
 kawaii.io: could not connect to host
 kawaiiku.com: could not connect to host
 kawaiiku.de: could not connect to host
 kayipmurekkep.com: could not connect to host
-kbfl.org: could not connect to host
 kcsordparticipation.org: could not connect to host
 kearney.io: could not connect to host
 kelm.me: could not connect to host
 kenyons.info: could not connect to host
 kevinbowers.me: could not connect to host
 kevindekoninck.com: could not connect to host
 keyserver.sexy: could not connect to host
 kgb.us: could not connect to host
+kgm-irm.be: could not connect to host
 kidbacker.com: could not connect to host
 kiedys.net: could not connect to host
 kieranweightman.me: could not connect to host
 kievradio.com: could not connect to host
 kinepolis-studio.ga: could not connect to host
 kingbird.me: could not connect to host
 kingclass.cn: could not connect to host
 kirill.ws: could not connect to host
 kj1396.net: could not connect to host
 kjchernov.info: could not connect to host
 kjoglum.me: could not connect to host
 klausimas.lt: could not connect to host
+kleinblogje.nl: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 119"  data: no]
 klingeletest.de: could not connect to host
 kngk-azs.ru: could not connect to host
 knightsweep.com: could not connect to host
 knownsec.cf: could not connect to host
 koez-mangal.ch: could not connect to host
 koezmangal.ch: could not connect to host
 kollawat.me: could not connect to host
 kongbaofang.com: could not connect to host
@@ -909,31 +915,31 @@ laboutiquemarocaineduconvoyeur.com: coul
 laboutiquemarocaineduconvoyeur.ma: could not connect to host
 lacasa.fr: could not connect to host
 lacasabelucci.com: could not connect to host
 lacasseroy.com: could not connect to host
 ladylikeit.com: could not connect to host
 lafr4nc3.net: could not connect to host
 lafr4nc3.xyz: could not connect to host
 lakewoodcomputerservices.com: could not connect to host
-lalaya.fr: could not connect to host
 landell.ml: could not connect to host
 lanonfire.com: 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
 lavapot.com: could not connect to host
 lazulu.com: could not connect to host
 lbarrios.es: could not connect to host
 lbrls.tk: could not connect to host
 lcti.biz: could not connect to host
 ldcraft.pw: could not connect to host
 lebal.se: could not connect to host
 leebiblestudycentre.net: could not connect to host
 leebiblestudycentre.org: could not connect to host
+leefindlow.com: could not connect to host
 legal.farm: could not connect to host
 legaltip.eu: could not connect to host
 leolana.com: could not connect to host
 leonardcamacho.me: could not connect to host
 lerlivros.online: could not connect to host
 lescomptoirsdepierrot.com: could not connect to host
 lesdouceursdeliyana.com: could not connect to host
 lessets-graphiques.com: could not connect to host
@@ -974,47 +980,48 @@ logcat.info: could not connect to host
 logic8.ml: could not connect to host
 logimagine.com: could not connect to host
 loothole.com: could not connect to host
 loqyu.co: could not connect to host
 losebellyfat.pro: could not connect to host
 loveandloyalty.se: could not connect to host
 lovelive.us: could not connect to host
 lowt.us: could not connect to host
+lowtherpavilion.co.uk: could not connect to host
 loyaltech.ch: could not connect to host
 ltransferts.com: could not connect to host
 lucascodes.com: could not connect to host
 lukasunger.cz: could not connect to host
 lukasunger.net: could not connect to host
 luom.net: could not connect to host
 luxonetwork.com: could not connect to host
 m4570.xyz: could not connect to host
 m4g.ru: could not connect to host
 maartenterpstra.xyz: could not connect to host
-machbach.net: could not connect to host
 macustar.eu: could not connect to host
 madeintucson.org: could not connect to host
 madusecurity.com: could not connect to host
 magnacumlaude.co: could not connect to host
 maik-mahlow.de: could not connect to host
 mailon.ga: could not connect to host
 malesbdsm.com: could not connect to host
 malgraph.net: could not connect to host
 marcelmarnitz.com: could not connect to host
 marche-nordic-jorat.ch: could not connect to host
 mare92.cz: could not connect to host
 marketingdesignu.cz: could not connect to host
+marko-fenster24.de: could not connect to host
 martynhare.co.uk: could not connect to host
 martynhare.uk: could not connect to host
 marxist.party: could not connect to host
-massoni.pl: could not connect to host
 mastodon.expert: could not connect to host
 mastodon.my: could not connect to host
 matarrosabierzo.com: could not connect to host
 mathijskingma.nl: could not connect to host
+matthewtester.com: could not connect to host
 mattli.us: could not connect to host
 mattwb65.com: could not connect to host
 maynardnetworks.com: could not connect to host
 mazurlabs.tk: could not connect to host
 mb-is.info: could not connect to host
 mbdrogenbos-usedcars.be: could not connect to host
 mbsec.net: could not connect to host
 mbwemmel-usedcars.be: could not connect to host
@@ -1043,38 +1050,39 @@ metrix-money-ptc.com: could not connect 
 metrix.design: could not connect to host
 mexior.nl: could not connect to host
 meyeraviation.com: could not connect to host
 mhjuma.com: could not connect to host
 michaelsulzer.com: could not connect to host
 michaelsulzer.eu: could not connect to host
 mikeybot.com: could not connect to host
 milktea.info: could not connect to host
+minakov.pro: could not connect to host
 mingy.ddns.net: could not connect to host
+mingyueli.com: could not connect to host
 minitruckin.net: could not connect to host
 mkfs.fr: could not connect to host
 mmstick.tk: could not connect to host
 modded-minecraft-server-list.com: could not connect to host
 moderntld.net: could not connect to host
 moe-max.jp: could not connect to host
-moellers.systems: could not connect to host
 moeyi.xyz: could not connect to host
+mokote.com: could not connect to host
 mongla168.net: could not connect to host
 mongla88.net: could not connect to host
 monitori.ng: could not connect to host
 moobo.xyz: could not connect to host
 mooselook.de: could not connect to host
 moparcraft.com: could not connect to host
 moparcraft.org: could not connect to host
 mordrum.com: could not connect to host
 morfitronik.pl: could not connect to host
 morz.org: could not connect to host
 mosaique-lachenaie.fr: could not connect to host
 moskva.guide: could not connect to host
-moso.io: could not connect to host
 motomorgen.com: could not connect to host
 motorbiketourhanoi.com: could not connect to host
 mountainadventureseminars.com: could not connect to host
 moving-pixtures.de: could not connect to host
 mowalls.net: could not connect to host
 mozzilla.cz: could not connect to host
 mpserver12.org: could not connect to host
 mrafrohead.com: could not connect to host
@@ -1086,81 +1094,75 @@ muj-svet.cz: could not connect to host
 munch.me: could not connect to host
 munduch.cz: could not connect to host
 murraycolin.org: could not connect to host
 muslimbanter.co.za: could not connect to host
 mybeautyjobs.de: could not connect to host
 mycamda.com: could not connect to host
 mycustomwriting.com: could not connect to host
 myfappening.org: could not connect to host
-myfloridadeferredcomp.com: could not connect to host
-myicare.org: could not connect to host
 mykeepsake.xyz: could not connect to host
 mynetworkingbuddy.com: could not connect to host
+myshirtsize.com: could not connect to host
 mytravelblog.de: could not connect to host
 mzlog.win: could not connect to host
 n0099.cf: could not connect to host
 naano.org: could not connect to host
 naphex.rocks: could not connect to host
 narodsovety.ru: could not connect to host
 nate.sh: could not connect to host
 ncdesigns-studio.com: could not connect to host
 neer.io: could not connect to host
 negativecurvature.net: could not connect to host
-neio.uk: could not connect to host
 nejnamc.org: could not connect to host
+nerdhouse.io: could not connect to host
 nestone.ru: could not connect to host
 nevadafiber.net: could not connect to host
 newcityinfo.info: could not connect to host
 nexgeneration-solutions.com: could not connect to host
 nexusbyte.de: could not connect to host
 nexuscorporation.in: could not connect to host
 nfluence.org: could not connect to host
-nfrost.me: could not connect to host
 ngtoys.com.br: could not connect to host
 nico.st: could not connect to host
 nienfun.com: could not connect to host
 nigger.racing: could not connect to host
 nikksno.io: could not connect to host
 nikolasbradshaw.com: could not connect to host
 niouininon.eu: could not connect to host
 nirada.info: could not connect to host
 nishikino-maki.com: could not connect to host
 niva.synology.me: could not connect to host
 nkadvertising.online: could not connect to host
 nodeselect.com: could not connect to host
 nonemu.ninja: could not connect to host
 norad.sytes.net: could not connect to host
-northernselfstorage.co.za: could not connect to host
 nosbenevolesontdutalent.com: could not connect to host
 notarobot.fr: could not connect to host
 note7forever.com: could not connect to host
 notesforpebble.com: could not connect to host
 notevencode.com: could not connect to host
 novascan.net: could not connect to host
 nowremindme.com: could not connect to host
-nsa.lol: could not connect to host
-nsa.wtf: could not connect to host
 nsbfalconacademy.org: could not connect to host
 nsdev.cn: could not connect to host
 nsmail.cn: could not connect to host
 nudel.ninja: could not connect to host
 nunnun.jp: could not connect to host
 nyanpasu.tv: could not connect to host
 nyxi.eu: could not connect to host
 obdolbacca.ru: could not connect to host
 oberam.de: could not connect to host
 oberhof.co: could not connect to host
 oblondata.io: could not connect to host
 off-the-clock.us: could not connect to host
 offgames.pro: could not connect to host
 office-ruru.com: could not connect to host
 ohyooo.com: could not connect to host
 oliverspringer.eu: could not connect to host
-omarh.net: could not connect to host
 omnibot.tv: could not connect to host
 onewebdev.info: could not connect to host
 onstud.com: could not connect to host
 onwie.fr: could not connect to host
 ooeste.com: could not connect to host
 opatut.de: could not connect to host
 opium.io: could not connect to host
 oscsdp.cz: could not connect to host
@@ -1192,37 +1194,35 @@ pathwaytofaith.com: could not connect to
 patrickbusch.net: could not connect to host
 patrickneuro.de: could not connect to host
 paulbramhall.uk: could not connect to host
 paulrudge.codes: could not connect to host
 paulshir.com: could not connect to host
 paulshir.is: could not connect to host
 paymon.tj: could not connect to host
 paypod.org: could not connect to host
-pbcknd.ml: could not connect to host
 pcmr.info: could not connect to host
 pcvirusclear.com: could not connect to host
 pear2pear.de: could not connect to host
 peirong.me: could not connect to host
 pengisatelier.net: could not connect to host
 persjrp.ca: could not connect to host
 persoform.ch: could not connect to host
 petlife.od.ua: could not connect to host
 peuf.shop: could not connect to host
 peykezamin.ir: could not connect to host
 pgmsource.com: could not connect to host
 phdwuda.com: could not connect to host
 phil.tw: could not connect to host
 philippa.cool: could not connect to host
-phoenixlogan.com: could not connect to host
 photops.fr: could not connect to host
-phra.gs: could not connect to host
 picallo.es: could not connect to host
 picone.com.au: could not connect to host
 pierrejeansuau.fr: could not connect to host
+pieterhordijk.com: could not connect to host
 pimspage.nl: could not connect to host
 pinebaylibrary.org: could not connect to host
 piwko.co: could not connect to host
 pixelgliders.de: could not connect to host
 plaasprodukte.com: could not connect to host
 placefade.com: could not connect to host
 planbox.info: could not connect to host
 playsharp.com: could not connect to host
@@ -1230,32 +1230,31 @@ plussizereviews.com: could not connect t
 pmbremer.de: could not connect to host
 pnsc.is: could not connect to host
 pogs.us: could not connect to host
 pointagri.com: could not connect to host
 polit.im: could not connect to host
 politic.org.ua: could not connect to host
 ponteencima.com: could not connect to host
 poolinstallers.co.za: could not connect to host
-portailevangelique.ca: could not connect to host
 potbar.com: could not connect to host
 potlytics.com: could not connect to host
 pouets.ovh: could not connect to host
 powerentertainment.tv: could not connect to host
 poy-tech.com: could not connect to host
 prepaid-cards.xyz: could not connect to host
 princessbackpack.de: could not connect to host
 printsos.com: could not connect to host
 prism-communication.com: could not connect to host
 privacymanatee.com: could not connect to host
-privateimarketing.com: could not connect to host
 privcloud.org: could not connect to host
 privilegevisa.fr: could not connect to host
 proactive.run: could not connect to host
 progressivecfo.co.nz: could not connect to host
+projectasterk.com: could not connect to host
 projectx.top: could not connect to host
 prokop.ovh: could not connect to host
 propmag.co: could not connect to host
 provitacare.com: could not connect to host
 proxydesk.eu: could not connect to host
 prpsss.com: could not connect to host
 pruikshop.nl: could not connect to host
 prytkov.com: could not connect to host
@@ -1274,32 +1273,29 @@ qforum.org: could not connect to host
 qikan.net: could not connect to host
 qldformulaford.org: could not connect to host
 qnatek.org: could not connect to host
 qoqo.us: could not connect to host
 qrlfinancial.com: could not connect to host
 qscloud.de: could not connect to host
 qto.net: could not connect to host
 quay.net: could not connect to host
-r40.us: could not connect to host
-ra.co.ke: could not connect to host
 rackblue.com: could not connect to host
 radeticlaw.com: could not connect to host
 rainbin.com: could not connect to host
 rally-vysledky.cz: could not connect to host
-randomquotesapp.com: could not connect to host
 ranos.org: could not connect to host
 rantanda.com: could not connect to host
 rapdogg.com: could not connect to host
+rapidstone.com: could not connect to host
 ravengergaming.net: could not connect to host
 ravse.dk: could not connect to host
 raxion.cf: could not connect to host
 rcoliveira.com: could not connect to host
 rdfz.tech: could not connect to host
-rdl.at: could not connect to host
 readify.com.au: could not connect to host
 readityourself.net: could not connect to host
 reaiaer.com: could not connect to host
 real-compare.com: could not connect to host
 realcli.com: could not connect to host
 realraghavgupta.com: could not connect to host
 realwoo.com: could not connect to host
 reevu.net: could not connect to host
@@ -1310,23 +1306,24 @@ reignsphere.net: could not connect to ho
 reismil.ch: could not connect to host
 relaxhavefun.com: could not connect to host
 renemayrhofer.com: could not connect to host
 rentbrowser.com: could not connect to host
 report-incident.de: could not connect to host
 reqognize.com: could not connect to host
 research.md: could not connect to host
 ressl.ch: could not connect to host
-retcor.net: could not connect to host
 reth.ch: could not connect to host
+retrowave.eu: could not connect to host
 retube.ga: could not connect to host
 reykjavik.guide: could not connect to host
 ribopierre.fr: could not connect to host
 riceglue.com: could not connect to host
 richeza.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 119"  data: no]
+rkc-hygrotherm.de: could not connect to host
 rngmeme.com: could not connect to host
 robi-net.it: could not connect to host
 robomonkey.org: could not connect to host
 robust.ga: could not connect to host
 rocketgnomes.com: could not connect to host
 rodehutskors.net: could not connect to host
 rofrank.space: could not connect to host
 rohanbassett.com: could not connect to host
@@ -1336,26 +1333,26 @@ ronghexx.com: could not connect to host
 roolevoi.ru: could not connect to host
 rootbsd.at: could not connect to host
 rospa100.com: could not connect to host
 rotterdamjazz.info: could not connect to host
 royzez.com: could not connect to host
 rozalynne-dawn.ga: could not connect to host
 rpasafrica.com: could not connect to host
 rs-devdemo.host: could not connect to host
-rsauget.fr: could not connect to host
 rsldb.com: could not connect to host
 rtc.fun: could not connect to host
 rubendv.be: could not connect to host
 ruhr3.de: could not connect to host
 ruht.ro: could not connect to host
 runcarina.com: could not connect to host
 rundumcolumn.xyz: could not connect to host
 runementors.com: could not connect to host
 ruudkoot.nl: could not connect to host
+rva-asbestgroep.nl: could not connect to host
 rzegroup.com: could not connect to host
 s0923.com: could not connect to host
 s3n.se: could not connect to host
 sa.net: could not connect to host
 sabine-forschbach.de: could not connect to host
 sabineforschbach.de: could not connect to host
 safejourney.education: could not connect to host
 saferedirectlink.com: could not connect to host
@@ -1399,49 +1396,49 @@ sellmoretires.com: could not connect to 
 seoscribe.net: could not connect to host
 servecrypt.com: could not connect to host
 server-essentials.com: could not connect to host
 serverlauget.no: could not connect to host
 serverpedia.de: could not connect to host
 servfefe.com: could not connect to host
 seryovpn.com: could not connect to host
 sesha.co.za: could not connect to host
-sfaturiit.ro: could not connect to host
 shadex.net: could not connect to host
 shadiku.com: could not connect to host
 shadowplus.net: could not connect to host
 shadowrocket.net: could not connect to host
-shaitan.eu: could not connect to host
 shang-yu.cn: could not connect to host
 shanxiapark.com: could not connect to host
 shavingks.com: could not connect to host
 sheying.tm: could not connect to host
 shirakaba-cc.com: could not connect to host
+shobhanayogsadan.com: could not connect to host
 shoppingreview.org: could not connect to host
 shortr.li: could not connect to host
 shred.ch: could not connect to host
 shredoptics.ch: could not connect to host
 shuzicai.cn: could not connect to host
 shymeck.pw: could not connect to host
+siamega.com: could not connect to host
 sickfile.com: could not connect to host
 siebens.net: could not connect to host
 signosquecombinam.com.br: could not connect to host
 sikatehtaat.fi: could not connect to host
 siku.pro: could not connect to host
 silvistefi.com: could not connect to host
 simbolo.co.uk: could not connect to host
 simplerses.com: could not connect to host
 sims4hub.ga: could not connect to host
+sinfulforums.net: could not connect to host
 siqi.wang: could not connect to host
 skarox.ru: could not connect to host
 sky-aroma.com: could not connect to host
 skylocker.net: could not connect to host
 skylocker.nl: could not connect to host
 slaps.be: could not connect to host
-sleepstar.co.uk: could not connect to host
 slovoice.org: could not connect to host
 slytech.ch: could not connect to host
 smallchat.nl: could not connect to host
 smith.is: could not connect to host
 sml.lc: could not connect to host
 smuhelper.cn: could not connect to host
 soboleva-pr.com.ua: could not connect to host
 socialworkout.com: could not connect to host
@@ -1483,47 +1480,48 @@ steven-bennett.com: could not connect to
 stickswag.cf: could not connect to host
 stilettomoda.com.br: could not connect to host
 stonemanbrasil.com.br: could not connect to host
 stpip.com: could not connect to host
 streams.dyndns.org: could not connect to host
 stressfreehousehold.com: could not connect to host
 stupendous.net: could not connect to host
 stylle.me: could not connect to host
-suchprogrammer.net: could not connect to host
 sudo.im: could not connect to host
 sudosu.fr: could not connect to host
 suitocracy.com: could not connect to host
 sulek.eu: could not connect to host
 summer.ga: could not connect to host
 suneilpatel.com: could not connect to host
 sunfireshop.com.br: could not connect to host
 sunxchina.com: could not connect to host
 superpase.com: could not connect to host
 surdam.casa: could not connect to host
 susconam.org: could not connect to host
 suspiciousdarknet.xyz: could not connect to host
 swaggerdile.com: could not connect to host
-swfloshatraining.com: could not connect to host
 synergisticsoccer.com: could not connect to host
 t3rror.net: could not connect to host
 takusan.ru: could not connect to host
 talktwincities.com: could not connect to host
 tangyue.date: could not connect to host
 tangzhao.net: could not connect to host
+tardis.io: could not connect to host
+tas2580.net: could not connect to host
 tcpweb.net: could not connect to host
 tdsb.cf: could not connect to host
 tdsbhack.tk: could not connect to host
 tearoy.faith: could not connect to host
 tebieer.com: could not connect to host
 techask.it: could not connect to host
 techpit.us: could not connect to host
 tektoria.de: could not connect to host
 telekollektiv.org: could not connect to host
 tenispopular.com: could not connect to host
+tequilazor.com: could not connect to host
 terra-x.net: could not connect to host
 terrax.net: could not connect to host
 testovaci.ml: could not connect to host
 tetsai.com: could not connect to host
 teulon.eu: could not connect to host
 thaigirls.xyz: could not connect to host
 the-digitale.com: could not connect to host
 the-finance-blog.com: could not connect to host
@@ -1531,34 +1529,30 @@ the-gist.io: could not connect to host
 thedarkartsandcrafts.com: could not connect to host
 thefox.co: could not connect to host
 thefrk.xyz: could not connect to host
 thehiddenbay.info: could not connect to host
 thenrdhrd.nl: could not connect to host
 theprincegame.com: could not connect to host
 theprivacysolution.com: could not connect to host
 thequillmagazine.org: could not connect to host
-therevenge.me: could not connect to host
 thermique.ch: could not connect to host
 thesehighsandlows.com: could not connect to host
 theserver201.tk: could not connect to host
 thierryhayoz.ch: could not connect to host
 thinkcash.nl: could not connect to host
 thompsonfamily.cloud: could not connect to host
 tianxicaipiao.win: could not connect to host
 tianxicp.com: could not connect to host
 tink.network: could not connect to host
 tipiakers.club: could not connect to host
 tkn.tokyo: could not connect to host
 tnb-plattform.de: could not connect to host
-tob-rulez.de: could not connect to host
-tobiaskorf.de: could not connect to host
 todosrv.com: could not connect to host
 tokoindo.top: could not connect to host
-tokototech.com: could not connect to host
 tollsjekk.no: could not connect to host
 tomm.yt: could not connect to host
 tommounsey.com: could not connect to host
 tooolroc.org: could not connect to host
 topdetoxcleanse.com: could not connect to host
 topdevbox.net: could not connect to host
 topnotchendings.com: could not connect to host
 tor2web.org: could not connect to host
@@ -1586,39 +1580,35 @@ turkiet.guide: could not connect to host
 turn-sticks.com: could not connect to host
 tuxhound.org: could not connect to host
 tverdohleb.com: could not connect to host
 twinkieman.com: could not connect to host
 twiri.net: could not connect to host
 twitter.ax: could not connect to host
 twotube.ie: could not connect to host
 tykoon.com: could not connect to host
-tyler.rs: could not connect to host
 tylerharcourt.com: could not connect to host
-tyleromeara.com: could not connect to host
+typehub.net: could not connect to host
 tysye.ca: could not connect to host
 tzwe.com: could not connect to host
 ubi.gg: could not connect to host
 ubicv.com: could not connect to host
 udo-luetkemeier.de: could not connect to host
 ueu.me: could not connect to host
 ulti.gq: could not connect to host
 umisonoda.com: could not connect to host
 umsapi.com: could not connect to host
 unefuite.ch: could not connect to host
 unhu.fr: could not connect to host
 uni2share.com: could not connect to host
 unicorn.li: could not connect to host
 uploadbro.com: could not connect to host
-upr.com.ua: could not connect to host
 urcentral.org: could not connect to host
-usafuelservice.com: could not connect to host
 uscp8.com: could not connect to host
 usportsgo.com: could not connect to host
-uswitch.com: could not connect to host
 utdsgda.com: could not connect to host
 uwesander.de: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 119"  data: no]
 uygindir.ml: could not connect to host
 vaaddress.co: could not connect to host
 vacationfund.co: could not connect to host
 vadik.me: could not connect to host
 vaeplatform.com: could not connect to host
 vaioswolke.xyz: could not connect to host
@@ -1626,42 +1616,41 @@ valaeris.de: could not connect to host
 valecnatechnika.cz: could not connect to host
 valenhub.com: could not connect to host
 valenhub.es: could not connect to host
 vanderstraeten.dynv6.net: could not connect to host
 vapeshopsupply.com: could not connect to host
 varela-electricite.fr: could not connect to host
 vayaport.com: could not connect to host
 velen.io: could not connect to host
-venicecomputerrepair.com: could not connect to host
-venicefloridawebsitedesign.com: could not connect to host
 venturavwparts.com: could not connect to host
 verdeandco.co.uk: could not connect to host
 versfin.net: could not connect to host
 veryyounglesbians.com: could not connect to host
 vgatest.nl: could not connect to host
 vicenage.com: could not connect to host
 videorullen.se: could not connect to host
-vidister.de: could not connect to host
 vikasbabyworld.de: could not connect to host
+vilaydin.com: could not connect to host
 vimeosucks.nyc: could not connect to host
 vinetalk.net: could not connect to host
+vishwashantiyoga.com: could not connect to host
 visionthroughknowledge.com: could not connect to host
 visiontree.eu: could not connect to host
 vlogge.com: could not connect to host
 voeux.io: could not connect to host
 vogt.tech: could not connect to host
 volcain.io: could not connect to host
 vorlif.org: could not connect to host
 vorodevops.com: could not connect to host
 votresiteweb.ch: could not connect to host
 vrtouring.org: could not connect to host
 vsx.ch: could not connect to host
 vxapps.com: could not connect to host
-w4.no: could not connect to host
+w3ctag.org: could not connect to host
 w4nvu.org: could not connect to host
 wabifoggynuts.com: could not connect to host
 waixingrenfuli.vip: could not connect to host
 wallpapers.pub: could not connect to host
 wanashi.com: could not connect to host
 wanda76.com: could not connect to host
 wanda78.com: could not connect to host
 wanda79.com: could not connect to host
@@ -1698,16 +1687,17 @@ werhatunsverraten.eu: could not connect 
 wespeakgeek.co.za: could not connect to host
 wetthost.com: could not connect to host
 wevg.org: could not connect to host
 weyland.tech: could not connect to host
 wg-tools.de: could not connect to host
 whereisjason.com: could not connect to host
 whereismyorigin.cf: could not connect to host
 whilsttraveling.com: could not connect to host
+whitworth.nyc: could not connect to host
 wibuw.com: could not connect to host
 wilhelm-nathan.de: could not connect to host
 willkommen-fuerstenberg.de: could not connect to host
 winnersports.co: could not connect to host
 winsufi.biz: could not connect to host
 wireframesoftware.com: could not connect to host
 wisak.eu: could not connect to host
 wishesbee.com: could not connect to host
@@ -1722,39 +1712,34 @@ wonderbooks.club: could not connect to h
 woomu.me: could not connect to host
 workemy.com: could not connect to host
 worldfree4.org: could not connect to host
 worldpeacetechnology.com: could not connect to host
 wp-fastsearch.de: could not connect to host
 wp-stack.pro: could not connect to host
 wp6.pw: could not connect to host
 wsdcap.com: could not connect to host
-wtf.ninja: could not connect to host
 wuchipc.com: could not connect to host
 www-68277.com: could not connect to host
 www-8887999.com: could not connect to host
 www.re: could not connect to host
 www.sb: could not connect to host
 www.simbolo.co.uk: could not connect to host
 xbc.nz: could not connect to host
 xeonlab.com: could not connect to host
 xeonlab.de: could not connect to host
 xia100.xyz: could not connect to host
 xianguocy.com: could not connect to host
-xiaoyu.net: could not connect to host
 xing.ml: could not connect to host
 xn--8mr166hf6s.xn--fiqs8s: could not connect to host
 xn--c5w27q.ml: could not connect to host
-xn--jbs-tna.de: could not connect to host
-xn--mllers-wxa.info: could not connect to host
 xn--srenpind-54a.dk: could not connect to host
 xn--t8j2a3042d.xyz: could not connect to host
 xn--yj8h0m.ws: could not connect to host
 xn--ykrp42k.com: could not connect to host
-xoda.pw: could not connect to host
 xpwn.cz: could not connect to host
 xqin.net: could not connect to host
 xuntaosms.com: could not connect to host
 xwaretech.info: could not connect to host
 y3451.com: could not connect to host
 yabrt.cn: could not connect to host
 yahoo.ax: could not connect to host
 yarchives.jp: could not connect to host
@@ -1770,17 +1755,16 @@ yibin0831.com: could not connect to host
 ying299.com: could not connect to host
 ying299.net: could not connect to host
 ylk.io: could not connect to host
 yobst.tk: could not connect to host
 yoga.is-an-engineer.com: could not connect to host
 yotilabs.com: could not connect to host
 yourznc.com: could not connect to host
 yousite.by: could not connect to host
-ytpak.com: could not connect to host
 yude.ml: could not connect to host
 yugege.cf: could not connect to host
 yum.beer: could not connect to host
 yux.fr: could not connect to host
 zachbolinger.com: could not connect to host
 zaoext.com: could not connect to host
 zbchen.com: could not connect to host
 zeitzer-turngala.de: could not connect to host
@@ -1789,17 +1773,16 @@ zero-x-baadf00d.com: could not connect t
 zerolab.org: could not connect to host
 zerosource.net: could not connect to host
 zhangfangzhou.com: could not connect to host
 zhangsir.net: could not connect to host
 zhaochen.xyz: could not connect to host
 zhenmeish.com: could not connect to host
 zhiin.net: could not connect to host
 zhikin.com: could not connect to host
-zhima.io: could not connect to host
 zhoujiashu.com: could not connect to host
 zikirakhirzaman.com: could not connect to host
 zobraz.cz: could not connect to host
 zokster.net: could not connect to host
 zudomc.me: could not connect to host
 zuefle.net: could not connect to host
 zuehlcke.de: could not connect to host
 zuviel.space: could not connect to host
@@ -1875,26 +1858,27 @@ 1years.cc: could not connect to host
 2-cpu.de: did not receive HSTS header
 206rc.net: max-age too low: 2592000
 20hs.cn: did not receive HSTS header
 21lg.co: could not connect to host
 247quickbooks.com: did not receive HSTS header
 2488.ch: did not receive HSTS header
 24hourpaint.com: could not connect to host
 24sihu.com: could not connect to host
+256pages.com: max-age too low: 2592000
 25daysof.io: could not connect to host
 2859cc.com: could not connect to host
 2acbi-asso.fr: did not receive HSTS header
 2bizi.ru: could not connect to host
 2brokegirls.org: could not connect to host
 2carpros.com: did not receive HSTS header
 2intermediate.co.uk: did not receive HSTS header
 2or3.tk: could not connect to host
 2smart4food.com: did not receive HSTS header
-2ss.jp: did not receive HSTS header
+2ss.jp: could not connect to host
 300651.ru: did not receive HSTS header
 300mbmovie24.com: could not connect to host
 300mbmovies4u.cc: could not connect to host
 301.website: could not connect to host
 302.nyc: could not connect to host
 314166.com: could not connect to host
 32ph.com: could not connect to host
 33836.com: did not receive HSTS header
@@ -2107,22 +2091,20 @@ agrias.com.br: did not receive HSTS head
 agrimap.com: did not receive HSTS header
 agro-id.gov.ua: did not receive HSTS header
 agtv.com.br: did not receive HSTS header
 ahabingo.com: did not receive HSTS header
 ahfazahmed.net: did not receive HSTS header
 ahoynetwork.com: did not receive HSTS header
 ahri.ovh: could not connect to host
 ahwatukeefoothillsmontessori.com: did not receive HSTS header
-aicial.co.uk: did not receive HSTS header
 aicial.com.au: could not connect to host
 aidanwoods.com: did not receive HSTS header
 aidikofflaw.com: did not receive HSTS header
 aids.gov: did not receive HSTS header
-aiforsocialmedia.com: did not receive HSTS header
 aifreeze.ru: could not connect to host
 aify.eu: could not connect to host
 ainrb.com: could not connect to host
 aip-marine.com: could not connect to host
 aiponne.com: could not connect to host
 airlea.com: could not connect to host
 airlinecheckins.com: did not receive HSTS header
 airmazinginflatables.com: did not receive HSTS header
@@ -2136,17 +2118,17 @@ ajouin.com: could not connect to host
 aka.my: did not receive HSTS header
 akboy.pw: could not connect to host
 akclinics.org: did not receive HSTS header
 akerek.hu: could not connect to host
 akgundemirbas.com: could not connect to host
 akkadia.cc: could not connect to host
 akombakom.net: could not connect to host
 akselimedia.fi: did not receive HSTS header
-akstudentsfirst.org: did not receive HSTS header
+akstudentsfirst.org: could not connect to host
 aktivist.in: did not receive HSTS header
 al-shami.net: could not connect to host
 aladdin.ie: did not receive HSTS header
 alanlee.net: could not connect to host
 alanrickmanflipstable.com: could not connect to host
 alariel.de: did not receive HSTS header
 alarme-gps.ch: could not connect to host
 alarmegps.ch: could not connect to host
@@ -2398,16 +2380,17 @@ as.se: could not connect to host
 as9178.net: could not connect to host
 asahikoji.net: could not connect to host
 asasuou.pw: could not connect to host
 asc16.com: could not connect to host
 ascamso.com: could not connect to host
 aschaefer.net: could not connect to host
 asdpress.cn: could not connect to host
 ashlane-cottages.com: could not connect to host
+ashleymedway.com: did not receive HSTS header
 asianodor.com: could not connect to host
 ask.pe: did not receive HSTS header
 askfit.cz: did not receive HSTS header
 asmui.ga: could not connect to host
 asmui.ml: could not connect to host
 ass.org.au: could not connect to host
 assekuranzjobs.de: could not connect to host
 asset-alive.com: did not receive HSTS header
@@ -2555,17 +2538,16 @@ banksaround.com: did not receive HSTS he
 banqingdiao.com: could not connect to host
 baobaobooks.net: did not receive HSTS header
 baobeiglass.com: did not receive HSTS header
 barcel.com.mx: max-age too low: 86400
 barely.sexy: did not receive HSTS header
 barrelhead.org: could not connect to host
 barrut.me: did not receive HSTS header
 barshout.co.uk: could not connect to host
-barss.io: could not connect to host
 bartbania.com: did not receive HSTS header
 barunisystems.com: could not connect to host
 bashcode.ninja: could not connect to host
 basicsolutionsus.com: did not receive HSTS header
 basilisk.io: could not connect to host
 bassh.net: did not receive HSTS header
 baud.ninja: could not connect to host
 baudairenergyservices.com: did not receive HSTS header
@@ -2675,17 +2657,16 @@ bf.am: max-age too low: 0
 bfd.vodka: did not receive HSTS header
 bfear.com: could not connect to host
 bfelob.gov: could not connect to host
 bffm.biz: could not connect to host
 bgcparkstad.nl: did not receive HSTS header
 bgmn.net: could not connect to host
 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]
 biapinheiro.com.br: max-age too low: 5184000
-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
@@ -3054,23 +3035,23 @@ carlolly.co.uk: could not connect to hos
 carlosalves.info: did not receive HSTS header
 carpliyz.com: could not connect to host
 carroarmato0.be: did not receive HSTS header
 carsforbackpackers.com: could not connect to host
 carstenfeuls.de: did not receive HSTS header
 cartesunicef.be: did not receive HSTS header
 cartoonhd.cc: did not receive HSTS header
 carwashvapeur.be: could not connect to host
+casashopp.com.br: did not receive HSTS header
 casc.cz: did not receive HSTS header
 casedi.org: max-age too low: 0
 casefall.com: could not connect to host
 cash-pos.com: could not connect to host
 cashmyphone.ch: could not connect to host
 casino-cashflow.ru: did not receive HSTS header
-casinolegal.pt: did not receive HSTS header
 casinostest.com: could not connect to host
 casioshop.eu: did not receive HSTS header
 casovi.cf: could not connect to host
 castagnonavocats.com: did not receive HSTS header
 cata.ga: could not connect to host
 catalin.pw: could not connect to host
 catarsisvr.com: could not connect to host
 catinmay.com: did not receive HSTS header
@@ -3220,17 +3201,16 @@ circ-logic.com: did not receive HSTS hea
 ciscohomeanalytics.com: could not connect to host
 ciscommerce.net: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 119"  data: no]
 citiagent.cz: could not connect to host
 cityoflaurel.org: did not receive HSTS header
 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
-clanwarz.com: did not receive HSTS header
 clara-baumert.de: could not connect to host
 claralabs.com: did not receive HSTS header
 clarity-c2ced.appspot.com: did not receive HSTS header
 classicday.nl: could not connect to host
 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
@@ -3350,16 +3330,17 @@ comitesaustria.at: could not connect to 
 comiteshopping.com: could not connect to host
 commercialplanet.eu: could not connect to host
 commune-preuilly.fr: did not receive HSTS header
 comocurarlashemorroides.org: could not connect to host
 comocurarlashemorroidesya.com: 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
+compareandrecycle.co.uk: did not receive HSTS header
 comparejewelleryprices.co.uk: could not connect to host
 comparetravelinsurance.com.au: did not receive HSTS header
 compassionate-biology.com: could not connect to host
 compiledworks.com: could not connect to host
 completesportperformance.com: did not receive HSTS header
 completionist.audio: could not connect to host
 complymd.com: did not receive HSTS header
 compsmag.com: did not receive HSTS header
@@ -3385,17 +3366,17 @@ consciousbrands.net.au: could not connec
 console.python.org: did not receive HSTS header
 console.support: did not receive HSTS header
 contactbig.com: did not receive HSTS header
 contactsingapore.sg: did not receive HSTS header
 contaimo.com: did not receive HSTS header
 container-lion.com: did not receive HSTS header
 containerstatistics.com: could not connect to host
 contarkos.xyz: could not connect to host
-content-design.de: could not connect to host
+content-design.de: did not receive HSTS header
 continuumgaming.com: could not connect to host
 controlcenter.gigahost.dk: did not receive HSTS header
 controleer-maar-een-ander.nl: did not receive HSTS header
 convert.zone: did not receive HSTS header
 cooink.net: could not connect to host
 coolaj86.com: did not receive HSTS header
 coolbutbroken.com: did not receive HSTS header
 coolchevy.org.ua: did not receive HSTS header
@@ -3433,17 +3414,17 @@ count.sh: could not connect to host
 couponcodeq.com: could not connect to host
 couragewhispers.ca: could not connect to host
 coursdeprogrammation.com: could not connect to host
 coursella.com: did not receive HSTS header
 covenantbank.net: could not connect to host
 coverdat.com: did not receive HSTS header
 coverduck.ru: could not connect to host
 cpuvinf.eu.org: could not connect to host
-cracking.org: did not receive HSTS header
+cracking.org: could not connect to host
 crackingking.com: did not receive HSTS header
 craftbeerbarn.co.uk: could not connect to host
 craftedge.xyz: could not connect to host
 craftmain.eu: could not connect to host
 cranems.com.ua: did not receive HSTS header
 cranioschule.com: did not receive HSTS header
 crate.io: did not receive HSTS header
 cravelyrics.com: could not connect to host
@@ -3541,17 +3522,16 @@ cusfit.com: did not receive HSTS header
 custe.rs: could not connect to host
 customadesign.com: did not receive HSTS header
 cutorrent.com: could not connect to host
 cuvva.insure: did not receive HSTS header
 cvjm-memmingen.de: did not receive HSTS header
 cvtparking.co.uk: did not receive HSTS header
 cwage.com: could not connect to host
 cyanogenmod.xxx: could not connect to host
-cyber-konzept.de: did not receive HSTS header
 cybercecurity.com: did not receive HSTS header
 cyberfrancais.ro: did not receive HSTS header
 cyberlab.kiev.ua: did not receive HSTS header
 cyberlab.team: did not receive HSTS header
 cyberpunk.ca: could not connect to host
 cybersafesolutions.com: did not receive HSTS header
 cybershambles.com: could not connect to host
 cybersmart.co.uk: did not receive HSTS header
@@ -3655,17 +3635,16 @@ dcurt.is: did not receive HSTS header
 dcw.io: did not receive HSTS header
 ddatsh.com: could not connect to host
 ddepot.us: did not receive HSTS header
 deadsoul.net: max-age too low: 0
 debank.tv: did not receive HSTS header
 debatch.se: could not connect to host
 debian-vhost.de: could not connect to host
 debiton.dk: could not connect to host
-debt.com: did not receive HSTS header
 debtkit.co.uk: did not receive HSTS header
 debtprotectionreporting.com: did not receive HSTS header
 decafu.co: could not connect to host
 decesus.com: could not connect to host
 decibelios.li: could not connect to host
 decloverly.com: did not receive HSTS header
 deco.me: could not connect to host
 decoboutique.com: did not receive HSTS header
@@ -3952,17 +3931,17 @@ dune.io: did not receive HSTS header
 dunea.nl: did not receive HSTS header
 dungi.org: could not connect to host
 duole30.com: did not receive HSTS header
 duongpho.com: did not receive HSTS header
 duskopy.top: could not connect to host
 dutchrank.com: did not receive HSTS header
 duuu.ch: could not connect to host
 dycem-ns.com: did not receive HSTS header
-dycoa.com: did not receive HSTS header
+dycoa.com: could not connect to host
 dycontrol.de: could not connect to host
 dylanscott.com.au: did not receive HSTS header
 dymersion.com: did not receive HSTS header
 dynamic-innovations.net: could not connect to host
 dynamize.solutions: did not receive HSTS header
 dyrkar.com: did not receive HSTS header
 dzimejl.sk: did not receive HSTS header
 dzlibs.io: could not connect to host
@@ -4136,16 +4115,17 @@ end.pp.ua: could not connect to host
 endlessdark.net: max-age too low: 600
 endlesshorizon.net: could not connect to host
 endlesstone.com: could not connect to host
 endohaus.ca: could not connect to host
 endohaus.com: could not connect to host
 endohaus.eu: could not connect to host
 enecoshop.nl: did not receive HSTS header
 enefan.jp: could not connect to host
+enfield-kitchens.co.uk: did not receive HSTS header
 engelwerbung.com: did not receive HSTS header
 enginsight.com: did not receive HSTS header
 englishyamal.ru: did not receive HSTS header
 enigmacpt.com: did not receive HSTS header
 enigmail.net: did not receive HSTS header
 enjen.net: did not receive HSTS header
 enjoymayfield.com: max-age too low: 0
 enteente.club: could not connect to host
@@ -4161,16 +4141,17 @@ enumify.com: could not connect to host
 enviapresentes.com.br: could not connect to host
 envygeeks.com: could not connect to host
 eol34.com: could not connect to host
 eoldb.org: could not connect to host
 epanurse.com: could not connect to host
 ephry.com: could not connect to host
 epicmc.games: could not connect to host
 epoxate.com: could not connect to host
+epulsar.ru: did not receive HSTS header
 eq8.net.au: could not connect to host
 eqib.nl: did not receive HSTS header
 eqim.me: could not connect to host
 equate.net.au: did not receive HSTS header
 equatetechnologies.com.au: did not receive HSTS header
 equilibre-yoga-jennifer-will.com: could not connect to host
 equitee.co: did not receive HSTS header
 equityflows.com: did not receive HSTS header
@@ -4222,17 +4203,16 @@ etaoinwu.tk: could not connect to host
 etdonline.co.uk: could not connect to host
 eternitylove.us: could not connect to host
 eth9.net: could not connect to host
 etheria-software.tk: did not receive HSTS header
 etherpad.fr: did not receive HSTS header
 ethicalexploiting.com: did not receive HSTS header
 ethicall.org.uk: did not receive HSTS header
 ethil-faer.fr: could not connect to host
-etidni.help: did not receive HSTS header
 etk2000.com: did not receive HSTS header
 etmirror.top: could not connect to host
 etmirror.xyz: could not connect to host
 etoto.pl: did not receive HSTS header
 etproxy.tech: could not connect to host
 etrker.com: did not receive HSTS header
 ets2mp.de: did not receive HSTS header
 etsysecure.com: could not connect to host
@@ -4356,16 +4336,17 @@ fatdoge.cn: did not receive HSTS header
 fatgeekflix.net: could not connect to host
 fatherhood.gov: did not receive HSTS header
 fatlossguide.xyz: could not connect to host
 fator25.com.br: could not connect to host
 fatwin.pw: could not connect to host
 fatzebra.com.au: max-age too low: 0
 fayolle.info: did not receive HSTS header
 fbox.li: could not connect to host
+fckd.net: did not receive HSTS header
 fcsic.gov: max-age too low: 2592000
 fdj.im: could not connect to host
 fdt.name: did not receive HSTS header
 feard.space: could not connect to host
 federalregister.gov: did not receive HSTS header
 fedo.moe: could not connect to host
 feedthebot.com: did not receive HSTS header
 feedthefuture.gov: did not receive HSTS header
@@ -4552,17 +4533,16 @@ freeflow.tv: could not connect to host
 freekdevries.nl: did not receive HSTS header
 freelanced.co.za: could not connect to host
 freelo.cz: did not receive HSTS header
 freematthale.net: did not receive HSTS header
 freesoftwaredriver.com: could not connect to host
 freethought.org.au: could not connect to host
 freeutopia.org: did not receive HSTS header
 freqlabs.com: did not receive HSTS header
-fresh-hotel.org: did not receive HSTS header
 freshfind.xyz: could not connect to host
 freshlymind.com: did not receive HSTS header
 frezbo.com: could not connect to host
 frforms.com: did not receive HSTS header
 fridaperfumaria.com.br: could not connect to host
 fridolinka.cz: could not connect to host
 friendica.ch: could not connect to host
 friendlyfiregameshow.com: could not connect to host
@@ -4663,17 +4643,16 @@ gamers-life.fr: could not connect to hos
 gamerslair.org: did not receive HSTS header
 gamerz-point.de: could not connect to host
 gamesdepartment.co.uk: did not receive HSTS header
 gameserver-sponsor.de: did not receive HSTS header
 gamesurferapp.com: could not connect to host
 gamingmedia.eu: did not receive HSTS header
 gamoice.com: did not receive HSTS header
 gampenhof.de: did not receive HSTS header
-gar-nich.net: did not receive HSTS header
 garageon.net: did not receive HSTS header
 garciamartin.me: could not connect to host
 garcinia--cambogia.com: could not connect to host
 garden.trade: could not connect to host
 gasser-daniel.ch: did not receive HSTS header
 gatapro.net: could not connect to host
 gatorsa.es: did not receive HSTS header
 gaussorgues.me: could not connect to host
@@ -4731,17 +4710,17 @@ getmassage.com.ng: could not connect to 
 getmondo.co.uk: could not connect to host
 getpake.com: could not connect to host
 getpop.org: did not receive HSTS header
 getremembrall.com: could not connect to host
 getronics.care: could not connect to host
 getsello.com: could not connect to host
 getspeaker.com: did not receive HSTS header
 getwashdaddy.com: could not connect to host
-gfbouncycastles.co.uk: did not receive HSTS header
+gfbouncycastles.co.uk: could not connect to host
 gfhgiro.nl: max-age too low: 0
 gfm.tech: could not connect to host
 gfwsb.ml: could not connect to host
 ggss.ml: could not connect to host
 gheorghe-sarcov.ga: could not connect to host
 gheorghesarcov.ga: could not connect to host
 gheorghesarcov.tk: could not connect to host
 ghi.gov: could not connect to host
@@ -4773,16 +4752,17 @@ gis3m.org: did not receive HSTS header
 gistfy.com: could not connect to host
 git-stuff.tk: could not connect to host
 givemyanswer.com: could not connect to host
 gizzo.sk: could not connect to host
 glass.google.com: did not receive HSTS header (error ignored - included regardless)
 glasslikes.com: did not receive HSTS header
 glbg.eu: did not receive HSTS header
 glentakahashi.com: could not connect to host
+glittersjabloon.nl: did not receive HSTS header
 glitzmirror.com: could not connect to host
 global-adult-webcams.com: did not receive HSTS header
 globalado.com: could not connect to host
 globalbridge-japan.com: did not receive HSTS header
 globalexpert.co.nz: could not connect to host
 globalinsights.xyz: could not connect to host
 globalittech.com: could not connect to host
 globalmusic.ga: could not connect to host
@@ -5265,17 +5245,17 @@ hydronium.ga: could not connect to host
 hydronium.me: could not connect to host
 hydronium.ml: could not connect to host
 hydronium.tk: could not connect to host
 hypa.net.au: did not receive HSTS header
 hyper69.com: did not receive HSTS header
 hypnoresults.com.au: did not receive HSTS header
 hypnos.hu: did not receive HSTS header
 hysg.me: could not connect to host
-hzh.pub: did not receive HSTS header
+hzh.pub: could not connect to host
 i-jp.net: could not connect to host
 i-partners.sk: did not receive HSTS header
 i-rickroll-n.pw: could not connect to host
 i10z.com: could not connect to host
 iacono.com.br: did not receive HSTS header
 iamjoshellis.com: could not connect to host
 iamokay.nl: did not receive HSTS header
 iamreubin.co.uk: did not receive HSTS header
@@ -5332,17 +5312,16 @@ igi.codes: max-age too low: 0
 igiftcards.nl: did not receive HSTS header
 ignatisd.gr: did not receive HSTS header
 igule.net: could not connect to host
 ihotel.io: did not receive HSTS header
 ihrlotto.de: could not connect to host
 ihrnationalrat.ch: could not connect to host
 ihsbsd.me: could not connect to host
 ihsbsd.tk: could not connect to host
-iideaz.org: did not receive HSTS header
 iispeed.com: did not receive HSTS header
 ijn-dd.nl: could not connect to host
 ijoda.com: could not connect to host
 ikocik.sk: did not receive HSTS header
 ikon.name: did not receive HSTS header
 ikwilguidobellen.nl: could not connect to host
 ikzoekjeugdhulp.nl: did not receive HSTS header
 ilbuongiorno.it: did not receive HSTS header
@@ -5483,17 +5462,17 @@ inverselink.com: could not connect to ho
 investnext.com: max-age too low: 43200
 investor.gov: did not receive HSTS header
 invictusmc.uk: could not connect to host
 invinsec.cloud: did not receive HSTS header
 inviosolutions.com: max-age too low: 0
 invite24.pro: could not connect to host
 iolife.dk: could not connect to host
 ionas-law.ro: did not receive HSTS header
-iop.intuit.com: did not receive HSTS header
+iop.intuit.com: max-age too low: 86400
 iora.fr: could not connect to host
 iosmods.com: did not receive HSTS header
 iostips.ru: could not connect to host
 ip6.im: did not receive HSTS header
 ipbill.org.uk: could not connect to host
 iplife.cn: could not connect to host
 ipmimagazine.com: did not receive HSTS header
 iprice.co.id: did not receive HSTS header
@@ -5840,18 +5819,20 @@ kaniklani.co.za: could not connect to ho
 kanscooking.org: could not connect to host
 kany.me: did not receive HSTS header
 kanzlei-wirtschaftsrecht.berlin: max-age too low: 600000
 kaohub.com: could not connect to host
 kaplatz.is: could not connect to host
 kapucini.si: max-age too low: 0
 kaputt.com: did not receive HSTS header
 kapverde.guide: could not connect to host
+karabas.com: did not receive HSTS header
 karaoketonight.com: could not connect to host
 karloskontana.tk: could not connect to host
+karmaspa.se: did not receive HSTS header
 karting34.com: did not receive HSTS header
 kashdash.ca: could not connect to host
 katalogakci.cz: did not receive HSTS header
 katiaetdavid.fr: could not connect to host
 katoju.co.jp: could not connect to host
 katproxy.al: could not connect to host
 katproxy.online: could not connect to host
 katproxy.site: could not connect to host
@@ -6066,17 +6047,16 @@ labrasaq8.com: did not receive HSTS head
 labs.directory: could not connect to host
 labs.moscow: did not receive HSTS header
 lacarpesaintaubinoise.fr: 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
-lacuevadechauvet.com: did not receive HSTS header
 ladylucks.co.uk: did not receive HSTS header
 laemen.com: did not receive HSTS header
 laemen.nl: could not connect to host
 laf.in.net: could not connect to host
 lagalerievirtuelle.fr: did not receive HSTS header
 lagier.xyz: could not connect to host
 lagoza.name: could not connect to host
 lainchan.org: did not receive HSTS header
@@ -6202,17 +6182,16 @@ liaoshuma.com: could not connect to host
 libanco.com: could not connect to host
 libertyrp.org: did not receive HSTS header
 libfte.org: did not receive HSTS header
 library.linode.com: did not receive HSTS header
 librechan.net: could not connect to host
 libreduca.com: could not connect to host
 lichess4545.com: did not receive HSTS header
 lichess4545.tv: did not receive HSTS header
-lidlovajogurteka.si: could not connect to host
 liebach.me: did not receive HSTS header
 liemen.net: did not receive HSTS header
 life-time.nl: did not receive HSTS header
 lifecoach.tw: did not receive HSTS header
 lifecoachproviders.com: did not receive HSTS header
 lifeguard.aecom.com: did not receive HSTS header
 lifeinitsownway.com: could not connect to host
 lifeng.us: did not receive HSTS header
@@ -6253,17 +6232,16 @@ linorman1997.me: could not connect to ho
 linux-mint.cz: could not connect to host
 linuxandstuff.de: could not connect to host
 linuxeyecandy.com: could not connect to host
 linuxfixed.it: could not connect to host
 linuxforyou.com: could not connect to host
 linuxgeek.ro: could not connect to host
 linuxmint.cz: could not connect to host
 linuxmonitoring.net: did not receive HSTS header
-lipo.lol: did not receive HSTS header
 liquid.solutions: did not receive HSTS header
 liquorsanthe.in: could not connect to host
 lisaco.de: could not connect to host
 lisbongold.com: did not receive HSTS header
 lisgade.dk: could not connect to host
 listafirmelor.com: could not connect to host
 listage.ovh: did not receive HSTS header
 litespeed.io: could not connect to host
@@ -6290,16 +6268,17 @@ lobste.rs: did not receive HSTS header
 localchum.com: could not connect to host
 localdrive.me: could not connect to host
 localnetwork.nz: could not connect to host
 locksmithrandburg24-7.co.za: could not connect to host
 locktheirphone.com: could not connect to host
 lockyourcomputer.pw: did not receive HSTS header
 locomotive.ca: did not receive HSTS header
 locvis.ru: did not receive HSTS header
+loforo.com: did not receive HSTS header
 loftboard.eu: could not connect to host
 log2n.uk: could not connect to host
 logario.com.br: could not connect to host
 logicaladvertising.com: could not connect to host
 login.corp.google.com: max-age too low: 7776000 (error ignored - included regardless)
 login.gov: did not receive HSTS header
 login.persona.org: could not connect to host
 loginseite.com: could not connect to host
@@ -6337,16 +6316,17 @@ lotsencafe.de: did not receive HSTS head
 lotuscloud.org: could not connect to host
 louduniverse.net: did not receive HSTS header
 louiewatch.com: could not connect to host
 loveable.de: could not connect to host
 lovelifelovelive.com: could not connect to host
 lovelyblogacademy.com: did not receive HSTS header
 lovelycorral.com: did not receive HSTS header
 lovelyfriends.org: did not receive HSTS header
+lovelytimes.net: did not receive HSTS header
 loveto.at: could not connect to host
 lovingearth.net: max-age too low: 0
 lowhangingfruitgrabber.com: could not connect to host
 loxis.be: did not receive HSTS header
 lpak.nl: could not connect to host
 lpgram.ga: could not connect to host
 lrhsclubs.com: could not connect to host
 lrhstsa.com: could not connect to host
@@ -6478,17 +6458,17 @@ manageall.de: could not connect to host
 manageforall.com: could not connect to host
 manageforall.de: could not connect to host
 managemynetsuite.com: did not receive HSTS header
 manantial.mx: did not receive HSTS header
 mandpress.com: did not receive HSTS header
 mangazuki.co: did not receive HSTS header
 maniadeprazer.com.br: could not connect to host
 manifestbin.com: did not receive HSTS header
-manipulatedtme.com: did not receive HSTS header
+manipulatedtme.com: could not connect to host
 manitasicily.com: did not receive HSTS header
 manningbrothers.com: did not receive HSTS header
 manns-solutions.com: did not receive HSTS header
 manns-solutions.ru: did not receive HSTS header
 mannsolutions.co.uk: did not receive HSTS header
 mansfieldplacevt.com: did not receive HSTS header
 manshop24.com: could not connect to host
 mansion-note.com: did not receive HSTS header
@@ -6516,17 +6496,16 @@ marie-en-provence.com: did not receive H
 marienschule-sundern.de: did not receive HSTS header
 marinela.com.mx: max-age too low: 86400
 marinelausa.com: max-age too low: 86400
 markaconnor.com: did not receive HSTS header
 markayapilandirma.com: could not connect to host
 markcp.me: could not connect to host
 market.android.com: did not receive HSTS header (error ignored - included regardless)
 marketespace.fr: did not receive HSTS header
-marketingvirtuales.com: did not receive HSTS header
 markllego.com: could not connect to host
 markorszulak.com: did not receive HSTS header
 markrobin.de: did not receive HSTS header
 marksill.com: could not connect to host
 marktboten.de: did not receive HSTS header
 markus-dev.com: did not receive HSTS header
 markusabraham.com: did not receive HSTS header
 markusweimar.de: did not receive HSTS header
@@ -6828,17 +6807,17 @@ mobilethreat.net: could not connect to h
 mobilethreatnetwork.net: could not connect to host
 mobilpass.no: could not connect to host
 mobiwalk.com: could not connect to host
 mobix5.com: did not receive HSTS header
 mockmyapp.com: could not connect to host
 mocloud.eu: could not connect to host
 mocsuite.club: could not connect to host
 mocurio.com: could not connect to host
-modaperuimport.com: did not receive HSTS header
+modaperuimport.com: could not connect to host
 moddedark.com: could not connect to host
 mode-marine.com: could not connect to host
 model9.io: did not receive HSTS header
 modeldimension.com: did not receive HSTS header
 modelsclub.org.ua: did not receive HSTS header
 modemagazines.co.uk: could not connect to host
 moderatortv.de: did not receive HSTS header
 modx.by: max-age too low: 31536
@@ -6870,17 +6849,16 @@ monautoneuve.fr: did not receive HSTS he
 mondar.io: could not connect to host
 mondopoint.com: did not receive HSTS header
 mondwandler.de: could not connect to host
 moneromerchant.com: could not connect to host
 moneycrownmedia.com: could not connect to host
 monika-sokol.de: did not receive HSTS header
 monitaure.io: could not connect to host
 monitman.com: did not receive HSTS header
-monsieurbureau.com: did not receive HSTS header
 montanacures.org: could not connect to host
 montanwerk.de: did not receive HSTS header
 montonicms.com: could not connect to host
 moon.lc: could not connect to host
 moonless.net: could not connect to host
 moonloupe.com: could not connect to host
 moonysbouncycastles.co.uk: did not receive HSTS header
 moosemanstudios.com: could not connect to host
@@ -6934,17 +6912,16 @@ mrksk.com: did not receive HSTS header
 mrning.com: did not receive HSTS header
 mrnonz.com: max-age too low: 0
 mrpopat.in: did not receive HSTS header
 mrs-shop.com: did not receive HSTS header
 mrsbairds.com: max-age too low: 86400
 msc-seereisen.net: max-age too low: 0
 mstd.tokyo: did not receive HSTS header
 mstdn-tech.jp: could not connect to host
-mstdn.io: did not receive HSTS header
 mszaki.com: did not receive HSTS header
 mt.me.uk: could not connect to host
 mtamaki.com: could not connect to host
 mtcgf.com: did not receive HSTS header
 mtdn.jp: could not connect to host
 mtg-esport.de: did not receive HSTS header
 muevetumundo.com.mx: max-age too low: 86400
 mujadin.se: did not receive HSTS header
@@ -6998,16 +6975,17 @@ mydnaresults.com: could not connect to h
 mydnatest.com: did not receive HSTS header
 mydriversedge.com: did not receive HSTS header
 myfdic.gov: could not connect to host
 mygate.at: could not connect to host
 mygivingcircle.org: did not receive HSTS header
 mygooder.com: did not receive HSTS header
 mygov.scot: did not receive HSTS header
 myhair.asia: did not receive HSTS header
+myicare.org: did not receive HSTS header
 myiocc.org: could not connect to host
 myip.tech: max-age too low: 2592000
 myjumpsuit.de: did not receive HSTS header
 mykolab.com: did not receive HSTS header
 mykreuzfahrt.de: could not connect to host
 mymp3singer.site: did not receive HSTS header
 mynetblog.com: did not receive HSTS header
 mynewleaf.co: did not receive HSTS header
@@ -7023,17 +7001,17 @@ myraytech.net: did not receive HSTS head
 myrig.net: could not connect to host
 myrsa.in: did not receive HSTS header
 mysecretrewards.com: could not connect to host
 myspa.asia: did not receive HSTS header
 mystery-science-theater-3000.de: did not receive HSTS header
 mysteryblog.de: did not receive HSTS header
 mythlogic.com: did not receive HSTS header
 mythslegendscollection.com: did not receive HSTS header
-mytweeps.com: could not connect to host
+mytweeps.com: did not receive HSTS header
 myweb360.de: did not receive HSTS header
 myzone.com: did not receive HSTS header
 n-rickroll-e.pw: could not connect to host
 n0psled.nl: could not connect to host
 n2x.in: could not connect to host
 n4l.pw: could not connect to host
 n8ch.net: could not connect to host
 nabru.co.uk: did not receive HSTS header
@@ -7099,17 +7077,17 @@ nearbiwa.com: did not receive HSTS heade
 neavision.de: did not receive HSTS header
 nebra.io: could not connect to host
 nebulousenhanced.com: could not connect to host
 nedcf.org.uk: did not receive HSTS header
 nedwave.com: did not receive HSTS header
 nedzad.me: could not connect to host
 neftaly.com: did not receive HSTS header
 negativzinsen.info: did not receive HSTS header
-neilgreen.net: did not receive HSTS header
+neilgreen.net: could not connect to host
 neko-life.com: did not receive HSTS header
 neko-system.com: did not receive HSTS header
 nemno.de: could not connect to host
 nemovement.org: could not connect to host
 neoani.me: did not receive HSTS header
 neofelhz.space: could not connect to host
 neonisi.com: could not connect to host
 neonnuke.tech: could not connect to host
@@ -7137,17 +7115,17 @@ netzpolitik.org: max-age too low: 259200
 netztest.at: did not receive HSTS header
 netzvieh.de: did not receive HSTS header
 netzzwerg4u.de: could not connect to host
 neueonlinecasino2016.com: could not connect to host
 neuralgic.net: could not connect to host
 neuro-plus-100.com: could not connect to host
 neuronfactor.com: max-age too low: 1000
 never-afk.de: did not receive HSTS header
-never.pet: could not connect to host
+never.pet: did not receive HSTS header
 neveta.com: could not connect to host
 newbieboss.com: did not receive HSTS header
 newedivideo.it: could not connect to host
 newgenerationplus.org: could not connect to host
 newhdmovies.io: could not connect to host
 newkaliningrad.ru: did not receive HSTS header
 newlooknow.com: did not receive HSTS header
 newmelalife.com: did not receive HSTS header
@@ -7184,16 +7162,17 @@ nidux.com: did not receive HSTS header
 niduxcomercial.com: could not connect to host
 nien.chat: could not connect to host
 nifpnet.nl: did not receive HSTS header
 nightsnack.cf: 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
 nikolaichik.photo: did not receive HSTS header
+nil2.org: 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: could not connect to host
 nippombashi.net: did not receive HSTS header
 nipponcareers.com: did not receive HSTS header
 nixien.fr: could not connect to host
@@ -7594,33 +7573,33 @@ pastdream.xyz: could not connect to host
 paste.linode.com: could not connect to host
 pastebin.linode.com: could not connect to host
 pastenib.com: could not connect to host
 paster.li: did not receive HSTS header
 pataua.kiwi: did not receive HSTS header
 paternitydnatest.com: could not connect to host
 patfs.com: did not receive HSTS header
 patientinsight.net: did not receive HSTS header
-patt.us: could not connect to host
+patt.us: did not receive HSTS header
 patterson.mp: could not connect to host
 paul-kerebel.pro: could not connect to host
 paulbunyanmls.com: did not receive HSTS header
 paulproell.at: could not connect to host
 paulyang.cn: did not receive HSTS header
 pavelfojt.cz: did not receive HSTS header
 pavelkahouseforcisco.com: did not receive HSTS header
 paxdei.com.br: could not connect to host
 paxwinkel.nl: did not receive HSTS header
 pay.gigahost.dk: did not receive HSTS header
 payfreez.com: could not connect to host
 payments-reference.org: could not connect to host
 payments.google.com: did not receive HSTS header (error ignored - included regardless)
 payroll.ch: could not connect to host
 paytwopay.com: could not connect to host
-pbapp.net: could not connect to host
+pbapp.net: did not receive HSTS header
 pbbr.com: did not receive HSTS header
 pbprint.ru: did not receive HSTS header
 pc-nf.de: did not receive HSTS header
 pcat.io: could not connect to host
 pcfun.net: could not connect to host
 pchax.net: could not connect to host
 pchospital.cc: could not connect to host
 pdamsidoarjo.co.id: could not connect to host
@@ -7720,18 +7699,19 @@ pidomex.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
 pimpmymac.ru: did not receive HSTS header
 pims.global: did not receive HSTS header
 pinkyf.com: could not connect to host
+pioche.ovh: did not receive HSTS header
 pippen.io: could not connect to host
-pips.rocks: did not receive HSTS header
+pips.rocks: could not connect to host
 pir9.com: did not receive HSTS header
 pirata.ga: did not receive HSTS header
 piratebit.tech: could not connect to host
 piratedb.com: could not connect to host
 piratedot.com: could not connect to host
 piratelist.online: could not connect to host
 piratenlogin.de: could not connect to host
 pirateproxy.pe: could not connect to host
@@ -7835,16 +7815,17 @@ porno-gif.ru: did not receive HSTS heade
 pornstars.me: did not receive HSTS header
 portalm.tk: could not connect to host
 portalplatform.net: could not connect to host
 portaluniversalista.org: could not connect to host
 portalzine.de: did not receive HSTS header
 poshpak.com: max-age too low: 86400
 postcodewise.co.uk: did not receive HSTS header
 posterspy.com: did not receive HSTS header
+postpot.co.kr: max-age too low: 0
 postscheduler.org: could not connect to host
 posylka.de: did not receive HSTS header
 potatoheads.net: could not connect to host
 potsky.com: did not receive HSTS header
 pourmesloisirs.com: did not receive HSTS header
 poussinooz.fr: could not connect to host
 povitria.net: could not connect to host
 power-l.ch: did not receive HSTS header
@@ -8088,16 +8069,17 @@ raven.lipetsk.ru: could not connect to h
 ravengergaming.ga: did not receive HSTS header
 ravkr.duckdns.org: max-age too low: 30
 raw-diets.com: did not receive HSTS header
 rawet.se: could not connect to host
 rawoil.com: could not connect to host
 rawstorieslondon.com: could not connect to host
 raydan.space: could not connect to host
 raydobe.me: could not connect to host
+raymondjcox.com: did not receive HSTS header
 raytron.org: could not connect to host
 razeencheng.com: could not connect to host
 razlaw.name: did not receive HSTS header
 razzolini.com.br: could not connect to host
 rbhighinc.org: could not connect to host
 rbose.org: could not connect to host
 rbqcloud.com: did not receive HSTS header
 rbti.me: could not connect to host
@@ -8199,17 +8181,17 @@ reporturl.io: did not receive HSTS heade
 reprolife.co.uk: could not connect to host
 res-rheingau.de: did not receive HSTS header
 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
 restaurace-klokocka.cz: did not receive HSTS header
-restchart.com: did not receive HSTS header
+restchart.com: could not connect to host
 retroarms.com: did not receive HSTS header
 retroarms.cz: 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
@@ -8270,16 +8252,17 @@ robtex.com: did not receive HSTS header
 robtex.net: did not receive HSTS header
 robtex.org: did not receive HSTS header
 rochman.id: could not connect to host
 rocket-wars.de: did not receive HSTS header
 rocketnet.ml: could not connect to host
 rockeyscrivo.com: did not receive HSTS header
 rocksberg.net: could not connect to host
 rockz.io: did not receive HSTS header
+roddis.net: did not receive HSTS header
 rodney.id.au: did not receive HSTS header
 rodneybrooksjr.com: did not receive HSTS header
 rodosto.com: did not receive HSTS header
 roeper.party: could not connect to host
 roesemann.email: could not connect to host
 roguelikecenter.fr: did not receive HSTS header
 rohlik.cz: did not receive HSTS header
 roketix.co.uk: did not receive HSTS header
@@ -8395,16 +8378,18 @@ saltedskies.com: could not connect to ho
 saltra.online: did not receive HSTS header
 samegoal.org: did not receive HSTS header
 sametovymesic.cz: could not connect to host
 saml2.com: could not connect to host
 sampcup.com: could not connect to host
 sampoznay.ru: did not receive HSTS header
 samraskauskas.com: could not connect to host
 samsen.club: could not connect to host
+samsungmobile.it: did not receive HSTS header
+samui-samui.de: did not receive HSTS header
 sanasalud.org: could not connect to host
 sanatfilan.com: did not receive HSTS header
 sandviks.com: did not receive HSTS header
 sanguoxiu.com: could not connect to host
 sanhei.ch: did not receive HSTS header
 sanik.my: did not receive HSTS header
 sanissimo.com.mx: max-age too low: 86400
 sansage.com.br: could not connect to host
@@ -8817,17 +8802,17 @@ smet.us: could not connect to host
 smexpt.com: did not receive HSTS header
 smileawei.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
-smol.cat: did not receive HSTS header
+smol.cat: could not connect to host
 smove.sg: did not receive HSTS header
 smplix.com: could not connect to host
 smspodmena.ru: did not receive HSTS header
 smtp.bz: did not receive HSTS header
 smusg.com: did not receive HSTS header
 smzsq.com: did not receive HSTS header
 snailing.org: could not connect to host
 snakehosting.dk: did not receive HSTS header
@@ -9016,16 +9001,17 @@ steelbea.ms: could not connect to host
 steem.io: did not receive HSTS header
 stefanweiser.de: did not receive HSTS header
 stepbystep3d.com: did not receive HSTS header
 steph-autoecole.ch: did not receive HSTS header
 stephanierxo.com: did not receive HSTS header
 stephanos.me: could not connect to host
 stephenandburns.com: did not receive HSTS header
 stevechekblain.win: could not connect to host
+stevenroddis.com: did not receive HSTS header
 stevensheffey.me: did not receive HSTS header
 stevensononthe.net: did not receive HSTS header
 stevenz.net: did not receive HSTS header
 stewartremodelingadvantage.com: could not connect to host
 sticklerjs.org: could not connect to host
 stig.io: could not connect to host
 stigroom.com: could not connect to host
 stillblackhat.id: could not connect to host
@@ -9097,17 +9083,16 @@ sugarsweetorsour.com: did not receive HS
 suian.or.jp: max-age too low: 86400
 suite73.org: could not connect to host
 summitbankofkc.com: did not receive HSTS header
 sumoatm.com: did not receive HSTS header
 sumoscout.de: could not connect to host
 sun-wellness-online.com.vn: did not receive HSTS header
 sunboxstore.jp: did not receive HSTS header
 suncountrymarine.com: did not receive HSTS header
-sunflyer.cn: did not receive HSTS header
 sungo.wtf: did not receive HSTS header
 sunlandsg.vn: did not receive HSTS header
 sunnyfruit.ru: could not connect to host
 sunshinepress.org: could not connect to host
 sunyanzi.tk: could not connect to host
 suos.io: could not connect to host
 supcro.com: could not connect to host
 super-erotica.ru: could not connect to host
@@ -9255,16 +9240,17 @@ tdsb.gq: could not connect to host
 tdsb.ml: could not connect to host
 tdsbhack.cf: could not connect to host
 tdsbhack.ga: could not connect to host
 tdsbhack.gq: could not connect to host
 tdsbhack.ml: could not connect to host
 teachforcanada.ca: did not receive HSTS header
 tealdrones.com: did not receive HSTS header
 team-teasers.com: could not connect to host
+teambeoplay.co.uk: did not receive HSTS header
 teamblueridge.org: could not connect to host
 teamhood.io: did not receive HSTS header
 teampoint.cz: could not connect to host
 teamsocial.co: did not receive HSTS header
 teamup.rocks: did not receive HSTS header
 teamzeus.cz: could not connect to host
 tech-blog.fr: did not receive HSTS header
 tech-finder.fr: could not connect to host
@@ -9480,17 +9466,17 @@ tidmore.us: could not connect to host
 tiendschuurstraat.nl: could not connect to host
 tiensnet.com: could not connect to host
 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
 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
 timeatlas.com: did not receive HSTS header
 timesavingplugins.com: could not connect to host
 timesavingplugins.net: could not connect to host
@@ -9779,17 +9765,16 @@ ukdropshipment.com: did not receive HSTS
 ukk.dk: did not receive HSTS header
 ukrgadget.com: could not connect to host
 ukrnet.co.uk: did not receive HSTS header
 ulabox.cat: did not receive HSTS header
 ulabox.es: did not receive HSTS header
 ullamodaintima.com.br: could not connect to host
 ulmer-schneesport.de: did not receive HSTS header
 ulmo.dk: could not connect to host
-ultima-ratio.at: did not receive HSTS header
 ultimate-garcinia-plus.com: could not connect to host
 ultimate-glow-skin.com: could not connect to host
 ultimate-memoryplus.com: could not connect to host
 ultimate-neuroplus.com: could not connect to host
 ultros.io: did not receive HSTS header
 umaimise.info: did not receive HSTS header
 umgardi.ca: could not connect to host
 umidev.com: did not receive HSTS header
@@ -9857,21 +9842,24 @@ upldr.pw: could not connect to host
 uporoops.com: could not connect to host
 uprotect.it: could not connect to host
 upstats.eu: could not connect to host
 uptic.net: did not receive HSTS header
 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
+url0.eu: did not receive HSTS header
 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: could not connect to host
 usbtypeccompliant.com: could not connect to host
 uscitizenship.info: did not receive HSTS header
 uscntalk.com: could not connect to host
 uscurrency.gov: did not receive HSTS header
 used-in.jp: could not connect to host
 user-new.com: did not receive HSTS header
 usercare.com: did not receive HSTS header
@@ -10173,17 +10161,17 @@ webmail.mayfirst.org: did not receive HS
 webmaniabr.com: did not receive HSTS header
 webmarketingfestival.it: did not receive HSTS header
 webninja.work: could not connect to host
 webnosql.com: could not connect to host
 webperformance.ru: could not connect to host
 webproshosting.tk: could not connect to host
 webpublica.pt: could not connect to host
 webrebels.org: could not connect to host
-websandbox.uk: could not connect to host
+websandbox.uk: did not receive HSTS header
 websitedesign.bg: did not receive HSTS header
 webstationservice.fr: could not connect to host
 webstellung.com: did not receive HSTS header
 webstory.xyz: did not receive HSTS header
 webswitch.io: could not connect to host
 webtechgadgetry.com: could not connect to host
 webtiles.co.uk: could not connect to host
 webuni.hu: did not receive HSTS header
@@ -10471,16 +10459,17 @@ xn--qckqc0nxbyc4cdb4527err7c.biz: did no
 xn--u9jy16ncfao19mo8i.nagoya: did not receive HSTS header
 xn--uist1idrju3i.jp: did not receive HSTS header
 xn--w22a.jp: did not receive HSTS header
 xn--wmq.jp: did not receive HSTS header
 xn--xdtx3pfzbiw3ar8e7yedqrhui.com: could not connect to host
 xn--yoamomisuasbcn-ynb.com: could not connect to host
 xn--zck9a4b352yuua.jp: did not receive HSTS header
 xobox.me: could not connect to host
+xoda.pw: did not receive HSTS header
 xoffy.com: did not receive HSTS header
 xom.party: could not connect to host
 xombra.com: did not receive HSTS header
 xor-a.net: could not connect to host
 xperiacodes.com: could not connect to host
 xpi.fr: could not connect to host
 xpj.sx: could not connect to host
 xrp.pw: could not connect to host
@@ -10525,17 +10514,16 @@ yetcore.io: could not connect to host
 yhrd.org: did not receive HSTS header
 yikzu.cn: could not connect to host
 yin.roma.it: did not receive HSTS header
 yingsuo.ltd: could not connect to host
 yingyj.com: did not receive HSTS header
 yinhe12.net: did not receive HSTS header
 yippie.nl: could not connect to host
 yizhu.com: could not connect to host
-yjsoft.me: did not receive HSTS header
 ynode.co: did not receive HSTS header
 ynsn.nl: could not connect to host
 yntongji.com: could not connect to host
 yob.vn: could not connect to host
 yoga-in-aying.de: did not receive HSTS header
 yogabhawnamission.com: did not receive HSTS header
 yogeshbeniwal.com: did not receive HSTS header
 yohanesmario.com: 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(1526842805617000);
+const PRTime gPreloadListExpirationTime = INT64_C(1526929053720000);
 %%
 0-1.party, 1
 0.me.uk, 1
 0005pay.com, 1
 0010100.net, 1
 00220022.net, 1
 007-preisvergleich.de, 1
 00881919.com, 1
@@ -220,17 +220,16 @@ 247a.co.uk, 1
 247healthshop.com, 1
 247medplan.com, 1
 24hrs.shopping, 1
 24ip.com, 1
 24ip.de, 1
 24ip.fr, 1
 24kbet.com, 1
 256k.me, 1
-256pages.com, 1
 25reinyan25.net, 1
 2600edinburgh.org, 1
 2600hq.com, 1
 263.info, 1
 27728522.com, 1
 281180.de, 1
 28spots.net, 1
 29227.com, 1
@@ -1065,24 +1064,26 @@ ahoy.travel, 1
 ahoyconference.com, 1
 ahrq.gov, 0
 ahughes03.com, 1
 ahwah.net, 1
 ahxxm.com, 1
 ai-english.jp, 1
 aia.de, 1
 aibenzi.com, 1
+aicial.co.uk, 1
 aicial.com, 1
 aid-web.ch, 1
 aidanmontare.net, 1
 aide-valais.ch, 1
 aiden.link, 1
 aidhan.net, 1
 aie.de, 1
 aiesecarad.ro, 1
+aiforsocialmedia.com, 1
 aigcev.org, 1
 aigenpul.se, 1
 aiicy.org, 1
 aiida.se, 1
 aijsk.com, 1
 aikenorganics.com, 1
 aikenpromotions.com, 1
 aikido-club-limburg.de, 1
@@ -2231,17 +2232,16 @@ asec01.net, 1
 aseith.com, 1
 asepms.com, 1
 aserver.co, 1
 asgapps.co.za, 1
 asge-handel.de, 1
 ashleakunowski.com, 1
 ashleyadum.com, 1
 ashleyfoley.photography, 1
-ashleymedway.com, 1
 ashmportfolio.com, 1
 ashutoshmishra.org, 1
 asia-gazette.com, 1
 asia.dating, 1
 asialeonding.at, 1
 asianbet77.net, 1
 asianshops.net, 1
 asiesvenezuela.com, 1
@@ -2862,16 +2862,17 @@ barreaudenice.com, 1
 barrera.io, 1
 barrett.ag, 1
 barriofut.com, 1
 bars.kh.ua, 1
 barsashop.com.br, 1
 barsil.de, 1
 barslecht.com, 1
 barslecht.nl, 1
+barss.io, 1
 barta.me, 1
 bartel.ws, 1
 bartelt.name, 1
 bartlamboo.nl, 1
 bartula.de, 1
 bartzutow.xyz, 1
 baruch.me, 1
 bas.co.jp, 1
@@ -3364,16 +3365,17 @@ biaggeo.com, 1
 bianinapiccanovias.com, 1
 biaoqingfuhao.net, 1
 biaoqingfuhao.org, 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
@@ -4993,33 +4995,33 @@ casa-mea-inteligenta.ro, 1
 casa-su.casa, 1
 casadoarbitro.com.br, 1
 casadowifi.com.br, 1
 casajardininsecticidas.com, 1
 casalindamex.com, 1
 casamariposaspi.com, 1
 casamorelli.com.br, 1
 casapalla.com.br, 1
-casashopp.com.br, 1
 casasuara.com, 1
 casasuleletrodomesticos.com.br, 1
 casbia.info, 1
 casbuijs.nl, 1
 casburggraaf.com, 1
 casecurity.org, 1
 cash-4x4.com, 1
 cashati.com, 1
 cashew3d.com, 1
 cashfortulsahouses.com, 1
 cashless.fr, 1
 cashlink.de, 1
 cashlink.io, 1
 cashlogic.ch, 1
 cashmaxtexas.com, 1
 cashplk.com, 1
+casinolegal.pt, 1
 casinolistings.com, 1
 casinoreal.com, 1
 casjay.cloud, 1
 casjay.com, 1
 casjay.info, 1
 casjay.us, 1
 casjaygames.com, 1
 casperpanel.com, 1
@@ -5693,17 +5695,17 @@ cirfi.com, 1
 ciri.com.co, 1
 cirope.com, 1
 cirrohost.com, 1
 cirrus0.de, 1
 cirugiasplasticas.com.mx, 1
 cirujanooral.com, 1
 cirurgicagervasio.com.br, 1
 cirurgicalucena.com.br, 1
-ciscodude.net, 0
+ciscodude.net, 1
 cisoaid.com, 1
 ciss.ltd, 1
 cisy.me, 1
 citationgurus.com, 1
 citcuit.in, 1
 citimarinestore.com, 1
 citizen-cam.de, 1
 citizensbankal.com, 1
@@ -5751,16 +5753,17 @@ claimconnect.com, 1
 claimconnect.us, 1
 claimnote.com, 1
 clairegold.com, 1
 claireidrac.fr, 1
 clairescastles.co.uk, 1
 clanebouncycastles.com, 1
 clanrose.org.uk, 1
 clanthor.com, 1
+clanwarz.com, 1
 clapping-rhymes.com, 1
 claretandbanter.uk, 1
 clarkeaward.com, 1
 clarksgaragedoorrepair.com, 1
 clarkwinkelmann.com, 1
 clashersrepublic.com, 1
 class.com.au, 1
 classdojo.com, 1
@@ -6200,17 +6203,16 @@ comogene.com, 1
 comohacerelamoraunhombrenet.com, 1
 comopuededejardefumar.net, 1
 comoquitarlasestriasrapidamente.com, 1
 comorecuperaratumujerpdf.com, 1
 comp2go.com.au, 1
 compagnia-buffo.de, 1
 compagniemartin.com, 1
 comparatif-moto.fr, 1
-compareandrecycle.co.uk, 0
 compareandrecycle.com, 0
 compareinsurance.com.au, 1
 comparesoft.com, 1
 comparexcloudcenter.com, 1
 compartir.party, 1
 compassdirectportal.com, 1
 compeuphoria.com, 1
 comphare.nl, 1
@@ -6891,16 +6893,17 @@ cvv.cn, 1
 cw.center, 1
 cwagner.me, 1
 cwmart.in, 1
 cwningen.cymru, 0
 cwrcoding.com, 1
 cy.technology, 1
 cybbh.space, 1
 cyber-computer.club, 1
+cyber-konzept.de, 1
 cyber-perikarp.eu, 1
 cyber.cafe, 1
 cybercloud.cc, 1
 cyberdos.de, 1
 cyberduck.io, 1
 cybergrx.com, 1
 cyberguerrilla.info, 1
 cyberguerrilla.org, 1
@@ -7395,16 +7398,17 @@ dearnevalleybouncycastles.co.uk, 1
 deathy.ro, 1
 debie-usedcars.be, 1
 debigare.com, 1
 debitoutil.com, 1
 debitpaie.com, 1
 deborahmarinelli.eu, 1
 debron-ot.nl, 1
 debrusoft.ch, 1
+debt.com, 1
 debtrecycling.com.au, 1
 debuemon.com, 1
 debuis.nl, 1
 decalquai.ch, 1
 decentralizedweb.net, 1
 dechat.nl, 1
 decidetreatment.org, 1
 decock-usedcars.be, 1
@@ -9296,17 +9300,16 @@ energyatlas.com, 1
 energyaupair.se, 1
 energydrinkblog.de, 1
 energyelephant.com, 1
 energyled.com.br, 1
 enersaveapp.org, 1
 enersec.co.uk, 1
 enet-navigator.de, 1
 enfantsdelarue.ch, 1
-enfield-kitchens.co.uk, 1
 enflow.nl, 1
 enfoqueseguro.com, 1
 enfu.se, 1
 engarde.net, 1
 engaugetools.com, 1
 engelundlicht.ch, 1
 engg.ca, 1
 engineowning.com, 1
@@ -9444,17 +9447,16 @@ epostplus.li, 1
 eposwales.co.uk, 1
 eposyork.co.uk, 1
 eppelblei.lu, 1
 eppelpress.lu, 1
 eprofitacademy.com, 1
 epsilon.dk, 1
 epsorting.cz, 1
 epublibre.org, 1
-epulsar.ru, 1
 eq-serve.com, 1
 eqorg.com, 1
 equalcloud.com, 1
 equalparts.eu, 1
 equidam.com, 1
 equinecoaching.ca, 1
 equinox.io, 1
 equipandoloja.net.br, 1
@@ -9670,16 +9672,17 @@ etherpad.nl, 1
 ethicaldata.co.uk, 1
 ethicaltek.com, 1
 ethicsburg.gov, 1
 ethika.com, 1
 ethiobaba.com, 1
 ethiopian.dating, 1
 ethitter.com, 1
 ethosinfo.com, 1
+etidni.help, 1
 etienne.cc, 1
 etincelle.ml, 1
 etiquetaunica.com.br, 1
 etkaddict.com, 1
 etoile-usedcars.com, 1
 etre-soi.ch, 1
 etre-vivant.fr, 1
 etudesbibliques.fr, 1
@@ -10197,17 +10200,16 @@ fbijobs.gov, 1
 fbsbx.com, 1
 fburl.com, 1
 fc.media, 1
 fca-tools.com, 1
 fcapartsdb.com, 1
 fcburk.de, 1
 fcforum.net, 1
 fcitasc.com, 1
-fckd.net, 1
 fcprovadia.com, 1
 fdevs.ch, 1
 fdlibre.eu, 1
 fdsys.gov, 0
 feac.us, 1
 feaden.me, 1
 fearghus.org, 1
 fearsomegaming.com, 1
@@ -10679,17 +10681,17 @@ fmarchal.fr, 1
 fmdance.cl, 1
 fmi.gov, 1
 fminsight.net, 1
 fmodoux.biz, 1
 fmovies.fyi, 1
 fmovies.life, 1
 fnb-griffinonline.com, 1
 fndout.com, 1
-fniephaus.com, 1
+fniephaus.com, 0
 fnof.ch, 1
 fnordserver.eu, 1
 fnzc.co.nz, 1
 foairbus.fr, 1
 foairbussas.fr, 1
 focalforest.com, 1
 focanamoda.com.br, 1
 focusmark.jp, 0
@@ -11016,16 +11018,17 @@ freifunk-nrw.de, 1
 freifunk-remscheid.de, 1
 freimeldungen.de, 1
 freims.cc, 1
 freiwurst.net, 1
 freizeitplaza.de, 1
 frenchcreekcog.org, 1
 frenzel.dk, 1
 frequencebanane.ch, 1
+fresh-hotel.org, 1
 fresh-networks.net, 1
 fresh.co.il, 1
 freshcode.nl, 1
 freshdesigns.de, 1
 freshdns.nl, 1
 freshempire.gov, 1
 freshmaza.com, 1
 freshmaza.net, 1
@@ -11385,16 +11388,17 @@ gancedo.com.es, 1
 gandalfservice.com, 1
 gandalfthefeline.com, 1
 gandgliquors.com, 1
 ganhonet.com.br, 1
 ganztagplus.de, 1
 gapdirect.com, 1
 gapfa.org, 1
 gaptek.id, 0
+gar-nich.net, 0
 garage-door.pro, 1
 garage-leone.com, 1
 garage-meynard.com, 1
 garageenginuity.com, 1
 garagegoossens.be, 1
 garagemhermetica.org, 1
 garagevanhulle-used.be, 1
 garanteasy.com, 1
@@ -11594,17 +11598,17 @@ gensonline.eu, 1
 gentianes.ch, 1
 gentoo-blog.de, 1
 genusshotel-riegersburg.at, 1
 genuxtsg.com, 1
 genxbeats.com, 1
 genxnotes.com, 1
 geocommunicator.gov, 1
 geoffanderinmyers.com, 1
-geoffmyers.com, 1
+geoffmyers.com, 0
 geofox.org, 1
 geoip.fedoraproject.org, 1
 geoip.stg.fedoraproject.org, 1
 geolad.com, 0
 geometra.roma.it, 1
 geoport.al, 1
 george-orwell.com, 1
 georgehalachev.com, 1
@@ -11759,17 +11763,17 @@ gianttree.de, 1
 giardinaggio.milano.it, 1
 giardinaggio.napoli.it, 1
 gibraltar.at, 1
 gichigamigames.com, 1
 giddyaunt.net, 1
 giduv.com, 1
 gierds.de, 1
 giftedconsortium.com, 1
-giftking.nl, 1
+giftking.nl, 0
 giftmaniabrilhos.com.br, 1
 gifts365.co.uk, 1
 giftsn.com.sg, 0
 gifzilla.net, 0
 gig.ru, 0
 giga.nl, 1
 gigantism.com, 1
 gigawa.lt, 1
@@ -11865,17 +11869,16 @@ glazedmag.fr, 1
 glcastlekings.co.uk, 1
 gleanview.com, 1
 glencarbide.com, 1
 glendarraghbouncycastles.co.uk, 1
 glenhuntlyapartments.com.au, 1
 glidingshop.cz, 1
 glidingshop.de, 1
 glidingshop.eu, 1
-glittersjabloon.nl, 1
 glloq.org, 1
 glob-coin.com, 1
 global-lights.ma, 1
 global-office.com, 1
 global-village.koeln, 1
 global.hr, 1
 globalchokepoints.org, 1
 globalcomix.com, 1
@@ -13859,16 +13862,17 @@ ih8sn0w.com, 1
 ihacklabs.com, 1
 ihatethissh.it, 1
 ihc.im, 1
 ihkk.net, 1
 ihollaback.org, 1
 ihopeit.works, 1
 ihostup.net, 1
 ihrhost.com, 1
+iideaz.org, 1
 iilin.com, 0
 iiong.com, 0
 iirii.com, 1
 iix.se, 1
 ijohan.nl, 1
 ijsclubtilburg.nl, 1
 ijunohana.jp, 1
 ik-life.com, 1
@@ -15673,17 +15677,16 @@ kaomojis.net, 1
 kap-genial.de, 1
 kapiorr.duckdns.org, 1
 kapo.info, 1
 kappit.dk, 1
 kapseli.net, 1
 kaptadata.com, 1
 kaptamedia.com, 1
 kara-fabian.com, 1
-karabas.com, 1
 karabijnhaken.nl, 0
 karachi.dating, 1
 karamna.com, 1
 karamomo.net, 1
 karanjthakkar.com, 1
 karanlyons.com, 1
 karasik.by, 1
 karateka.org, 1
@@ -15703,17 +15706,16 @@ karlis-kavacis.id.lv, 1
 karlsmithmn.org, 1
 karlstabo.se, 1
 karlzotter.com, 1
 karmaassurance.ca, 1
 karmabaker.com, 1
 karmaflux.com, 1
 karmainsurance.ca, 1
 karmaplatform.com, 1
-karmaspa.se, 1
 karmic.com, 1
 karn.nu, 1
 karneid.info, 1
 karpanhellas.com, 0
 karsofsystems.com, 1
 kartacha.com, 1
 kartec.com, 1
 kartonmodellbau.org, 1
@@ -16599,33 +16601,34 @@ labfox.de, 1
 labiblioafronebrulepas.com, 1
 labobooks.com, 1
 laboiteanem.fr, 1
 labouncycastlehire.co.uk, 1
 labourreedevergheas.fr, 1
 laboutiquemarocaineduconvoyeur.com, 1
 laboutiquemarocaineduconvoyeur.ma, 1
 laboxfaitsoncinema.com, 1
-labradorpuppiesforsalebyregisteredlabradorbreeders.com, 1
+labradorpuppiesforsalebyregisteredlabradorbreeders.com, 0
 lacasa.fr, 1
 lacasabelucci.com, 1
 lacasseroy.com, 1
 lacaveducinquantenaire.com, 1
 lacetsroses.ch, 1
 lachainedesentrepreneurs.fr, 1
 lachawoj.de, 1
 lachlan.com, 1
 lacicloud.net, 1
 lacigf.org, 1
 laclaque.ch, 1
 lacledelareussite.com, 1
 lacledeslan.com, 0
 lacledor.ch, 1
 laclefdor.ch, 1
 lacliniquefinanciere.com, 1
+lacuevadechauvet.com, 1
 lacyc3.eu, 1
 ladbroke.net, 1
 lady-2.jp, 1
 ladybugjam.com, 1
 ladylikeit.com, 1
 laextra.mx, 1
 lafayette-rushford.com, 1
 lafeemam.fr, 1
@@ -17214,16 +17217,17 @@ liderwalut.pl, 0
 lidl-gewinnspiel.de, 1
 lidl-holidays.com, 1
 lidl-menubox.ch, 1
 lidl-selection.at, 1
 lidl-shop.be, 1
 lidl-shop.cz, 1
 lidl-shop.nl, 1
 lidl-tour.ro, 1
+lidlovajogurteka.si, 1
 lidogr.com, 1
 lidong.me, 1
 lidow.eu, 1
 liduan.com, 1
 liduan.net, 1
 liebel.org, 1
 liebestarot.at, 1
 lied8.eu, 1
@@ -17362,16 +17366,17 @@ linvx.org, 1
 linx.li, 1
 linx.net, 1
 linxmind.eu, 1
 linzgau.de, 1
 lionlyrics.com, 1
 lionsdeal.com, 1
 lipartydepot.com, 1
 lipex.com, 1
+lipo.lol, 1
 lipoabaltimore.org, 1
 liqd.net, 1
 liquid.cz, 1
 liquidcomm.net, 1
 liquidhost.co, 1
 liquidinternet.co, 1
 liquidradio.pro, 1
 lirion.de, 1
@@ -17528,17 +17533,16 @@ lockpicks.se, 1
 lockr.io, 1
 locksport.org.nz, 1
 locomore.com, 1
 lodash.com, 0
 lodgesdureynou.fr, 1
 loeildansledoigt.fr, 1
 loenshotel.de, 1
 loew.de, 1
-loforo.com, 1
 lofttravel.com, 1
 log.my, 0
 logaldeveloper.com, 1
 loganmarchione.com, 1
 loganparkneighborhood.org, 1
 logbook.ch, 1
 logbot.info, 1
 logcat.info, 1
@@ -17699,17 +17703,16 @@ loveismore.pl, 0
 loveismore.ru, 0
 loveismore.sk, 0
 loveisourweapon.com, 1
 lovelens.ch, 1
 lovelens.li, 1
 lovelive-anime.tk, 1
 lovelive.us, 1
 lovelivewiki.com, 1
-lovelytimes.net, 1
 lovemomiji.com, 1
 lovemysafetynet.com, 1
 lovenwishes.com, 1
 loveph.one, 1
 lover-bg.com, 1
 loveread-ec.appspot.com, 1
 loverepublic.ru, 1
 lovesmagical.com, 1
@@ -18311,16 +18314,17 @@ marjoleindens.be, 1
 mark-a-hydrant.com, 1
 mark-semmler.de, 1
 markepps.com, 1
 market.android.com, 1
 marketgot.com, 1
 marketing-advertising.eu, 1
 marketing.limited, 1
 marketingdesignu.cz, 1
+marketingvirtuales.com, 1
 marketio.co, 1
 marketizare.ro, 1
 marketnsight.com, 1
 markhaehnel.de, 1
 markido.com, 1
 markitzeroday.com, 1
 marko-fenster24.de, 1
 markoh.co.uk, 1
@@ -19522,16 +19526,17 @@ monolithinteractive.com, 1
 monoseis-monotica.gr, 1
 monothesis.com, 1
 monotsuku.com, 1
 monpc-pro.fr, 1
 monpermismoto.com, 1
 monpermisvoiture.com, 1
 monpetitforfait.com, 1
 monpetitmobile.com, 1
+monsieurbureau.com, 1
 monsieursavon.ch, 1
 monstermashentertainments.co.uk, 1
 montage-kaika.de, 1
 montagne-tendance.ch, 1
 montanana.com, 1
 montand.com, 1
 montarfotoaki.com, 1
 montas.io, 1
@@ -19749,16 +19754,17 @@ msmails.de, 1
 msnr.net, 1
 msp66.de, 1
 mspnocsupport.com, 1
 msquadrat.de, 1
 mssys.de, 1
 mstdn.blue, 1
 mstdn.club, 1
 mstdn.fr, 1
+mstdn.io, 1
 mstdn.nl, 1
 mstdn.onl, 1
 mstiles92.com, 1
 msuess.me, 1
 msuna.net, 1
 msv-limpezas.pt, 1
 msx.org, 1
 msz-fotografie.de, 1
@@ -20020,17 +20026,16 @@ mygpsite.com, 1
 mygreatjob.eu, 1
 mygreatjobs.de, 1
 mygretchen.de, 1
 mygrotto.org, 1
 mygymer.ch, 1
 myhatsuden.jp, 1
 myhealthreviews.com, 1
 myhostname.net, 1
-myicare.org, 1
 myimds.com, 1
 myimmitracker.com, 1
 myjumparoo.co.uk, 1
 mykeepsake.xyz, 0
 myki.co, 1
 mykontool.de, 1
 mylatestnews.org, 1
 mylawyer.be, 1
@@ -20833,17 +20838,16 @@ nikksno.io, 1
 niklas.pw, 1
 niklasbabel.com, 1
 nikobradshaw.com, 1
 nikolasbradshaw.com, 1
 nikolasgrottendieck.com, 1
 nikomo.fi, 0
 nikz.in, 1
 nil.gs, 1
-nil2.org, 1
 nilrem.org, 1
 nimeshjm.com, 1
 ninaforever.com, 1
 ninarinaldi.com.br, 1
 ninaundandre.de, 1
 ninchat.com, 1
 ninebennink.com, 1
 ninebytes.xyz, 1
@@ -22721,17 +22725,16 @@ pinscher.com.br, 1
 pinterest.at, 1
 pinterest.co.uk, 1
 pinterest.com, 1
 pinterest.de, 1
 pinterest.engineering, 1
 pinterest.ie, 1
 pinterest.info, 1
 pinterest.jp, 1
-pioche.ovh, 1
 pipenny.net, 1
 piranil.com, 1
 pirate.trade, 1
 pirateahoy.eu, 1
 piratebayproxy.tf, 1
 piraten-basel.ch, 1
 piraten-bv-nord.de, 1
 piratepay.io, 1
@@ -23136,17 +23139,16 @@ postdarwinian.com, 1
 postdarwinism.com, 1
 postdeck.de, 1
 posteo.de, 0
 posters.win, 1
 postfalls-naturopathic.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
 potbar.com, 1
 potbox.com, 1
 potentialproject.com, 1
 pothe.com, 1
@@ -24055,17 +24057,16 @@ ray-home.de, 1
 ray-works.de, 1
 raycarruthersphotography.co.uk, 1
 rayiris.com, 1
 raykitchenware.com, 1
 raymcbride.com, 1
 raymd.de, 1
 raymii.org, 1
 raymondelooff.nl, 1
-raymondjcox.com, 0
 rayworks.de, 1
 razberry.kr, 1
 rb-china.net, 1
 rbensch.com, 1
 rbflote.lv, 1
 rbltracker.com, 1
 rbmafrica.co.za, 1
 rbnet.xyz, 1
@@ -24741,17 +24742,16 @@ rockfax.com, 1
 rockhounds.co.za, 1
 rockinronniescastles.co.uk, 1
 rockitinflatables.co.uk, 1
 rockpesado.com.br, 1
 rockthebabybump.com, 1
 rockuse.com.br, 1
 rockymountainspice.com, 1
 rocssti.net, 1
-roddis.net, 1
 rodehutskors.net, 1
 rodeobull.biz, 1
 rodeohire.com, 1
 rodeosales.co.uk, 1
 rodevlaggen.nl, 1
 rodichi.net, 1
 rodolfo.gs, 1
 rodomonte.org, 1
@@ -25256,22 +25256,20 @@ samifar.in, 1
 samizdat.cz, 1
 samkelleher.com, 1
 saml-gateway.org, 1
 samm.com.au, 1
 sammyjohnson.com, 0
 sammyservers.com, 1
 samp.im, 1
 samsonova.de, 1
-samsungmobile.it, 1
 samsungphonegenerator.xyz, 1
 samsungxoa.com, 1
 samuelkeeley.com, 1
 samuellaulhau.fr, 1
-samui-samui.de, 1
 samuirehabcenter.com, 1
 samvanderkris.com, 1
 samwilberforce.com, 1
 samwu.tw, 0
 samyerkes.com, 1
 sana-store.com, 1
 sana-store.cz, 1
 sana-store.sk, 1
@@ -27609,17 +27607,16 @@ steveborba.com, 1
 stevedesmond.ca, 1
 stevedoggett.com, 1
 stevegrav.es, 1
 steven-bennett.com, 1
 stevenberg.net, 1
 stevengoodpaster.com, 1
 stevenhumphrey.uk, 1
 stevenkwan.me, 1
-stevenroddis.com, 1
 stevens.se, 1
 stevenski.com, 0
 steventress.com, 1
 stevenwooding.com, 1
 stevenz.science, 1
 stevenz.xyz, 1
 stevesdrivingschooltyneside.com, 1
 stewartswines.com, 1
@@ -27894,16 +27891,17 @@ summitmasters.net, 1
 sumthing.com, 1
 sunbritetv.com, 1
 sundanceusa.com, 1
 sundaycooks.com, 1
 sundayfundayjapan.com, 1
 suneilpatel.com, 1
 sunfeathers.net, 1
 sunfireshop.com.br, 1
+sunflyer.cn, 0
 sunfox.cz, 1
 sunfulong.me, 1
 sunjaydhama.com, 1
 sunn.ie, 1
 sunsetwx.com, 1
 sunshinesf.org, 1
 sunsmartresorts.com, 1
 sunstar.bg, 1
@@ -28402,17 +28400,16 @@ team-azerty.com, 1
 team-bbd.com, 1
 team-pancake.eu, 1
 team3482.com, 1
 teamassists.com, 1
 teambeam.at, 1
 teambeam.ch, 1
 teambeam.com, 1
 teambeam.de, 1
-teambeoplay.co.uk, 1
 teambition.com, 1
 teamcombat.com, 1
 teamdaylo.xyz, 1
 teamliquidpro.com, 1
 teammathics.com, 1
 teamnetsol.com, 1
 teamnissannorthparts.com, 1
 teamnorthgermany.de, 1
@@ -30174,16 +30171,17 @@ ukrigging.net, 1
 ukwct.org.uk, 1
 ulabox.com, 1
 ulalau.com, 1
 uli-eckhardt.de, 1
 ullah.se, 1
 ulrik.moe, 1
 ulti.gq, 1
 ultieme.be, 0
+ultima-ratio.at, 1
 ultimateanu.com, 1
 ultimatemafia.net, 1
 ultratechlp.com, 1
 umassfive.coop, 1
 umbricht.li, 1
 umenlisam.com, 1
 umisonoda.com, 1
 umkmjogja.com, 1
@@ -30374,46 +30372,43 @@ urban-karuizawa.co.jp, 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.net, 1
 urcentral.org, 1
 ureka.org, 1
 urgences-valais.ch, 1
 uripura.de, 1
 urist1011.ru, 1
 url.cab, 1
 url.fi, 1
 url.fm, 1
 url.rw, 1
-url0.eu, 1
 urlachershop.com.br, 1
 urlaub-leitner.at, 1
 urlscan.io, 1
 urology.wiki, 1
 urown.net, 1
 ursa-minor-beta.org, 1
 ursae.co, 1
 urspringer.de, 1
 ursuslibris.hu, 1
 urukproject.org, 1
 usaa.com, 0
 usabackground.com, 1
 usability.gov, 1
 usaestaonline.com, 1
-usafuelservice.com, 1
 usajobs.com, 1
 usajobs.gov, 1
 usakitchensandflooring.com, 1
 usap.gov, 0
 usbcraft.com, 1
 usbevents.co.uk, 1
 uscloud.nl, 1
 uscp8.com, 1
@@ -31064,17 +31059,17 @@ vorderklier.de, 1
 vorkbaard.nl, 1
 vorlicek.de, 1
 vorlif.org, 1
 vorm2.com, 1
 vorodevops.com, 1
 vos-fleurs.ch, 1
 vos-fleurs.com, 1
 vosgym.jp, 1
-voshod.org, 0
+voshod.org, 1
 vosky.fr, 1
 vostronet.com, 1
 voter-info.uk, 1
 votercircle.com, 1
 voterstartingpoint.uk, 1
 votocek.cz, 1
 votockova.cz, 1
 votoot.com, 1
@@ -32250,17 +32245,17 @@ www.intercom.io, 1
 www.irccloud.com, 0
 www.lastpass.com, 0
 www.linode.com, 0
 www.lookout.com, 0
 www.makeyourlaws.org, 1
 www.messenger.com, 1
 www.mydigipass.com, 0
 www.mylookout.com, 0
-www.noisebridge.net, 0
+www.noisebridge.net, 1
 www.opsmate.com, 1
 www.paypal.com, 0
 www.python.org, 1
 www.re, 1
 www.rememberthemilk.com, 1
 www.sb, 1
 www.simbolo.co.uk, 0
 www.simple.com, 0
@@ -32529,17 +32524,16 @@ xn--zettlmeil-n1a.de, 1
 xn5.de, 1
 xnaas.info, 1
 xnet-x.net, 1
 xng.io, 1
 xninja.xyz, 1
 xnode.org, 1
 xntrik.wtf, 1
 xo.tc, 1
-xoda.pw, 1
 xolphin.nl, 1
 xombitgames.com, 1
 xombitmusic.com, 1
 xonn.de, 1
 xotika.tv, 1
 xp2.de, 1
 xpd.se, 1
 xpenology-fr.net, 1
@@ -32730,16 +32724,17 @@ yinfor.com, 1
 ying299.com, 1
 ying299.net, 1
 yinga.ga, 1
 yingatech.com, 1
 yinglinda.love, 1
 yinlei.org, 1
 yiyuanzhong.com, 1
 yiz96.com, 1
+yjsoft.me, 1
 yjsw.sh.cn, 1
 yksityisyydensuoja.fi, 1
 ylilauta.org, 1
 ylinternal.com, 1
 ylk.io, 1
 ymarion.de, 1
 ymblaw.com, 1
 ympl.de, 1
--- a/taskcluster/ci/build/android.yml
+++ b/taskcluster/ci/build/android.yml
@@ -16,17 +16,17 @@ android-api-16/debug:
         artifacts:
             - name: public/android/R
               path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/app/R
               type: directory
             - name: public/android/maven
               path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview/maven/
               type: directory
             - name: public/build/geckoview_example.apk
-              path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/geckoview_example-withGeckoBinaries.apk
+              path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/officialWithGeckoBinariesNoMinApi/debug/geckoview_example-official-withGeckoBinaries-noMinApi-debug.apk
               type: file
             - name: public/build
               path: /builds/worker/artifacts/
               type: directory
     run:
         using: mozharness
         actions: [get-secrets build multi-l10n update]
         config:
@@ -68,17 +68,17 @@ android-x86/opt:
         artifacts:
             - name: public/android/R
               path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/app/R
               type: directory
             - name: public/android/maven
               path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview/maven/
               type: directory
             - name: public/build/geckoview_example.apk
-              path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/geckoview_example-withGeckoBinaries.apk
+              path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/officialWithGeckoBinariesNoMinApi/debug/geckoview_example-official-withGeckoBinaries-noMinApi-debug.apk
               type: file
             - name: public/build
               path: /builds/worker/artifacts/
               type: directory
     run:
         using: mozharness
         actions: [get-secrets build multi-l10n update]
         config:
@@ -125,17 +125,17 @@ android-x86-nightly/opt:
         artifacts:
             - name: public/android/R
               path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/app/R
               type: directory
             - name: public/android/maven
               path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview/maven/
               type: directory
             - name: public/build/geckoview_example.apk
-              path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/geckoview_example-withGeckoBinaries.apk
+              path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/officialWithGeckoBinariesNoMinApi/debug/geckoview_example-official-withGeckoBinaries-noMinApi-debug.apk
               type: file
             - name: public/build
               path: /builds/worker/artifacts/
               type: directory
     run:
         using: mozharness
         actions: [get-secrets build multi-l10n update]
         config:
@@ -173,17 +173,17 @@ android-api-16/opt:
         artifacts:
             - name: public/android/R
               path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/app/R
               type: directory
             - name: public/android/maven
               path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview/maven/
               type: directory
             - name: public/build/geckoview_example.apk
-              path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/geckoview_example-withGeckoBinaries.apk
+              path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/officialWithGeckoBinariesNoMinApi/debug/geckoview_example-official-withGeckoBinaries-noMinApi-debug.apk
               type: file
             - name: public/build
               path: /builds/worker/artifacts/
               type: directory
     run:
         using: mozharness
         actions: [get-secrets build multi-l10n update]
         config:
@@ -225,17 +225,17 @@ android-api-16-nightly/opt:
         artifacts:
             - name: public/android/R
               path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/app/R
               type: directory
             - name: public/android/maven
               path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview/maven/
               type: directory
             - name: public/build/geckoview_example.apk
-              path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/geckoview_example-withGeckoBinaries.apk
+              path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/officialWithGeckoBinariesNoMinApi/debug/geckoview_example-official-withGeckoBinaries-noMinApi-debug.apk
               type: file
             - name: public/build
               path: /builds/worker/artifacts/
               type: directory
     run:
         using: mozharness
         actions: [get-secrets build multi-l10n update]
         config:
@@ -278,17 +278,17 @@ android-x86-old-id/opt:
         artifacts:
             - name: public/android/R
               path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/app/R
               type: directory
             - name: public/android/maven
               path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview/maven/
               type: directory
             - name: public/build/geckoview_example.apk
-              path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/geckoview_example-withGeckoBinaries.apk
+              path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/officialWithGeckoBinariesNoMinApi/debug/geckoview_example-official-withGeckoBinaries-noMinApi-debug.apk
               type: file
             - name: public/build
               path: /builds/worker/artifacts/
               type: directory
     run:
         using: mozharness
         actions: [get-secrets build multi-l10n update]
         config:
@@ -334,17 +334,17 @@ android-x86-old-id-nightly/opt:
         artifacts:
             - name: public/android/R
               path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/app/R
               type: directory
             - name: public/android/maven
               path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview/maven/
               type: directory
             - name: public/build/geckoview_example.apk
-              path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/geckoview_example-withGeckoBinaries.apk
+              path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/officialWithGeckoBinariesNoMinApi/debug/geckoview_example-official-withGeckoBinaries-noMinApi-debug.apk
               type: file
             - name: public/build
               path: /builds/worker/artifacts/
               type: directory
     run:
         using: mozharness
         actions: [get-secrets build multi-l10n update]
         config:
@@ -383,17 +383,17 @@ android-api-16-old-id/opt:
         artifacts:
             - name: public/android/R
               path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/app/R
               type: directory
             - name: public/android/maven
               path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview/maven/
               type: directory
             - name: public/build/geckoview_example.apk
-              path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/geckoview_example-withGeckoBinaries.apk
+              path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/officialWithGeckoBinariesNoMinApi/debug/geckoview_example-official-withGeckoBinaries-noMinApi-debug.apk
               type: file
             - name: public/build
               path: /builds/worker/artifacts/
               type: directory
     run:
         using: mozharness
         actions: [get-secrets build multi-l10n update]
         config:
@@ -434,17 +434,17 @@ android-api-16-old-id-nightly/opt:
         artifacts:
             - name: public/android/R
               path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/app/R
               type: directory
             - name: public/android/maven
               path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview/maven/
               type: directory
             - name: public/build/geckoview_example.apk
-              path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/geckoview_example-withGeckoBinaries.apk
+              path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/officialWithGeckoBinariesNoMinApi/debug/geckoview_example-official-withGeckoBinaries-noMinApi-debug.apk
               type: file
             - name: public/build
               path: /builds/worker/artifacts/
               type: directory
     run:
         using: mozharness
         actions: [get-secrets build multi-l10n update]
         config:
@@ -483,17 +483,17 @@ android-api-16-gradle/opt:
         artifacts:
             - name: public/android/R
               path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/app/R
               type: directory
             - name: public/android/maven
               path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview/maven/
               type: directory
             - name: public/build/geckoview_example.apk
-              path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/geckoview_example-withGeckoBinaries.apk
+              path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/officialWithGeckoBinariesNoMinApi/debug/geckoview_example-official-withGeckoBinaries-noMinApi-debug.apk
               type: file
             - name: public/build
               path: /builds/worker/artifacts/
               type: directory
     run:
         using: mozharness
         actions: [get-secrets build multi-l10n update]
         config:
@@ -529,17 +529,17 @@ android-aarch64/opt:
         artifacts:
             - name: public/android/R
               path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/app/R
               type: directory
             - name: public/android/maven
               path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview/maven/
               type: directory
             - name: public/build/geckoview_example.apk
-              path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/geckoview_example-withGeckoBinaries.apk
+              path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/officialWithGeckoBinariesNoMinApi/debug/geckoview_example-official-withGeckoBinaries-noMinApi-debug.apk
               type: file
             - name: public/build
               path: /builds/worker/artifacts/
               type: directory
     run:
         using: mozharness
         actions: [get-secrets build multi-l10n update]
         config:
@@ -581,17 +581,17 @@ android-aarch64-nightly/opt:
         artifacts:
             - name: public/android/R
               path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/app/R
               type: directory
             - name: public/android/maven
               path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview/maven/
               type: directory
             - name: public/build/geckoview_example.apk
-              path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/geckoview_example-withGeckoBinaries.apk
+              path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/officialWithGeckoBinariesNoMinApi/debug/geckoview_example-official-withGeckoBinaries-noMinApi-debug.apk
               type: file
             - name: public/build
               path: /builds/worker/artifacts/
               type: directory
     run:
         using: mozharness
         actions: [get-secrets build multi-l10n update]
         config:
--- a/taskcluster/scripts/misc/android-gradle-dependencies/after.sh
+++ b/taskcluster/scripts/misc/android-gradle-dependencies/after.sh
@@ -1,16 +1,16 @@
 #!/bin/bash -vex
 
 set -x -e
 
 echo "running as" $(id)
 
 : WORKSPACE ${WORKSPACE:=/builds/worker/workspace}
-: GRADLE_VERSION ${GRADLE_VERSION:=3.4.1}
+: GRADLE_VERSION ${GRADLE_VERSION:=4.1}
 
 set -v
 
 # Package everything up.
 pushd $WORKSPACE
 mkdir -p android-gradle-dependencies /builds/worker/artifacts
 
 cp -R ${NEXUS_WORK}/storage/jcenter android-gradle-dependencies
--- a/taskcluster/scripts/misc/android-gradle-dependencies/nexus.xml
+++ b/taskcluster/scripts/misc/android-gradle-dependencies/nexus.xml
@@ -67,17 +67,18 @@
       <localStorage>
         <provider>file</provider>
       </localStorage>
       <remoteStorage>
         <url>https://maven.google.com/</url>
       </remoteStorage>
       <externalConfiguration>
         <repositoryPolicy>RELEASE</repositoryPolicy>
-        <checksumPolicy>STRICT</checksumPolicy>
+        <!-- Google doesn't publish checksums.  Why, Google, why? -->
+        <checksumPolicy>STRICT_IF_EXISTS</checksumPolicy>
         <fileTypeValidation>true</fileTypeValidation>
         <downloadRemoteIndex>false</downloadRemoteIndex>
         <artifactMaxAge>-1</artifactMaxAge>
         <metadataMaxAge>1440</metadataMaxAge>
         <itemMaxAge>1440</itemMaxAge>
         <autoBlockActive>true</autoBlockActive>
       </externalConfiguration>
     </repository>
--- a/testing/marionette/driver.js
+++ b/testing/marionette/driver.js
@@ -2762,23 +2762,18 @@ GeckoDriver.prototype.closeChromeWindow 
 };
 
 /** Delete Marionette session. */
 GeckoDriver.prototype.deleteSession = function() {
   if (this.curBrowser !== null) {
     // frame scripts can be safely reused
     Preferences.set(CONTENT_LISTENER_PREF, false);
 
-    // clean up state in each frame in each browser
-    for (let win in this.browsers) {
-      let browser = this.browsers[win];
-      browser.knownFrames.forEach(() => {
-        globalMessageManager.broadcastAsyncMessage("Marionette:Deregister");
-      });
-    }
+    globalMessageManager.broadcastAsyncMessage("Marionette:Session:Delete");
+    globalMessageManager.broadcastAsyncMessage("Marionette:Deregister");
 
     for (let win of this.windows) {
       if (win.messageManager) {
         win.messageManager.removeDelayedFrameScript(FRAME_SCRIPT);
       } else {
         logger.error(
             `Could not remove listener from page ${win.location.href}`);
       }
--- a/testing/marionette/listener.js
+++ b/testing/marionette/listener.js
@@ -41,17 +41,16 @@ const {ContentEventObserverService} = Cu
 Cu.import("chrome://marionette/content/interaction.js");
 Cu.import("chrome://marionette/content/legacyaction.js");
 Cu.import("chrome://marionette/content/navigate.js");
 Cu.import("chrome://marionette/content/proxy.js");
 Cu.import("chrome://marionette/content/session.js");
 
 Cu.importGlobalProperties(["URL"]);
 
-let outerWindowID = null;
 let curContainer = {frame: content, shadowRoot: null};
 
 // Listen for click event to indicate one click has happened, so actions
 // code can send dblclick event, also resetClick and cancelTimer
 // after dblclick has happened.
 addEventListener("click", event.DoubleClickTracker.setClick);
 addEventListener("dblclick", event.DoubleClickTracker.resetClick);
 addEventListener("dblclick", event.DoubleClickTracker.cancelTimer);
@@ -442,32 +441,34 @@ const loadListener = {
 };
 
 /**
  * Called when listener is first started up.  The listener sends its
  * unique window ID and its current URI to the actor.  If the actor returns
  * an ID, we start the listeners. Otherwise, nothing happens.
  */
 function registerSelf() {
-  outerWindowID = winUtil.outerWindowID;
+  let {outerWindowID} = winUtil;
   logger.debug(`Register listener.js for window ${outerWindowID}`);
 
   sandboxes.clear();
   curContainer = {
     frame: content,
     shadowRoot: null,
   };
   legacyactions.mouseEventsOnly = false;
   action.inputStateMap = new Map();
   action.inputsToCancel = [];
 
-  // register will have the ID and a boolean describing if this is the
-  // main process or not
-  let register = sendSyncMessage("Marionette:Register", {outerWindowID});
-  if (register[0].outerWindowID === outerWindowID) {
+  let reply = sendSyncMessage("Marionette:Register", {outerWindowID});
+  if (reply.length == 0) {
+    logger.error("No reply from Marionette:Register");
+  }
+
+  if (reply[0].outerWindowID === outerWindowID) {
     startListeners();
     sendAsyncMessage("Marionette:ListenersAttached", {outerWindowID});
   }
 }
 
 // Eventually we will not have a closure for every single command,
 // but use a generic dispatch for all listener commands.
 //
@@ -552,16 +553,17 @@ function startListeners() {
   addMessageListener("Marionette:isElementEnabled", isElementEnabledFn);
   addMessageListener("Marionette:isElementSelected", isElementSelectedFn);
   addMessageListener("Marionette:multiAction", multiActionFn);
   addMessageListener("Marionette:performActions", performActionsFn);
   addMessageListener("Marionette:refresh", refresh);
   addMessageListener("Marionette:reftestWait", reftestWaitFn);
   addMessageListener("Marionette:releaseActions", releaseActionsFn);
   addMessageListener("Marionette:sendKeysToElement", sendKeysToElementFn);
+  addMessageListener("Marionette:Session:Delete", deleteSession);
   addMessageListener("Marionette:singleTap", singleTapFn);
   addMessageListener("Marionette:switchToFrame", switchToFrame);
   addMessageListener("Marionette:switchToParentFrame", switchToParentFrame);
   addMessageListener("Marionette:switchToShadowRoot", switchToShadowRootFn);
   addMessageListener("Marionette:takeScreenshot", takeScreenshotFn);
   addMessageListener("Marionette:waitForPageLoaded", waitForPageLoaded);
 }
 
@@ -589,23 +591,26 @@ function deregister() {
   removeMessageListener("Marionette:isElementDisplayed", isElementDisplayedFn);
   removeMessageListener("Marionette:isElementEnabled", isElementEnabledFn);
   removeMessageListener("Marionette:isElementSelected", isElementSelectedFn);
   removeMessageListener("Marionette:multiAction", multiActionFn);
   removeMessageListener("Marionette:performActions", performActionsFn);
   removeMessageListener("Marionette:refresh", refresh);
   removeMessageListener("Marionette:releaseActions", releaseActionsFn);
   removeMessageListener("Marionette:sendKeysToElement", sendKeysToElementFn);
+  removeMessageListener("Marionette:Session:Delete", deleteSession);
   removeMessageListener("Marionette:singleTap", singleTapFn);
   removeMessageListener("Marionette:switchToFrame", switchToFrame);
   removeMessageListener("Marionette:switchToParentFrame", switchToParentFrame);
   removeMessageListener("Marionette:switchToShadowRoot", switchToShadowRootFn);
   removeMessageListener("Marionette:takeScreenshot", takeScreenshotFn);
   removeMessageListener("Marionette:waitForPageLoaded", waitForPageLoaded);
+}
 
+function deleteSession() {
   seenEls.clear();
   // reset container frame to the top-most frame
   curContainer = {frame: content, shadowRoot: null};
   curContainer.frame.focus();
   legacyactions.touchIds = {};
   if (action.inputStateMap !== undefined) {
     action.inputStateMap.clear();
   }
--- a/toolkit/content/jar.mn
+++ b/toolkit/content/jar.mn
@@ -52,17 +52,19 @@ toolkit.jar:
    content/global/process-content.js
    content/global/resetProfile.css
    content/global/resetProfile.js
    content/global/resetProfile.xul
    content/global/resetProfileProgress.xul
    content/global/TopLevelVideoDocument.js
    content/global/timepicker.xhtml
    content/global/treeUtils.js
+#ifndef MOZ_FENNEC
    content/global/viewZoomOverlay.js
+#endif
    content/global/bindings/autocomplete.xml    (widgets/autocomplete.xml)
    content/global/bindings/browser.xml         (widgets/browser.xml)
    content/global/bindings/button.xml          (widgets/button.xml)
    content/global/bindings/calendar.js         (widgets/calendar.js)
    content/global/bindings/checkbox.xml        (widgets/checkbox.xml)
    content/global/bindings/colorpicker.xml     (widgets/colorpicker.xml)
    content/global/bindings/datekeeper.js       (widgets/datekeeper.js)
    content/global/bindings/datepicker.js       (widgets/datepicker.js)
--- a/toolkit/library/moz.build
+++ b/toolkit/library/moz.build
@@ -136,16 +136,21 @@ if CONFIG['USE_ICU']:
         'icu',
     ]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk3':
     USE_LIBS += [
         'mozgtk_stub',
     ]
 
+if CONFIG['MOZ_WAYLAND']:
+    USE_LIBS += [
+        'mozwayland',
+    ]
+
 if CONFIG['MOZ_JPROF']:
     USE_LIBS += [
         'jprof',
     ]
 
 if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT'] or \
         CONFIG['MOZ_TREE_FREETYPE']:
     USE_LIBS += [
--- a/widget/gtk/WindowSurfaceProvider.cpp
+++ b/widget/gtk/WindowSurfaceProvider.cpp
@@ -51,17 +51,17 @@ void WindowSurfaceProvider::Initialize(
   mXVisual = aVisual;
   mXDepth = aDepth;
   mIsX11Display = true;
 }
 
 #ifdef MOZ_WAYLAND
 void WindowSurfaceProvider::Initialize(nsWindow *aWidget)
 {
-  MOZ_ASSERT(!aWidget->IsX11Display(),
+  MOZ_ASSERT(aWidget->GetWaylandDisplay(),
              "We are supposed to have a Wayland display!");
 
   mWidget = aWidget;
   mIsX11Display = false;
 }
 #endif
 
 void WindowSurfaceProvider::CleanupResources()
--- a/widget/gtk/WindowSurfaceWayland.cpp
+++ b/widget/gtk/WindowSurfaceWayland.cpp
@@ -215,17 +215,20 @@ static void
 WaylandDisplayLoopLocked(wl_display* aDisplay,
                          const StaticMutexAutoLock&)
 {
   int len = gWaylandDisplays.Count();
   for (int i = 0; i < len; i++) {
     if (gWaylandDisplays[i]->Matches(aDisplay)) {
       if (gWaylandDisplays[i]->DisplayLoop()) {
         MessageLoop::current()->PostDelayedTask(
-            NewRunnableFunction(&WaylandDisplayLoop, aDisplay), EVENT_LOOP_DELAY);
+            NewRunnableFunction("WaylandDisplayLoop",
+                               &WaylandDisplayLoop,
+                               aDisplay),
+            EVENT_LOOP_DELAY);
       }
       break;
     }
   }
 }
 
 static void
 WaylandDisplayLoop(wl_display* aDisplay)
@@ -266,16 +269,17 @@ nsWaylandDisplay::GetShm()
   if (!mShm) {
     // wl_shm is not provided by Gtk so we need to query wayland directly
     // See weston/simple-shm.c and create_display() for reference.
     wl_registry* registry = wl_display_get_registry(mDisplay);
     wl_registry_add_listener(registry, &registry_listener, this);
 
     wl_proxy_set_queue((struct wl_proxy *)registry, mEventQueue);
     wl_display_roundtrip_queue(mDisplay, mEventQueue);
+
     MOZ_RELEASE_ASSERT(mShm, "Wayland registry query failed!");
   }
 
   return(mShm);
 }
 
 bool
 nsWaylandDisplay::DisplayLoop()
@@ -300,18 +304,18 @@ nsWaylandDisplay::nsWaylandDisplay(wl_di
   , mShm(nullptr)
   , mDisplay(aDisplay)
 {
   if (NS_IsMainThread()) {
     // Use default event queue in main thread operated by Gtk+.
     mEventQueue = nullptr;
   } else {
     mEventQueue = wl_display_create_queue(mDisplay);
-    MessageLoop::current()->PostTask(NewRunnableFunction(&WaylandDisplayLoop,
-                                                         mDisplay));
+    MessageLoop::current()->PostTask(NewRunnableFunction(
+        "WaylandDisplayLoop", &WaylandDisplayLoop, mDisplay));
   }
 }
 
 nsWaylandDisplay::~nsWaylandDisplay()
 {
   MOZ_ASSERT(mThreadId == PR_GetCurrentThread());
   // Owned by Gtk+, we don't need to release
   mDisplay = nullptr;
@@ -572,17 +576,19 @@ WindowSurfaceWayland::~WindowSurfaceWayl
     wl_callback_destroy(mFrameCallback);
   }
 
   if (!mIsMainThread) {
     // We can be destroyed from main thread even though we was created/used
     // in compositor thread. We have to unref/delete WaylandDisplay in compositor
     // thread then and we can't use MessageLoop::current() here.
     mDisplayThreadMessageLoop->PostTask(
-      NewRunnableFunction(&WaylandDisplayRelease, mWaylandDisplay->GetDisplay()));
+      NewRunnableFunction("WaylandDisplayRelease",
+                          &WaylandDisplayRelease,
+                          mWaylandDisplay->GetDisplay()));
   } else {
     WaylandDisplayRelease(mWaylandDisplay->GetDisplay());
   }
 }
 
 WindowBackBuffer*
 WindowSurfaceWayland::GetBufferToDraw(int aWidth, int aHeight)
 {
--- a/widget/gtk/moz.build
+++ b/widget/gtk/moz.build
@@ -11,16 +11,22 @@ with Files("*CompositorWidget*"):
     BUG_COMPONENT = ("Core", "Graphics")
 
 with Files("*WindowSurface*"):
     BUG_COMPONENT = ("Core", "Graphics")
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk3':
     DIRS += ['mozgtk']
 
+if CONFIG['MOZ_WAYLAND']:
+    if CONFIG['GLIB_LIBS']:
+        DIRS += ['mozwayland']
+    else:
+        error('We support Wayland on glibc systems only, see Bug 1409707 for reference.')
+
 EXPORTS += [
     'mozcontainer.h',
     'nsGTKToolkit.h',
     'nsIImageToPixbuf.h',
 ]
 
 EXPORTS.mozilla += [
     'WidgetUtilsGtk.h'
--- a/widget/gtk/mozcontainer.cpp
+++ b/widget/gtk/mozcontainer.cpp
@@ -7,16 +7,17 @@
 
 #include "mozcontainer.h"
 #include <gtk/gtk.h>
 #ifdef MOZ_WAYLAND
 #include <gdk/gdkx.h>
 #include <gdk/gdkwayland.h>
 #endif
 #include <stdio.h>
+#include <dlfcn.h>
 
 #ifdef ACCESSIBILITY
 #include <atk/atk.h>
 #include "maiRedundantObjectFactory.h"
 #endif
 
 /* init methods */
 static void moz_container_class_init          (MozContainerClass *klass);
@@ -203,17 +204,22 @@ moz_container_init (MozContainer *contai
     gtk_widget_set_can_focus(GTK_WIDGET(container), TRUE);
     gtk_container_set_resize_mode(GTK_CONTAINER(container), GTK_RESIZE_IMMEDIATE);
     gtk_widget_set_redraw_on_allocate(GTK_WIDGET(container), FALSE);
 
 #if defined(MOZ_WAYLAND)
     {
       GdkDisplay *gdk_display = gtk_widget_get_display(GTK_WIDGET(container));
       if (GDK_IS_WAYLAND_DISPLAY (gdk_display)) {
-          wl_display* display = gdk_wayland_display_get_wl_display(gdk_display);
+          // Available as of GTK 3.8+
+          static auto sGdkWaylandDisplayGetWlDisplay =
+              (wl_display *(*)(GdkDisplay *))
+              dlsym(RTLD_DEFAULT, "gdk_wayland_display_get_wl_display");
+
+          wl_display* display = sGdkWaylandDisplayGetWlDisplay(gdk_display);
           wl_registry* registry = wl_display_get_registry(display);
           wl_registry_add_listener(registry, &registry_listener, container);
           wl_display_dispatch(display);
           wl_display_roundtrip(display);
         }
     }
 #endif
 }
@@ -224,32 +230,40 @@ moz_container_init (MozContainer *contai
  * and attach it as an overlay to GdkWindow.
  *
  * see gtk_clutter_embed_ensure_subsurface() at gtk-clutter-embed.c
 *  for reference.
  */
 static gboolean
 moz_container_map_surface(MozContainer *container)
 {
+    // Available as of GTK 3.8+
+    static auto sGdkWaylandDisplayGetWlCompositor =
+        (wl_compositor *(*)(GdkDisplay *))
+        dlsym(RTLD_DEFAULT, "gdk_wayland_display_get_wl_compositor");
+    static auto sGdkWaylandWindowGetWlSurface =
+        (wl_surface *(*)(GdkWindow *))
+        dlsym(RTLD_DEFAULT, "gdk_wayland_window_get_wl_surface");
+
     GdkDisplay *display = gtk_widget_get_display(GTK_WIDGET(container));
     if (GDK_IS_X11_DISPLAY(display))
         return false;
 
     if (container->subsurface && container->surface)
         return true;