merge mozilla-inbound to mozilla-central. r=merge a=merge
authorSebastian Hengst <archaeopteryx@coole-files.de>
Thu, 05 Oct 2017 10:55:31 +0200
changeset 384650 53bbdaaa2b8c1819061be26101b075c081b23260
parent 384632 66042a70698006d3371c87e092a2c25a80584320 (current diff)
parent 384649 4a84d687f1d2d943a41a0f8b048261f5f0efd6f4 (diff)
child 384651 19b32a138d08f73961df878a29de6f0aad441683
child 384677 b25870b6590be5e881987ec7092be735e668ee80
child 384781 d31bc8ceaebf51ebb1ddb0ffa38c28295f9dbeaa
push id32632
push userarchaeopteryx@coole-files.de
push dateThu, 05 Oct 2017 08:56:01 +0000
treeherdermozilla-central@53bbdaaa2b8c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge, merge
milestone58.0a1
first release with
nightly linux32
53bbdaaa2b8c / 58.0a1 / 20171005100211 / files
nightly linux64
53bbdaaa2b8c / 58.0a1 / 20171005100211 / files
nightly mac
53bbdaaa2b8c / 58.0a1 / 20171005100211 / files
nightly win32
53bbdaaa2b8c / 58.0a1 / 20171005100211 / files
nightly win64
53bbdaaa2b8c / 58.0a1 / 20171005100211 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
merge mozilla-inbound to mozilla-central. r=merge a=merge MozReview-Commit-ID: CsjtXJM2vcs
gfx/webrender_bindings/WebRenderAPI.cpp
gfx/webrender_bindings/WebRenderAPI.h
gfx/webrender_bindings/src/bindings.rs
gfx/webrender_bindings/webrender_ffi_generated.h
layout/painting/nsDisplayList.cpp
toolkit/modules/addons/MatchPattern.jsm
toolkit/modules/tests/xpcshell/test_MatchGlobs.js
toolkit/modules/tests/xpcshell/test_MatchPattern.js
--- a/browser/themes/shared/places/bookmarksMenu.svg
+++ b/browser/themes/shared/places/bookmarksMenu.svg
@@ -1,9 +1,9 @@
 <!-- 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 width="16" height="16" viewBox="0 0 16 16" fill="context-fill" xmlns="http://www.w3.org/2000/svg">
+<svg width="16" height="16" viewBox="0 0 16 16" fill="context-fill" fill-opacity="context-fill-opacity" xmlns="http://www.w3.org/2000/svg">
   <path fill-opacity=".05" d="M15,2H1v12c0,0.6,0.5,1,1,1h12c0.6,0,1-0.4,1-1V2L15,2z"/>
   <path d="M3,5v1h2V5H3z M3,9h2V8H3V9z M3,12h2v-1H3V12z"/>
   <path fill-opacity=".9" d="M6,5v1h7V5H6z M12,8H6v1h6V8z M6,12h7v-1H6V12z"/>
   <path d="M7,2V1H1v1v1v11c0,0.5,0.5,1,1,1h12c0.5,0,1-0.5,1-1V2H7z M13.5,14h-11C2.2,14,2,13.8,2,13.5V3h12v10.5 C14,13.8,13.8,14,13.5,14z"/>
 </svg>
--- a/browser/themes/shared/places/bookmarksToolbar.svg
+++ b/browser/themes/shared/places/bookmarksToolbar.svg
@@ -1,8 +1,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/. -->
-<svg width="16" height="16" viewBox="0 0 16 16" fill="context-fill" xmlns="http://www.w3.org/2000/svg">
+<svg width="16" height="16" viewBox="0 0 16 16" fill="context-fill" fill-opacity="context-fill-opacity" xmlns="http://www.w3.org/2000/svg">
   <path fill-opacity=".15" d="M15,14H1c-0.6,0-1-0.4-1-1V3c0-0.5,0.4-1,1-1h14c0.6,0,1,0.5,1,1v10C16,13.6,15.6,14,15,14z"/>
   <path d="M8.4,4.2l1,2.1l2.3,0.3c0.3,0,0.5,0.4,0.2,0.7l-1.7,1.7l0.4,2.4c0.1,0.3-0.3,0.6-0.6,0.4L8,10.8L6,12 c-0.3,0.1-0.6-0.1-0.6-0.4l0.4-2.4L4.1,7.4C3.9,7.2,4,6.8,4.3,6.7l2.3-0.3l1-2.1C7.8,3.9,8.2,3.9,8.4,4.2z"/>
   <path d="M15,2H1C0.5,2,0,2.5,0,3v10c0,0.5,0.5,1,1,1h14c0.5,0,1-0.5,1-1V3C16,2.5,15.5,2,15,2z M15,12.5 c0,0.3-0.2,0.5-0.5,0.5h-13C1.2,13,1,12.8,1,12.5v-9C1,3.2,1.2,3,1.5,3h13C14.8,3,15,3.2,15,3.5V12.5z"/>
 </svg>
--- a/browser/themes/shared/places/folder-live.svg
+++ b/browser/themes/shared/places/folder-live.svg
@@ -1,6 +1,6 @@
 <!-- This Source Code Form is subject to the terms of the Mozilla Public
    - License, v. 2.0. If a copy of the MPL was not distributed with this
    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-  <path fill="context-fill" d="M3.5,10A2.5,2.5,0,1,0,6,12.5,2.5,2.5,0,0,0,3.5,10ZM2,1A1,1,0,0,0,2,3,10.883,10.883,0,0,1,13,14a1,1,0,0,0,2,0A12.862,12.862,0,0,0,2,1ZM2,5A1,1,0,0,0,2,7a6.926,6.926,0,0,1,7,7,1,1,0,0,0,2,0A8.9,8.9,0,0,0,2,5Z"/>
+<svg width="16" height="16" viewBox="0 0 16 16" fill="context-fill" fill-opacity="context-fill-opacity" xmlns="http://www.w3.org/2000/svg">
+  <path d="M3.5,10A2.5,2.5,0,1,0,6,12.5,2.5,2.5,0,0,0,3.5,10ZM2,1A1,1,0,0,0,2,3,10.883,10.883,0,0,1,13,14a1,1,0,0,0,2,0A12.862,12.862,0,0,0,2,1ZM2,5A1,1,0,0,0,2,7a6.926,6.926,0,0,1,7,7,1,1,0,0,0,2,0A8.9,8.9,0,0,0,2,5Z"/>
 </svg>
--- a/browser/themes/shared/places/folder-smart.svg
+++ b/browser/themes/shared/places/folder-smart.svg
@@ -1,6 +1,6 @@
 <!-- This Source Code Form is subject to the terms of the Mozilla Public
    - License, v. 2.0. If a copy of the MPL was not distributed with this
    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-  <path fill="context-fill" d="M14,7H12.9a4.967,4.967,0,0,0-.732-1.753l.782-.783A1,1,0,1,0,11.535,3.05l-.782.783A4.968,4.968,0,0,0,9,3.1V2A1,1,0,0,0,7,2V3.1a4.968,4.968,0,0,0-1.753.732L4.464,3.05A1,1,0,0,0,3.05,4.464l.783.783A4.968,4.968,0,0,0,3.1,7H2A1,1,0,0,0,2,9H3.1a4.968,4.968,0,0,0,.732,1.753l-.783.782a1,1,0,1,0,1.414,1.414l.783-.782A4.967,4.967,0,0,0,7,12.9V14a1,1,0,0,0,2,0V12.9a4.968,4.968,0,0,0,1.753-.732l.782.782a1,1,0,0,0,1.414-1.414l-.782-.782A4.968,4.968,0,0,0,12.9,9H14a1,1,0,0,0,0-2ZM8,11a3,3,0,1,1,3-3A3,3,0,0,1,8,11Z"/>
+<svg width="16" height="16" viewBox="0 0 16 16" fill="context-fill" fill-opacity="context-fill-opacity" xmlns="http://www.w3.org/2000/svg">
+  <path  d="M14,7H12.9a4.967,4.967,0,0,0-.732-1.753l.782-.783A1,1,0,1,0,11.535,3.05l-.782.783A4.968,4.968,0,0,0,9,3.1V2A1,1,0,0,0,7,2V3.1a4.968,4.968,0,0,0-1.753.732L4.464,3.05A1,1,0,0,0,3.05,4.464l.783.783A4.968,4.968,0,0,0,3.1,7H2A1,1,0,0,0,2,9H3.1a4.968,4.968,0,0,0,.732,1.753l-.783.782a1,1,0,1,0,1.414,1.414l.783-.782A4.967,4.967,0,0,0,7,12.9V14a1,1,0,0,0,2,0V12.9a4.968,4.968,0,0,0,1.753-.732l.782.782a1,1,0,0,0,1.414-1.414l-.782-.782A4.968,4.968,0,0,0,12.9,9H14a1,1,0,0,0,0-2ZM8,11a3,3,0,1,1,3-3A3,3,0,0,1,8,11Z"/>
 </svg>
--- a/browser/themes/shared/places/folder.svg
+++ b/browser/themes/shared/places/folder.svg
@@ -1,10 +1,10 @@
 <!-- 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 width="16" height="16" viewBox="0 0 16 16" fill="context-fill" xmlns="http://www.w3.org/2000/svg">
+<svg width="16" height="16" viewBox="0 0 16 16" fill="context-fill" fill-opacity="context-fill-opacity" xmlns="http://www.w3.org/2000/svg">
   <path fill-opacity=".15" d="M5,1H1C0.4,1,0,1.4,0,2v12.1C0,14.6,0.4,15,0.9,15h14.2c0.5,0,0.9-0.4,0.9-0.9V3.9C16,3.4,15.6,3,15.1,3H7 L6.2,1.9C6.2,1.9,5.6,1,5,1L5,1z"/>
   <path d="M4.9,2C5,2.1,5.2,2.3,5.4,2.5l0.8,1.1L6.5,4H7h7.5C14.8,4,15,4.2,15,4.5v9c0,0.3-0.2,0.5-0.5,0.5h-13 C1.2,14,1,13.8,1,13.5v-11C1,2.2,1.2,2,1.5,2H4.9 M5,1H1C0.4,1,0,1.4,0,2v12.1C0,14.6,0.4,15,0.9,15h14.2c0.5,0,0.9-0.4,0.9-0.9V3.9 C16,3.4,15.6,3,15.1,3H7L6.2,1.9C6.2,1.9,5.6,1,5,1L5,1z"/>
   <path fill-opacity=".15" d="M14,5H2C0.9,5,0,5.9,0,7v7c0,0.6,0.4,1,1,1h14c0.6,0,1-0.4,1-1V7C16,5.9,15.1,5,14,5L14,5z"/>
   <path fill-opacity=".15" d="M16,13H0v1c0,0.6,0.4,1,1,1h14c0.6,0,1-0.4,1-1V13z"/>
   <path d="M14,6c0.6,0,1,0.4,1,1v6.5c0,0.3-0.2,0.5-0.5,0.5h-13C1.2,14,1,13.8,1,13.5V7c0-0.6,0.4-1,1-1H14 M14,5H2 C0.9,5,0,5.9,0,7v7c0,0.6,0.4,1,1,1h14c0.6,0,1-0.4,1-1V7C16,5.9,15.1,5,14,5L14,5z"/>
 </svg>
--- a/browser/themes/shared/places/unfiledBookmarks.svg
+++ b/browser/themes/shared/places/unfiledBookmarks.svg
@@ -1,9 +1,9 @@
 <!-- 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 width="16" height="16" viewBox="0 0 16 16" fill="context-fill" xmlns="http://www.w3.org/2000/svg">
+<svg width="16" height="16" viewBox="0 0 16 16" fill="context-fill" fill-opacity="context-fill-opacity" xmlns="http://www.w3.org/2000/svg">
   <path fill-opacity=".05" d="M12.7,1H3.3l-.2.6L.1,9,0,9.2V13a2.006,2.006,0,0,0,2,2H14a2.006,2.006,0,0,0,2-2V9.2L15.9,9l-3-7.4L12.7,1Z"/>
   <path d="M12,2l3,7.4V13a.945.945,0,0,1-1,1H2a.945.945,0,0,1-1-1V9.4L4,2h8m.7-1H3.3L.1,9.1,0,9.2V13a2.006,2.006,0,0,0,2,2H14a2.006,2.006,0,0,0,2-2V9.2L15.9,9,12.7,1Z"/>
   <path fill-opacity=".05" d="M14.988,9,12,2H4L.851,9H5.023A2.931,2.931,0,0,0,8,11.6,2.889,2.889,0,0,0,11.012,9Z"/>
   <path d="M10,9A2,2,0,0,1,6,9H0v1H5.184a2.983,2.983,0,0,0,5.633,0H16V9Z"/>
 </svg>
--- a/browser/themes/shared/toolbarbutton-icons.inc.css
+++ b/browser/themes/shared/toolbarbutton-icons.inc.css
@@ -521,18 +521,19 @@ toolbar[brighttext] {
   animation-duration: 2s;
   animation-timing-function: ease-out;
 }
 
 /* ----- BOOKMARK BUTTONS ----- */
 
 .bookmark-item {
   list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.svg");
-  -moz-context-properties: fill;
+  -moz-context-properties: fill, fill-opacity;
   fill: currentColor;
+  fill-opacity: var(--toolbarbutton-icon-fill-opacity);
 }
 
 .bookmark-item[container] {
   list-style-image: url("chrome://browser/skin/places/folder.svg");
 }
 
 .bookmark-item[container][livemark] {
   list-style-image: url("chrome://browser/skin/places/folder-live.svg");
--- a/build/build-clang/build-clang.py
+++ b/build/build-clang/build-clang.py
@@ -253,16 +253,17 @@ def get_tool(config, key):
 # This function is intended to be called on the final build directory when
 # building clang-tidy.  Its job is to remove all of the files which won't
 # be used for clang-tidy to reduce the download size.  Currently when this
 # function finishes its job, it will leave final_dir with a layout like this:
 #
 # clang/
 #   bin/
 #     clang-tidy
+#     clang-apply-replacements
 #   include/
 #     * (nothing will be deleted here)
 #   lib/
 #     clang/
 #       4.0.0/
 #         include/
 #           * (nothing will be deleted here)
 #   share/
@@ -273,18 +274,20 @@ def prune_final_dir_for_clang_tidy(final
     # Make sure we only have what we expect.
     dirs = ("bin", "include", "lib", "libexec", "msbuild-bin", "share", "tools")
     for f in glob.glob("%s/*" % final_dir):
         if os.path.basename(f) not in dirs:
             raise Exception("Found unknown file %s in the final directory" % f)
         if not os.path.isdir(f):
             raise Exception("Expected %s to be a directory" %f)
 
-    # In bin/, only keep clang-tidy.
-    re_clang_tidy = re.compile(r"^clang-tidy(\.exe)?$", re.I)
+    # In bin/, only keep clang-tidy and clang-apply-replacements. The last one
+    # is used to auto-fix some of the issues detected by clang-tidy.
+    re_clang_tidy = re.compile(
+        r"^clang-(tidy|apply-replacements)(\.exe)?$", re.I)
     for f in glob.glob("%s/bin/*" % final_dir):
         if re_clang_tidy.search(os.path.basename(f)) is None:
             delete(f)
 
     # Keep include/ intact.
 
     # In lib/, only keep lib/clang/N.M.O/include.
     re_ver_num = re.compile(r"^\d+\.\d+\.\d+$", re.I)
--- a/devtools/client/preferences/devtools.js
+++ b/devtools/client/preferences/devtools.js
@@ -54,17 +54,17 @@ pref("devtools.inspector.show_pseudo_ele
 pref("devtools.inspector.imagePreviewTooltipSize", 300);
 // Enable user agent style inspection in rule-view
 pref("devtools.inspector.showUserAgentStyles", false);
 // Show all native anonymous content (like controls in <video> tags)
 pref("devtools.inspector.showAllAnonymousContent", false);
 // Enable the new color widget
 pref("devtools.inspector.colorWidget.enabled", false);
 // Enable the CSS shapes highlighter
-pref("devtools.inspector.shapesHighlighter.enabled", false);
+pref("devtools.inspector.shapesHighlighter.enabled", true);
 
 // Enable the Font Inspector
 pref("devtools.fontinspector.enabled", true);
 
 // Counter to promote the inspector layout view.
 // @remove after release 56 (See Bug 1355747)
 pref("devtools.promote.layoutview", 1);
 // Whether or not to show the promote bar in the layout view
--- a/devtools/client/shared/output-parser.js
+++ b/devtools/client/shared/output-parser.js
@@ -24,16 +24,17 @@ const Services = require("Services");
 
 const STYLE_INSPECTOR_PROPERTIES = "devtools/shared/locales/styleinspector.properties";
 const {LocalizationHelper} = require("devtools/shared/l10n");
 const STYLE_INSPECTOR_L10N = new LocalizationHelper(STYLE_INSPECTOR_PROPERTIES);
 
 const HTML_NS = "http://www.w3.org/1999/xhtml";
 const CSS_GRID_ENABLED_PREF = "layout.css.grid.enabled";
 const CSS_SHAPES_ENABLED_PREF = "devtools.inspector.shapesHighlighter.enabled";
+const CSS_SHAPE_OUTSIDE_ENABLED_PREF = "layout.css.shape-outside.enabled";
 
 /**
  * This module is used to process text for output by developer tools. This means
  * linking JS files with the debugger, CSS files with the style editor, JS
  * functions with the debugger, placing color swatches next to colors and
  * adding doorhanger previews where possible (images, angles, lengths,
  * border radius, cubic-bezier etc.).
  *
@@ -83,17 +84,19 @@ OutputParser.prototype = {
    *         A document fragment containing color swatches etc.
    */
   parseCssProperty: function (name, value, options = {}) {
     options = this._mergeOptions(options);
 
     options.expectCubicBezier = this.supportsType(name, CSS_TYPES.TIMING_FUNCTION);
     options.expectDisplay = name === "display";
     options.expectFilter = name === "filter";
-    options.expectShape = name === "clip-path" || name === "shape-outside";
+    options.expectShape = name === "clip-path" ||
+                          (name === "shape-outside"
+                           && Services.prefs.getBoolPref(CSS_SHAPE_OUTSIDE_ENABLED_PREF));
     options.supportsColor = this.supportsType(name, CSS_TYPES.COLOR) ||
                             this.supportsType(name, CSS_TYPES.GRADIENT);
 
     // The filter property is special in that we want to show the
     // swatch even if the value is invalid, because this way the user
     // can easily use the editor to fix it.
     if (options.expectFilter || this._cssPropertySupportsValue(name, value)) {
       return this._parse(value, options);
--- a/dom/base/nsINode.h
+++ b/dom/base/nsINode.h
@@ -2082,22 +2082,22 @@ protected:
    * Note that the selector list returned here is owned by the owner doc's
    * selector cache.
    */
   const RawServoSelectorList* ParseServoSelectorList(
     const nsAString& aSelectorString,
     mozilla::ErrorResult& aRv);
 
   /**
-   * Parse the given selector string into a SelectorList.
+   * Parse the given selector string a SelectorList, depending on whether we're
+   * in a Servo or Gecko-backed document, and execute either aServoFunctor or
+   * aGeckoFunctor on it.
    *
-   * A null return value with a non-failing aRv means the string only
-   * contained pseudo-element selectors.
-   *
-   * A failing aRv means the string was not a valid selector.
+   * Note that the selector list is owned by the owner doc's selector cache
+   * which can get expired, so you shouldn't keep it around for long.
    */
   template<typename Ret, typename ServoFunctor, typename GeckoFunctor>
   Ret WithSelectorList(
     const nsAString& aSelectorString,
     mozilla::ErrorResult& aRv,
     const ServoFunctor& aServoFunctor,
     const GeckoFunctor& aGeckoFunctor)
   {
--- a/dom/cache/FileUtils.cpp
+++ b/dom/cache/FileUtils.cpp
@@ -870,20 +870,20 @@ LockedDirectoryPaddingFinalizeWrite(nsIF
 nsresult
 LockedDirectoryPaddingRestore(nsIFile* aBaseDir, mozIStorageConnection* aConn)
 {
   MOZ_DIAGNOSTIC_ASSERT(aBaseDir);
   MOZ_DIAGNOSTIC_ASSERT(aConn);
 
   // The content of padding file is untrusted, so remove it here.
   nsresult rv = LockedDirectoryPaddingDeleteFile(aBaseDir,
-                                                 DirPaddingFile::TMP_FILE);
+                                                 DirPaddingFile::FILE);
   if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
-  rv = LockedDirectoryPaddingDeleteFile(aBaseDir, DirPaddingFile::FILE);
+  rv = LockedDirectoryPaddingDeleteFile(aBaseDir, DirPaddingFile::TMP_FILE);
   if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
   int64_t paddingSize = 0;
   rv = db::FindOverallPaddingSize(aConn, &paddingSize);
   if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
   MOZ_DIAGNOSTIC_ASSERT(paddingSize >= 0);
 
--- a/dom/cache/Manager.cpp
+++ b/dom/cache/Manager.cpp
@@ -490,16 +490,23 @@ public:
     Unused << NS_WARN_IF(NS_FAILED(rv));
 
     return rv;
   }
 
   virtual void
   CompleteOnInitiatingThread(nsresult aRv) override
   {
+    // If the transaction fails, we shouldn't delete the body files and decrease
+    // their padding size.
+    if (NS_FAILED(aRv)) {
+      mDeletedBodyIdList.Clear();
+      mDeletedPaddingSize = 0;
+    }
+
     mManager->NoteOrphanedBodyIdList(mDeletedBodyIdList);
 
     if (mDeletedPaddingSize > 0) {
       DecreaseUsageForQuotaInfo(mQuotaInfo.ref(), mDeletedPaddingSize);
     }
 
     // ensure we release the manager on the initiating thread
     mManager = nullptr;
@@ -862,16 +869,23 @@ private:
   {
     NS_ASSERT_OWNINGTHREAD(Action);
 
     for (uint32_t i = 0; i < mList.Length(); ++i) {
       mList[i].mRequestStream = nullptr;
       mList[i].mResponseStream = nullptr;
     }
 
+    // If the transaction fails, we shouldn't delete the body files and decrease
+    // their padding size.
+    if (NS_FAILED(aRv)) {
+      mDeletedBodyIdList.Clear();
+      mDeletedPaddingSize = 0;
+    }
+
     mManager->NoteOrphanedBodyIdList(mDeletedBodyIdList);
 
     if (mDeletedPaddingSize > 0) {
       DecreaseUsageForQuotaInfo(mQuotaInfo.ref(), mDeletedPaddingSize);
     }
 
     Listener* listener = mManager->GetListener(mListenerId);
     mManager = nullptr;
@@ -1102,16 +1116,23 @@ public:
     }
 
     return rv;
   }
 
   virtual void
   Complete(Listener* aListener, ErrorResult&& aRv) override
   {
+    // If the transaction fails, we shouldn't delete the body files and decrease
+    // their padding size.
+    if (aRv.Failed()) {
+      mDeletedBodyIdList.Clear();
+      mDeletedPaddingSize = 0;
+    }
+
     mManager->NoteOrphanedBodyIdList(mDeletedBodyIdList);
 
     if (mDeletedPaddingSize > 0) {
       DecreaseUsageForQuotaInfo(mQuotaInfo.ref(), mDeletedPaddingSize);
     }
 
     aListener->OnOpComplete(Move(aRv), CacheDeleteResult(mSuccess));
   }
--- a/dom/cache/QuotaClient.cpp
+++ b/dom/cache/QuotaClient.cpp
@@ -324,33 +324,44 @@ public:
     {
       MutexAutoLock lock(mDirPaddingFileMutex);
       rv =
         mozilla::dom::cache::
         LockedUpdateDirectoryPaddingFile(aBaseDir, aConn, aIncreaseSize,
                                          aDecreaseSize,
                                          temporaryPaddingFileExist);
       if (NS_WARN_IF(NS_FAILED(rv))) {
-        mozilla::dom::cache::
-        LockedDirectoryPaddingDeleteFile(aBaseDir, DirPaddingFile::TMP_FILE);
+        // Don't delete the temporary padding file here to force the next action
+        // recalculate the padding size.
         return rv;
       }
 
       rv = aCommitHook();
       if (NS_WARN_IF(NS_FAILED(rv))) {
-        mozilla::dom::cache::
-        LockedDirectoryPaddingDeleteFile(aBaseDir, DirPaddingFile::TMP_FILE);
+        // Don't delete the temporary padding file here to force the next action
+        // recalculate the padding size.
         return rv;
       }
 
       rv = mozilla::dom::cache::LockedDirectoryPaddingFinalizeWrite(aBaseDir);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         // Force restore file next time.
-        mozilla::dom::cache::
-        LockedDirectoryPaddingDeleteFile(aBaseDir, DirPaddingFile::FILE);
+        Unused << mozilla::dom::cache::
+                  LockedDirectoryPaddingDeleteFile(aBaseDir,
+                                                   DirPaddingFile::FILE);
+
+        // Ensure that we are able to force the padding file to be restored.
+        MOZ_ASSERT(
+          mozilla::dom::cache::
+          DirectoryPaddingFileExists(aBaseDir, DirPaddingFile::TMP_FILE));
+
+        // Since both the body file and header have been stored in the
+        // file-system, just make the action be resolve and let the padding file
+        // be restored in the next action.
+        rv = NS_OK;
       }
     }
 
     return rv;
   }
 
   // static
   nsresult
--- a/gfx/layers/wr/WebRenderBridgeChild.cpp
+++ b/gfx/layers/wr/WebRenderBridgeChild.cpp
@@ -110,52 +110,50 @@ WebRenderBridgeChild::UpdateResources(wr
   nsTArray<ipc::Shmem> smallShmems;
   nsTArray<ipc::Shmem> largeShmems;
   aResources.Flush(resourceUpdates, smallShmems, largeShmems);
 
   this->SendUpdateResources(resourceUpdates, Move(smallShmems), Move(largeShmems));
 }
 
 void
-WebRenderBridgeChild::EndTransaction(wr::DisplayListBuilder &aBuilder,
+WebRenderBridgeChild::EndTransaction(const wr::LayoutSize& aContentSize,
+                                     wr::BuiltDisplayList& aDL,
                                      wr::IpcResourceUpdateQueue& aResources,
                                      const gfx::IntSize& aSize,
                                      bool aIsSync,
                                      uint64_t aTransactionId,
                                      const WebRenderScrollData& aScrollData,
                                      const mozilla::TimeStamp& aTxnStartTime)
 {
   MOZ_ASSERT(!mDestroyed);
   MOZ_ASSERT(mIsInTransaction);
 
-  wr::BuiltDisplayList dl;
-  wr::LayoutSize contentSize;
-  aBuilder.Finalize(contentSize, dl);
-  ByteBuffer dlData(Move(dl.dl));
+  ByteBuffer dlData(Move(aDL.dl));
 
   TimeStamp fwdTime;
 #if defined(ENABLE_FRAME_LATENCY_LOG)
   fwdTime = TimeStamp::Now();
 #endif
 
   nsTArray<OpUpdateResource> resourceUpdates;
   nsTArray<ipc::Shmem> smallShmems;
   nsTArray<ipc::Shmem> largeShmems;
   aResources.Flush(resourceUpdates, smallShmems, largeShmems);
 
   if (aIsSync) {
     this->SendSetDisplayListSync(aSize, mParentCommands, mDestroyedActors,
                                  GetFwdTransactionId(), aTransactionId,
-                                 contentSize, dlData, dl.dl_desc, aScrollData,
+                                 aContentSize, dlData, aDL.dl_desc, aScrollData,
                                  Move(resourceUpdates), Move(smallShmems), Move(largeShmems),
                                  mIdNamespace, aTxnStartTime, fwdTime);
   } else {
     this->SendSetDisplayList(aSize, mParentCommands, mDestroyedActors,
                              GetFwdTransactionId(), aTransactionId,
-                             contentSize, dlData, dl.dl_desc, aScrollData,
+                             aContentSize, dlData, aDL.dl_desc, aScrollData,
                              Move(resourceUpdates), Move(smallShmems), Move(largeShmems),
                              mIdNamespace, aTxnStartTime, fwdTime);
   }
 
   mParentCommands.Clear();
   mDestroyedActors.Clear();
   mIsInTransaction = false;
 }
--- a/gfx/layers/wr/WebRenderBridgeChild.h
+++ b/gfx/layers/wr/WebRenderBridgeChild.h
@@ -63,17 +63,18 @@ class WebRenderBridgeChild final : publi
 public:
   explicit WebRenderBridgeChild(const wr::PipelineId& aPipelineId);
 
   void AddWebRenderParentCommand(const WebRenderParentCommand& aCmd);
   void AddWebRenderParentCommands(const nsTArray<WebRenderParentCommand>& aCommands);
 
   void UpdateResources(wr::IpcResourceUpdateQueue& aResources);
   bool BeginTransaction(const  gfx::IntSize& aSize);
-  void EndTransaction(wr::DisplayListBuilder &aBuilder,
+  void EndTransaction(const wr::LayoutSize& aContentSize,
+                      wr::BuiltDisplayList& dl,
                       wr::IpcResourceUpdateQueue& aResources,
                       const gfx::IntSize& aSize,
                       bool aIsSync, uint64_t aTransactionId,
                       const WebRenderScrollData& aScrollData,
                       const mozilla::TimeStamp& aTxnStartTime);
   void ProcessWebRenderParentCommands();
 
   CompositorBridgeChild* GetCompositorBridgeChild();
--- a/gfx/layers/wr/WebRenderCommandBuilder.cpp
+++ b/gfx/layers/wr/WebRenderCommandBuilder.cpp
@@ -44,18 +44,16 @@ WebRenderCommandBuilder::BuildWebRenderC
     aScrollData = WebRenderScrollData();
     MOZ_ASSERT(mLayerScrollData.empty());
     mLastCanvasDatas.Clear();
     mLastAsr = nullptr;
 
     CreateWebRenderCommandsFromDisplayList(aDisplayList, aDisplayListBuilder, sc,
                                            aBuilder, aResourceUpdates);
 
-    aBuilder.Finalize(aContentSize, mBuiltDisplayList);
-
     // Make a "root" layer data that has everything else as descendants
     mLayerScrollData.emplace_back();
     mLayerScrollData.back().InitializeRoot(mLayerScrollData.size() - 1);
     if (aDisplayListBuilder->IsBuildingLayerEventRegions()) {
       nsIPresShell* shell = aDisplayListBuilder->RootReferenceFrame()->PresContext()->PresShell();
       if (nsLayoutUtils::HasDocumentLevelListenersForApzAwareEvents(shell)) {
         mLayerScrollData.back().SetEventRegionsOverride(EventRegionsOverride::ForceDispatchToContent);
       }
@@ -76,17 +74,16 @@ WebRenderCommandBuilder::BuildWebRenderC
     mLayerScrollData.clear();
     mClipIdCache.clear();
 
     // Remove the user data those are not displayed on the screen and
     // also reset the data to unused for next transaction.
     RemoveUnusedAndResetWebRenderUserData();
   }
 
-  aBuilder.PushBuiltDisplayList(mBuiltDisplayList);
   mManager->WrBridge()->AddWebRenderParentCommands(mParentCommands);
 }
 
 void
 WebRenderCommandBuilder::CreateWebRenderCommandsFromDisplayList(nsDisplayList* aDisplayList,
                                                                 nsDisplayListBuilder* aDisplayListBuilder,
                                                                 const StackingContextHelper& aSc,
                                                                 wr::DisplayListBuilder& aBuilder,
--- a/gfx/layers/wr/WebRenderCommandBuilder.h
+++ b/gfx/layers/wr/WebRenderCommandBuilder.h
@@ -153,17 +153,16 @@ public:
   typedef std::unordered_map<const DisplayItemClipChain*, wr::WrClipId> ClipIdMap;
 
 private:
   WebRenderLayerManager* mManager;
   ClipIdMap mClipIdCache;
 
   // These fields are used to save a copy of the display list for
   // empty transactions in layers-free mode.
-  wr::BuiltDisplayList mBuiltDisplayList;
   nsTArray<WebRenderParentCommand> mParentCommands;
 
   // We use this as a temporary data structure while building the mScrollData
   // inside a layers-free transaction.
   std::vector<WebRenderLayerScrollData> mLayerScrollData;
   // We use this as a temporary data structure to track the current display
   // item's ASR as we recurse in CreateWebRenderCommandsFromDisplayList. We
   // need this so that WebRenderLayerScrollData items that deeper in the
--- a/gfx/layers/wr/WebRenderLayerManager.cpp
+++ b/gfx/layers/wr/WebRenderLayerManager.cpp
@@ -29,16 +29,17 @@ namespace layers {
 WebRenderLayerManager::WebRenderLayerManager(nsIWidget* aWidget)
   : mWidget(aWidget)
   , mLatestTransactionId(0)
   , mNeedsComposite(false)
   , mIsFirstPaint(false)
   , mTarget(nullptr)
   , mPaintSequenceNumber(0)
   , mWebRenderCommandBuilder(this)
+  , mLastDisplayListSize(0)
 {
   MOZ_COUNT_CTOR(WebRenderLayerManager);
 }
 
 KnowsCompositor*
 WebRenderLayerManager::AsKnowsCompositor()
 {
   return mWrChild;
@@ -239,17 +240,17 @@ WebRenderLayerManager::EndTransactionWit
 
   LayoutDeviceIntSize size = mWidget->GetClientSize();
   if (!WrBridge()->BeginTransaction(size.ToUnknownSize())) {
     return;
   }
   DiscardCompositorAnimations();
 
   wr::LayoutSize contentSize { (float)size.width, (float)size.height };
-  wr::DisplayListBuilder builder(WrBridge()->GetPipeline(), contentSize);
+  wr::DisplayListBuilder builder(WrBridge()->GetPipeline(), contentSize, mLastDisplayListSize);
   wr::IpcResourceUpdateQueue resourceUpdates(WrBridge()->GetShmemAllocator());
 
   mWebRenderCommandBuilder.BuildWebRenderCommands(builder,
                                                   resourceUpdates,
                                                   aDisplayList,
                                                   aDisplayListBuilder,
                                                   mScrollData,
                                                   contentSize);
@@ -290,20 +291,25 @@ WebRenderLayerManager::EndTransactionWit
   // Skip the synchronization for buffer since we also skip the painting during
   // device-reset status.
   if (!gfxPlatform::GetPlatform()->DidRenderingDeviceReset()) {
     if (WrBridge()->GetSyncObject() &&
         WrBridge()->GetSyncObject()->IsSyncObjectValid()) {
       WrBridge()->GetSyncObject()->Synchronize();
     }
   }
+
+  wr::BuiltDisplayList dl;
+  builder.Finalize(contentSize, dl);
+  mLastDisplayListSize = dl.dl.inner.capacity;
+
   {
     AutoProfilerTracing
       tracing("Paint", sync ? "ForwardDPTransactionSync":"ForwardDPTransaction");
-    WrBridge()->EndTransaction(builder, resourceUpdates, size.ToUnknownSize(), sync,
+    WrBridge()->EndTransaction(contentSize, dl, resourceUpdates, size.ToUnknownSize(), sync,
                                mLatestTransactionId, mScrollData, transactionStart);
   }
 
   MakeSnapshotIfRequired(size);
   mNeedsComposite = false;
 
   ClearDisplayItemLayers();
 }
--- a/gfx/layers/wr/WebRenderLayerManager.h
+++ b/gfx/layers/wr/WebRenderLayerManager.h
@@ -207,14 +207,16 @@ private:
   RefPtr<gfxContext> mTarget;
 
   // See equivalent field in ClientLayerManager
   uint32_t mPaintSequenceNumber;
   // See equivalent field in ClientLayerManager
   APZTestData mApzTestData;
 
   WebRenderCommandBuilder mWebRenderCommandBuilder;
+
+  size_t mLastDisplayListSize;
 };
 
 } // namespace layers
 } // namespace mozilla
 
 #endif /* GFX_WEBRENDERLAYERMANAGER_H */
--- a/gfx/thebes/gfxPrefs.h
+++ b/gfx/thebes/gfxPrefs.h
@@ -533,17 +533,17 @@ private:
   DECL_GFX_PREF(Once, "image.mem.surfacecache.size_factor",    ImageMemSurfaceCacheSizeFactor, uint32_t, 64);
   DECL_GFX_PREF(Once, "image.multithreaded_decoding.limit",    ImageMTDecodingLimit, int32_t, -1);
 
   DECL_GFX_PREF(Once, "layers.acceleration.disabled",          LayersAccelerationDisabledDoNotUseDirectly, bool, false);
   DECL_GFX_PREF(Live, "layers.acceleration.draw-fps",          LayersDrawFPS, bool, false);
   DECL_GFX_PREF(Live, "layers.acceleration.draw-fps.print-histogram",  FPSPrintHistogram, bool, false);
   DECL_GFX_PREF(Live, "layers.acceleration.draw-fps.write-to-file", WriteFPSToFile, bool, false);
   DECL_GFX_PREF(Once, "layers.acceleration.force-enabled",     LayersAccelerationForceEnabledDoNotUseDirectly, bool, false);
-  DECL_OVERRIDE_PREF(Live, "layers.advanced.background-color",        LayersAllowBackgroundColorLayers, gfxPrefs::OverrideBase_WebRender());
+  DECL_GFX_PREF(Live, "layers.advanced.background-color",      LayersAllowBackgroundColorLayers, bool, false);
   DECL_OVERRIDE_PREF(Live, "layers.advanced.background-image",        LayersAllowBackgroundImage, gfxPrefs::OverrideBase_WebRender());
   DECL_GFX_PREF(Live, "layers.advanced.basic-layer.enabled",          LayersAdvancedBasicLayerEnabled, bool, false);
   DECL_OVERRIDE_PREF(Live, "layers.advanced.border-layers",           LayersAllowBorderLayers, gfxPrefs::OverrideBase_WebRender());
   DECL_OVERRIDE_PREF(Live, "layers.advanced.boxshadow-inset-layers",  LayersAllowInsetBoxShadow, gfxPrefs::OverrideBase_WebRender());
   DECL_OVERRIDE_PREF(Live, "layers.advanced.boxshadow-outer-layers",  LayersAllowOuterBoxShadow, gfxPrefs::OverrideBase_WebRender());
   DECL_OVERRIDE_PREF(Live, "layers.advanced.bullet-layers",           LayersAllowBulletLayers, gfxPrefs::OverrideBase_WebRender());
   DECL_OVERRIDE_PREF(Live, "layers.advanced.button-foreground-layers", LayersAllowButtonForegroundLayers, gfxPrefs::OverrideBase_WebRender());
   DECL_OVERRIDE_PREF(Live, "layers.advanced.canvas-background-color", LayersAllowCanvasBackgroundColorLayers, gfxPrefs::OverrideBase_WebRender());
--- a/gfx/webrender_bindings/WebRenderAPI.cpp
+++ b/gfx/webrender_bindings/WebRenderAPI.cpp
@@ -618,21 +618,22 @@ WebRenderAPI::SetFrameStartTime(const Ti
 void
 WebRenderAPI::RunOnRenderThread(UniquePtr<RendererEvent> aEvent)
 {
   auto event = reinterpret_cast<uintptr_t>(aEvent.release());
   wr_api_send_external_event(mDocHandle, event);
 }
 
 DisplayListBuilder::DisplayListBuilder(PipelineId aId,
-                                       const wr::LayoutSize& aContentSize)
+                                       const wr::LayoutSize& aContentSize,
+                                       size_t aCapacity)
   : mMaskClipCount(0)
 {
   MOZ_COUNT_CTOR(DisplayListBuilder);
-  mWrState = wr_state_new(aId, aContentSize);
+  mWrState = wr_state_new(aId, aContentSize, aCapacity);
 }
 
 DisplayListBuilder::~DisplayListBuilder()
 {
   MOZ_COUNT_DTOR(DisplayListBuilder);
   wr_state_delete(mWrState);
 }
 
--- a/gfx/webrender_bindings/WebRenderAPI.h
+++ b/gfx/webrender_bindings/WebRenderAPI.h
@@ -197,17 +197,18 @@ protected:
 };
 
 /// This is a simple C++ wrapper around WrState defined in the rust bindings.
 /// We may want to turn this into a direct wrapper on top of WebRenderFrameBuilder
 /// instead, so the interface may change a bit.
 class DisplayListBuilder {
 public:
   explicit DisplayListBuilder(wr::PipelineId aId,
-                              const wr::LayoutSize& aContentSize);
+                              const wr::LayoutSize& aContentSize,
+                              size_t aCapacity = 0);
   DisplayListBuilder(DisplayListBuilder&&) = default;
 
   ~DisplayListBuilder();
 
   void Finalize(wr::LayoutSize& aOutContentSize,
                 wr::BuiltDisplayList& aOutDisplayList);
 
   void PushStackingContext(const wr::LayoutRect& aBounds, // TODO: We should work with strongly typed rects
--- a/gfx/webrender_bindings/src/bindings.rs
+++ b/gfx/webrender_bindings/src/bindings.rs
@@ -1057,32 +1057,43 @@ pub struct WebRenderFrameBuilder {
 impl WebRenderFrameBuilder {
     pub fn new(root_pipeline_id: WrPipelineId,
                content_size: LayoutSize) -> WebRenderFrameBuilder {
         WebRenderFrameBuilder {
             root_pipeline_id: root_pipeline_id,
             dl_builder: webrender_api::DisplayListBuilder::new(root_pipeline_id, content_size),
         }
     }
+    pub fn with_capacity(root_pipeline_id: WrPipelineId,
+               content_size: LayoutSize,
+               capacity: usize) -> WebRenderFrameBuilder {
+        WebRenderFrameBuilder {
+            root_pipeline_id: root_pipeline_id,
+            dl_builder: webrender_api::DisplayListBuilder::with_capacity(root_pipeline_id, content_size, capacity),
+        }
+    }
+
 }
 
 pub struct WrState {
     pipeline_id: WrPipelineId,
     frame_builder: WebRenderFrameBuilder,
 }
 
 #[no_mangle]
 pub extern "C" fn wr_state_new(pipeline_id: WrPipelineId,
-                               content_size: LayoutSize) -> *mut WrState {
+                               content_size: LayoutSize,
+                               capacity: usize) -> *mut WrState {
     assert!(unsafe { !is_in_render_thread() });
 
     let state = Box::new(WrState {
                              pipeline_id: pipeline_id,
-                             frame_builder: WebRenderFrameBuilder::new(pipeline_id,
-                                                                       content_size),
+                             frame_builder: WebRenderFrameBuilder::with_capacity(pipeline_id,
+                                                                                 content_size,
+                                                                                 capacity),
                          });
 
     Box::into_raw(state)
 }
 
 /// cbindgen:postfix=WR_DESTRUCTOR_SAFE_FUNC
 #[no_mangle]
 pub extern "C" fn wr_state_delete(state: *mut WrState) {
--- a/gfx/webrender_bindings/webrender_ffi_generated.h
+++ b/gfx/webrender_bindings/webrender_ffi_generated.h
@@ -1302,17 +1302,18 @@ void wr_scroll_layer_with_id(DocumentHan
 WR_FUNC;
 
 WR_INLINE
 void wr_state_delete(WrState *aState)
 WR_DESTRUCTOR_SAFE_FUNC;
 
 WR_INLINE
 WrState *wr_state_new(WrPipelineId aPipelineId,
-                      LayoutSize aContentSize)
+                      LayoutSize aContentSize,
+                      size_t aCapacity)
 WR_FUNC;
 
 WR_INLINE
 void wr_thread_pool_delete(WrThreadPool *aThreadPool)
 WR_DESTRUCTOR_SAFE_FUNC;
 
 WR_INLINE
 WrThreadPool *wr_thread_pool_new()
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -4257,25 +4257,25 @@ nsDisplayBackgroundColor::BuildLayer(nsD
 
 bool
 nsDisplayBackgroundColor::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
                                                   mozilla::wr::IpcResourceUpdateQueue& aResources,
                                                   const StackingContextHelper& aSc,
                                                   mozilla::layers::WebRenderLayerManager* aManager,
                                                   nsDisplayListBuilder* aDisplayListBuilder)
 {
-  ContainerLayerParameters parameter;
-  if (GetLayerState(aDisplayListBuilder, aManager, parameter) != LAYER_ACTIVE) {
-    return false;
-  }
-
   if (mColor == Color()) {
     return true;
   }
 
+  StyleGeometryBox clip = mBackgroundStyle->mImage.mLayers[0].mClip;
+  if (clip == StyleGeometryBox::Text) {
+    return false;
+  }
+
   LayoutDeviceRect bounds = LayoutDeviceRect::FromAppUnits(
         mBackgroundRect, mFrame->PresContext()->AppUnitsPerDevPixel());
   wr::LayoutRect transformedRect = aSc.ToRelativeLayoutRect(bounds);
 
   aBuilder.PushRect(transformedRect,
                     transformedRect,
                     !BackfaceIsHidden(),
                     wr::ToColorF(ToDeviceColor(mColor)));
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -5883,17 +5883,17 @@ pref("layers.mlgpu.enable-on-windows7", 
 #endif
 
 // Set advanced layers preferences here to have them show up in about:config or
 // to be overridable in reftest.list files. They should pretty much all be set
 // to a value of 2, and the conditional-pref code in gfxPrefs.h will convert
 // it to a boolean as appropriate. In particular, do NOT add ifdefs here to
 // turn these on and off, instead use the conditional-pref code in gfxPrefs.h
 // to do that.
-pref("layers.advanced.background-color", 2);
+pref("layers.advanced.background-color", false);
 pref("layers.advanced.background-image", 2);
 pref("layers.advanced.border-layers", 2);
 pref("layers.advanced.boxshadow-inset-layers", 2);
 pref("layers.advanced.boxshadow-outer-layers", 2);
 pref("layers.advanced.bullet-layers", 2);
 pref("layers.advanced.button-foreground-layers", 2);
 pref("layers.advanced.canvas-background-color", 2);
 pref("layers.advanced.caret-layers", 2);
--- a/netwerk/cookie/nsCookieService.cpp
+++ b/netwerk/cookie/nsCookieService.cpp
@@ -3315,17 +3315,17 @@ nsCookieService::GetCookiesForURI(nsIURI
   case STATUS_REJECTED:
   case STATUS_REJECTED_WITH_ERROR:
     return;
   default:
     break;
   }
 
   // Note: The following permissions logic is mirrored in
-  // toolkit/modules/addons/MatchPattern.jsm:MatchPattern.matchesCookie().
+  // extensions::MatchPattern::MatchesCookie.
   // If it changes, please update that function, or file a bug for someone
   // else to do so.
 
   // check if aHostURI is using an https secure protocol.
   // if it isn't, then we can't send a secure cookie over the connection.
   // if SchemeIs fails, assume an insecure connection, to be on the safe side
   bool isSecure;
   if (NS_FAILED(aHostURI->SchemeIs("https", &isSecure))) {
--- a/toolkit/components/extensions/ext-webNavigation.js
+++ b/toolkit/components/extensions/ext-webNavigation.js
@@ -3,17 +3,17 @@
 // The ext-* files are imported into the same scopes.
 /* import-globals-from ext-toolkit.js */
 
 // This file expectes tabTracker to be defined in the global scope (e.g.
 // by ext-utils.js).
 /* global tabTracker */
 
 XPCOMUtils.defineLazyModuleGetter(this, "MatchURLFilters",
-                                  "resource://gre/modules/MatchPattern.jsm");
+                                  "resource://gre/modules/MatchURLFilters.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "WebNavigation",
                                   "resource://gre/modules/WebNavigation.jsm");
 
 const defaultTransitionTypes = {
   topFrame: "link",
   subFrame: "auto_subframe",
 };
 
--- a/toolkit/components/extensions/test/mochitest/chrome.ini
+++ b/toolkit/components/extensions/test/mochitest/chrome.ini
@@ -29,16 +29,17 @@ skip-if = os == 'android' # Bug 1350559
 [test_chrome_ext_storage_cleanup.html]
 [test_chrome_ext_trackingprotection.html]
 [test_chrome_ext_trustworthy_origin.html]
 [test_chrome_ext_webnavigation_resolved_urls.html]
 [test_chrome_ext_webrequest_background_events.html]
 [test_chrome_ext_webrequest_errors.html]
 [test_chrome_ext_webrequest_host_permissions.html]
 [test_chrome_ext_webrequest_mozextension.html]
+skip-if = true # Bug 1404172
 [test_chrome_native_messaging_paths.html]
 skip-if = os != "mac" && os != "linux"
 [test_ext_cookies_expiry.html]
 [test_ext_cookies_permissions_bad.html]
 [test_ext_cookies_permissions_good.html]
 [test_ext_cookies_containers.html]
 [test_ext_jsversion.html]
 [test_ext_schema.html]
rename from toolkit/modules/addons/MatchPattern.jsm
rename to toolkit/modules/addons/MatchURLFilters.jsm
--- a/toolkit/modules/addons/MatchPattern.jsm
+++ b/toolkit/modules/addons/MatchURLFilters.jsm
@@ -4,283 +4,39 @@
 
 "use strict";
 
 const Cu = Components.utils;
 const Ci = Components.interfaces;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
-XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
-                                  "resource://gre/modules/NetUtil.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Services",
                                   "resource://gre/modules/Services.jsm");
 
-this.EXPORTED_SYMBOLS = ["MatchPattern", "MatchGlobs", "MatchURLFilters"];
-
-/* globals MatchPattern, MatchGlobs */
-
-const PERMITTED_SCHEMES = ["http", "https", "ws", "wss", "file", "ftp", "data"];
-const PERMITTED_SCHEMES_REGEXP = [...PERMITTED_SCHEMES, "moz-extension"].join("|");
+/* exported MatchURLFilters */
 
-// The basic RE for matching patterns
-const PATTERN_REGEXP = new RegExp(`^(${PERMITTED_SCHEMES_REGEXP}|\\*)://(\\*|\\*\\.[^*/]+|[^*/]+|)(/.*)$`);
-
-// The schemes/protocols implied by a pattern that starts with *://
-const WILDCARD_SCHEMES = ["http", "https"];
-
-// This function converts a glob pattern (containing * and possibly ?
-// as wildcards) to a regular expression.
-function globToRegexp(pat, allowQuestion) {
-  // Escape everything except ? and *.
-  pat = pat.replace(/[.+^${}()|[\]\\]/g, "\\$&");
+this.EXPORTED_SYMBOLS = ["MatchURLFilters"];
 
-  if (allowQuestion) {
-    pat = pat.replace(/\?/g, ".");
-  } else {
-    pat = pat.replace(/\?/g, "\\?");
-  }
-  pat = pat.replace(/\*/g, ".*");
-  return new RegExp("^" + pat + "$");
-}
-
-// These patterns follow the syntax in
-// https://developer.chrome.com/extensions/match_patterns
-function SingleMatchPattern(pat) {
-  this.pat = pat;
-  if (pat == "<all_urls>") {
-    this.schemes = PERMITTED_SCHEMES;
-    this.hostMatch = () => true;
-    this.pathMatch = () => true;
-  } else if (!pat) {
-    this.schemes = [];
-  } else {
-    let match = PATTERN_REGEXP.exec(pat);
-    if (!match) {
-      Cu.reportError(`Invalid match pattern: '${pat}'`);
-      this.schemes = [];
-      return;
-    }
-
-    if (match[1] == "*") {
-      this.schemes = WILDCARD_SCHEMES;
-    } else {
-      this.schemes = [match[1]];
+// Match WebNavigation URL Filters.
+class MatchURLFilters {
+  constructor(filters) {
+    if (!Array.isArray(filters)) {
+      throw new TypeError("filters should be an array");
     }
 
-    // We allow the host to be empty for file URLs.
-    if (match[2] == "" && this.schemes[0] != "file") {
-      Cu.reportError(`Invalid match pattern: '${pat}'`);
-      this.schemes = [];
-      return;
-    }
-
-    // We disallow the host to be * for moz-extension URLs.
-    if (match[2] == "*" && this.schemes[0] == "moz-extension") {
-      Cu.reportError(`Invalid match pattern: '${pat}'`);
-      this.schemes = [];
-      return;
+    if (filters.length == 0) {
+      throw new Error("filters array should not be empty");
     }
 
-    this.host = match[2];
-    this.hostMatch = this.getHostMatcher(match[2]);
-
-    let pathMatch = globToRegexp(match[3], false);
-    this.pathMatch = pathMatch.test.bind(pathMatch);
-  }
-}
-
-SingleMatchPattern.prototype = {
-  getHostMatcher(host) {
-    // This code ignores the port, as Chrome does.
-    if (host == "*") {
-      return () => true;
-    }
-    if (host.startsWith("*.")) {
-      let suffix = host.substr(2);
-      let dotSuffix = "." + suffix;
-
-      return ({host}) => host === suffix || host.endsWith(dotSuffix);
-    }
-    return uri => uri.host === host;
-  },
-
-  matches(uri, ignorePath = false) {
-    return (
-      this.schemes.includes(uri.scheme) &&
-      this.hostMatch(uri) &&
-      (ignorePath || (
-        this.pathMatch(uri.cloneIgnoringRef().pathQueryRef)
-      ))
-    );
-  },
-
-  // Tests if this can possibly overlap with the |other| SingleMatchPattern.
-  overlapsIgnoringPath(other) {
-    return this.schemes.some(scheme => other.schemes.includes(scheme)) &&
-           (this.hostMatch(other) || other.hostMatch(this));
-  },
-
-  get pattern() { return this.pat; },
-};
-
-this.MatchPattern = function(pat) {
-  this.pat = pat;
-  if (!pat) {
-    this.matchers = [];
-  } else if (pat instanceof String || typeof(pat) == "string") {
-    this.matchers = [new SingleMatchPattern(pat)];
-  } else {
-    this.matchers = pat.map(p => new SingleMatchPattern(p));
+    this.filters = filters;
   }
 
-  XPCOMUtils.defineLazyGetter(this, "explicitMatchers", () => {
-    return this.matchers.filter(matcher => matcher.pat != "<all_urls>" &&
-                                           matcher.host &&
-                                           !matcher.host.startsWith("*"));
-  });
-};
-
-MatchPattern.prototype = {
-  // |uri| should be an nsIURI.
-  matches(uri) {
-    return this.matchers.some(matcher => matcher.matches(uri));
-  },
-
-  get patterns() { return this.matchers; },
-
-  matchesIgnoringPath(uri, explicit = false) {
-    if (explicit) {
-      return this.explicitMatchers.some(matcher => matcher.matches(uri, true));
-    }
-    return this.matchers.some(matcher => matcher.matches(uri, true));
-  },
-
-  // Checks that this match pattern grants access to read the given
-  // cookie. |cookie| should be an |nsICookie2| instance.
-  matchesCookie(cookie) {
-    // First check for simple matches.
-    let secureURI = NetUtil.newURI(`https://${cookie.rawHost}/`);
-    if (this.matchesIgnoringPath(secureURI)) {
-      return true;
-    }
-
-    let plainURI = NetUtil.newURI(`http://${cookie.rawHost}/`);
-    if (!cookie.isSecure && this.matchesIgnoringPath(plainURI)) {
-      return true;
-    }
-
-    if (!cookie.isDomain) {
-      return false;
-    }
-
-    // Things get tricker for domain cookies. The extension needs to be able
-    // to read any cookies that could be read any host it has permissions
-    // for. This means that our normal host matching checks won't work,
-    // since the pattern "*://*.foo.example.com/" doesn't match ".example.com",
-    // but it does match "bar.foo.example.com", which can read cookies
-    // with the domain ".example.com".
-    //
-    // So, instead, we need to manually check our filters, and accept any
-    // with hosts that end with our cookie's host.
-
-    let {host, isSecure} = cookie;
-
-    for (let matcher of this.matchers) {
-      let schemes = matcher.schemes;
-      if (schemes.includes("https") || (!isSecure && schemes.includes("http"))) {
-        if (matcher.host.endsWith(host)) {
-          return true;
-        }
-      }
-    }
-
-    return false;
-  },
-
-  // Checks if every part of this filter overlaps with
-  // some of the |hosts| or |optional| permissions MatchPatterns.
-  overlapsPermissions(hosts, optional) {
-    const perms = hosts.matchers.concat(optional.matchers);
-    return this.matchers.length &&
-           this.matchers.every(m => perms.some(p => p.overlapsIgnoringPath(m)));
-  },
-
-  // Test if this MatchPattern subsumes the given pattern (i.e., whether
-  // this pattern matches everything the given pattern does).
-  // Note, this method considers only to protocols and hosts/domains,
-  // paths are ignored.
-  subsumes(pattern) {
-    let match = PATTERN_REGEXP.exec(pattern);
-    if (!match) {
-      throw new Error("Invalid match pattern");
-    }
-
-    if (match[1] == "*") {
-      return WILDCARD_SCHEMES.every(scheme => this.matchesIgnoringPath({scheme, host: match[2]}));
-    }
-
-    return this.matchesIgnoringPath({scheme: match[1], host: match[2]});
-  },
-
-  serialize() {
-    return this.pat;
-  },
-
-  removeOne(pattern) {
-    if (!Array.isArray(this.pat)) {
-      return;
-    }
-
-    let index = this.pat.indexOf(pattern);
-    if (index >= 0) {
-      if (this.matchers[index].pat != pattern) {
-        throw new Error("pat/matcher mismatch in removeOne()");
-      }
-      this.pat.splice(index, 1);
-      this.matchers.splice(index, 1);
-    }
-  },
-};
-
-// Globs can match everything. Be careful, this DOES NOT filter by allowed schemes!
-this.MatchGlobs = function(globs) {
-  this.original = globs;
-  if (globs) {
-    this.regexps = Array.from(globs, (glob) => globToRegexp(glob, true));
-  } else {
-    this.regexps = [];
-  }
-};
-
-MatchGlobs.prototype = {
-  matches(str) {
-    return this.regexps.some(regexp => regexp.test(str));
-  },
-  serialize() {
-    return this.original;
-  },
-};
-
-// Match WebNavigation URL Filters.
-this.MatchURLFilters = function(filters) {
-  if (!Array.isArray(filters)) {
-    throw new TypeError("filters should be an array");
-  }
-
-  if (filters.length == 0) {
-    throw new Error("filters array should not be empty");
-  }
-
-  this.filters = filters;
-};
-
-MatchURLFilters.prototype = {
   matches(url) {
-    let uri = NetUtil.newURI(url);
+    let uri = Services.io.newURI(url);
     // Set uriURL to an empty object (needed because some schemes, e.g. about doesn't support nsIURL).
     let uriURL = {};
     if (uri instanceof Ci.nsIURL) {
       uriURL = uri;
     }
 
     // Set host to a empty string by default (needed so that schemes without an host,
     // e.g. about, can pass an empty string for host based event filtering as expected).
@@ -308,17 +64,17 @@ MatchURLFilters.prototype = {
       query: uriURL.query,
       host,
       port,
       url,
     };
 
     // If any of the filters matches, matches returns true.
     return this.filters.some(filter => this.matchURLFilter({filter, data, uri, uriURL}));
-  },
+  }
 
   matchURLFilter({filter, data, uri, uriURL}) {
     // Test for scheme based filtering.
     if (filter.schemes) {
       // Return false if none of the schemes matches.
       if (!filter.schemes.some((scheme) => uri.schemeIs(scheme))) {
         return false;
       }
@@ -377,17 +133,17 @@ MatchURLFilters.prototype = {
       // of null)
       if (!urlWithoutQueryAndRef ||
           !urlWithoutQueryAndRef.match(filter.originAndPathMatches)) {
         return false;
       }
     }
 
     return true;
-  },
+  }
 
   testMatchOnURLComponent({urlComponent: key, data, filter}) {
     // Test for equals.
     // NOTE: an empty string should not be considered a filter to skip.
     if (filter[`${key}Equals`] != null) {
       if (data[key] !== filter[`${key}Equals`]) {
         return false;
       }
@@ -411,14 +167,14 @@ MatchURLFilters.prototype = {
     // Test for suffix.
     if (filter[`${key}Suffix`]) {
       if (!data[key] || !data[key].endsWith(filter[`${key}Suffix`])) {
         return false;
       }
     }
 
     return true;
-  },
+  }
 
   serialize() {
     return this.filters;
-  },
-};
+  }
+}
--- a/toolkit/modules/addons/WebRequestContent.js
+++ b/toolkit/modules/addons/WebRequestContent.js
@@ -1,27 +1,25 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 // Managed via the message managers.
-/* global initialProcessData */
+/* globals MatchPatternSet, initialProcessData */
 
 "use strict";
 
 var Ci = Components.interfaces;
 var Cc = Components.classes;
 var Cu = Components.utils;
 var Cr = Components.results;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 
-XPCOMUtils.defineLazyModuleGetter(this, "MatchPattern",
-                                  "resource://gre/modules/MatchPattern.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "WebRequestCommon",
                                   "resource://gre/modules/WebRequestCommon.jsm");
 
 // Websockets will get handled via httpchannel notifications same as http
 // requests, treat them the same as http in ContentPolicy.
 const IS_HTTP = /^https?:|wss?:/;
 
 var ContentPolicy = {
@@ -48,17 +46,17 @@ var ContentPolicy = {
     }
   },
 
   addContentPolicy({id, blocking, filter}) {
     if (this.contentPolicies.size == 0) {
       this.register();
     }
     if (filter.urls) {
-      filter.urls = new MatchPattern(filter.urls);
+      filter.urls = new MatchPatternSet(filter.urls);
     }
     this.contentPolicies.set(id, {blocking, filter});
   },
 
   receiveMessage(msg) {
     switch (msg.name) {
       case "WebRequest:AddContentPolicy":
         this.addContentPolicy(msg.data);
--- a/toolkit/modules/moz.build
+++ b/toolkit/modules/moz.build
@@ -158,17 +158,17 @@ TESTING_JS_MODULES += [
     'tests/modules/MockDocument.jsm',
     'tests/modules/PromiseTestUtils.jsm',
     'tests/xpcshell/TestIntegration.jsm',
 ]
 
 SPHINX_TREES['toolkit_modules'] = 'docs'
 
 EXTRA_JS_MODULES += [
-    'addons/MatchPattern.jsm',
+    'addons/MatchURLFilters.jsm',
     'addons/WebNavigation.jsm',
     'addons/WebNavigationContent.js',
     'addons/WebNavigationFrames.jsm',
     'addons/WebRequest.jsm',
     'addons/WebRequestCommon.jsm',
     'addons/WebRequestContent.js',
     'addons/WebRequestUpload.jsm',
     'AppMenuNotifications.jsm',
deleted file mode 100644
--- a/toolkit/modules/tests/xpcshell/test_MatchGlobs.js
+++ /dev/null
@@ -1,58 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-"use strict";
-
-Components.utils.import("resource://gre/modules/MatchPattern.jsm");
-Components.utils.import("resource://gre/modules/Services.jsm");
-
-function test(url, pattern) {
-  let uri = Services.io.newURI(url);
-  let m = new MatchGlobs(pattern);
-  return m.matches(uri.spec);
-}
-
-function pass({url, pattern}) {
-  ok(test(url, pattern), `Expected match: ${JSON.stringify(pattern)}, ${url}`);
-}
-
-function fail({url, pattern}) {
-  ok(!test(url, pattern), `Expected no match: ${JSON.stringify(pattern)}, ${url}`);
-}
-
-function run_test() {
-  let moz = "http://mozilla.org";
-
-  pass({url: moz, pattern: ["*"]});
-  pass({url: moz, pattern: ["http://*"]}),
-  pass({url: moz, pattern: ["*mozilla*"]});
-  pass({url: moz, pattern: ["*example*", "*mozilla*"]});
-
-  pass({url: moz, pattern: ["*://*"]});
-  pass({url: "https://mozilla.org", pattern: ["*://*"]});
-
-  // Documentation example
-  pass({url: "http://www.example.com/foo/bar", pattern: ["http://???.example.com/foo/*"]});
-  pass({url: "http://the.example.com/foo/", pattern: ["http://???.example.com/foo/*"]});
-  fail({url: "http://my.example.com/foo/bar", pattern: ["http://???.example.com/foo/*"]});
-  fail({url: "http://example.com/foo/", pattern: ["http://???.example.com/foo/*"]});
-  fail({url: "http://www.example.com/foo", pattern: ["http://???.example.com/foo/*"]});
-
-  // Matches path
-  let path = moz + "/abc/def";
-  pass({url: path, pattern: ["*def"]});
-  pass({url: path, pattern: ["*c/d*"]});
-  pass({url: path, pattern: ["*org/abc*"]});
-  fail({url: path + "/", pattern: ["*def"]});
-
-  // Trailing slash
-  pass({url: moz, pattern: ["*.org/"]});
-  fail({url: moz, pattern: ["*.org"]});
-
-  // Wrong TLD
-  fail({url: moz, pattern: ["www*.m*.com/"]});
-  // Case sensitive
-  fail({url: moz, pattern: ["*.ORG/"]});
-
-  fail({url: moz, pattern: []});
-}
deleted file mode 100644
--- a/toolkit/modules/tests/xpcshell/test_MatchPattern.js
+++ /dev/null
@@ -1,158 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-"use strict";
-
-Components.utils.import("resource://gre/modules/MatchPattern.jsm");
-Components.utils.import("resource://gre/modules/Services.jsm");
-
-function test_matches() {
-  function test(url, pattern) {
-    let uri = Services.io.newURI(url);
-    let m = new MatchPattern(pattern);
-    return m.matches(uri);
-  }
-
-  function pass({url, pattern}) {
-    do_check_true(test(url, pattern), `Expected match: ${JSON.stringify(pattern)}, ${url}`);
-  }
-
-  function fail({url, pattern}) {
-    do_check_false(test(url, pattern), `Expected no match: ${JSON.stringify(pattern)}, ${url}`);
-  }
-
-  // Invalid pattern.
-  fail({url: "http://mozilla.org", pattern: ""});
-
-  // Pattern must include trailing slash.
-  fail({url: "http://mozilla.org", pattern: "http://mozilla.org"});
-
-  // Protocol not allowed.
-  fail({url: "http://mozilla.org", pattern: "gopher://wuarchive.wustl.edu/"});
-
-  pass({url: "http://mozilla.org", pattern: "http://mozilla.org/"});
-  pass({url: "http://mozilla.org/", pattern: "http://mozilla.org/"});
-
-  pass({url: "http://mozilla.org/", pattern: "*://mozilla.org/"});
-  pass({url: "https://mozilla.org/", pattern: "*://mozilla.org/"});
-  fail({url: "file://mozilla.org/", pattern: "*://mozilla.org/"});
-  fail({url: "ftp://mozilla.org/", pattern: "*://mozilla.org/"});
-
-  fail({url: "http://mozilla.com", pattern: "http://*mozilla.com*/"});
-  fail({url: "http://mozilla.com", pattern: "http://mozilla.*/"});
-  fail({url: "http://mozilla.com", pattern: "http:/mozilla.com/"});
-
-  pass({url: "http://google.com", pattern: "http://*.google.com/"});
-  pass({url: "http://docs.google.com", pattern: "http://*.google.com/"});
-
-  pass({url: "http://mozilla.org:8080", pattern: "http://mozilla.org/"});
-  pass({url: "http://mozilla.org:8080", pattern: "*://mozilla.org/"});
-  fail({url: "http://mozilla.org:8080", pattern: "http://mozilla.org:8080/"});
-
-  // Now try with * in the path.
-  pass({url: "http://mozilla.org", pattern: "http://mozilla.org/*"});
-  pass({url: "http://mozilla.org/", pattern: "http://mozilla.org/*"});
-
-  pass({url: "http://mozilla.org/", pattern: "*://mozilla.org/*"});
-  pass({url: "https://mozilla.org/", pattern: "*://mozilla.org/*"});
-  fail({url: "file://mozilla.org/", pattern: "*://mozilla.org/*"});
-  fail({url: "http://mozilla.com", pattern: "http://mozilla.*/*"});
-
-  pass({url: "http://google.com", pattern: "http://*.google.com/*"});
-  pass({url: "http://docs.google.com", pattern: "http://*.google.com/*"});
-
-  // Check path stuff.
-  fail({url: "http://mozilla.com/abc/def", pattern: "http://mozilla.com/"});
-  pass({url: "http://mozilla.com/abc/def", pattern: "http://mozilla.com/*"});
-  pass({url: "http://mozilla.com/abc/def", pattern: "http://mozilla.com/a*f"});
-  pass({url: "http://mozilla.com/abc/def", pattern: "http://mozilla.com/a*"});
-  pass({url: "http://mozilla.com/abc/def", pattern: "http://mozilla.com/*f"});
-  fail({url: "http://mozilla.com/abc/def", pattern: "http://mozilla.com/*e"});
-  fail({url: "http://mozilla.com/abc/def", pattern: "http://mozilla.com/*c"});
-
-  fail({url: "http:///a.html", pattern: "http:///a.html"});
-  pass({url: "file:///foo", pattern: "file:///foo*"});
-  pass({url: "file:///foo/bar.html", pattern: "file:///foo*"});
-
-  pass({url: "http://mozilla.org/a", pattern: "<all_urls>"});
-  pass({url: "https://mozilla.org/a", pattern: "<all_urls>"});
-  pass({url: "ftp://mozilla.org/a", pattern: "<all_urls>"});
-  pass({url: "file:///a", pattern: "<all_urls>"});
-  fail({url: "gopher://wuarchive.wustl.edu/a", pattern: "<all_urls>"});
-
-  // Multiple patterns.
-  pass({url: "http://mozilla.org", pattern: ["http://mozilla.org/"]});
-  pass({url: "http://mozilla.org", pattern: ["http://mozilla.org/", "http://mozilla.com/"]});
-  pass({url: "http://mozilla.com", pattern: ["http://mozilla.org/", "http://mozilla.com/"]});
-  fail({url: "http://mozilla.biz", pattern: ["http://mozilla.org/", "http://mozilla.com/"]});
-
-  // Match url with fragments.
-  pass({url: "http://mozilla.org/base#some-fragment", pattern: "http://mozilla.org/base"});
-}
-
-function test_overlaps() {
-  function test(filter, hosts, optional) {
-    const f = new MatchPattern(filter);
-    return f.overlapsPermissions(new MatchPattern(hosts), new MatchPattern(optional));
-  }
-
-  function pass({filter = [], hosts = [], optional = []}) {
-    ok(test(filter, hosts, optional), `Expected overlap: ${filter}, ${hosts} (${optional})`);
-  }
-
-  function fail({filter = [], hosts = [], optional = []}) {
-    ok(!test(filter, hosts, optional), `Expected no overlap: ${filter}, ${hosts} (${optional})`);
-  }
-
-  // Direct comparison.
-  pass({hosts: "http://ab.cd/", filter: "http://ab.cd/"});
-  fail({hosts: "http://ab.cd/", filter: "ftp://ab.cd/"});
-
-  // Wildcard protocol.
-  pass({hosts: "*://ab.cd/", filter: "https://ab.cd/"});
-  fail({hosts: "*://ab.cd/", filter: "ftp://ab.cd/"});
-
-  // Wildcard subdomain.
-  pass({hosts: "http://*.ab.cd/", filter: "http://ab.cd/"});
-  pass({hosts: "http://*.ab.cd/", filter: "http://www.ab.cd/"});
-  fail({hosts: "http://*.ab.cd/", filter: "http://ab.cd.ef/"});
-  fail({hosts: "http://*.ab.cd/", filter: "http://www.cd/"});
-
-  // Wildcard subsumed.
-  pass({hosts: "http://*.ab.cd/", filter: "http://*.cd/"});
-  fail({hosts: "http://*.cd/", filter: "http://*.xy/"});
-
-  // Subdomain vs substring.
-  fail({hosts: "http://*.ab.cd/", filter: "http://fake-ab.cd/"});
-  fail({hosts: "http://*.ab.cd/", filter: "http://*.fake-ab.cd/"});
-
-  // Wildcard domain.
-  pass({hosts: "http://*/", filter: "http://ab.cd/"});
-  fail({hosts: "http://*/", filter: "https://ab.cd/"});
-
-  // Wildcard wildcards.
-  pass({hosts: "<all_urls>", filter: "ftp://ab.cd/"});
-  fail({hosts: "<all_urls>", filter: ""});
-  fail({hosts: "<all_urls>"});
-
-  // Multiple hosts.
-  pass({hosts: ["http://ab.cd/"], filter: ["http://ab.cd/"]});
-  pass({hosts: ["http://ab.cd/", "http://ab.xy/"], filter: "http://ab.cd/"});
-  pass({hosts: ["http://ab.cd/", "http://ab.xy/"], filter: "http://ab.xy/"});
-  fail({hosts: ["http://ab.cd/", "http://ab.xy/"], filter: "http://ab.zz/"});
-
-  // Multiple Multiples.
-  pass({hosts: ["http://*.ab.cd/"], filter: ["http://ab.cd/", "http://www.ab.cd/"]});
-  pass({hosts: ["http://ab.cd/", "http://ab.xy/"], filter: ["http://ab.cd/", "http://ab.xy/"]});
-  fail({hosts: ["http://ab.cd/", "http://ab.xy/"], filter: ["http://ab.cd/", "http://ab.zz/"]});
-
-  // Optional.
-  pass({hosts: [], optional: "http://ab.cd/", filter: "http://ab.cd/"});
-  pass({hosts: "http://ab.cd/", optional: "http://ab.xy/", filter: ["http://ab.cd/", "http://ab.xy/"]});
-  fail({hosts: "http://ab.cd/", optional: "https://ab.xy/", filter: "http://ab.xy/"});
-}
-
-function run_test() {
-  test_matches();
-  test_overlaps();
-}
--- a/toolkit/modules/tests/xpcshell/test_MatchURLFilters.js
+++ b/toolkit/modules/tests/xpcshell/test_MatchURLFilters.js
@@ -1,14 +1,14 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
-Components.utils.import("resource://gre/modules/MatchPattern.jsm");
+Components.utils.import("resource://gre/modules/MatchURLFilters.jsm");
 Components.utils.import("resource://gre/modules/Services.jsm");
 
 function createTestFilter({url, filters}) {
   let m = new MatchURLFilters(filters);
   return m.matches(url);
 }
 
 function expectPass({url, filters}) {
--- a/toolkit/modules/tests/xpcshell/xpcshell.ini
+++ b/toolkit/modules/tests/xpcshell/xpcshell.ini
@@ -23,20 +23,16 @@ skip-if = toolkit == 'android'
 skip-if = toolkit == 'android'
 [test_Integration.js]
 [test_jsesc.js]
 skip-if = toolkit == 'android'
 [test_JSONFile.js]
 skip-if = toolkit == 'android'
 [test_Log.js]
 skip-if = toolkit == 'android'
-[test_MatchPattern.js]
-skip-if = toolkit == 'android'
-[test_MatchGlobs.js]
-skip-if = toolkit == 'android'
 [test_MatchURLFilters.js]
 skip-if = toolkit == 'android'
 [test_NewTabUtils.js]
 skip-if = toolkit == 'android'
 [test_ObjectUtils.js]
 skip-if = toolkit == 'android'
 [test_ObjectUtils_strict.js]
 skip-if = toolkit == 'android'
--- a/tools/lint/eslint/modules.json
+++ b/tools/lint/eslint/modules.json
@@ -126,17 +126,17 @@
   "logger.jsm": ["Logger"],
   "logging.js": ["getTestLogger", "initTestLogging"],
   "LoginManagerContent.jsm": ["LoginManagerContent", "LoginFormFactory", "UserAutoCompleteResult"],
   "LoginRecipes.jsm": ["LoginRecipesContent", "LoginRecipesParent"],
   "logmanager.js": ["LogManager"],
   "lz4.js": ["Lz4"],
   "lz4_internal.js": ["Primitives"],
   "main.js": ["Weave"],
-  "MatchPattern.jsm": ["MatchPattern", "MatchGlobs", "MatchURLFilters"],
+  "MatchURLFilters.jsm": ["MatchURLFilters"],
   "mcc_iso3166_table.jsm": ["MCC_ISO3166_TABLE"],
   "message.js": ["Command", "Message", "MessageOrigin", "Response"],
   "MessageContext.jsm": ["MessageContext"],
   "Messaging.jsm": ["sendMessageToJava", "Messaging", "EventDispatcher"],
   "microformat-shiv.js": ["Microformats"],
   "MigrationUtils.jsm": ["MigrationUtils", "MigratorPrototype"],
   "mozelement.js": ["Elem", "Selector", "ID", "Link", "XPath", "Name", "Lookup", "MozMillElement", "MozMillCheckBox", "MozMillRadio", "MozMillDropList", "MozMillTextBox", "subclasses"],
   "mozmill.js": ["controller", "utils", "elementslib", "os", "getBrowserController", "newBrowserController", "getAddonsController", "getPreferencesController", "newMail3PaneController", "getMail3PaneController", "wm", "platform", "getAddrbkController", "getMsgComposeController", "getDownloadsController", "Application", "findElement", "getPlacesController", "isMac", "isLinux", "isWindows", "firePythonCallback", "getAddons"],
--- a/widget/android/GeckoEditableSupport.cpp
+++ b/widget/android/GeckoEditableSupport.cpp
@@ -7,16 +7,17 @@
 #include "GeckoEditableSupport.h"
 
 #include "AndroidRect.h"
 #include "KeyEvent.h"
 #include "PuppetWidget.h"
 #include "nsIContent.h"
 #include "nsISelection.h"
 
+#include "mozilla/EventStateManager.h"
 #include "mozilla/IMEStateManager.h"
 #include "mozilla/TextComposition.h"
 #include "mozilla/TextEventDispatcherListener.h"
 #include "mozilla/TextEvents.h"
 
 #include <android/log.h>
 
 #ifdef DEBUG_ANDROID_IME
@@ -1148,32 +1149,32 @@ GeckoEditableSupport::SetInputContext(co
 {
     MOZ_ASSERT(mEditable);
 
     ALOGIME("IME: SetInputContext: s=0x%X, 0x%X, action=0x%X, 0x%X",
             aContext.mIMEState.mEnabled, aContext.mIMEState.mOpen,
             aAction.mCause, aAction.mFocusChange);
 
     mInputContext = aContext;
+    const bool isUserAction = EventStateManager::IsHandlingUserInput();
 
     if (mInputContext.mIMEState.mEnabled == IMEState::ENABLED &&
-        aAction.UserMightRequestOpenVKB()) {
+        isUserAction &&
+        aAction.mFocusChange == InputContextAction::FOCUS_NOT_CHANGED) {
         // Don't reset keyboard when we should simply open the vkb
         mEditable->NotifyIME(GeckoEditableListener::NOTIFY_IME_OPEN_VKB);
         return;
     }
 
     if (mIMEUpdatingContext) {
         return;
     }
     mIMEUpdatingContext = true;
 
     RefPtr<GeckoEditableSupport> self(this);
-    bool isUserAction = aAction.IsUserAction();
-
     nsAppShell::PostEvent([this, self, isUserAction] {
         nsCOMPtr<nsIWidget> widget = GetWidget();
 
         mIMEUpdatingContext = false;
         if (!widget || widget->Destroyed()) {
             return;
         }
         mEditable->NotifyIMEContext(mInputContext.mIMEState.mEnabled,