Merge mozilla-central to inbound. a=merge CLOSED TREE
authorNarcis Beleuzu <nbeleuzu@mozilla.com>
Fri, 25 Jan 2019 06:41:23 +0200
changeset 515412 dc5946f21fce29326b7020d0c01e7ed40a74a122
parent 515411 c00ab2984f8a48fdf89f3793e8fe00da5520014c (current diff)
parent 515395 53330ebb7967c54ae13a018a1b2935b3fcef67b0 (diff)
child 515413 0d747e05337bdedc46a153a7ae710cda95913c62
push id1953
push userffxbld-merge
push dateMon, 11 Mar 2019 12:10:20 +0000
treeherdermozilla-release@9c35dcbaa899 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone66.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge mozilla-central to inbound. a=merge CLOSED TREE
dom/svg/SVGAngle.h
dom/svg/SVGBoolean.h
dom/svg/SVGElement.h
toolkit/components/passwordmgr/test/subtst_prompt_async.html
toolkit/components/passwordmgr/test/test_prompt_async.html
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -42,17 +42,16 @@ XPCOMUtils.defineLazyModuleGetters(this,
   PlacesUtils: "resource://gre/modules/PlacesUtils.jsm",
   PlacesUIUtils: "resource:///modules/PlacesUIUtils.jsm",
   PlacesTransactions: "resource://gre/modules/PlacesTransactions.jsm",
   PluralForm: "resource://gre/modules/PluralForm.jsm",
   Pocket: "chrome://pocket/content/Pocket.jsm",
   PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.jsm",
   ProcessHangMonitor: "resource:///modules/ProcessHangMonitor.jsm",
   PromiseUtils: "resource://gre/modules/PromiseUtils.jsm",
-  ReaderMode: "resource://gre/modules/ReaderMode.jsm",
   ReaderParent: "resource:///modules/ReaderParent.jsm",
   SafeBrowsing: "resource://gre/modules/SafeBrowsing.jsm",
   Sanitizer: "resource:///modules/Sanitizer.jsm",
   SessionStartup: "resource:///modules/sessionstore/SessionStartup.jsm",
   SessionStore: "resource:///modules/sessionstore/SessionStore.jsm",
   ShortcutUtils: "resource://gre/modules/ShortcutUtils.jsm",
   SimpleServiceDiscovery: "resource://gre/modules/SimpleServiceDiscovery.jsm",
   SiteDataManager: "resource:///modules/SiteDataManager.jsm",
@@ -76,16 +75,21 @@ XPCOMUtils.defineLazyModuleGetters(this,
   ZoomUI: "resource:///modules/ZoomUI.jsm",
 });
 
 if (AppConstants.MOZ_CRASHREPORTER) {
   ChromeUtils.defineModuleGetter(this, "PluginCrashReporter",
     "resource:///modules/ContentCrashHandlers.jsm");
 }
 
+if (!Services.prefs.getBoolPref("browser.urlbar.quantumbar", false)) {
+  ChromeUtils.defineModuleGetter(this, "ReaderMode",
+    "resource://gre/modules/ReaderMode.jsm");
+}
+
 XPCOMUtils.defineLazyScriptGetter(this, "PlacesTreeView",
                                   "chrome://browser/content/places/treeView.js");
 XPCOMUtils.defineLazyScriptGetter(this, ["PlacesInsertionPoint", "PlacesController",
                                          "PlacesControllerDragHelper"],
                                   "chrome://browser/content/places/controller.js");
 XPCOMUtils.defineLazyScriptGetter(this, "PrintUtils",
                                   "chrome://global/content/printUtils.js");
 XPCOMUtils.defineLazyScriptGetter(this, "ZoomManager",
--- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_about.js
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_about.js
@@ -40,16 +40,27 @@ async function testLinkOpensUrl({ win, t
     content.document.getElementById(elemId).click();
   });
   await loadedPromise;
   is(tab.currentURI.spec, expectedUrl,
      `Clicking ${elementId} opened ${expectedUrl} in the same tab.`);
 }
 
 /**
+ * Enables the searchUI pref.
+ */
+function enableSearchUI() {
+  Services.prefs.setBoolPref("browser.privatebrowsing.searchUI", true);
+
+  registerCleanupFunction(function() {
+    Services.prefs.clearUserPref("browser.privatebrowsing.searchUI");
+  });
+}
+
+/**
  * Tests the links in "about:privatebrowsing".
  */
 add_task(async function test_links() {
   // Use full version and change the remote URLs to prevent network access.
   Services.prefs.setCharPref("app.support.baseURL", "https://example.com/");
   Services.prefs.setCharPref("privacy.trackingprotection.introURL",
                              "https://example.com/tour");
   registerCleanupFunction(function() {
@@ -71,16 +82,17 @@ add_task(async function test_links() {
 
   await BrowserTestUtils.closeWindow(win);
 });
 
 /**
  * Tests the private-browsing-myths link in "about:privatebrowsing".
  */
 add_task(async function test_myths_link() {
+  enableSearchUI();
   Services.prefs.setCharPref("app.support.baseURL", "https://example.com/");
   registerCleanupFunction(function() {
     Services.prefs.clearUserPref("app.support.baseURL");
   });
 
   let { win, tab } = await openAboutPrivateBrowsing();
 
   await testLinkOpensUrl({ win, tab,
@@ -98,16 +110,17 @@ function urlBarHasHiddenFocus(win) {
 function urlBarHasNormalFocus(win) {
   return win.gURLBar.hasAttribute("focused") && !win.gURLBar.classList.contains("hidden-focus");
 }
 
 /**
  * Tests the search hand-off on character keydown in "about:privatebrowsing".
  */
 add_task(async function test_search_handoff_on_keydown() {
+  enableSearchUI();
   let { win, tab } = await openAboutPrivateBrowsing();
 
   await ContentTask.spawn(tab, null, async function() {
     let btn = content.document.getElementById("search-handoff-button");
     btn.click();
     ok(btn.classList.contains("focused"), "in-content search has focus styles");
   });
   ok(urlBarHasHiddenFocus(win), "url bar has hidden focused");
@@ -128,32 +141,34 @@ add_task(async function test_search_hand
 
   await BrowserTestUtils.closeWindow(win);
 });
 
 /**
  * Tests the search hand-off on composition start in "about:privatebrowsing".
  */
 add_task(async function test_search_handoff_on_composition_start() {
+  enableSearchUI();
   let { win, tab } = await openAboutPrivateBrowsing();
 
   await ContentTask.spawn(tab, null, async function() {
     content.document.getElementById("search-handoff-button").click();
   });
   ok(urlBarHasHiddenFocus(win), "url bar has hidden focused");
   await new Promise(r => EventUtils.synthesizeComposition({type: "compositionstart"}, win, r));
   ok(urlBarHasNormalFocus(win), "url bar has normal focused");
 
   await BrowserTestUtils.closeWindow(win);
 });
 
 /**
 * Tests the search hand-off on paste in "about:privatebrowsing".
 */
 add_task(async function test_search_handoff_on_paste() {
+  enableSearchUI();
   let { win, tab } = await openAboutPrivateBrowsing();
 
   await ContentTask.spawn(tab, null, async function() {
     content.document.getElementById("search-handoff-button").click();
   });
   ok(urlBarHasHiddenFocus(win), "url bar has hidden focused");
   var helper = SpecialPowers.Cc["@mozilla.org/widget/clipboardhelper;1"]
      .getService(SpecialPowers.Ci.nsIClipboardHelper);
--- a/browser/components/shell/ShellService.jsm
+++ b/browser/components/shell/ShellService.jsm
@@ -81,17 +81,17 @@ let ShellServiceInternal = {
   isDefaultBrowser(startupCheck, forAllTypes) {
     // If this is the first browser window, maintain internal state that we've
     // checked this session (so that subsequent window opens don't show the
     // default browser dialog).
     if (startupCheck) {
       this._checkedThisSession = true;
     }
     if (this.shellService) {
-      return this.shellService.isDefaultBrowser(startupCheck, forAllTypes);
+      return this.shellService.isDefaultBrowser(forAllTypes);
     }
     return false;
   },
 };
 
 XPCOMUtils.defineLazyServiceGetter(ShellServiceInternal, "shellService",
   "@mozilla.org/browser/shell-service;1", Ci.nsIShellService);
 
--- a/browser/components/shell/nsGNOMEShellService.cpp
+++ b/browser/components/shell/nsGNOMEShellService.cpp
@@ -185,17 +185,17 @@ bool nsGNOMEShellService::CheckHandlerMa
 
   if (!KeyMatchesAppName(command.get()))
     return false;  // the handler is set to another app
 
   return true;
 }
 
 NS_IMETHODIMP
-nsGNOMEShellService::IsDefaultBrowser(bool aStartupCheck, bool aForAllTypes,
+nsGNOMEShellService::IsDefaultBrowser(bool aForAllTypes,
                                       bool *aIsDefaultBrowser) {
   *aIsDefaultBrowser = false;
 
   if (IsRunningAsASnap()) {
     const gchar *argv[] = {"xdg-settings", "check", "default-web-browser",
                            "firefox.desktop", nullptr};
     GSpawnFlags flags = static_cast<GSpawnFlags>(G_SPAWN_SEARCH_PATH |
                                                  G_SPAWN_STDERR_TO_DEV_NULL);
--- a/browser/components/shell/nsIShellService.idl
+++ b/browser/components/shell/nsIShellService.idl
@@ -12,25 +12,21 @@ webidl Element;
 [scriptable, uuid(2d1a95e4-5bd8-4eeb-b0a8-c1455fd2a357)]
 interface nsIShellService : nsISupports
 {
   /**
    * Determines whether or not Firefox is the "Default Browser."
    * This is simply whether or not Firefox is registered to handle
    * http links.
    *
-   * @param aStartupCheck true if this is the check being performed
-   *                      by the first browser window at startup,
-   *                      false otherwise.
    * @param aForAllTypes  true if the check should be made for HTTP and HTML.
    *                      false if the check should be made for HTTP only.
    *                      This parameter may be ignored on some platforms.
    */
-  boolean isDefaultBrowser(in boolean aStartupCheck,
-                           [optional] in boolean aForAllTypes);
+  boolean isDefaultBrowser([optional] in boolean aForAllTypes);
 
   /**
    * Registers Firefox as the "Default Browser."
    *
    * @param aClaimAllTypes Register Firefox as the handler for 
    *                       additional protocols (ftp, chrome etc)
    *                       and web documents (.html, .xhtml etc).
    * @param aForAllUsers   Whether or not Firefox should attempt
--- a/browser/components/shell/nsMacShellService.cpp
+++ b/browser/components/shell/nsMacShellService.cpp
@@ -35,17 +35,17 @@ using mozilla::dom::Element;
       "/System/Library/PreferencePanes/DesktopScreenEffectsPref.prefPane")
 
 #define SAFARI_BUNDLE_IDENTIFIER "com.apple.Safari"
 
 NS_IMPL_ISUPPORTS(nsMacShellService, nsIMacShellService, nsIShellService,
                   nsIWebProgressListener)
 
 NS_IMETHODIMP
-nsMacShellService::IsDefaultBrowser(bool aStartupCheck, bool aForAllTypes,
+nsMacShellService::IsDefaultBrowser(bool aForAllTypes,
                                     bool* aIsDefaultBrowser) {
   *aIsDefaultBrowser = false;
 
   CFStringRef firefoxID = ::CFBundleGetIdentifier(::CFBundleGetMainBundle());
   if (!firefoxID) {
     // CFBundleGetIdentifier is expected to return nullptr only if the specified
     // bundle doesn't have a bundle identifier in its plist. In this case, that
     // means a failure, since our bundle does have an identifier.
--- a/browser/components/shell/nsWindowsShellService.cpp
+++ b/browser/components/shell/nsWindowsShellService.cpp
@@ -194,20 +194,18 @@ static nsresult GetAppRegName(nsAutoStri
                  appDirStr.Length() * sizeof(nsAutoString::char_type));
   aAppRegName.AppendInt((int)(hash >> 32), 16);
   aAppRegName.AppendInt((int)hash, 16);
 
   return rv;
 }
 
 NS_IMETHODIMP
-nsWindowsShellService::IsDefaultBrowser(bool aStartupCheck, bool aForAllTypes,
+nsWindowsShellService::IsDefaultBrowser(bool aForAllTypes,
                                         bool* aIsDefaultBrowser) {
-  mozilla::Unused << aStartupCheck;
-
   *aIsDefaultBrowser = false;
 
   RefPtr<IApplicationAssociationRegistration> pAAR;
   HRESULT hr = CoCreateInstance(
       CLSID_ApplicationAssociationRegistration, nullptr, CLSCTX_INPROC,
       IID_IApplicationAssociationRegistration, getter_AddRefs(pAAR));
   if (FAILED(hr)) {
     return NS_OK;
--- a/browser/components/urlbar/UrlbarInput.jsm
+++ b/browser/components/urlbar/UrlbarInput.jsm
@@ -7,16 +7,17 @@
 var EXPORTED_SYMBOLS = ["UrlbarInput"];
 
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetters(this, {
   AppConstants: "resource://gre/modules/AppConstants.jsm",
   ExtensionSearchHandler: "resource://gre/modules/ExtensionSearchHandler.jsm",
   PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.jsm",
+  ReaderMode: "resource://gre/modules/ReaderMode.jsm",
   Services: "resource://gre/modules/Services.jsm",
   UrlbarController: "resource:///modules/UrlbarController.jsm",
   UrlbarPrefs: "resource:///modules/UrlbarPrefs.jsm",
   UrlbarQueryContext: "resource:///modules/UrlbarUtils.jsm",
   UrlbarUtils: "resource:///modules/UrlbarUtils.jsm",
   UrlbarValueFormatter: "resource:///modules/UrlbarValueFormatter.jsm",
   UrlbarView: "resource:///modules/UrlbarView.jsm",
 });
@@ -156,17 +157,17 @@ class UrlbarInput {
    * @param {nsIURI} uri
    *   The URI to be converted
    * @returns {nsIURI}
    *   The converted, exposable URI
    */
   makeURIReadable(uri) {
     // Avoid copying 'about:reader?url=', and always provide the original URI:
     // Reader mode ensures we call createExposableURI itself.
-    let readerStrippedURI = this.window.ReaderMode.getOriginalUrlObjectForDisplay(uri.displaySpec);
+    let readerStrippedURI = ReaderMode.getOriginalUrlObjectForDisplay(uri.displaySpec);
     if (readerStrippedURI) {
       return readerStrippedURI;
     }
 
     try {
       return Services.uriFixup.createExposableURI(uri);
     } catch (ex) {}
 
@@ -486,16 +487,21 @@ class UrlbarInput {
 
   get value() {
     return this._untrimmedValue;
   }
 
   set value(val) {
     this._untrimmedValue = val;
 
+    let originalUrl = ReaderMode.getOriginalUrlObjectForDisplay(val);
+    if (originalUrl) {
+      val = originalUrl.displaySpec;
+    }
+
     val = this.trimValue(val);
 
     this.valueIsTyped = false;
     this.inputField.value = val;
     this.formatValue();
 
     // Dispatch ValueChange event for accessibility.
     let event = this.document.createEvent("Events");
--- a/build/autoconf/compiler-opts.m4
+++ b/build/autoconf/compiler-opts.m4
@@ -119,17 +119,17 @@ if test "$GNU_CC" -a "$GCC_USE_GNU_LD" -
         LD_SUPPORTS_ICF,
         [echo 'int foo() {return 42;}' \
               'int bar() {return 42;}' \
               'int main() {return foo() - bar();}' > conftest.${ac_ext}
         # If the linker supports ICF, foo and bar symbols will have
         # the same address
         if AC_TRY_COMMAND([${CC-cc} -o conftest${ac_exeext} $LDFLAGS -Wl,--icf=safe -ffunction-sections conftest.${ac_ext} $LIBS 1>&2]) &&
            test -s conftest${ac_exeext} &&
-           objdump -t conftest${ac_exeext} | awk changequote(<<, >>)'{a[<<$>>6] = <<$>>1} END {if (a["foo"] && (a["foo"] != a["bar"])) { exit 1 }}'changequote([, ]); then
+           $LLVM_OBJDUMP -t conftest${ac_exeext} | awk changequote(<<, >>)'{a[<<$>>6] = <<$>>1} END {if (a["foo"] && (a["foo"] != a["bar"])) { exit 1 }}'changequote([, ]); then
             LD_SUPPORTS_ICF=yes
         else
             LD_SUPPORTS_ICF=no
         fi
         rm -rf conftest*])
     if test "$LD_SUPPORTS_ICF" = yes; then
         _SAVE_LDFLAGS="$LDFLAGS -Wl,--icf=safe"
         LDFLAGS="$LDFLAGS -Wl,--icf=safe -Wl,--print-icf-sections"
--- a/build/moz.configure/init.configure
+++ b/build/moz.configure/init.configure
@@ -4,16 +4,19 @@
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 include('util.configure')
 include('checks.configure')
 
 # Make `toolkit` available when toolkit/moz.configure is not included.
 toolkit = dependable(None)
+# Likewise with `bindgen_config_paths` when
+# build/moz.configure/bindgen.configure is not included.
+bindgen_config_paths = dependable(None)
 
 option(env='DIST', nargs=1, help='DIST directory')
 
 
 # Do not allow objdir == srcdir builds.
 # ==============================================================
 @depends('--help', 'DIST')
 @imports(_from='__builtin__', _import='open')
--- a/dom/canvas/WebGLContext.cpp
+++ b/dom/canvas/WebGLContext.cpp
@@ -1715,18 +1715,19 @@ gfx::IntSize WebGLContext::DrawingBuffer
   const gfx::IntSize zeros{0, 0};
   if (IsContextLost()) return zeros;
 
   if (!EnsureDefaultFB()) return zeros;
 
   return mDefaultFB->mSize;
 }
 
-bool WebGLContext::ValidateAndInitFB(const WebGLFramebuffer* const fb) {
-  if (fb) return fb->ValidateAndInitAttachments();
+bool WebGLContext::ValidateAndInitFB(const WebGLFramebuffer* const fb,
+                                     const GLenum incompleteFbError) {
+  if (fb) return fb->ValidateAndInitAttachments(incompleteFbError);
 
   if (!EnsureDefaultFB()) return false;
 
   if (mDefaultFB_IsInvalid) {
     // Clear it!
     gl->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mDefaultFB->mFB);
     const webgl::ScopedPrepForResourceClear scopedPrep(*this);
     if (!mOptions.alpha) {
@@ -1753,21 +1754,21 @@ bool WebGLContext::BindCurFBForDraw() {
   if (!ValidateAndInitFB(fb)) return false;
 
   DoBindFB(fb);
   return true;
 }
 
 bool WebGLContext::BindCurFBForColorRead(
     const webgl::FormatUsageInfo** const out_format, uint32_t* const out_width,
-    uint32_t* const out_height) {
+    uint32_t* const out_height, const GLenum incompleteFbError) {
   const auto& fb = mBoundReadFramebuffer;
 
   if (fb) {
-    if (!ValidateAndInitFB(fb)) return false;
+    if (!ValidateAndInitFB(fb, incompleteFbError)) return false;
     if (!fb->ValidateForColorRead(out_format, out_width, out_height))
       return false;
 
     gl->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, fb->mGLName);
     return true;
   }
 
   if (!BindDefaultFBForRead()) return false;
--- a/dom/canvas/WebGLContext.h
+++ b/dom/canvas/WebGLContext.h
@@ -415,17 +415,17 @@ class WebGLContext : public nsICanvasRen
     void OnCheckContextLost() const {
 #ifdef DEBUG
       mStillNeedsToCheckContextLost = false;
 #endif
     }
   };
 
   void SynthesizeGLError(GLenum err) const;
-  void SynthesizeGLError(GLenum err, const char* fmt, ...) const
+  void GenerateError(GLenum err, const char* fmt, ...) const
       MOZ_FORMAT_PRINTF(3, 4);
 
   void ErrorInvalidEnum(const char* fmt = 0, ...) const MOZ_FORMAT_PRINTF(2, 3);
   void ErrorInvalidOperation(const char* fmt = 0, ...) const
       MOZ_FORMAT_PRINTF(2, 3);
   void ErrorInvalidValue(const char* fmt = 0, ...) const
       MOZ_FORMAT_PRINTF(2, 3);
   void ErrorInvalidFramebufferOperation(const char* fmt = 0, ...) const
@@ -1944,23 +1944,27 @@ class WebGLContext : public nsICanvasRen
   mutable gfx::IntSize mRequestedSize;
   mutable UniquePtr<gl::MozFramebuffer> mDefaultFB;
   mutable bool mDefaultFB_IsInvalid = false;
   mutable UniquePtr<gl::MozFramebuffer> mResolvedDefaultFB;
 
   // --
 
   bool EnsureDefaultFB();
-  bool ValidateAndInitFB(const WebGLFramebuffer* fb);
+  bool ValidateAndInitFB(
+      const WebGLFramebuffer* fb,
+      GLenum incompleteFbError = LOCAL_GL_INVALID_FRAMEBUFFER_OPERATION);
   void DoBindFB(const WebGLFramebuffer* fb,
                 GLenum target = LOCAL_GL_FRAMEBUFFER) const;
 
   bool BindCurFBForDraw();
-  bool BindCurFBForColorRead(const webgl::FormatUsageInfo** out_format,
-                             uint32_t* out_width, uint32_t* out_height);
+  bool BindCurFBForColorRead(
+      const webgl::FormatUsageInfo** out_format, uint32_t* out_width,
+      uint32_t* out_height,
+      GLenum incompleteFbError = LOCAL_GL_INVALID_FRAMEBUFFER_OPERATION);
   void DoColorMask(uint8_t bitmask) const;
   void BlitBackbufferToCurDriverFB() const;
   bool BindDefaultFBForRead();
 
   // --
 
  public:
   void LoseOldestWebGLContextIfLimitExceeded();
--- a/dom/canvas/WebGLContextState.cpp
+++ b/dom/canvas/WebGLContextState.cpp
@@ -233,17 +233,18 @@ JS::Value WebGLContext::GetParameter(JSC
 
     case LOCAL_GL_GENERATE_MIPMAP_HINT:
       return JS::NumberValue(mGenerateMipmapHint);
 
     case LOCAL_GL_IMPLEMENTATION_COLOR_READ_FORMAT:
     case LOCAL_GL_IMPLEMENTATION_COLOR_READ_TYPE: {
       const webgl::FormatUsageInfo* usage;
       uint32_t width, height;
-      if (!BindCurFBForColorRead(&usage, &width, &height))
+      if (!BindCurFBForColorRead(&usage, &width, &height,
+                                 LOCAL_GL_INVALID_OPERATION))
         return JS::NullValue();
 
       const auto implPI = ValidImplementationColorReadPI(usage);
 
       GLenum ret;
       if (pname == LOCAL_GL_IMPLEMENTATION_COLOR_READ_FORMAT) {
         ret = implPI.format;
       } else {
--- a/dom/canvas/WebGLContextUtils.cpp
+++ b/dom/canvas/WebGLContextUtils.cpp
@@ -136,17 +136,18 @@ void WebGLContext::SynthesizeGLError(GLe
    * multiple 'flags', as errors might be caught in different parts of
    * a distributed implementation.
    * We're signing up as a distributed implementation here, with
    * separate flags for WebGL and the underlying GLContext.
    */
   if (!mWebGLError) mWebGLError = err;
 }
 
-void WebGLContext::SynthesizeGLError(GLenum err, const char* fmt, ...) const {
+void WebGLContext::GenerateError(const GLenum err, const char* const fmt,
+                                 ...) const {
   va_list va;
   va_start(va, fmt);
   GenerateWarning(fmt, va);
   va_end(va);
 
   return SynthesizeGLError(err);
 }
 
--- a/dom/canvas/WebGLFramebuffer.cpp
+++ b/dom/canvas/WebGLFramebuffer.cpp
@@ -675,24 +675,25 @@ FBStatus WebGLFramebuffer::PrecheckFrame
   }
 
   return LOCAL_GL_FRAMEBUFFER_COMPLETE;
 }
 
 ////////////////////////////////////////
 // Validation
 
-bool WebGLFramebuffer::ValidateAndInitAttachments() const {
+bool WebGLFramebuffer::ValidateAndInitAttachments(
+    const GLenum incompleteFbError) const {
   MOZ_ASSERT(mContext->mBoundDrawFramebuffer == this ||
              mContext->mBoundReadFramebuffer == this);
 
   const auto fbStatus = CheckFramebufferStatus();
   if (fbStatus == LOCAL_GL_FRAMEBUFFER_COMPLETE) return true;
 
-  mContext->ErrorInvalidFramebufferOperation("Framebuffer must be complete.");
+  mContext->GenerateError(incompleteFbError, "Framebuffer must be complete.");
   return false;
 }
 
 bool WebGLFramebuffer::ValidateClearBufferType(GLenum buffer,
                                                uint32_t drawBuffer,
                                                GLenum funcType) const {
   if (buffer != LOCAL_GL_COLOR) return true;
 
--- a/dom/canvas/WebGLFramebuffer.h
+++ b/dom/canvas/WebGLFramebuffer.h
@@ -213,17 +213,17 @@ class WebGLFramebuffer final : public ns
   void DoDeferredAttachments() const;
   void RefreshDrawBuffers() const;
   void RefreshReadBuffer() const;
   void ResolveAttachmentData() const;
 
  public:
   void DetachTexture(const WebGLTexture* tex);
   void DetachRenderbuffer(const WebGLRenderbuffer* rb);
-  bool ValidateAndInitAttachments() const;
+  bool ValidateAndInitAttachments(GLenum incompleteFbError) const;
   bool ValidateClearBufferType(GLenum buffer, uint32_t drawBuffer,
                                GLenum funcType) const;
 
   bool ValidateForColorRead(const webgl::FormatUsageInfo** out_format,
                             uint32_t* out_width, uint32_t* out_height) const;
 
   ////////////////
   // Getters
--- a/dom/svg/DOMSVGAnimatedLengthList.cpp
+++ b/dom/svg/DOMSVGAnimatedLengthList.cpp
@@ -1,22 +1,22 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "DOMSVGAnimatedLengthList.h"
 
-#include "nsCOMPtr.h"
 #include "DOMSVGLengthList.h"
 #include "SVGAnimatedLengthList.h"
 #include "SVGAttrTearoffTable.h"
 #include "mozilla/dom/SVGAnimatedLengthListBinding.h"
 #include "mozilla/dom/SVGElement.h"
+#include "mozilla/RefPtr.h"
 
 // See the architecture comment in this file's header.
 
 namespace mozilla {
 namespace dom {
 
 static inline SVGAttrTearoffTable<SVGAnimatedLengthList,
                                   DOMSVGAnimatedLengthList>&
--- a/dom/svg/DOMSVGAnimatedLengthList.h
+++ b/dom/svg/DOMSVGAnimatedLengthList.h
@@ -2,20 +2,20 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef MOZILLA_DOMSVGANIMATEDLENGTHLIST_H__
 #define MOZILLA_DOMSVGANIMATEDLENGTHLIST_H__
 
-#include "nsCOMPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "SVGElement.h"
 #include "mozilla/Attributes.h"
+#include "mozilla/RefPtr.h"
 
 namespace mozilla {
 
 class SVGAnimatedLengthList;
 class SVGLengthList;
 
 namespace dom {
 
--- a/dom/svg/DOMSVGAnimatedNumberList.cpp
+++ b/dom/svg/DOMSVGAnimatedNumberList.cpp
@@ -1,22 +1,22 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "DOMSVGAnimatedNumberList.h"
 
-#include "nsCOMPtr.h"
 #include "DOMSVGNumberList.h"
 #include "SVGAnimatedNumberList.h"
 #include "SVGAttrTearoffTable.h"
 #include "mozilla/dom/SVGAnimatedNumberListBinding.h"
 #include "mozilla/dom/SVGElement.h"
+#include "mozilla/RefPtr.h"
 
 // See the architecture comment in this file's header.
 
 namespace mozilla {
 namespace dom {
 
 static inline SVGAttrTearoffTable<SVGAnimatedNumberList,
                                   DOMSVGAnimatedNumberList>&
--- a/dom/svg/DOMSVGAnimatedNumberList.h
+++ b/dom/svg/DOMSVGAnimatedNumberList.h
@@ -2,21 +2,21 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef MOZILLA_DOMSVGANIMATEDNUMBERLIST_H__
 #define MOZILLA_DOMSVGANIMATEDNUMBERLIST_H__
 
-#include "nsCOMPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "SVGElement.h"
 #include "nsWrapperCache.h"
 #include "mozilla/Attributes.h"
+#include "mozilla/RefPtr.h"
 
 namespace mozilla {
 
 class SVGAnimatedNumberList;
 class SVGNumberList;
 
 namespace dom {
 
--- a/dom/svg/DOMSVGAnimatedTransformList.h
+++ b/dom/svg/DOMSVGAnimatedTransformList.h
@@ -2,22 +2,21 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_SVGAnimatedTransformList_h
 #define mozilla_dom_SVGAnimatedTransformList_h
 
-#include "nsAutoPtr.h"
-#include "nsCOMPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "SVGElement.h"
 #include "nsWrapperCache.h"
 #include "mozilla/Attributes.h"
+#include "mozilla/RefPtr.h"
 
 namespace mozilla {
 
 class DOMSVGTransformList;
 class SVGAnimatedTransformList;
 
 namespace dom {
 
--- a/dom/svg/DOMSVGNumber.h
+++ b/dom/svg/DOMSVGNumber.h
@@ -3,20 +3,22 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef MOZILLA_DOMSVGNUMBER_H__
 #define MOZILLA_DOMSVGNUMBER_H__
 
 #include "DOMSVGNumberList.h"
+#include "nsCOMPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsTArray.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/ErrorResult.h"
+#include "mozilla/RefPtr.h"
 #include "nsWrapperCache.h"
 
 #define MOZ_SVG_LIST_INDEX_BIT_COUNT 27  // supports > 134 million list items
 
 namespace mozilla {
 
 namespace dom {
 class SVGElement;
--- a/dom/svg/DOMSVGNumberList.cpp
+++ b/dom/svg/DOMSVGNumberList.cpp
@@ -5,18 +5,18 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "DOMSVGNumberList.h"
 
 #include "SVGElement.h"
 #include "DOMSVGNumber.h"
 #include "nsError.h"
 #include "SVGAnimatedNumberList.h"
-#include "nsCOMPtr.h"
 #include "mozilla/dom/SVGNumberListBinding.h"
+#include "mozilla/RefPtr.h"
 #include <algorithm>
 
 // See the comment in this file's header.
 
 // local helper functions
 namespace {
 
 using mozilla::dom::DOMSVGNumber;
--- a/dom/svg/DOMSVGNumberList.h
+++ b/dom/svg/DOMSVGNumberList.h
@@ -9,16 +9,17 @@
 
 #include "DOMSVGAnimatedNumberList.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsDebug.h"
 #include "nsTArray.h"
 #include "SVGNumberList.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/ErrorResult.h"
+#include "mozilla/RefPtr.h"
 
 namespace mozilla {
 
 namespace dom {
 class DOMSVGNumber;
 class SVGElement;
 
 /**
--- a/dom/svg/DOMSVGPathSegList.cpp
+++ b/dom/svg/DOMSVGPathSegList.cpp
@@ -1,24 +1,24 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "DOMSVGPathSegList.h"
 
-#include "nsCOMPtr.h"
 #include "DOMSVGPathSeg.h"
 #include "nsError.h"
 #include "SVGAnimatedPathSegList.h"
 #include "SVGAttrTearoffTable.h"
 #include "SVGPathSegUtils.h"
 #include "mozilla/dom/SVGElement.h"
 #include "mozilla/dom/SVGPathSegListBinding.h"
+#include "mozilla/RefPtr.h"
 
 using namespace mozilla::dom;
 
 // See the comment in this file's header.
 
 namespace mozilla {
 
 static inline SVGAttrTearoffTable<void, DOMSVGPathSegList>&
--- a/dom/svg/DOMSVGPathSegList.h
+++ b/dom/svg/DOMSVGPathSegList.h
@@ -2,24 +2,24 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef MOZILLA_DOMSVGPATHSEGLIST_H__
 #define MOZILLA_DOMSVGPATHSEGLIST_H__
 
-#include "nsCOMPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsDebug.h"
 #include "SVGElement.h"
 #include "nsTArray.h"
 #include "SVGPathData.h"  // IWYU pragma: keep
 #include "mozilla/Attributes.h"
 #include "mozilla/ErrorResult.h"
+#include "mozilla/RefPtr.h"
 
 namespace mozilla {
 
 class DOMSVGPathSeg;
 class SVGAnimatedPathSegList;
 
 /**
  * Class DOMSVGPathSegList
--- a/dom/svg/DOMSVGPoint.cpp
+++ b/dom/svg/DOMSVGPoint.cpp
@@ -1,19 +1,21 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "DOMSVGPoint.h"
+
 #include "DOMSVGPointList.h"
 #include "SVGPoint.h"
 #include "gfx2DGlue.h"
 #include "SVGElement.h"
+#include "nsCOMPtr.h"
 #include "nsError.h"
 #include "mozilla/dom/SVGMatrix.h"
 
 // See the architecture comment in DOMSVGPointList.h.
 
 using namespace mozilla;
 using namespace mozilla::gfx;
 
--- a/dom/svg/DOMSVGPointList.h
+++ b/dom/svg/DOMSVGPointList.h
@@ -2,24 +2,24 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef MOZILLA_DOMSVGPOINTLIST_H__
 #define MOZILLA_DOMSVGPOINTLIST_H__
 
-#include "nsCOMPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsDebug.h"
 #include "SVGElement.h"
 #include "nsTArray.h"
 #include "SVGPointList.h"  // IWYU pragma: keep
 #include "mozilla/Attributes.h"
 #include "mozilla/ErrorResult.h"
+#include "mozilla/RefPtr.h"
 
 namespace mozilla {
 
 class DOMSVGPoint;
 class nsISVGPoint;
 class SVGAnimatedPointList;
 
 /**
--- a/dom/svg/DOMSVGStringList.h
+++ b/dom/svg/DOMSVGStringList.h
@@ -2,20 +2,20 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef MOZILLA_DOMSVGSTRINGLIST_H__
 #define MOZILLA_DOMSVGSTRINGLIST_H__
 
-#include "nsCOMPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "SVGElement.h"
 #include "mozilla/Attributes.h"
+#include "mozilla/RefPtr.h"
 
 namespace mozilla {
 
 class ErrorResult;
 class SVGStringList;
 
 /**
  * Class DOMSVGStringList
--- a/dom/svg/SVGAngle.h
+++ b/dom/svg/SVGAngle.h
@@ -2,20 +2,20 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef __NS_SVGANGLE_H__
 #define __NS_SVGANGLE_H__
 
-#include "nsCOMPtr.h"
 #include "nsError.h"
+#include "mozilla/AlreadyAddRefed.h"
+#include "mozilla/Attributes.h"
 #include "mozilla/SMILAttr.h"
-#include "mozilla/Attributes.h"
 #include "mozilla/dom/SVGAngleBinding.h"
 #include "mozilla/UniquePtr.h"
 
 class nsISupports;
 
 namespace mozilla {
 
 class SMILValue;
--- a/dom/svg/SVGBoolean.h
+++ b/dom/svg/SVGBoolean.h
@@ -2,20 +2,20 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef __NS_SVGBOOLEAN_H__
 #define __NS_SVGBOOLEAN_H__
 
-#include "nsCOMPtr.h"
 #include "nsError.h"
+#include "mozilla/SMILAttr.h"
+#include "mozilla/AlreadyAddRefed.h"
 #include "mozilla/Attributes.h"
-#include "mozilla/SMILAttr.h"
 #include "mozilla/UniquePtr.h"
 
 class nsAtom;
 
 namespace mozilla {
 
 class SMILValue;
 
--- a/dom/svg/SVGElement.h
+++ b/dom/svg/SVGElement.h
@@ -8,24 +8,24 @@
 #define __NS_SVGELEMENT_H__
 
 /*
   SVGElement is the base class for all SVG content elements.
   It implements all the common DOM interfaces and handles attributes.
 */
 
 #include "mozilla/Attributes.h"
+#include "mozilla/RefPtr.h"
 #include "mozilla/SVGContentUtils.h"
 #include "mozilla/dom/DOMRect.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/SVGClass.h"
 #include "mozilla/gfx/MatrixFwd.h"
 #include "nsAutoPtr.h"
 #include "nsChangeHint.h"
-#include "nsCOMPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsError.h"
 #include "nsISupportsImpl.h"
 #include "nsStyledElement.h"
 #include "gfxMatrix.h"
 
 class nsSVGLength2;
 class nsSVGNumber2;
--- a/dom/svg/SVGFilterElement.cpp
+++ b/dom/svg/SVGFilterElement.cpp
@@ -2,17 +2,17 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/SVGFilterElement.h"
 
 #include "nsGkAtoms.h"
-#include "nsCOMPtr.h"
+#include "mozilla/AlreadyAddRefed.h"
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/dom/SVGFilterElementBinding.h"
 #include "mozilla/dom/SVGLengthBinding.h"
 #include "mozilla/dom/SVGUnitTypesBinding.h"
 #include "nsQueryObject.h"
 #include "nsSVGUtils.h"
 #include "SVGObserverUtils.h"
 
--- a/dom/svg/SVGForeignObjectElement.cpp
+++ b/dom/svg/SVGForeignObjectElement.cpp
@@ -1,17 +1,17 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/SVGForeignObjectElement.h"
 
-#include "nsCOMPtr.h"
+#include "mozilla/AlreadyAddRefed.h"
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/dom/SVGDocument.h"
 #include "mozilla/dom/SVGForeignObjectElementBinding.h"
 #include "mozilla/dom/SVGLengthBinding.h"
 
 NS_IMPL_NS_NEW_SVG_ELEMENT(ForeignObject)
 
 namespace mozilla {
--- a/dom/svg/SVGGeometryElement.cpp
+++ b/dom/svg/SVGGeometryElement.cpp
@@ -1,20 +1,22 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "SVGGeometryElement.h"
 
+#include "nsCOMPtr.h"
 #include "DOMSVGPoint.h"
 #include "gfxPlatform.h"
 #include "mozilla/gfx/2D.h"
 #include "mozilla/dom/SVGLengthBinding.h"
+#include "mozilla/RefPtr.h"
 #include "nsComputedDOMStyle.h"
 #include "nsSVGUtils.h"
 #include "nsSVGLength2.h"
 #include "SVGContentUtils.h"
 
 using namespace mozilla;
 using namespace mozilla::gfx;
 using namespace mozilla::dom;
--- a/dom/svg/SVGGradientElement.cpp
+++ b/dom/svg/SVGGradientElement.cpp
@@ -1,25 +1,25 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/SVGGradientElement.h"
 
+#include "mozilla/AlreadyAddRefed.h"
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/dom/SVGElement.h"
 #include "mozilla/dom/SVGGradientElementBinding.h"
 #include "mozilla/dom/SVGLengthBinding.h"
 #include "mozilla/dom/SVGLinearGradientElementBinding.h"
 #include "mozilla/dom/SVGRadialGradientElementBinding.h"
 #include "mozilla/dom/SVGUnitTypesBinding.h"
 #include "DOMSVGAnimatedTransformList.h"
-#include "nsCOMPtr.h"
 #include "nsGkAtoms.h"
 
 NS_IMPL_NS_NEW_SVG_ELEMENT(LinearGradient)
 NS_IMPL_NS_NEW_SVG_ELEMENT(RadialGradient)
 
 namespace mozilla {
 namespace dom {
 
--- a/dom/svg/SVGMarkerElement.cpp
+++ b/dom/svg/SVGMarkerElement.cpp
@@ -2,26 +2,26 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/SVGMarkerElement.h"
 
 #include "nsGkAtoms.h"
-#include "nsCOMPtr.h"
 #include "SVGAnimatedPreserveAspectRatio.h"
 #include "nsError.h"
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/dom/DOMSVGAngle.h"
 #include "mozilla/dom/SVGGeometryElement.h"
 #include "mozilla/dom/SVGLengthBinding.h"
 #include "mozilla/dom/SVGMarkerElementBinding.h"
 #include "mozilla/gfx/Matrix.h"
 #include "mozilla/FloatingPoint.h"
+#include "mozilla/RefPtr.h"
 #include "SVGContentUtils.h"
 
 using namespace mozilla::gfx;
 using namespace mozilla::dom::SVGMarkerElement_Binding;
 
 NS_IMPL_NS_NEW_SVG_ELEMENT(Marker)
 
 namespace mozilla {
--- a/dom/svg/SVGMaskElement.cpp
+++ b/dom/svg/SVGMaskElement.cpp
@@ -1,18 +1,18 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/SVGMaskElement.h"
 
-#include "nsCOMPtr.h"
 #include "nsGkAtoms.h"
+#include "mozilla/AlreadyAddRefed.h"
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/dom/SVGLengthBinding.h"
 #include "mozilla/dom/SVGMaskElementBinding.h"
 #include "mozilla/dom/SVGUnitTypesBinding.h"
 
 NS_IMPL_NS_NEW_SVG_ELEMENT(Mask)
 
 namespace mozilla {
--- a/dom/svg/SVGPathElement.cpp
+++ b/dom/svg/SVGPathElement.cpp
@@ -10,17 +10,16 @@
 
 #include "DOMSVGPathSeg.h"
 #include "DOMSVGPathSegList.h"
 #include "gfx2DGlue.h"
 #include "gfxPlatform.h"
 #include "mozilla/dom/SVGPathElementBinding.h"
 #include "mozilla/gfx/2D.h"
 #include "mozilla/RefPtr.h"
-#include "nsCOMPtr.h"
 #include "nsComputedDOMStyle.h"
 #include "nsGkAtoms.h"
 #include "nsStyleConsts.h"
 #include "nsStyleStruct.h"
 #include "nsWindowSizes.h"
 #include "SVGContentUtils.h"
 
 NS_IMPL_NS_NEW_SVG_ELEMENT(Path)
--- a/dom/svg/SVGPatternElement.cpp
+++ b/dom/svg/SVGPatternElement.cpp
@@ -1,22 +1,22 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/SVGPatternElement.h"
 
+#include "mozilla/AlreadyAddRefed.h"
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/dom/SVGLengthBinding.h"
 #include "mozilla/dom/SVGPatternElementBinding.h"
 #include "mozilla/dom/SVGUnitTypesBinding.h"
 #include "DOMSVGAnimatedTransformList.h"
-#include "nsCOMPtr.h"
 #include "nsGkAtoms.h"
 
 NS_IMPL_NS_NEW_SVG_ELEMENT(Pattern)
 
 namespace mozilla {
 namespace dom {
 
 using namespace SVGUnitTypes_Binding;
--- a/dom/svg/SVGRect.h
+++ b/dom/svg/SVGRect.h
@@ -4,16 +4,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_SVGRect_h
 #define mozilla_dom_SVGRect_h
 
 #include "mozilla/dom/SVGIRect.h"
 #include "mozilla/gfx/Rect.h"
+#include "nsCOMPtr.h"
 #include "SVGElement.h"
 
 ////////////////////////////////////////////////////////////////////////
 // SVGRect class
 
 namespace mozilla {
 namespace dom {
 
--- a/dom/svg/SVGScriptElement.h
+++ b/dom/svg/SVGScriptElement.h
@@ -3,18 +3,18 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_SVGScriptElement_h
 #define mozilla_dom_SVGScriptElement_h
 
 #include "SVGElement.h"
-#include "nsCOMPtr.h"
 #include "SVGString.h"
+#include "mozilla/AlreadyAddRefed.h"
 #include "mozilla/dom/ScriptElement.h"
 
 nsresult NS_NewSVGScriptElement(
     nsIContent** aResult, already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
     mozilla::dom::FromParser aFromParser);
 
 namespace mozilla {
 namespace dom {
--- a/dom/svg/SVGStyleElement.cpp
+++ b/dom/svg/SVGStyleElement.cpp
@@ -2,18 +2,19 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/SVGStyleElement.h"
 
 #include "mozilla/dom/Element.h"
+#include "mozilla/dom/SVGStyleElementBinding.h"
+#include "nsCOMPtr.h"
 #include "nsContentUtils.h"
-#include "mozilla/dom/SVGStyleElementBinding.h"
 
 NS_IMPL_NS_NEW_SVG_ELEMENT(Style)
 
 namespace mozilla {
 namespace dom {
 
 JSObject* SVGStyleElement::WrapNode(JSContext* aCx,
                                     JS::Handle<JSObject*> aGivenProto) {
--- a/dom/svg/SVGSwitchElement.h
+++ b/dom/svg/SVGSwitchElement.h
@@ -3,16 +3,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_SVGSwitchElement_h
 #define mozilla_dom_SVGSwitchElement_h
 
 #include "mozilla/dom/SVGGraphicsElement.h"
+#include "nsCOMPtr.h"
 
 class nsSVGSwitchFrame;
 
 nsresult NS_NewSVGSwitchElement(
     nsIContent** aResult, already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo);
 
 namespace mozilla {
 namespace dom {
--- a/dom/svg/SVGTests.h
+++ b/dom/svg/SVGTests.h
@@ -2,18 +2,18 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_SVGTests_h
 #define mozilla_dom_SVGTests_h
 
-#include "nsCOMPtr.h"
 #include "nsStringFwd.h"
+#include "mozilla/AlreadyAddRefed.h"
 #include "mozilla/SVGStringList.h"
 
 class nsAttrValue;
 class nsAtom;
 class nsStaticAtom;
 
 namespace mozilla {
 class DOMSVGStringList;
--- a/dom/svg/SVGUseElement.h
+++ b/dom/svg/SVGUseElement.h
@@ -4,18 +4,20 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_SVGUseElement_h
 #define mozilla_dom_SVGUseElement_h
 
 #include "mozilla/dom/FromParser.h"
 #include "mozilla/dom/IDTracker.h"
+#include "mozilla/dom/SVGGraphicsElement.h"
+#include "mozilla/RefPtr.h"
+#include "nsCOMPtr.h"
 #include "nsStubMutationObserver.h"
-#include "mozilla/dom/SVGGraphicsElement.h"
 #include "nsSVGLength2.h"
 #include "SVGString.h"
 #include "nsTArray.h"
 
 class nsIContent;
 class nsSVGUseFrame;
 
 nsresult NS_NewSVGSVGElement(
--- a/dom/svg/SVGViewportElement.cpp
+++ b/dom/svg/SVGViewportElement.cpp
@@ -2,30 +2,30 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/SVGViewportElement.h"
 
 #include <stdint.h>
+#include "mozilla/AlreadyAddRefed.h"
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/ContentEvents.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/Likely.h"
 #include "mozilla/SMILTypes.h"
 #include "mozilla/SVGContentUtils.h"
 #include "mozilla/dom/Document.h"
 #include "mozilla/dom/SVGLengthBinding.h"
 #include "mozilla/dom/SVGMatrix.h"
 #include "mozilla/dom/SVGViewElement.h"
 
 #include "DOMSVGLength.h"
 #include "DOMSVGPoint.h"
-#include "nsCOMPtr.h"
 #include "nsContentUtils.h"
 #include "nsFrameSelection.h"
 #include "nsError.h"
 #include "nsGkAtoms.h"
 #include "nsIFrame.h"
 #include "nsIPresShell.h"
 #include "nsISVGSVGFrame.h"
 #include "nsLayoutUtils.h"
--- a/gfx/layers/wr/AsyncImagePipelineManager.cpp
+++ b/gfx/layers/wr/AsyncImagePipelineManager.cpp
@@ -394,22 +394,24 @@ void AsyncImagePipelineManager::ApplyAsy
 
   aPipeline->mIsChanged = false;
 
   wr::LayoutSize contentSize{aPipeline->mScBounds.Width(),
                              aPipeline->mScBounds.Height()};
   wr::DisplayListBuilder builder(aPipelineId, contentSize);
 
   float opacity = 1.0f;
+  wr::StackingContextParams params;
+  params.opacity = &opacity;
+  params.mTransformPtr =
+      aPipeline->mScTransform.IsIdentity() ? nullptr : &aPipeline->mScTransform;
+  params.mix_blend_mode = aPipeline->mMixBlendMode;
+
   Maybe<wr::WrSpatialId> referenceFrameId = builder.PushStackingContext(
-      wr::ToRoundedLayoutRect(aPipeline->mScBounds),
-      wr::WrStackingContextClip::None(), nullptr, &opacity,
-      aPipeline->mScTransform.IsIdentity() ? nullptr : &aPipeline->mScTransform,
-      wr::TransformStyle::Flat, wr::ReferenceFrameKind::Transform,
-      aPipeline->mMixBlendMode, nsTArray<wr::FilterOp>(), true,
+      params, wr::ToRoundedLayoutRect(aPipeline->mScBounds),
       // This is fine to do unconditionally because we only push images here.
       wr::RasterSpace::Screen());
 
   Maybe<wr::SpaceAndClipChainHelper> spaceAndClipChainHelper;
   if (referenceFrameId) {
     spaceAndClipChainHelper.emplace(builder, referenceFrameId.ref());
   }
 
--- a/gfx/layers/wr/StackingContextHelper.cpp
+++ b/gfx/layers/wr/StackingContextHelper.cpp
@@ -19,45 +19,39 @@ StackingContextHelper::StackingContextHe
       mIsPreserve3D(false),
       mRasterizeLocally(false) {
   // mOrigin remains at 0,0
 }
 
 StackingContextHelper::StackingContextHelper(
     const StackingContextHelper& aParentSC, const ActiveScrolledRoot* aAsr,
     nsIFrame* aContainerFrame, nsDisplayItem* aContainerItem,
-    wr::DisplayListBuilder& aBuilder, const nsTArray<wr::FilterOp>& aFilters,
-    const LayoutDeviceRect& aBounds, const gfx::Matrix4x4* aBoundTransform,
-    const wr::WrAnimationProperty* aAnimation, const float* aOpacityPtr,
-    const gfx::Matrix4x4* aTransformPtr,
-    wr::ReferenceFrameKind aReferenceFrameKind,
-    const gfx::CompositionOp& aMixBlendMode, bool aBackfaceVisible,
-    bool aIsPreserve3D,
-    const Maybe<nsDisplayTransform*>& aDeferredTransformItem,
-    const wr::WrStackingContextClip& aClip, bool aAnimated)
+    wr::DisplayListBuilder& aBuilder, const wr::StackingContextParams& aParams,
+    const LayoutDeviceRect& aBounds)
     : mBuilder(&aBuilder),
       mScale(1.0f, 1.0f),
-      mDeferredTransformItem(aDeferredTransformItem),
-      mIsPreserve3D(aIsPreserve3D),
-      mRasterizeLocally(aAnimated || aParentSC.mRasterizeLocally) {
+      mDeferredTransformItem(aParams.mDeferredTransformItem),
+      mIsPreserve3D(aParams.transform_style == wr::TransformStyle::Preserve3D),
+      mRasterizeLocally(aParams.mAnimated || aParentSC.mRasterizeLocally) {
   // Compute scale for fallback rendering. We don't try to guess a scale for 3d
   // transformed items
   gfx::Matrix transform2d;
-  if (aBoundTransform && aBoundTransform->CanDraw2D(&transform2d) &&
-      aReferenceFrameKind != wr::ReferenceFrameKind::Perspective &&
+  if (aParams.mBoundTransform &&
+      aParams.mBoundTransform->CanDraw2D(&transform2d) &&
+      aParams.reference_frame_kind != wr::ReferenceFrameKind::Perspective &&
       !aParentSC.mIsPreserve3D) {
     mInheritedTransform = transform2d * aParentSC.mInheritedTransform;
 
     int32_t apd = aContainerFrame->PresContext()->AppUnitsPerDevPixel();
     nsRect r = LayoutDevicePixel::ToAppUnits(aBounds, apd);
     mScale = FrameLayerBuilder::ChooseScale(aContainerFrame, aContainerItem, r,
                                             1.f, 1.f, mInheritedTransform,
                                             /* aCanDraw2D = */ true);
 
-    if (aAnimated) {
+    if (aParams.mAnimated) {
       mSnappingSurfaceTransform =
           gfx::Matrix::Scaling(mScale.width, mScale.height);
     } else {
       mSnappingSurfaceTransform =
           transform2d * aParentSC.mSnappingSurfaceTransform;
     }
   } else {
     mInheritedTransform = aParentSC.mInheritedTransform;
@@ -65,20 +59,17 @@ StackingContextHelper::StackingContextHe
   }
 
   auto rasterSpace =
       mRasterizeLocally
           ? wr::RasterSpace::Local(std::max(mScale.width, mScale.height))
           : wr::RasterSpace::Screen();
 
   mReferenceFrameId = mBuilder->PushStackingContext(
-      wr::ToLayoutRect(aBounds), aClip, aAnimation, aOpacityPtr, aTransformPtr,
-      aIsPreserve3D ? wr::TransformStyle::Preserve3D : wr::TransformStyle::Flat,
-      aReferenceFrameKind, wr::ToMixBlendMode(aMixBlendMode), aFilters,
-      aBackfaceVisible, rasterSpace);
+      aParams, wr::ToLayoutRect(aBounds), rasterSpace);
 
   if (mReferenceFrameId) {
     mSpaceAndClipChainHelper.emplace(aBuilder, mReferenceFrameId.ref());
   }
 
   mAffectsClipPositioning =
       mReferenceFrameId.isSome() || (aBounds.TopLeft() != LayoutDevicePoint());
 
--- a/gfx/layers/wr/StackingContextHelper.h
+++ b/gfx/layers/wr/StackingContextHelper.h
@@ -26,28 +26,19 @@ namespace layers {
  * some of the coordinate space transformations needed.
  */
 class MOZ_RAII StackingContextHelper {
  public:
   StackingContextHelper(
       const StackingContextHelper& aParentSC, const ActiveScrolledRoot* aAsr,
       nsIFrame* aContainerFrame, nsDisplayItem* aContainerItem,
       wr::DisplayListBuilder& aBuilder,
-      const nsTArray<wr::FilterOp>& aFilters = nsTArray<wr::FilterOp>(),
-      const LayoutDeviceRect& aBounds = LayoutDeviceRect(),
-      const gfx::Matrix4x4* aBoundTransform = nullptr,
-      const wr::WrAnimationProperty* aAnimation = nullptr,
-      const float* aOpacityPtr = nullptr,
-      const gfx::Matrix4x4* aTransformPtr = nullptr,
-      const wr::ReferenceFrameKind = wr::ReferenceFrameKind::Transform,
-      const gfx::CompositionOp& aMixBlendMode = gfx::CompositionOp::OP_OVER,
-      bool aBackfaceVisible = true, bool aIsPreserve3D = false,
-      const Maybe<nsDisplayTransform*>& aDeferredTransformItem = Nothing(),
-      const wr::WrStackingContextClip& = wr::WrStackingContextClip::None(),
-      bool aAnimated = false);
+      const wr::StackingContextParams& aParams = wr::StackingContextParams(),
+      const LayoutDeviceRect& aBounds = LayoutDeviceRect());
+
   // This version of the constructor should only be used at the root level
   // of the tree, so that we have a StackingContextHelper to pass down into
   // the RenderLayer traversal, but don't actually want it to push a stacking
   // context on the display list builder.
   StackingContextHelper();
 
   // Pops the stacking context, if one was pushed during the constructor.
   ~StackingContextHelper();
--- a/gfx/layers/wr/WebRenderCommandBuilder.cpp
+++ b/gfx/layers/wr/WebRenderCommandBuilder.cpp
@@ -1428,17 +1428,17 @@ void WebRenderCommandBuilder::EmptyTrans
 bool WebRenderCommandBuilder::NeedsEmptyTransaction() {
   return !mLastCanvasDatas.IsEmpty();
 }
 
 void WebRenderCommandBuilder::BuildWebRenderCommands(
     wr::DisplayListBuilder& aBuilder,
     wr::IpcResourceUpdateQueue& aResourceUpdates, nsDisplayList* aDisplayList,
     nsDisplayListBuilder* aDisplayListBuilder, WebRenderScrollData& aScrollData,
-    wr::LayoutSize& aContentSize, const nsTArray<wr::FilterOp>& aFilters) {
+    wr::LayoutSize& aContentSize, nsTArray<wr::FilterOp>&& aFilters) {
   StackingContextHelper sc;
   aScrollData = WebRenderScrollData(mManager);
   MOZ_ASSERT(mLayerScrollData.empty());
   mLastCanvasDatas.Clear();
   mLastAsr = nullptr;
   mBuilderDumpIndex = 0;
   mContainsSVGGroup = false;
   MOZ_ASSERT(mDumpIndent == 0);
@@ -1446,19 +1446,28 @@ void WebRenderCommandBuilder::BuildWebRe
 
   {
     if (!mZoomProp && gfxPrefs::APZAllowZooming() && XRE_IsContentProcess()) {
       mZoomProp.emplace();
       mZoomProp->effect_type = wr::WrAnimationType::Transform;
       mZoomProp->id = AnimationHelper::GetNextCompositorAnimationsId();
     }
 
+    nsPresContext* presContext =
+        aDisplayListBuilder->RootReferenceFrame()->PresContext();
+    bool isTopLevelContent =
+        presContext->Document()->IsTopLevelContentDocument();
+
+    wr::StackingContextParams params;
+    params.mFilters = std::move(aFilters);
+    params.animation = mZoomProp.ptrOr(nullptr);
+    params.cache_tiles = isTopLevelContent;
+
     StackingContextHelper pageRootSc(sc, nullptr, nullptr, nullptr, aBuilder,
-                                     aFilters, LayoutDeviceRect(), nullptr,
-                                     mZoomProp.ptrOr(nullptr));
+                                     params);
     if (ShouldDumpDisplayList(aDisplayListBuilder)) {
       mBuilderDumpIndex =
           aBuilder.Dump(mDumpIndent + 1, Some(mBuilderDumpIndex), Nothing());
     }
     CreateWebRenderCommandsFromDisplayList(aDisplayList, nullptr,
                                            aDisplayListBuilder, pageRootSc,
                                            aBuilder, aResourceUpdates);
   }
--- a/gfx/layers/wr/WebRenderCommandBuilder.h
+++ b/gfx/layers/wr/WebRenderCommandBuilder.h
@@ -52,17 +52,17 @@ class WebRenderCommandBuilder {
   bool NeedsEmptyTransaction();
 
   void BuildWebRenderCommands(wr::DisplayListBuilder& aBuilder,
                               wr::IpcResourceUpdateQueue& aResourceUpdates,
                               nsDisplayList* aDisplayList,
                               nsDisplayListBuilder* aDisplayListBuilder,
                               WebRenderScrollData& aScrollData,
                               wr::LayoutSize& aContentSize,
-                              const nsTArray<wr::FilterOp>& aFilters);
+                              nsTArray<wr::FilterOp>&& aFilters);
 
   void PushOverrideForASR(const ActiveScrolledRoot* aASR,
                           const wr::WrSpatialId& aSpatialId);
   void PopOverrideForASR(const ActiveScrolledRoot* aASR);
 
   Maybe<wr::ImageKey> CreateImageKey(
       nsDisplayItem* aItem, ImageContainer* aContainer,
       mozilla::wr::DisplayListBuilder& aBuilder,
--- a/gfx/layers/wr/WebRenderLayerManager.cpp
+++ b/gfx/layers/wr/WebRenderLayerManager.cpp
@@ -241,18 +241,17 @@ void WebRenderLayerManager::EndTransacti
                                            EndTransactionFlags aFlags) {
   // This should never get called, all callers should use
   // EndTransactionWithoutLayer instead.
   MOZ_ASSERT(false);
 }
 
 void WebRenderLayerManager::EndTransactionWithoutLayer(
     nsDisplayList* aDisplayList, nsDisplayListBuilder* aDisplayListBuilder,
-    const nsTArray<wr::FilterOp>& aFilters,
-    WebRenderBackgroundData* aBackground) {
+    nsTArray<wr::FilterOp>&& aFilters, WebRenderBackgroundData* aBackground) {
   AUTO_PROFILER_TRACING("Paint", "RenderLayers", GRAPHICS);
 
   // Since we don't do repeat transactions right now, just set the time
   mAnimationReadyTime = TimeStamp::Now();
 
   WrBridge()->BeginTransaction();
 
   LayoutDeviceIntSize size = mWidget->GetClientSize();
@@ -271,17 +270,17 @@ void WebRenderLayerManager::EndTransacti
   if (aDisplayList) {
     MOZ_ASSERT(aDisplayListBuilder && !aBackground);
     // Record the time spent "layerizing". WR doesn't actually layerize but
     // generating the WR display list is the closest equivalent
     PaintTelemetry::AutoRecord record(PaintTelemetry::Metric::Layerization);
 
     mWebRenderCommandBuilder.BuildWebRenderCommands(
         builder, resourceUpdates, aDisplayList, aDisplayListBuilder,
-        mScrollData, contentSize, aFilters);
+        mScrollData, contentSize, std::move(aFilters));
     builderDumpIndex = mWebRenderCommandBuilder.GetBuilderDumpIndex();
     containsSVGGroup = mWebRenderCommandBuilder.GetContainsSVGGroup();
   } else {
     // ViewToPaint does not have frame yet, then render only background clolor.
     MOZ_ASSERT(!aDisplayListBuilder && aBackground);
     aBackground->AddWebRenderCommands(builder);
     if (dumpEnabled) {
       printf_stderr("(no display list; background only)\n");
--- a/gfx/layers/wr/WebRenderLayerManager.h
+++ b/gfx/layers/wr/WebRenderLayerManager.h
@@ -74,17 +74,17 @@ class WebRenderLayerManager final : publ
 
   virtual bool BeginTransactionWithTarget(gfxContext* aTarget,
                                           const nsCString& aURL) override;
   virtual bool BeginTransaction(const nsCString& aURL) override;
   virtual bool EndEmptyTransaction(
       EndTransactionFlags aFlags = END_DEFAULT) override;
   void EndTransactionWithoutLayer(
       nsDisplayList* aDisplayList, nsDisplayListBuilder* aDisplayListBuilder,
-      const nsTArray<wr::FilterOp>& aFilters = nsTArray<wr::FilterOp>(),
+      nsTArray<wr::FilterOp>&& aFilters = nsTArray<wr::FilterOp>(),
       WebRenderBackgroundData* aBackground = nullptr);
   virtual void EndTransaction(
       DrawPaintedLayerCallback aCallback, void* aCallbackData,
       EndTransactionFlags aFlags = END_DEFAULT) override;
 
   virtual LayersBackend GetBackendType() override {
     return LayersBackend::LAYERS_WR;
   }
--- a/gfx/webrender_bindings/WebRenderAPI.cpp
+++ b/gfx/webrender_bindings/WebRenderAPI.cpp
@@ -668,39 +668,34 @@ usize DisplayListBuilder::Dump(usize aIn
 
 void DisplayListBuilder::Finalize(wr::LayoutSize& aOutContentSize,
                                   BuiltDisplayList& aOutDisplayList) {
   wr_api_finalize_builder(mWrState, &aOutContentSize, &aOutDisplayList.dl_desc,
                           &aOutDisplayList.dl.inner);
 }
 
 Maybe<wr::WrSpatialId> DisplayListBuilder::PushStackingContext(
-    const wr::LayoutRect& aBounds, const wr::WrStackingContextClip& aClip,
-    const WrAnimationProperty* aAnimation, const float* aOpacity,
-    const gfx::Matrix4x4* aTransform, wr::TransformStyle aTransformStyle,
-    const wr::ReferenceFrameKind aReferenceFrameKind,
-    const wr::MixBlendMode& aMixBlendMode,
-    const nsTArray<wr::FilterOp>& aFilters, bool aIsBackfaceVisible,
+    const wr::StackingContextParams& aParams, const wr::LayoutRect& aBounds,
     const wr::RasterSpace& aRasterSpace) {
   MOZ_ASSERT(mClipChainLeaf.isNothing(),
              "Non-empty leaf from clip chain given, but not used with SC!");
 
   wr::LayoutTransform matrix;
-  if (aTransform) {
-    matrix = ToLayoutTransform(*aTransform);
+  const gfx::Matrix4x4* transform = aParams.mTransformPtr;
+  if (transform) {
+    matrix = ToLayoutTransform(*transform);
   }
-  const wr::LayoutTransform* maybeTransform = aTransform ? &matrix : nullptr;
+  const wr::LayoutTransform* maybeTransform = transform ? &matrix : nullptr;
   WRDL_LOG("PushStackingContext b=%s t=%s\n", mWrState,
            Stringify(aBounds).c_str(),
-           aTransform ? Stringify(*aTransform).c_str() : "none");
+           transform ? Stringify(*transform).c_str() : "none");
 
   auto spatialId = wr_dp_push_stacking_context(
-      mWrState, aBounds, mCurrentSpaceAndClipChain.space, &aClip, aAnimation,
-      aOpacity, maybeTransform, aTransformStyle, aReferenceFrameKind,
-      aMixBlendMode, aFilters.Elements(), aFilters.Length(), aIsBackfaceVisible,
+      mWrState, aBounds, mCurrentSpaceAndClipChain.space, &aParams,
+      maybeTransform, aParams.mFilters.Elements(), aParams.mFilters.Length(),
       aRasterSpace);
 
   return spatialId.id != 0 ? Some(spatialId) : Nothing();
 }
 
 void DisplayListBuilder::PopStackingContext(bool aIsReferenceFrame) {
   WRDL_LOG("PopStackingContext\n", mWrState);
   wr_dp_pop_stacking_context(mWrState, aIsReferenceFrame);
--- a/gfx/webrender_bindings/WebRenderAPI.h
+++ b/gfx/webrender_bindings/WebRenderAPI.h
@@ -18,16 +18,17 @@
 #include "mozilla/layers/SyncObject.h"
 #include "mozilla/Range.h"
 #include "mozilla/webrender/webrender_ffi.h"
 #include "mozilla/webrender/WebRenderTypes.h"
 #include "GLTypes.h"
 #include "Units.h"
 
 class nsDisplayItem;
+class nsDisplayTransform;
 
 namespace mozilla {
 
 struct ActiveScrolledRoot;
 
 namespace widget {
 class CompositorWidget;
 }
@@ -302,16 +303,43 @@ class MOZ_RAII AutoTransactionSender {
 
   ~AutoTransactionSender() { mApi->SendTransaction(*mTxn); }
 
  private:
   WebRenderAPI* mApi;
   TransactionBuilder* mTxn;
 };
 
+/**
+ * A set of optional parameters for stacking context creation.
+ */
+struct MOZ_STACK_CLASS StackingContextParams : public WrStackingContextParams {
+  StackingContextParams()
+      : WrStackingContextParams{WrStackingContextClip::None(),
+                                nullptr,
+                                nullptr,
+                                wr::TransformStyle::Flat,
+                                wr::ReferenceFrameKind::Transform,
+                                /* is_backface_visible = */ true,
+                                /* cache_tiles = */ false,
+                                wr::MixBlendMode::Normal} {}
+
+  void SetPreserve3D(bool aPreserve) {
+    transform_style =
+        aPreserve ? wr::TransformStyle::Preserve3D : wr::TransformStyle::Flat;
+  }
+
+  nsTArray<wr::FilterOp> mFilters;
+  wr::LayoutRect mBounds = wr::ToLayoutRect(LayoutDeviceRect());
+  const gfx::Matrix4x4* mBoundTransform = nullptr;
+  const gfx::Matrix4x4* mTransformPtr = nullptr;
+  Maybe<nsDisplayTransform*> mDeferredTransformItem;
+  bool mAnimated = false;
+};
+
 /// 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,
                               size_t aCapacity = 0);
@@ -324,22 +352,17 @@ class DisplayListBuilder {
   void ClearSave();
   usize Dump(usize aIndent, const Maybe<usize>& aStart,
              const Maybe<usize>& aEnd);
 
   void Finalize(wr::LayoutSize& aOutContentSize,
                 wr::BuiltDisplayList& aOutDisplayList);
 
   Maybe<wr::WrSpatialId> PushStackingContext(
-      // TODO: We should work with strongly typed rects
-      const wr::LayoutRect& aBounds, const wr::WrStackingContextClip& aClip,
-      const wr::WrAnimationProperty* aAnimation, const float* aOpacity,
-      const gfx::Matrix4x4* aTransform, wr::TransformStyle aTransformStyle,
-      const wr::ReferenceFrameKind, const wr::MixBlendMode& aMixBlendMode,
-      const nsTArray<wr::FilterOp>& aFilters, bool aIsBackfaceVisible,
+      const StackingContextParams& aParams, const wr::LayoutRect& aBounds,
       const wr::RasterSpace& aRasterSpace);
   void PopStackingContext(bool aIsReferenceFrame);
 
   wr::WrClipChainId DefineClipChain(const Maybe<wr::WrClipChainId>& aParent,
                                     const nsTArray<wr::WrClipId>& aClips);
 
   wr::WrClipId DefineClip(
       const Maybe<wr::WrSpaceAndClip>& aParent, const wr::LayoutRect& aClipRect,
--- a/gfx/webrender_bindings/src/bindings.rs
+++ b/gfx/webrender_bindings/src/bindings.rs
@@ -1890,49 +1890,58 @@ pub extern "C" fn wr_dp_restore(state: &
     state.frame_builder.dl_builder.restore();
 }
 
 #[no_mangle]
 pub extern "C" fn wr_dp_clear_save(state: &mut WrState) {
     state.frame_builder.dl_builder.clear_save();
 }
 
+/// IMPORTANT: If you add fields to this struct, you need to also add initializers
+/// for those fields in WebRenderAPI.h.
+#[repr(C)]
+pub struct WrStackingContextParams {
+    pub clip: WrStackingContextClip,
+    pub animation: *const WrAnimationProperty,
+    pub opacity: *const f32,
+    pub transform_style: TransformStyle,
+    pub reference_frame_kind: ReferenceFrameKind,
+    pub is_backface_visible: bool,
+    /// True if picture caching should be enabled for this stacking context.
+    pub cache_tiles: bool,
+    pub mix_blend_mode: MixBlendMode,
+}
+
 #[no_mangle]
 pub extern "C" fn wr_dp_push_stacking_context(
     state: &mut WrState,
     mut bounds: LayoutRect,
     spatial_id: WrSpatialId,
-    clip: &WrStackingContextClip,
-    animation: *const WrAnimationProperty,
-    opacity: *const f32,
+    params: &WrStackingContextParams,
     transform: *const LayoutTransform,
-    transform_style: TransformStyle,
-    reference_frame_kind: ReferenceFrameKind,
-    mix_blend_mode: MixBlendMode,
     filters: *const FilterOp,
     filter_count: usize,
-    is_backface_visible: bool,
     glyph_raster_space: RasterSpace,
 ) -> WrSpatialId {
     debug_assert!(unsafe { !is_in_render_thread() });
 
     let c_filters = make_slice(filters, filter_count);
     let mut filters : Vec<FilterOp> = c_filters.iter().map(|c_filter| {
                                                            *c_filter
     }).collect();
 
     let transform_ref = unsafe { transform.as_ref() };
     let mut transform_binding = match transform_ref {
-        Some(transform) => Some(PropertyBinding::Value(transform.clone())),
+        Some(t) => Some(PropertyBinding::Value(t.clone())),
         None => None,
     };
 
-    let opacity_ref = unsafe { opacity.as_ref() };
+    let opacity_ref = unsafe { params.opacity.as_ref() };
     let mut has_opacity_animation = false;
-    let anim = unsafe { animation.as_ref() };
+    let anim = unsafe { params.animation.as_ref() };
     if let Some(anim) = anim {
         debug_assert!(anim.id > 0);
         match anim.effect_type {
             WrAnimationType::Opacity => {
                 filters.push(FilterOp::Opacity(PropertyBinding::Binding(PropertyBindingKey::new(anim.id),
                                                                         // We have to set the static opacity value as
                                                                         // the value for the case where the animation is
                                                                         // in not in-effect (e.g. in the delay phase
@@ -1952,52 +1961,53 @@ pub extern "C" fn wr_dp_push_stacking_co
 
     if let Some(opacity) = opacity_ref {
         if !has_opacity_animation && *opacity < 1.0 {
             filters.push(FilterOp::Opacity(PropertyBinding::Value(*opacity), *opacity));
         }
     }
 
     let mut wr_spatial_id = spatial_id.to_webrender(state.pipeline_id);
-    let wr_clip_id = clip.to_webrender(state.pipeline_id);
+    let wr_clip_id = params.clip.to_webrender(state.pipeline_id);
 
     // Note: 0 has special meaning in WR land, standing for ROOT_REFERENCE_FRAME.
     // However, it is never returned by `push_reference_frame`, and we need to return
     // an option here across FFI, so we take that 0 value for the None semantics.
     // This is resolved into proper `Maybe<WrSpatialId>` inside `WebRenderAPI::PushStackingContext`.
     let mut result = WrSpatialId { id: 0 };
     if let Some(transform_binding) = transform_binding {
         wr_spatial_id = state.frame_builder.dl_builder.push_reference_frame(
             &bounds,
             wr_spatial_id,
-            transform_style,
+            params.transform_style,
             transform_binding,
-            reference_frame_kind,
+            params.reference_frame_kind,
         );
 
         bounds.origin = LayoutPoint::zero();
         result.id = wr_spatial_id.0;
         assert_ne!(wr_spatial_id.0, 0);
     }
 
     let prim_info = LayoutPrimitiveInfo {
-        is_backface_visible,
+        is_backface_visible: params.is_backface_visible,
         tag: state.current_tag,
         .. LayoutPrimitiveInfo::new(bounds)
     };
 
     state.frame_builder
          .dl_builder
          .push_stacking_context(&prim_info,
                                 wr_spatial_id,
                                 wr_clip_id,
-                                transform_style,
-                                mix_blend_mode,
+                                params.transform_style,
+                                params.mix_blend_mode,
                                 &filters,
-                                glyph_raster_space);
+                                glyph_raster_space,
+                                params.cache_tiles);
 
     result
 }
 
 #[no_mangle]
 pub extern "C" fn wr_dp_pop_stacking_context(state: &mut WrState,
                                              is_reference_frame: bool) {
     debug_assert!(unsafe { !is_in_render_thread() });
--- a/gfx/wr/examples/alpha_perf.rs
+++ b/gfx/wr/examples/alpha_perf.rs
@@ -28,24 +28,19 @@ impl Example for App {
         _framebuffer_size: DeviceIntSize,
         pipeline_id: PipelineId,
         _document_id: DocumentId,
     ) {
         let bounds = (0, 0).to(1920, 1080);
         let info = LayoutPrimitiveInfo::new(bounds);
         let space_and_clip = SpaceAndClipInfo::root_scroll(pipeline_id);
 
-        builder.push_stacking_context(
+        builder.push_simple_stacking_context(
             &info,
             space_and_clip.spatial_id,
-            None,
-            TransformStyle::Flat,
-            MixBlendMode::Normal,
-            &[],
-            RasterSpace::Screen,
         );
 
         for _ in 0 .. self.rect_count {
             builder.push_rect(&info, &space_and_clip, ColorF::new(1.0, 1.0, 1.0, 0.05));
         }
 
         builder.pop_stacking_context();
     }
--- a/gfx/wr/examples/animation.rs
+++ b/gfx/wr/examples/animation.rs
@@ -58,24 +58,20 @@ impl App {
         let spatial_id = builder.push_reference_frame(
             &LayoutRect::new(bounds.origin, LayoutSize::zero()),
             SpatialId::root_scroll_node(pipeline_id),
             TransformStyle::Flat,
             PropertyBinding::Binding(property_key, LayoutTransform::identity()),
             ReferenceFrameKind::Transform,
         );
 
-        builder.push_stacking_context(
+        builder.push_simple_stacking_context_with_filters(
             &LayoutPrimitiveInfo::new(LayoutRect::zero()),
             spatial_id,
-            None,
-            TransformStyle::Flat,
-            MixBlendMode::Normal,
             &filters,
-            RasterSpace::Screen,
         );
 
         let space_and_clip = SpaceAndClipInfo {
             spatial_id,
             clip_id: ClipId::root(pipeline_id),
         };
         let clip_bounds = LayoutRect::new(LayoutPoint::zero(), bounds.size);
         let complex_clip = ComplexClipRegion {
--- a/gfx/wr/examples/basic.rs
+++ b/gfx/wr/examples/basic.rs
@@ -189,24 +189,19 @@ impl Example for App {
         pipeline_id: PipelineId,
         _document_id: DocumentId,
     ) {
         let bounds = LayoutRect::new(LayoutPoint::zero(), builder.content_size());
         let info = LayoutPrimitiveInfo::new(bounds);
         let root_space_and_clip = SpaceAndClipInfo::root_scroll(pipeline_id);
         let spatial_id = root_space_and_clip.spatial_id;
 
-        builder.push_stacking_context(
+        builder.push_simple_stacking_context(
             &info,
             spatial_id,
-            None,
-            TransformStyle::Flat,
-            MixBlendMode::Normal,
-            &[],
-            RasterSpace::Screen,
         );
 
         let image_mask_key = api.generate_image_key();
         txn.add_image(
             image_mask_key,
             ImageDescriptor::new(2, 2, ImageFormat::R8, true, false),
             ImageData::new(vec![0, 80, 180, 255]),
             None,
--- a/gfx/wr/examples/blob.rs
+++ b/gfx/wr/examples/blob.rs
@@ -217,24 +217,19 @@ impl Example for App {
             api::ImageDescriptor::new(200, 200, api::ImageFormat::BGRA8, true, false),
             serialize_blob(api::ColorU::new(50, 150, 50, 255)),
             None,
         );
 
         let bounds = api::LayoutRect::new(api::LayoutPoint::zero(), builder.content_size());
         let space_and_clip = SpaceAndClipInfo::root_scroll(pipeline_id);
 
-        builder.push_stacking_context(
+        builder.push_simple_stacking_context(
             &api::LayoutPrimitiveInfo::new(bounds),
             space_and_clip.spatial_id,
-            None,
-            api::TransformStyle::Flat,
-            api::MixBlendMode::Normal,
-            &[],
-            api::RasterSpace::Screen,
         );
 
         builder.push_image(
             &api::LayoutPrimitiveInfo::new((30, 30).by(500, 500)),
             &space_and_clip,
             api::LayoutSize::new(500.0, 500.0),
             api::LayoutSize::new(0.0, 0.0),
             api::ImageRendering::Auto,
--- a/gfx/wr/examples/document.rs
+++ b/gfx/wr/examples/document.rs
@@ -107,24 +107,19 @@ impl Example for App {
                 doc.pipeline_id,
                 doc.content_rect.size,
             );
             let local_rect = LayoutRect::new(
                 LayoutPoint::zero(),
                 doc.content_rect.size,
             );
 
-            builder.push_stacking_context(
+            builder.push_simple_stacking_context(
                 &LayoutPrimitiveInfo::new(doc.content_rect),
                 space_and_clip.spatial_id,
-                None,
-                TransformStyle::Flat,
-                MixBlendMode::Normal,
-                &[],
-                RasterSpace::Screen,
             );
             builder.push_rect(
                 &LayoutPrimitiveInfo::new(local_rect),
                 &space_and_clip,
                 doc.color,
             );
             builder.pop_stacking_context();
 
--- a/gfx/wr/examples/frame_output.rs
+++ b/gfx/wr/examples/frame_output.rs
@@ -108,24 +108,19 @@ impl App {
 
         let info = LayoutPrimitiveInfo::new(document.content_rect);
         let space_and_clip = SpaceAndClipInfo::root_scroll(pipeline_id);
         let mut builder = DisplayListBuilder::new(
             document.pipeline_id,
             document.content_rect.size,
         );
 
-        builder.push_stacking_context(
+        builder.push_simple_stacking_context(
             &info,
             space_and_clip.spatial_id,
-            None,
-            TransformStyle::Flat,
-            MixBlendMode::Normal,
-            &[],
-            RasterSpace::Screen,
         );
 
         builder.push_rect(&info, &space_and_clip, ColorF::new(1.0, 1.0, 0.0, 1.0));
         builder.pop_stacking_context();
 
         txn.set_root_pipeline(pipeline_id);
         txn.set_display_list(
             Epoch(0),
@@ -154,24 +149,19 @@ impl Example for App {
             let device_pixel_ratio = framebuffer_size.width as f32 /
                 builder.content_size().width;
             self.init_output_document(api, DeviceIntSize::new(200, 200), device_pixel_ratio);
         }
 
         let info = LayoutPrimitiveInfo::new((100, 100).to(200, 200));
         let space_and_clip = SpaceAndClipInfo::root_scroll(pipeline_id);
 
-        builder.push_stacking_context(
+        builder.push_simple_stacking_context(
             &info,
             space_and_clip.spatial_id,
-            None,
-            TransformStyle::Flat,
-            MixBlendMode::Normal,
-            &[],
-            RasterSpace::Screen,
         );
 
         builder.push_image(
             &info,
             &space_and_clip,
             info.rect.size,
             LayoutSize::zero(),
             ImageRendering::Auto,
--- a/gfx/wr/examples/iframe.rs
+++ b/gfx/wr/examples/iframe.rs
@@ -33,24 +33,19 @@ impl Example for App {
         let sub_size = DeviceIntSize::new(100, 100);
         let sub_bounds = (0, 0).to(sub_size.width as i32, sub_size.height as i32);
 
         let sub_pipeline_id = PipelineId(pipeline_id.0, 42);
         let mut sub_builder = DisplayListBuilder::new(sub_pipeline_id, sub_bounds.size);
         let mut space_and_clip = SpaceAndClipInfo::root_scroll(pipeline_id);
 
         let info = LayoutPrimitiveInfo::new(sub_bounds);
-        sub_builder.push_stacking_context(
+        sub_builder.push_simple_stacking_context(
             &info,
             space_and_clip.spatial_id,
-            None,
-            TransformStyle::Flat,
-            MixBlendMode::Normal,
-            &[],
-            RasterSpace::Screen,
         );
 
         // green rect visible == success
         sub_builder.push_rect(&info, &space_and_clip, ColorF::new(0.0, 1.0, 0.0, 1.0));
         sub_builder.pop_stacking_context();
 
         let mut txn = Transaction::new();
         txn.set_display_list(
@@ -67,24 +62,19 @@ impl Example for App {
             space_and_clip.spatial_id,
             TransformStyle::Flat,
             PropertyBinding::Binding(PropertyBindingKey::new(42), LayoutTransform::identity()),
             ReferenceFrameKind::Transform,
         );
 
         // And this is for the root pipeline
         let info = LayoutPrimitiveInfo::new(sub_bounds);
-        builder.push_stacking_context(
+        builder.push_simple_stacking_context(
             &info,
             space_and_clip.spatial_id,
-            None,
-            TransformStyle::Flat,
-            MixBlendMode::Normal,
-            &[],
-            RasterSpace::Screen,
         );
         // red rect under the iframe: if this is visible, things have gone wrong
         builder.push_rect(&info, &space_and_clip, ColorF::new(1.0, 0.0, 0.0, 1.0));
         builder.push_iframe(&info, &space_and_clip, sub_pipeline_id, false);
         builder.pop_stacking_context();
         builder.pop_reference_frame();
     }
 }
--- a/gfx/wr/examples/image_resize.rs
+++ b/gfx/wr/examples/image_resize.rs
@@ -36,24 +36,19 @@ impl Example for App {
             image_data,
             None,
         );
 
         let bounds = (0, 0).to(512, 512);
         let info = LayoutPrimitiveInfo::new(bounds);
         let space_and_clip = SpaceAndClipInfo::root_scroll(pipeline_id);
 
-        builder.push_stacking_context(
+        builder.push_simple_stacking_context(
             &info,
             space_and_clip.spatial_id,
-            None,
-            TransformStyle::Flat,
-            MixBlendMode::Normal,
-            &[],
-            RasterSpace::Screen,
         );
 
         let image_size = LayoutSize::new(100.0, 100.0);
 
         let info = LayoutPrimitiveInfo::with_clip_rect(
             LayoutRect::new(LayoutPoint::new(100.0, 100.0), image_size),
             bounds,
         );
--- a/gfx/wr/examples/multiwindow.rs
+++ b/gfx/wr/examples/multiwindow.rs
@@ -186,24 +186,19 @@ impl Window {
         };
         let layout_size = framebuffer_size.to_f32() / euclid::TypedScale::new(device_pixel_ratio);
         let mut txn = Transaction::new();
         let mut builder = DisplayListBuilder::new(self.pipeline_id, layout_size);
         let space_and_clip = SpaceAndClipInfo::root_scroll(self.pipeline_id);
 
         let bounds = LayoutRect::new(LayoutPoint::zero(), builder.content_size());
         let info = LayoutPrimitiveInfo::new(bounds);
-        builder.push_stacking_context(
+        builder.push_simple_stacking_context(
             &info,
             space_and_clip.spatial_id,
-            None,
-            TransformStyle::Flat,
-            MixBlendMode::Normal,
-            &[],
-            RasterSpace::Screen,
         );
 
         let info = LayoutPrimitiveInfo::new(LayoutRect::new(
             LayoutPoint::new(100.0, 100.0),
             LayoutSize::new(100.0, 200.0)
         ));
         builder.push_rect(&info, &space_and_clip, ColorF::new(0.0, 1.0, 0.0, 1.0));
 
--- a/gfx/wr/examples/scrolling.rs
+++ b/gfx/wr/examples/scrolling.rs
@@ -29,38 +29,28 @@ impl Example for App {
         _framebuffer_size: DeviceIntSize,
         pipeline_id: PipelineId,
         _document_id: DocumentId,
     ) {
         let info = LayoutPrimitiveInfo::new(
             LayoutRect::new(LayoutPoint::zero(), builder.content_size())
         );
         let root_space_and_clip = SpaceAndClipInfo::root_scroll(pipeline_id);
-        builder.push_stacking_context(
+        builder.push_simple_stacking_context(
             &info,
             root_space_and_clip.spatial_id,
-            None,
-            TransformStyle::Flat,
-            MixBlendMode::Normal,
-            &[],
-            RasterSpace::Screen,
         );
 
         if true {
             // scrolling and clips stuff
             // let's make a scrollbox
             let scrollbox = (0, 0).to(300, 400);
-            builder.push_stacking_context(
+            builder.push_simple_stacking_context(
                 &LayoutPrimitiveInfo::new((10, 10).by(0, 0)),
                 root_space_and_clip.spatial_id,
-                None,
-                TransformStyle::Flat,
-                MixBlendMode::Normal,
-                &[],
-                RasterSpace::Screen,
             );
             // set the scrolling clip
             let space_and_clip1 = builder.define_scroll_frame(
                 &root_space_and_clip,
                 None,
                 (0, 0).by(1000, 1000),
                 scrollbox,
                 vec![],
--- a/gfx/wr/examples/texture_cache_stress.rs
+++ b/gfx/wr/examples/texture_cache_stress.rs
@@ -93,24 +93,19 @@ impl Example for App {
         _framebuffer_size: DeviceIntSize,
         pipeline_id: PipelineId,
         _document_id: DocumentId,
     ) {
         let bounds = (0, 0).to(512, 512);
         let info = LayoutPrimitiveInfo::new(bounds);
         let space_and_clip = SpaceAndClipInfo::root_scroll(pipeline_id);
 
-        builder.push_stacking_context(
+        builder.push_simple_stacking_context(
             &info,
             space_and_clip.spatial_id,
-            None,
-            TransformStyle::Flat,
-            MixBlendMode::Normal,
-            &[],
-            RasterSpace::Screen,
         );
 
         let x0 = 50.0;
         let y0 = 50.0;
         let image_size = LayoutSize::new(4.0, 4.0);
 
         if self.swap_keys.is_empty() {
             let key0 = api.generate_image_key();
--- a/gfx/wr/examples/yuv.rs
+++ b/gfx/wr/examples/yuv.rs
@@ -90,24 +90,19 @@ impl Example for App {
         _framebuffer_size: DeviceIntSize,
         pipeline_id: PipelineId,
         _document_id: DocumentId,
     ) {
         let bounds = LayoutRect::new(LayoutPoint::zero(), builder.content_size());
         let info = LayoutPrimitiveInfo::new(bounds);
         let space_and_clip = SpaceAndClipInfo::root_scroll(pipeline_id);
 
-        builder.push_stacking_context(
+        builder.push_simple_stacking_context(
             &info,
             space_and_clip.spatial_id,
-            None,
-            TransformStyle::Flat,
-            MixBlendMode::Normal,
-            &[],
-            RasterSpace::Screen,
         );
 
         let yuv_chanel1 = api.generate_image_key();
         let yuv_chanel2 = api.generate_image_key();
         let yuv_chanel2_1 = api.generate_image_key();
         let yuv_chanel3 = api.generate_image_key();
         txn.add_image(
             yuv_chanel1,
--- a/gfx/wr/webrender/src/box_shadow.rs
+++ b/gfx/wr/webrender/src/box_shadow.rs
@@ -164,17 +164,17 @@ impl<'a> DisplayListFlattener<'a> {
                 &LayoutPrimitiveInfo::with_clip_rect(final_prim_rect, prim_info.clip_rect),
                 clips,
                 PrimitiveKeyKind::Rectangle {
                     color: color.into(),
                 },
             );
         } else {
             // Normal path for box-shadows with a valid blur radius.
-            let blur_offset = BLUR_SAMPLE_SCALE * blur_radius;
+            let blur_offset = (BLUR_SAMPLE_SCALE * blur_radius).ceil();
             let mut extra_clips = vec![];
 
             // Add a normal clip mask to clip out the contents
             // of the surrounding primitive.
             extra_clips.push(
                 (
                     prim_info.rect.origin,
                     ClipItemKey::rounded_rect(
--- a/gfx/wr/webrender/src/display_list_flattener.rs
+++ b/gfx/wr/webrender/src/display_list_flattener.rs
@@ -29,17 +29,17 @@ use prim_store::{register_prim_chase_id,
 use prim_store::borders::{ImageBorder, NormalBorderPrim};
 use prim_store::gradient::{GradientStopKey, LinearGradient, RadialGradient, RadialGradientParams};
 use prim_store::image::{Image, YuvImage};
 use prim_store::line_dec::{LineDecoration, LineDecorationCacheKey};
 use prim_store::picture::{Picture, PictureCompositeKey, PictureKey};
 use prim_store::text_run::TextRun;
 use render_backend::{DocumentView};
 use resource_cache::{FontInstanceMap, ImageRequest};
-use scene::{Scene, ScenePipeline, StackingContextHelpers};
+use scene::{Scene, StackingContextHelpers};
 use scene_builder::{InternerMut, Interners};
 use spatial_node::{StickyFrameInfo, ScrollFrameKind, SpatialNodeType};
 use std::{f32, mem, usize};
 use std::collections::vec_deque::VecDeque;
 use std::sync::Arc;
 use tiling::{CompositeOps};
 use util::{MaxRect, VecHelper};
 
@@ -185,21 +185,46 @@ impl<'a> DisplayListFlattener<'a> {
         };
 
         flattener.push_root(
             root_pipeline_id,
             &root_pipeline.viewport_size,
             &root_pipeline.content_size,
         );
 
-        flattener.flatten_root(
-            root_pipeline,
-            &root_pipeline.viewport_size,
+        // In order to ensure we have a single root stacking context for the
+        // entire display list, we push one here. Gecko _almost_ wraps its
+        // entire display list within a single stacking context, but sometimes
+        // appends a few extra items in AddWindowOverlayWebRenderCommands. We
+        // could fix it there, but it's easier and more robust for WebRender
+        // to just ensure there's a context on the stack whenever we append
+        // primitives (since otherwise we'd panic).
+        //
+        // Note that we don't do this for iframes, even if they're pipeline
+        // roots, because they should be entirely contained within a stacking
+        // context, and we probably wouldn't crash if they weren't.
+        flattener.push_stacking_context(
+            root_pipeline.pipeline_id,
+            CompositeOps::default(),
+            TransformStyle::Flat,
+            /* is_backface_visible = */ true,
+            /* create_tile_cache = */ false,
+            ROOT_SPATIAL_NODE_INDEX,
+            ClipChainId::NONE,
+            RasterSpace::Screen,
         );
 
+        flattener.flatten_items(
+            &mut root_pipeline.display_list.iter(),
+            root_pipeline.pipeline_id,
+            LayoutVector2D::zero(),
+        );
+
+        flattener.pop_stacking_context();
+
         debug_assert!(flattener.sc_stack.is_empty());
 
         new_scene.root_pipeline_id = Some(root_pipeline_id);
         new_scene.pipeline_epochs = scene.pipeline_epochs.clone();
         new_scene.pipelines = scene.pipelines.clone();
 
         FrameBuilder::with_display_list_flattener(
             view.inner_rect,
@@ -434,65 +459,16 @@ impl<'a> DisplayListFlattener<'a> {
         pipeline_id: PipelineId,
         items: ItemRange<ClipId>,
     ) -> impl 'a + Iterator<Item = ClipId> {
         self.scene
             .get_display_list_for_pipeline(pipeline_id)
             .get(items)
     }
 
-    fn flatten_root(
-        &mut self,
-        pipeline: &'a ScenePipeline,
-        frame_size: &LayoutSize,
-    ) {
-        let pipeline_id = pipeline.pipeline_id;
-
-        self.push_stacking_context(
-            pipeline_id,
-            CompositeOps::default(),
-            TransformStyle::Flat,
-            true,
-            true,
-            ROOT_SPATIAL_NODE_INDEX,
-            ClipChainId::NONE,
-            RasterSpace::Screen,
-        );
-
-        // For the root pipeline, there's no need to add a full screen rectangle
-        // here, as it's handled by the framebuffer clear.
-        // TODO(gw): In future, we can probably remove this code completely and handle
-        //           it as part of the tile cache background color clearing.
-        if self.scene.root_pipeline_id != Some(pipeline_id) {
-            if let Some(pipeline) = self.scene.pipelines.get(&pipeline_id) {
-                if let Some(bg_color) = pipeline.background_color {
-                    let reference_frame_info = ScrollNodeAndClipChain::new(
-                        self.id_to_index_mapper.get_spatial_node_index(SpatialId::root_reference_frame(pipeline_id)),
-                        ClipChainId::NONE,
-                    );
-                    let root_bounds = LayoutRect::new(LayoutPoint::zero(), *frame_size);
-                    let info = LayoutPrimitiveInfo::new(root_bounds);
-                    self.add_solid_rectangle(
-                        reference_frame_info,
-                        &info,
-                        bg_color,
-                    );
-                }
-            }
-        }
-
-        self.flatten_items(
-            &mut pipeline.display_list.iter(),
-            pipeline_id,
-            LayoutVector2D::zero(),
-        );
-
-        self.pop_stacking_context();
-    }
-
     fn flatten_items(
         &mut self,
         traversal: &mut BuiltDisplayListIter<'a>,
         pipeline_id: PipelineId,
         reference_frame_relative_offset: LayoutVector2D,
     ) {
         loop {
             let subtraversal = {
@@ -636,17 +612,17 @@ impl<'a> DisplayListFlattener<'a> {
             None => ClipChainId::NONE,
         };
 
         self.push_stacking_context(
             pipeline_id,
             composition_operations,
             stacking_context.transform_style,
             is_backface_visible,
-            false,
+            stacking_context.cache_tiles,
             spatial_node_index,
             clip_chain_id,
             stacking_context.raster_space,
         );
 
         self.flatten_items(
             traversal,
             pipeline_id,
@@ -701,19 +677,20 @@ impl<'a> DisplayListFlattener<'a> {
             Some(ExternalScrollId(0, iframe_pipeline_id)),
             iframe_pipeline_id,
             &iframe_rect,
             &pipeline.content_size,
             ScrollSensitivity::ScriptAndInputEvents,
             ScrollFrameKind::PipelineRoot,
         );
 
-        self.flatten_root(
-            pipeline,
-            &iframe_rect.size,
+        self.flatten_items(
+            &mut pipeline.display_list.iter(),
+            pipeline.pipeline_id,
+            LayoutVector2D::zero(),
         );
 
         self.pipeline_clip_chain_stack.pop();
     }
 
     fn flatten_item<'b>(
         &'b mut self,
         item: DisplayItemRef<'a, 'b>,
@@ -1207,32 +1184,31 @@ impl<'a> DisplayListFlattener<'a> {
     }
 
     pub fn push_stacking_context(
         &mut self,
         pipeline_id: PipelineId,
         composite_ops: CompositeOps,
         transform_style: TransformStyle,
         is_backface_visible: bool,
-        is_pipeline_root: bool,
+        create_tile_cache: bool,
         spatial_node_index: SpatialNodeIndex,
         clip_chain_id: ClipChainId,
         requested_raster_space: RasterSpace,
     ) {
         // Check if this stacking context is the root of a pipeline, and the caller
         // has requested it as an output frame.
+        let is_pipeline_root =
+            self.sc_stack.last().map_or(true, |sc| sc.pipeline_id != pipeline_id);
         let frame_output_pipeline_id = if is_pipeline_root && self.output_pipelines.contains(&pipeline_id) {
             Some(pipeline_id)
         } else {
             None
         };
 
-        let create_tile_cache = is_pipeline_root &&
-                                self.sc_stack.len() == 2;
-
         // Get the transform-style of the parent stacking context,
         // which determines if we *might* need to draw this on
         // an intermediate surface for plane splitting purposes.
         let (parent_is_3d, extra_3d_instance) = match self.sc_stack.last_mut() {
             Some(sc) => {
                 // Cut the sequence of flat children before starting a child stacking context,
                 // so that the relative order between them and our current SC is preserved.
                 let extra_instance = sc.cut_flat_item_sequence(
@@ -2574,18 +2550,18 @@ impl FlattenedStackingContext {
             return false;
         }
 
         // If represents a transform, it may affect backface visibility of children
         if !clip_scroll_tree.node_is_identity(self.spatial_node_index) {
             return false;
         }
 
-        // If the pipelines are different, we care for purposes of selecting tile caches
-        if self.pipeline_id != parent.pipeline_id {
+        // If this stacking context gets picture caching, we need it.
+        if self.create_tile_cache {
             return false;
         }
 
         // It is redundant!
         true
     }
 
     /// For a Preserve3D context, cut the sequence of the immediate flat children
--- a/gfx/wr/webrender/src/picture.rs
+++ b/gfx/wr/webrender/src/picture.rs
@@ -1294,17 +1294,17 @@ impl TileCache {
     /// Apply any updates after prim dependency updates. This applies
     /// any late tile invalidations, and sets up the dirty rect and
     /// set of tile blits.
     pub fn post_update(
         &mut self,
         resource_cache: &mut ResourceCache,
         gpu_cache: &mut GpuCache,
         frame_context: &FrameVisibilityContext,
-        _scratch: &mut PrimitiveScratchBuffer,
+        scratch: &mut PrimitiveScratchBuffer,
     ) -> LayoutRect {
         self.dirty_region.clear();
         self.pending_blits.clear();
 
         let descriptor = ImageDescriptor::new(
             TILE_SIZE_WIDTH,
             TILE_SIZE_HEIGHT,
             ImageFormat::BGRA8,
@@ -1395,40 +1395,48 @@ impl TileCache {
 
             // Decide how to handle this tile when drawing this frame.
             if tile.is_valid {
                 // No need to include this is any dirty rect calculations.
                 tile.consider_for_dirty_rect = false;
                 self.tiles_to_draw.push(TileIndex(i));
 
                 if frame_context.debug_flags.contains(DebugFlags::PICTURE_CACHING_DBG) {
-                    let tile_device_rect = tile.world_rect * frame_context.device_pixel_scale;
-                    let mut label_pos = tile_device_rect.origin + DeviceVector2D::new(20.0, 30.0);
-                    _scratch.push_debug_rect(
-                        tile_device_rect,
-                        debug_colors::GREEN,
-                    );
-                    _scratch.push_debug_string(
-                        label_pos,
-                        debug_colors::RED,
-                        format!("{:?} {:?} {:?}", tile.id, tile.handle, tile.world_rect),
-                    );
-                    label_pos.y += 20.0;
-                    _scratch.push_debug_string(
-                        label_pos,
-                        debug_colors::RED,
-                        format!("same: {} frames", tile.same_frames),
-                    );
+                    if let Some(world_rect) = tile.world_rect.intersection(&self.world_bounding_rect) {
+                        let tile_device_rect = world_rect * frame_context.device_pixel_scale;
+                        let mut label_offset = DeviceVector2D::new(20.0, 30.0);
+                        scratch.push_debug_rect(
+                            tile_device_rect,
+                            debug_colors::GREEN,
+                        );
+                        if tile_device_rect.size.height >= label_offset.y {
+                            scratch.push_debug_string(
+                                tile_device_rect.origin + label_offset,
+                                debug_colors::RED,
+                                format!("{:?} {:?} {:?}", tile.id, tile.handle, tile.world_rect),
+                            );
+                        }
+                        label_offset.y += 20.0;
+                        if tile_device_rect.size.height >= label_offset.y {
+                            scratch.push_debug_string(
+                                tile_device_rect.origin + label_offset,
+                                debug_colors::RED,
+                                format!("same: {} frames", tile.same_frames),
+                            );
+                        }
+                    }
                 }
             } else {
                 if frame_context.debug_flags.contains(DebugFlags::PICTURE_CACHING_DBG) {
-                    _scratch.push_debug_rect(
-                        visible_rect * frame_context.device_pixel_scale,
-                        debug_colors::RED,
-                    );
+                    if let Some(world_rect) = visible_rect.intersection(&self.world_bounding_rect) {
+                        scratch.push_debug_rect(
+                            world_rect * frame_context.device_pixel_scale,
+                            debug_colors::RED,
+                        );
+                    }
                 }
 
                 // Only cache tiles that have had the same content for at least two
                 // frames. This skips caching on pages / benchmarks that are changing
                 // every frame, which is wasteful.
                 if tile.same_frames > FRAMES_BEFORE_CACHING {
                     // Ensure that this texture is allocated.
                     resource_cache.texture_cache.update(
--- a/gfx/wr/webrender/src/prim_store/mod.rs
+++ b/gfx/wr/webrender/src/prim_store/mod.rs
@@ -1984,30 +1984,32 @@ impl PrimitiveStore {
                         continue;
                     }
                 };
 
                 // When the debug display is enabled, paint a colored rectangle around each
                 // primitive.
                 if frame_context.debug_flags.contains(::api::DebugFlags::PRIMITIVE_DBG) {
                     let debug_color = match prim_instance.kind {
-                        PrimitiveInstanceKind::Picture { .. } => debug_colors::GREEN,
+                        PrimitiveInstanceKind::Picture { .. } => ColorF::TRANSPARENT,
                         PrimitiveInstanceKind::TextRun { .. } => debug_colors::RED,
                         PrimitiveInstanceKind::LineDecoration { .. } => debug_colors::PURPLE,
                         PrimitiveInstanceKind::NormalBorder { .. } |
                         PrimitiveInstanceKind::ImageBorder { .. } => debug_colors::ORANGE,
                         PrimitiveInstanceKind::Rectangle { .. } => ColorF { r: 0.8, g: 0.8, b: 0.8, a: 0.5 },
                         PrimitiveInstanceKind::YuvImage { .. } => debug_colors::BLUE,
                         PrimitiveInstanceKind::Image { .. } => debug_colors::BLUE,
                         PrimitiveInstanceKind::LinearGradient { .. } => debug_colors::PINK,
                         PrimitiveInstanceKind::RadialGradient { .. } => debug_colors::PINK,
                         PrimitiveInstanceKind::Clear { .. } => debug_colors::CYAN,
                     };
-                    let debug_rect = clipped_world_rect * frame_context.device_pixel_scale;
-                    frame_state.scratch.push_debug_rect(debug_rect, debug_color);
+                    if debug_color.a != 0.0 {
+                        let debug_rect = clipped_world_rect * frame_context.device_pixel_scale;
+                        frame_state.scratch.push_debug_rect(debug_rect, debug_color);
+                    }
                 }
 
                 let vis_index = PrimitiveVisibilityIndex(frame_state.scratch.prim_info.len() as u32);
 
                 frame_state.scratch.prim_info.push(
                     PrimitiveVisibility {
                         clipped_world_rect,
                         clip_chain,
--- a/gfx/wr/webrender_api/src/display_item.rs
+++ b/gfx/wr/webrender_api/src/display_item.rs
@@ -547,16 +547,18 @@ pub struct PushStackingContextDisplayIte
 }
 
 #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
 pub struct StackingContext {
     pub transform_style: TransformStyle,
     pub mix_blend_mode: MixBlendMode,
     pub clip_id: Option<ClipId>,
     pub raster_space: RasterSpace,
+    /// True if picture caching should be used on this stacking context.
+    pub cache_tiles: bool,
 } // IMPLICIT: filters: Vec<FilterOp>
 
 
 #[repr(u32)]
 #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
 pub enum TransformStyle {
     Flat = 0,
     Preserve3D = 1,
--- a/gfx/wr/webrender_api/src/display_list.rs
+++ b/gfx/wr/webrender_api/src/display_list.rs
@@ -1299,33 +1299,63 @@ impl DisplayListBuilder {
         &mut self,
         layout: &LayoutPrimitiveInfo,
         spatial_id: SpatialId,
         clip_id: Option<ClipId>,
         transform_style: TransformStyle,
         mix_blend_mode: MixBlendMode,
         filters: &[FilterOp],
         raster_space: RasterSpace,
+        cache_tiles: bool,
     ) {
         let item = SpecificDisplayItem::PushStackingContext(PushStackingContextDisplayItem {
             stacking_context: StackingContext {
                 transform_style,
                 mix_blend_mode,
                 clip_id,
                 raster_space,
+                cache_tiles,
             },
         });
 
         self.push_item(&item, layout, &SpaceAndClipInfo {
             spatial_id,
             clip_id: ClipId::invalid(),
         });
         self.push_iter(filters);
     }
 
+    /// Helper for examples/ code.
+    pub fn push_simple_stacking_context(
+        &mut self,
+        layout: &LayoutPrimitiveInfo,
+        spatial_id: SpatialId,
+    ) {
+        self.push_simple_stacking_context_with_filters(layout, spatial_id, &[]);
+    }
+
+    /// Helper for examples/ code.
+    pub fn push_simple_stacking_context_with_filters(
+        &mut self,
+        layout: &LayoutPrimitiveInfo,
+        spatial_id: SpatialId,
+        filters: &[FilterOp],
+    ) {
+        self.push_stacking_context(
+            layout,
+            spatial_id,
+            None,
+            TransformStyle::Flat,
+            MixBlendMode::Normal,
+            filters,
+            RasterSpace::Screen,
+            /* cache_tiles = */ false,
+        );
+    }
+
     pub fn pop_stacking_context(&mut self) {
         self.push_new_empty_item(&SpecificDisplayItem::PopStackingContext);
     }
 
     pub fn push_stops(&mut self, stops: &[GradientStop]) {
         if stops.is_empty() {
             return;
         }
index 9968a6a054590973ea4791353660f3244310b025..4c2d561da1dd99ce4106bf0fc2e638fa0773940b
GIT binary patch
literal 48931
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%0AMco04pCUZ+ce-@=3
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
index e90988ff31e16849507b2f5d3149b13cfc57bab2..c89ec417e6ab307d19565520806af1a5e5dbb976
GIT binary patch
literal 3957
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
St4+{zTENWMf?8l?ANoHN^;<ar
--- a/gfx/wr/wrench/src/yaml_frame_reader.rs
+++ b/gfx/wr/wrench/src/yaml_frame_reader.rs
@@ -1772,16 +1772,17 @@ impl YamlFrameReader {
         dl.push_stacking_context(
             &info,
             *self.spatial_id_stack.last().unwrap(),
             clip_node_id,
             transform_style,
             mix_blend_mode,
             &filters,
             raster_space,
+            /* cache_tiles = */ false,
         );
 
         if !yaml["items"].is_badvalue() {
             self.add_display_list_items_from_yaml(dl, wrench, &yaml["items"]);
         }
 
         dl.pop_stacking_context();
 
--- a/layout/base/PresShell.cpp
+++ b/layout/base/PresShell.cpp
@@ -6095,17 +6095,17 @@ void PresShell::Paint(nsView* aViewToPai
         pc->GetVisibleArea(), pc->AppUnitsPerDevPixel());
     bgcolor = NS_ComposeColors(bgcolor, mCanvasBackgroundColor);
     WebRenderBackgroundData data(wr::ToLayoutRect(bounds),
                                  wr::ToColorF(ToDeviceColor(bgcolor)));
     nsTArray<wr::FilterOp> wrFilters;
 
     MaybeSetupTransactionIdAllocator(layerManager, presContext);
     layerManager->AsWebRenderLayerManager()->EndTransactionWithoutLayer(
-        nullptr, nullptr, wrFilters, &data);
+        nullptr, nullptr, std::move(wrFilters), &data);
     return;
   }
 
   RefPtr<ColorLayer> root = layerManager->CreateColorLayer();
   if (root) {
     nsPresContext* pc = GetPresContext();
     nsIntRect bounds =
         pc->GetVisibleArea().ToOutsidePixels(pc->AppUnitsPerDevPixel());
--- a/layout/generic/ReflowInput.cpp
+++ b/layout/generic/ReflowInput.cpp
@@ -817,18 +817,17 @@ static bool AreDynamicReflowRootsEnabled
   return sAreDynamicReflowRootsEnabled;
 }
 
 void ReflowInput::InitDynamicReflowRoot() {
   auto display = mStyleDisplay->mDisplay;
   if (mFrame->IsFrameOfType(nsIFrame::eLineParticipant) ||
       nsStyleDisplay::IsRubyDisplayType(display) ||
       mFrameType == NS_CSS_FRAME_TYPE_INTERNAL_TABLE ||
-      display == StyleDisplay::Table || display == StyleDisplay::TableCaption ||
-      display == StyleDisplay::InlineTable ||
+      display == StyleDisplay::Table || display == StyleDisplay::InlineTable ||
       (mFrame->GetParent() && mFrame->GetParent()->IsXULBoxFrame())) {
     // We have a display type where 'width' and 'height' don't actually
     // set the width or height (i.e., the size depends on content).
     NS_ASSERTION(!(mFrame->GetStateBits() & NS_FRAME_DYNAMIC_REFLOW_ROOT),
                  "should not have dynamic reflow root bit");
     return;
   }
 
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -2623,17 +2623,18 @@ already_AddRefed<LayerManager> nsDisplay
       nsTArray<wr::FilterOp> wrFilters;
       gfx::Matrix5x4* colorMatrix =
           nsDocShell::Cast(docShell)->GetColorMatrix();
       if (colorMatrix) {
         wrFilters.AppendElement(
             wr::FilterOp::ColorMatrix(colorMatrix->components));
       }
 
-      wrManager->EndTransactionWithoutLayer(this, aBuilder, wrFilters);
+      wrManager->EndTransactionWithoutLayer(this, aBuilder,
+                                            std::move(wrFilters));
     }
 
     // For layers-free mode, we check the invalidation state bits in the
     // EndTransaction. So we clear the invalidation state bits after
     // EndTransaction.
     if (widgetTransaction ||
         // SVG-as-an-image docs don't paint as part of the retained layer tree,
         // but they still need the invalidation state bits cleared in order for
@@ -6071,20 +6072,21 @@ bool nsDisplayOpacity::CreateWebRenderCo
 
   uint64_t animationsId = AddAnimationsForWebRender(
       this, eCSSProperty_opacity, aManager, aDisplayListBuilder);
   wr::WrAnimationProperty prop{
       wr::WrAnimationType::Opacity,
       animationsId,
   };
 
-  nsTArray<mozilla::wr::FilterOp> filters;
+  wr::StackingContextParams params;
+  params.animation = animationsId ? &prop : nullptr;
+  params.opacity = opacityForSC;
   StackingContextHelper sc(aSc, GetActiveScrolledRoot(), mFrame, this, aBuilder,
-                           filters, LayoutDeviceRect(), nullptr,
-                           animationsId ? &prop : nullptr, opacityForSC);
+                           params);
 
   aManager->CommandBuilder().CreateWebRenderCommandsFromDisplayList(
       &mList, this, aDisplayListBuilder, sc, aBuilder, aResources);
   return true;
 }
 
 nsDisplayBlendMode::nsDisplayBlendMode(
     nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, nsDisplayList* aList,
@@ -6110,21 +6112,21 @@ LayerState nsDisplayBlendMode::GetLayerS
 }
 
 bool nsDisplayBlendMode::CreateWebRenderCommands(
     mozilla::wr::DisplayListBuilder& aBuilder,
     mozilla::wr::IpcResourceUpdateQueue& aResources,
     const StackingContextHelper& aSc,
     mozilla::layers::RenderRootStateManager* aManager,
     nsDisplayListBuilder* aDisplayListBuilder) {
-  nsTArray<mozilla::wr::FilterOp> filters;
+  wr::StackingContextParams params;
+  params.mix_blend_mode =
+      wr::ToMixBlendMode(nsCSSRendering::GetGFXBlendMode(mBlendMode));
   StackingContextHelper sc(aSc, GetActiveScrolledRoot(), mFrame, this, aBuilder,
-                           filters, LayoutDeviceRect(), nullptr, nullptr,
-                           nullptr, nullptr, wr::ReferenceFrameKind::Transform,
-                           nsCSSRendering::GetGFXBlendMode(mBlendMode));
+                           params);
 
   return nsDisplayWrapList::CreateWebRenderCommands(
       aBuilder, aResources, sc, aManager, aDisplayListBuilder);
 }
 
 // nsDisplayBlendMode uses layers for rendering
 already_AddRefed<Layer> nsDisplayBlendMode::BuildLayer(
     nsDisplayListBuilder* aBuilder, LayerManager* aManager,
@@ -6341,19 +6343,21 @@ bool nsDisplayOwnLayer::CreateWebRenderC
   AnimationInfo& animationInfo = animationData->GetAnimationInfo();
   animationInfo.EnsureAnimationsId();
   mWrAnimationId = animationInfo.GetCompositorAnimationsId();
 
   wr::WrAnimationProperty prop;
   prop.id = mWrAnimationId;
   prop.effect_type = wr::WrAnimationType::Transform;
 
+  wr::StackingContextParams params;
+  params.animation = &prop;
+
   StackingContextHelper sc(aSc, GetActiveScrolledRoot(), mFrame, this, aBuilder,
-                           nsTArray<wr::FilterOp>(), LayoutDeviceRect(),
-                           nullptr, &prop);
+                           params);
 
   nsDisplayWrapList::CreateWebRenderCommands(aBuilder, aResources, sc, aManager,
                                              aDisplayListBuilder);
   return true;
 }
 
 bool nsDisplayOwnLayer::UpdateScrollData(
     mozilla::layers::WebRenderScrollData* aData,
@@ -7873,41 +7877,43 @@ bool nsDisplayTransform::CreateWebRender
 
   uint64_t animationsId = AddAnimationsForWebRender(
       this, eCSSProperty_transform, aManager, aDisplayListBuilder);
   wr::WrAnimationProperty prop{
       wr::WrAnimationType::Transform,
       animationsId,
   };
 
-  nsTArray<mozilla::wr::FilterOp> filters;
   Maybe<nsDisplayTransform*> deferredTransformItem;
   if (!mFrame->ChildrenHavePerspective()) {
     // If it has perspective, we create a new scroll data via the
     // UpdateScrollData call because that scenario is more complex. Otherwise
     // we can just stash the transform on the StackingContextHelper and
     // apply it to any scroll data that are created inside this
     // nsDisplayTransform.
     deferredTransformItem = Some(this);
   }
 
   // If it looks like we're animated, we should rasterize in local space
   // (disabling subpixel-aa and global pixel snapping)
   bool animated =
       ActiveLayerTracker::IsStyleMaybeAnimated(Frame(), eCSSProperty_transform);
 
-  bool preserve3D = mFrame->Extend3DContext() && !mIsTransformSeparator;
-
-  StackingContextHelper sc(
-      aSc, GetActiveScrolledRoot(), mFrame, this, aBuilder, filters,
-      LayoutDeviceRect(position, LayoutDeviceSize()), &newTransformMatrix,
-      animationsId ? &prop : nullptr, nullptr, transformForSC,
-      wr::ReferenceFrameKind::Transform, gfx::CompositionOp::OP_OVER,
-      !BackfaceIsHidden(), preserve3D, deferredTransformItem,
-      wr::WrStackingContextClip::None(), animated);
+  wr::StackingContextParams params;
+  params.mBoundTransform = &newTransformMatrix;
+  params.animation = animationsId ? &prop : nullptr;
+  params.mTransformPtr = transformForSC;
+  params.is_backface_visible = !BackfaceIsHidden();
+  params.mDeferredTransformItem = deferredTransformItem;
+  params.mAnimated = animated;
+  params.SetPreserve3D(mFrame->Extend3DContext() && !mIsTransformSeparator);
+
+  StackingContextHelper sc(aSc, GetActiveScrolledRoot(), mFrame, this, aBuilder,
+                           params,
+                           LayoutDeviceRect(position, LayoutDeviceSize()));
 
   return mStoredList.CreateWebRenderCommands(aBuilder, aResources, sc, aManager,
                                              aDisplayListBuilder);
 }
 
 bool nsDisplayTransform::UpdateScrollData(
     mozilla::layers::WebRenderScrollData* aData,
     mozilla::layers::WebRenderLayerScrollData* aLayerData) {
@@ -8496,22 +8502,24 @@ bool nsDisplayPerspective::CreateWebRend
   // WR knows how to treat perspective in that case, so the only thing we need
   // to do is to ensure we pass true when we're involved in a 3d context in any
   // other way via the transform-style property on either the transformed frame
   // or the perspective frame in order to not confuse WR's preserve-3d code in
   // very awful ways.
   bool preserve3D =
       mFrame->Extend3DContext() || perspectiveFrame->Extend3DContext();
 
-  nsTArray<mozilla::wr::FilterOp> filters;
-  StackingContextHelper sc(
-      aSc, GetActiveScrolledRoot(), mFrame, this, aBuilder, filters,
-      LayoutDeviceRect(), nullptr, nullptr, nullptr, &perspectiveMatrix,
-      wr::ReferenceFrameKind::Perspective, gfx::CompositionOp::OP_OVER,
-      !BackfaceIsHidden(), preserve3D);
+  wr::StackingContextParams params;
+  params.mTransformPtr = &perspectiveMatrix;
+  params.reference_frame_kind = wr::ReferenceFrameKind::Perspective;
+  params.is_backface_visible = !BackfaceIsHidden();
+  params.SetPreserve3D(preserve3D);
+
+  StackingContextHelper sc(aSc, GetActiveScrolledRoot(), mFrame, this, aBuilder,
+                           params);
 
   return mList.CreateWebRenderCommands(aBuilder, aResources, sc, aManager,
                                        aDisplayListBuilder);
 }
 
 nsDisplayItemGeometry* nsCharClipDisplayItem::AllocateGeometry(
     nsDisplayListBuilder* aBuilder) {
   return new nsCharClipGeometry(this, aBuilder);
@@ -9092,29 +9100,21 @@ bool nsDisplayMasksAndClipPaths::CreateW
     bounds.MoveTo(0, 0);
 
     wr::WrClipId clipId = clip->first();
 
     Maybe<float> opacity = clip->second() == HandleOpacity::Yes
                                ? Some(mFrame->StyleEffects()->mOpacity)
                                : Nothing();
 
-    layer.emplace(aSc, GetActiveScrolledRoot(), mFrame, this, aBuilder,
-                  /*aFilters: */ nsTArray<wr::FilterOp>(),
-                  /*aBounds: */ bounds,
-                  /*aBoundTransform: */ nullptr,
-                  /*aAnimation: */ nullptr,
-                  /*aOpacity: */ opacity.ptrOr(nullptr),
-                  /*aTransform: */ nullptr,
-                  /*aReferenceFrameKind: */ wr::ReferenceFrameKind::Transform,
-                  /*aMixBlendMode: */ gfx::CompositionOp::OP_OVER,
-                  /*aBackfaceVisible: */ true,
-                  /*aIsPreserve3D: */ false,
-                  /*aTransformForScrollData: */ Nothing(),
-                  /*aClip: */ wr::WrStackingContextClip::ClipId(clipId));
+    wr::StackingContextParams params;
+    params.clip = wr::WrStackingContextClip::ClipId(clipId);
+    params.opacity = opacity.ptrOr(nullptr);
+    layer.emplace(aSc, GetActiveScrolledRoot(), mFrame, this, aBuilder, params,
+                  bounds);
     sc = layer.ptr();
   }
 
   nsDisplayEffectsBase::CreateWebRenderCommands(aBuilder, aResources, *sc,
                                                 aManager, aDisplayListBuilder);
 
   return true;
 }
@@ -9408,22 +9408,22 @@ bool nsDisplayFilters::CreateWebRenderCo
     wr::WrClipId clipId =
         aBuilder.DefineClip(Nothing(), wr::ToRoundedLayoutRect(devPxRect));
     clip = wr::WrStackingContextClip::ClipId(clipId);
   } else {
     clip = wr::WrStackingContextClip::ClipChain(aBuilder.CurrentClipChainId());
   }
 
   float opacity = mFrame->StyleEffects()->mOpacity;
-  StackingContextHelper sc(
-      aSc, GetActiveScrolledRoot(), mFrame, this, aBuilder, wrFilters,
-      LayoutDeviceRect(), nullptr, nullptr,
-      opacity != 1.0f && mHandleOpacity ? &opacity : nullptr, nullptr,
-      wr::ReferenceFrameKind::Transform, gfx::CompositionOp::OP_OVER, true,
-      false, Nothing(), clip);
+  wr::StackingContextParams params;
+  params.mFilters = std::move(wrFilters);
+  params.opacity = opacity != 1.0f && mHandleOpacity ? &opacity : nullptr;
+  params.clip = clip;
+  StackingContextHelper sc(aSc, GetActiveScrolledRoot(), mFrame, this, aBuilder,
+                           params);
 
   nsDisplayEffectsBase::CreateWebRenderCommands(aBuilder, aResources, sc,
                                                 aManager, aDisplayListBuilder);
 
   return true;
 }
 
 #ifdef MOZ_DUMP_PAINTING
--- a/layout/reftests/box-shadow/reftest.list
+++ b/layout/reftests/box-shadow/reftest.list
@@ -6,28 +6,28 @@ random != boxshadow-blur-2.html boxshado
 == boxshadow-multiple.html boxshadow-multiple-ref.html
 == boxshadow-spread.html boxshadow-spread-ref.html
 == tableboxshadow-basic.html tableboxshadow-basic-ref.html
 == tableboxshadow-trshadow.html tableboxshadow-trshadow-ref.html
 == tableboxshadow-tdshadow.html tableboxshadow-tdshadow-ref.html
 == boxshadow-rounding.html boxshadow-rounding-ref.html
 # One uses old path, one uses WR box shadow.
 fails-if(Android) == boxshadow-button.html boxshadow-button-ref.html
-fuzzy-if(OSX==1010,0-1,0-24) fuzzy-if(d2d,0-16,0-999) fuzzy-if(skiaContent,0-1,0-12) fuzzy-if(webrender,5-9,1560-1680) == boxshadow-large-border-radius.html boxshadow-large-border-radius-ref.html # Bug 1209649
+fuzzy-if(OSX==1010,0-1,0-24) fuzzy-if(d2d,0-16,0-999) fuzzy-if(skiaContent,0-1,0-12) fuzzy-if(webrender,5-9,700-850) == boxshadow-large-border-radius.html boxshadow-large-border-radius-ref.html # Bug 1209649
 
 fails-if(Android) == boxshadow-fileupload.html boxshadow-fileupload-ref.html
 fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu),0-98,0-152) fuzzy-if(skiaContent,0-13,0-28) fuzzy-if(webrender,19-19,49-52) == boxshadow-inner-basic.html boxshadow-inner-basic-ref.svg
 fuzzy-if(skiaContent,0-1,0-17) random-if(layersGPUAccelerated) == boxshadow-mixed.html boxshadow-mixed-ref.html
 fuzzy-if(skiaContent,0-1,0-17) == boxshadow-mixed-2.html boxshadow-mixed-2-ref.html
 random-if(d2d) fuzzy-if(skiaContent,0-1,0-212) fuzzy-if(webrender,0-127,0-3528) == boxshadow-rounded-spread.html boxshadow-rounded-spread-ref.html
 fuzzy-if(skiaContent,0-1,0-50) == boxshadow-dynamic.xul boxshadow-dynamic-ref.xul
 random-if(d2d) fuzzy-if(skiaContent,0-1,0-14) == boxshadow-onecorner.html boxshadow-onecorner-ref.html
 random-if(d2d) fuzzy-if(skiaContent,0-1,0-22) == boxshadow-twocorners.html boxshadow-twocorners-ref.html
 random-if(d2d) fuzzy-if(skiaContent,0-1,0-36) == boxshadow-threecorners.html boxshadow-threecorners-ref.html
-fuzzy(0-2,0-440) fails-if(webrender&&gtkWidget) == boxshadow-skiprect.html boxshadow-skiprect-ref.html
+fuzzy(0-2,0-440) == boxshadow-skiprect.html boxshadow-skiprect-ref.html
 == boxshadow-opacity.html boxshadow-opacity-ref.html
 == boxshadow-color-rounding.html boxshadow-color-rounding-ref.html
 == boxshadow-color-rounding-middle.html boxshadow-color-rounding-middle-ref.html
 fuzzy(0-3,0-500) fuzzy-if(d2d,0-2,0-1080) == boxshadow-border-radius-int.html boxshadow-border-radius-int-ref.html
 == boxshadow-inset-neg-spread.html about:blank
 == boxshadow-inset-neg-spread2.html boxshadow-inset-neg-spread2-ref.html
 fuzzy(0-26,0-3610) fuzzy-if(d2d,0-26,0-5910) == boxshadow-rotated.html boxshadow-rotated-ref.html # Bug 1211264
 == boxshadow-inset-large-border-radius.html boxshadow-inset-large-border-radius-ref.html
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/TrackingProtection.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/TrackingProtection.java
@@ -10,21 +10,21 @@ import org.mozilla.geckoview.GeckoSessio
 
 /* package */ class TrackingProtection {
     private static final String TEST = "test-track-simple";
     private static final String AD = "ads-track-digest256";
     private static final String ANALYTIC = "analytics-track-digest256";
     private static final String SOCIAL = "social-track-digest256";
     private static final String CONTENT = "content-track-digest256";
     private static final String[] AD_EXT = new String[] {
-        "fanboy-annoyance-digest256",
-        "fanboy-social-digest256",
-        "easylist-digest25",
-        "easyprivacy-digest25",
-        "adguard-digest25"
+        "fanboyannoyance-ads-digest256",
+        "fanboysocial-ads-digest256",
+        "easylist-ads-digest25",
+        "easyprivacy-ads-digest25",
+        "adguard-ads-digest25"
     };
 
     /* package */ static String buildPrefValue(int categories) {
         StringBuilder builder = new StringBuilder();
 
         if ((categories == TrackingProtectionDelegate.CATEGORY_NONE)) {
             return "";
         }
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -5561,23 +5561,23 @@ pref("urlclassifier.passwordAllowTable",
 pref("urlclassifier.trackingAnnotationTable", "test-track-simple,base-track-digest256,content-track-digest256");
 #else
 pref("urlclassifier.trackingAnnotationTable", "test-track-simple,base-track-digest256");
 #endif
 pref("urlclassifier.trackingAnnotationWhitelistTable", "test-trackwhite-simple,mozstd-trackwhite-digest256");
 pref("urlclassifier.trackingTable", "test-track-simple,base-track-digest256");
 pref("urlclassifier.trackingWhitelistTable", "test-trackwhite-simple,mozstd-trackwhite-digest256");
 
-pref("urlclassifier.features.fingerprinting.blacklistTables", "");
-pref("urlclassifier.features.fingerprinting.whitelistTables", "");
-pref("urlclassifier.features.cryptomining.blacklistTables", "");
-pref("urlclassifier.features.cryptomining.whitelistTables", "");
+pref("urlclassifier.features.fingerprinting.blacklistTables", "base-fingerprinting-track-digest256");
+pref("urlclassifier.features.fingerprinting.whitelistTables", "mozstd-trackwhite-digest256");
+pref("urlclassifier.features.cryptomining.blacklistTables", "base-cryptomining-track-digest256");
+pref("urlclassifier.features.cryptomining.whitelistTables", "mozstd-trackwhite-digest256");
 
 // These tables will never trigger a gethash call.
-pref("urlclassifier.disallow_completions", "test-malware-simple,test-harmful-simple,test-phish-simple,test-unwanted-simple,test-track-simple,test-trackwhite-simple,test-block-simple,goog-downloadwhite-digest256,base-track-digest256,mozstd-trackwhite-digest256,content-track-digest256,mozplugin-block-digest256,mozplugin2-block-digest256,block-flash-digest256,except-flash-digest256,allow-flashallow-digest256,except-flashallow-digest256,block-flashsubdoc-digest256,except-flashsubdoc-digest256,goog-passwordwhite-proto,ads-track-digest256,social-track-digest256,analytics-track-digest256,base-fingerprinting-track-digest256,content-fingerprinting-track-digest256,base-cryptomining-track-digest256,content-cryptomining-track-digest256,fanboy-annoyance-digest256,fanboy-social-digest256,easylist-digest256,easyprivacy-digest256,adguard-digest256");
+pref("urlclassifier.disallow_completions", "test-malware-simple,test-harmful-simple,test-phish-simple,test-unwanted-simple,test-track-simple,test-trackwhite-simple,test-block-simple,goog-downloadwhite-digest256,base-track-digest256,mozstd-trackwhite-digest256,content-track-digest256,mozplugin-block-digest256,mozplugin2-block-digest256,block-flash-digest256,except-flash-digest256,allow-flashallow-digest256,except-flashallow-digest256,block-flashsubdoc-digest256,except-flashsubdoc-digest256,goog-passwordwhite-proto,ads-track-digest256,social-track-digest256,analytics-track-digest256,base-fingerprinting-track-digest256,content-fingerprinting-track-digest256,base-cryptomining-track-digest256,content-cryptomining-track-digest256,fanboyannoyance-ads-digest256,fanboysocial-ads-digest256,easylist-ads-digest256,easyprivacy-ads-digest256,adguard-ads-digest256");
 
 // Number of random entries to send with a gethash request
 pref("urlclassifier.gethashnoise", 4);
 
 // Gethash timeout for Safe Browsing
 pref("urlclassifier.gethash.timeout_ms", 5000);
 // Update server response timeout for Safe Browsing
 pref("urlclassifier.update.response_timeout_ms", 30000);
@@ -5636,17 +5636,17 @@ pref("browser.safebrowsing.provider.goog
 pref("browser.safebrowsing.provider.google4.advisoryName", "Google Safe Browsing");
 pref("browser.safebrowsing.provider.google4.dataSharingURL", "https://safebrowsing.googleapis.com/v4/threatHits?$ct=application/x-protobuf&key=%GOOGLE_API_KEY%&$httpMethod=POST");
 pref("browser.safebrowsing.provider.google4.dataSharing.enabled", false);
 
 pref("browser.safebrowsing.reportPhishURL", "https://%LOCALE%.phish-report.mozilla.com/?hl=%LOCALE%&url=");
 
 // Mozilla Safe Browsing provider (for tracking protection and plugin blocking)
 pref("browser.safebrowsing.provider.mozilla.pver", "2.2");
-pref("browser.safebrowsing.provider.mozilla.lists", "base-track-digest256,mozstd-trackwhite-digest256,content-track-digest256,mozplugin-block-digest256,mozplugin2-block-digest256,block-flash-digest256,except-flash-digest256,allow-flashallow-digest256,except-flashallow-digest256,block-flashsubdoc-digest256,except-flashsubdoc-digest256,ads-track-digest256,social-track-digest256,analytics-track-digest256,base-fingerprinting-track-digest256,content-fingerprinting-track-digest256,base-cryptomining-track-digest256,content-cryptomining-track-digest256,fanboy-annoyance-digest256,fanboy-social-digest256,easylist-digest256,easyprivacy-digest256,adguard-digest256");
+pref("browser.safebrowsing.provider.mozilla.lists", "base-track-digest256,mozstd-trackwhite-digest256,content-track-digest256,mozplugin-block-digest256,mozplugin2-block-digest256,block-flash-digest256,except-flash-digest256,allow-flashallow-digest256,except-flashallow-digest256,block-flashsubdoc-digest256,except-flashsubdoc-digest256,ads-track-digest256,social-track-digest256,analytics-track-digest256,base-fingerprinting-track-digest256,content-fingerprinting-track-digest256,base-cryptomining-track-digest256,content-cryptomining-track-digest256,fanboyannoyance-ads-digest256,fanboysocial-ads-digest256,easylist-ads-digest256,easyprivacy-ads-digest256,adguard-ads-digest256");
 pref("browser.safebrowsing.provider.mozilla.updateURL", "https://shavar.services.mozilla.com/downloads?client=SAFEBROWSING_ID&appver=%MAJOR_VERSION%&pver=2.2");
 pref("browser.safebrowsing.provider.mozilla.gethashURL", "https://shavar.services.mozilla.com/gethash?client=SAFEBROWSING_ID&appver=%MAJOR_VERSION%&pver=2.2");
 // Set to a date in the past to force immediate download in new profiles.
 pref("browser.safebrowsing.provider.mozilla.nextupdatetime", "1");
 // Block lists for tracking protection. The name values will be used as the keys
 // to lookup the localized name in preferences.properties.
 pref("browser.safebrowsing.provider.mozilla.lists.base", "moz-std");
 pref("browser.safebrowsing.provider.mozilla.lists.content", "moz-full");
--- a/moz.configure
+++ b/moz.configure
@@ -578,16 +578,41 @@ def nsis_flags(host):
     if host.kernel != 'WINNT':
         return '-nocd'
     return ''
 
 set_config('MAKENSISU_FLAGS', nsis_flags)
 
 check_prog('7Z', ('7z', '7za'), allow_missing=True, when=target_is_windows)
 
+
+@depends(c_compiler, bindgen_config_paths)
+def llvm_objdump(c_compiler, bindgen_config_paths):
+    clang = None
+    if c_compiler and c_compiler.type == 'clang':
+        clang = c_compiler.compiler
+    elif c_compiler and c_compiler.type == 'clang-cl':
+        clang = os.path.join(os.path.dirname(c_compiler.compiler), 'clang')
+    elif bindgen_config_paths:
+        clang = bindgen_config_paths.clang_path
+    llvm_objdump = 'llvm-objdump'
+    if clang:
+        out = check_cmd_output(clang, '--print-prog-name=llvm-objdump',
+                               onerror=lambda: None)
+        if out:
+            llvm_objdump = out.rstrip()
+    return (llvm_objdump,)
+
+
+llvm_objdump = check_prog('LLVM_OBJDUMP', llvm_objdump, what='llvm-objdump',
+                          when='--enable-compile-environment')
+
+add_old_configure_assignment('LLVM_OBJDUMP', llvm_objdump)
+
+
 # Please do not add configure checks from here on.
 
 # Fallthrough to autoconf-based configure
 include('build/moz.configure/old.configure')
 
 # JS Subconfigure.
 include('js/sub.configure', when=compile_environment & toolkit)
 
--- a/python/mozbuild/mozbuild/action/check_binary.py
+++ b/python/mozbuild/mozbuild/action/check_binary.py
@@ -1,52 +1,53 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 from __future__ import print_function, unicode_literals
 
 import argparse
 import os
+import re
 import subprocess
 import sys
 
 from distutils.version import StrictVersion as Version
 
 import buildconfig
 from mozbuild.util import memoize
 from mozpack.executables import (
     get_type,
     ELF,
     MACHO,
+    UNKNOWN,
 )
 
 
 STDCXX_MAX_VERSION = Version('3.4.16')
 GLIBC_MAX_VERSION = Version('2.12')
 LIBGCC_MAX_VERSION = Version('4.8')
 
 HOST = {
     'MOZ_LIBSTDCXX_VERSION':
         buildconfig.substs.get('MOZ_LIBSTDCXX_HOST_VERSION'),
     'platform': buildconfig.substs['HOST_OS_ARCH'],
     'readelf': 'readelf',
-    'nm': 'nm',
 }
 
 TARGET = {
     'MOZ_LIBSTDCXX_VERSION':
         buildconfig.substs.get('MOZ_LIBSTDCXX_TARGET_VERSION'),
     'platform': buildconfig.substs['OS_TARGET'],
     'readelf': '{}readelf'.format(
         buildconfig.substs.get('TOOLCHAIN_PREFIX', '')),
-    'nm': '{}nm'.format(buildconfig.substs.get('TOOLCHAIN_PREFIX', '')),
-    'readobj': '{}readobj'.format(buildconfig.substs.get('TOOLCHAIN_PREFIX', '')),
 }
 
+ADDR_RE = re.compile(r'[0-9a-f]{8,16}')
+
 if buildconfig.substs.get('HAVE_64BIT_BUILD'):
     GUESSED_NSMODULE_SIZE = 8
 else:
     GUESSED_NSMODULE_SIZE = 4
 
 
 get_type = memoize(get_type)
 
@@ -70,62 +71,107 @@ def at_least_one(iter):
     saw_one = False
     for item in iter:
         saw_one = True
         yield item
     if not saw_one:
         raise Empty()
 
 
-def iter_readelf_symbols(target, binary):
-    for line in get_output(target['readelf'], '-sW', binary):
-        data = line.split()
-        if len(data) >= 8 and data[0].endswith(':') and data[0][:-1].isdigit():
-            n, addr, size, type, bind, vis, index, name = data[:8]
+# Iterates the symbol table on ELF and MACHO, and the export table on
+# COFF/PE.
+def iter_symbols(binary):
+    ty = get_type(binary)
+    # XXX: Static libraries on ELF, MACHO and COFF/PE systems are all
+    # ar archives. So technically speaking, the following is wrong
+    # but is enough for now. llvm-objdump -t can actually be used on all
+    # platforms for static libraries, but its format is different for
+    # Windows .obj files, so the following won't work for them, but
+    # it currently doesn't matter.
+    if ty == UNKNOWN and open(binary).read(8) == '!<arch>\n':
+        ty = ELF
+    if ty in (ELF, MACHO):
+        for line in get_output(buildconfig.substs['LLVM_OBJDUMP'], '-t',
+                               binary):
+            m = ADDR_RE.match(line)
+            if not m:
+                continue
+            addr = int(m.group(0), 16)
+            # The second "column" is 7 one-character items that can be
+            # whitespaces. We don't have use for their value, so just skip
+            # those.
+            rest = line[m.end() + 9:].split()
+            # The number of remaining colums will vary between ELF and MACHO.
+            # On ELF, we have:
+            #   Section Size .hidden? Name
+            # On Macho, the size is skipped.
+            # In every case, the symbol name is last.
+            name = rest[-1]
             if '@' in name:
                 name, ver = name.rsplit('@', 1)
                 while name.endswith('@'):
                     name = name[:-1]
             else:
                 ver = None
             yield {
-                'addr': int(addr, 16),
-                # readelf output may contain decimal values or hexadecimal
-                # values prefixed with 0x for the size. Let python autodetect.
-                'size': int(size, 0),
-                'type': type,
-                'binding': bind,
-                'visibility': vis,
-                'index': index,
+                'addr': addr,
+                'size': int(rest[1], 16) if ty == ELF else 0,
                 'name': name,
-                'version': ver,
+                'version': ver or None,
+            }
+    else:
+        export_table = False
+        for line in get_output(buildconfig.substs['LLVM_OBJDUMP'], '-p',
+                               binary):
+            if line.strip() == 'Export Table:':
+                export_table = True
+                continue
+            elif not export_table:
+                continue
+
+            cols = line.split()
+            # The data we're interested in comes in 3 columns, and the first
+            # column is a number.
+            if len(cols) != 3 or not cols[0].isdigit():
+                continue
+            _, rva, name = cols
+            # - The MSVC mangling has some type info following `@@`
+            # - Any namespacing that can happen on the symbol appears as a
+            #   suffix, after a `@`.
+            # - Mangled symbols are prefixed with `?`.
+            name = name.split('@@')[0].split('@')[0].lstrip('?')
+            yield {
+                'addr': int(rva, 16),
+                'size': 0,
+                'name': name,
+                'version': None,
             }
 
 
 def iter_readelf_dynamic(target, binary):
     for line in get_output(target['readelf'], '-d', binary):
         data = line.split(None, 2)
         if data and len(data) == 3 and data[0].startswith('0x'):
             yield data[1].rstrip(')').lstrip('('), data[2]
 
 
 def check_dep_versions(target, binary, lib, prefix, max_version):
     if get_type(binary) != ELF:
         raise Skip()
     unwanted = []
     prefix = prefix + '_'
     try:
-        for sym in at_least_one(iter_readelf_symbols(target, binary)):
-            if sym['index'] == 'UND' and sym['version'] and \
+        for sym in at_least_one(iter_symbols(binary)):
+            if sym['addr'] == 0 and sym['version'] and \
                     sym['version'].startswith(prefix):
                 version = Version(sym['version'][len(prefix):])
                 if version > max_version:
                     unwanted.append(sym)
     except Empty:
-        raise RuntimeError('Could not parse readelf output?')
+        raise RuntimeError('Could not parse llvm-objdump output?')
     if unwanted:
         raise RuntimeError('\n'.join([
             'We do not want these {} symbol versions to be used:'.format(lib)
         ] + [
             ' {} ({})'.format(s['name'], s['version']) for s in unwanted
         ]))
 
 
@@ -167,72 +213,33 @@ def is_libxul(binary):
     basename = os.path.basename(binary).lower()
     return 'xul' in basename
 
 
 def check_nsmodules(target, binary):
     if target is HOST or not is_libxul(binary):
         raise Skip()
     symbols = []
-    if buildconfig.substs.get('CC_TYPE') in ('msvc', 'clang-cl'):
-        for line in get_output('dumpbin.exe', '-exports', binary):
-            data = line.split(None, 3)
-            if data and len(data) == 4 and data[0].isdigit() and \
-                    ishex(data[1]) and ishex(data[2]):
-                # - Some symbols in the table can be aliases, and appear as
-                #   `foo = bar`.
-                # - The MSVC mangling has some type info following `@@`
-                # - Any namespacing that can happen on the symbol appears as a
-                #   suffix, after a `@`.
-                # - Mangled symbols are prefixed with `?`.
-                name = data[3].split(' = ')[0].split('@@')[0].split('@')[0] \
-                              .lstrip('?')
-                if name.endswith('_NSModule') or name in (
-                        '__start_kPStaticModules',
-                        '__stop_kPStaticModules'):
-                    symbols.append((int(data[2], 16), GUESSED_NSMODULE_SIZE,
-                                    name))
-    else:
-        # MinGW-Clang, when building pdbs, doesn't include the symbol table into
-        # the final module. To get the NSModule info, we can look at the exported
-        # symbols. (#1475562)
-        if buildconfig.substs['OS_ARCH'] == 'WINNT' and \
-           buildconfig.substs['HOST_OS_ARCH'] != 'WINNT':
-            readobj_output = get_output(target['readobj'], '-coff-exports', binary)
-            # Transform the output of readobj into nm-like output
-            output = []
-            for line in readobj_output:
-                if "Name" in line:
-                    name = line.replace("Name:", "").strip()
-                elif "RVA" in line:
-                    rva = line.replace("RVA:", "").strip()
-                    output.append("%s r %s" % (name, rva))
-        else:
-            output = get_output(target['nm'], '-P', binary)
-
-        for line in output:
-            data = line.split()
-            # Some symbols may not have a size listed at all.
-            if len(data) == 3:
-                data.append('0')
-            if len(data) == 4:
-                sym, _, addr, size = data
-                # NSModules symbols end with _NSModule or _NSModuleE when
-                # C++-mangled.
-                if sym.endswith(('_NSModule', '_NSModuleE')):
-                    # On mac, nm doesn't actually print anything other than 0
-                    # for the size. So take our best guess.
-                    size = int(size, 16) or GUESSED_NSMODULE_SIZE
-                    symbols.append((int(addr, 16), size, sym))
-                elif sym.endswith(('__start_kPStaticModules',
-                                   '__stop_kPStaticModules')):
-                    # On ELF and mac systems, these symbols have no size, such
-                    # that the first actual NSModule has the same address as
-                    # the start symbol.
-                    symbols.append((int(addr, 16), 0, sym))
+    for sym in iter_symbols(binary):
+        if sym['addr'] == 0:
+            continue
+        name = sym['name']
+        # NSModules symbols end with _NSModule or _NSModuleE when C++-mangled.
+        if name.endswith(('_NSModule', '_NSModuleE')):
+            # We don't have a valid size in the symbol list for macho and coff.
+            # Use our guesstimate.
+            size = sym['size'] or GUESSED_NSMODULE_SIZE
+            symbols.append((sym['addr'], size, name))
+        elif name in ('__start_kPStaticModules', '__stop_kPStaticModules'):
+            # For coff, these symbols have a size.
+            if get_type(binary) not in (ELF, MACHO):
+                size = GUESSED_NSMODULE_SIZE
+            else:
+                size = 0
+            symbols.append((sym['addr'], size, name))
     if not symbols:
         raise RuntimeError('Could not find NSModules')
 
     def print_symbols(symbols):
         for addr, size, sym in symbols:
             print('%x %d %s' % (addr, size, sym))
 
     symbols = sorted(symbols)
--- a/python/mozbuild/mozbuild/action/test_archive.py
+++ b/python/mozbuild/mozbuild/action/test_archive.py
@@ -586,16 +586,27 @@ if buildconfig.substs.get('MOZ_ASAN') an
         'source': buildconfig.topobjdir,
         'base': 'dist/bin',
         'pattern': os.path.basename(buildconfig.substs['MOZ_CLANG_RT_ASAN_LIB_PATH']),
         'dest': 'bin'
     }
     ARCHIVE_FILES['common'].append(asan_dll)
 
 
+if buildconfig.substs.get('commtopsrcdir'):
+    commtopsrcdir = buildconfig.substs.get('commtopsrcdir')
+    mozharness_comm = {
+        'source': commtopsrcdir,
+        'base': 'mozharness',
+        'pattern': '**',
+        'dest': 'mozharness/configs'
+    }
+    ARCHIVE_FILES['mozharness'].append(mozharness_comm)
+
+
 # "common" is our catch all archive and it ignores things from other archives.
 # Verify nothing sneaks into ARCHIVE_FILES without a corresponding exclusion
 # rule in the "common" archive.
 for k, v in ARCHIVE_FILES.items():
     # Skip mozharness because it isn't staged.
     if k in ('common', 'mozharness'):
         continue
 
--- a/services/sync/modules/UIState.jsm
+++ b/services/sync/modules/UIState.jsm
@@ -158,16 +158,17 @@ const UIStateInternal = {
       let loginFailed = await this._loginFailed();
       if (loginFailed) {
         status = STATUS_LOGIN_FAILED;
       } else if (!userData.verified) {
         status = STATUS_NOT_VERIFIED;
       } else {
         status = STATUS_SIGNED_IN;
       }
+      state.uid = userData.uid;
       state.email = userData.email;
     }
     state.status = status;
   },
 
   _populateWithProfile(state, profile) {
     state.displayName = profile.displayName;
     state.avatarURL = profile.avatar;
--- a/services/sync/tests/unit/test_uistate.js
+++ b/services/sync/tests/unit/test_uistate.js
@@ -47,24 +47,25 @@ add_task(async function test_refreshStat
   UIState.reset();
   const fxAccountsOrig = UIStateInternal.fxAccounts;
 
   const now = new Date().toString();
   Services.prefs.setCharPref("services.sync.lastSync", now);
   UIStateInternal.syncing = false;
 
   UIStateInternal.fxAccounts = {
-    getSignedInUser: () => Promise.resolve({ verified: true, email: "foo@bar.com" }),
+    getSignedInUser: () => Promise.resolve({ verified: true, uid: "123", email: "foo@bar.com" }),
     getSignedInUserProfile: () => Promise.resolve({ displayName: "Foo Bar", avatar: "https://foo/bar" }),
     hasLocalSession: () => Promise.resolve(true),
   };
 
   let state = await UIState.refresh();
 
   equal(state.status, UIState.STATUS_SIGNED_IN);
+  equal(state.uid, "123");
   equal(state.email, "foo@bar.com");
   equal(state.displayName, "Foo Bar");
   equal(state.avatarURL, "https://foo/bar");
   equal(state.lastSync, now);
   equal(state.syncing, false);
 
   UIStateInternal.fxAccounts = fxAccountsOrig;
 });
@@ -80,16 +81,17 @@ add_task(async function test_refreshStat
 
   UIStateInternal.fxAccounts = {
     getSignedInUser: () => Promise.resolve(null),
   };
 
   let state = await UIState.refresh();
 
   equal(state.status, UIState.STATUS_LOGIN_FAILED);
+  equal(state.uid, undefined);
   equal(state.email, "test@test.com");
   equal(state.displayName, undefined);
   equal(state.avatarURL, undefined);
   equal(state.lastSync, undefined); // only set when STATUS_SIGNED_IN.
   equal(state.syncing, false);
 
   UIStateInternal.fxAccounts = fxAccountsOrig;
   Services.prefs.clearUserPref("services.sync.lastSync");
@@ -101,24 +103,25 @@ add_task(async function test_refreshStat
   UIState.reset();
   const fxAccountsOrig = UIStateInternal.fxAccounts;
 
   const now = new Date().toString();
   Services.prefs.setCharPref("services.sync.lastSync", now);
   UIStateInternal.syncing = false;
 
   UIStateInternal.fxAccounts = {
-    getSignedInUser: () => Promise.resolve({ verified: true, email: "foo@bar.com" }),
+    getSignedInUser: () => Promise.resolve({ verified: true, uid: "123", email: "foo@bar.com" }),
     getSignedInUserProfile: () => Promise.reject(new Error("Profile unavailable")),
     hasLocalSession: () => Promise.resolve(true),
   };
 
   let state = await UIState.refresh();
 
   equal(state.status, UIState.STATUS_SIGNED_IN);
+  equal(state.uid, "123");
   equal(state.email, "foo@bar.com");
   equal(state.displayName, undefined);
   equal(state.avatarURL, undefined);
   equal(state.lastSync, now);
   equal(state.syncing, false);
 
   UIStateInternal.fxAccounts = fxAccountsOrig;
 });
@@ -147,49 +150,51 @@ add_task(async function test_refreshStat
 });
 
 add_task(async function test_refreshState_unverified() {
   UIState.reset();
   const fxAccountsOrig = UIStateInternal.fxAccounts;
 
   let getSignedInUserProfile = sinon.spy();
   UIStateInternal.fxAccounts = {
-    getSignedInUser: () => Promise.resolve({ verified: false, email: "foo@bar.com" }),
+    getSignedInUser: () => Promise.resolve({ verified: false, uid: "123", email: "foo@bar.com" }),
     getSignedInUserProfile,
     hasLocalSession: () => Promise.resolve(true),
   };
 
   let state = await UIState.refresh();
 
   equal(state.status, UIState.STATUS_NOT_VERIFIED);
+  equal(state.uid, "123");
   equal(state.email, "foo@bar.com");
   equal(state.displayName, undefined);
   equal(state.avatarURL, undefined);
   equal(state.lastSync, undefined);
 
   ok(!getSignedInUserProfile.called);
 
   UIStateInternal.fxAccounts = fxAccountsOrig;
 });
 
 add_task(async function test_refreshState_unverified_nosession() {
   UIState.reset();
   const fxAccountsOrig = UIStateInternal.fxAccounts;
 
   let getSignedInUserProfile = sinon.spy();
   UIStateInternal.fxAccounts = {
-    getSignedInUser: () => Promise.resolve({ verified: false, email: "foo@bar.com" }),
+    getSignedInUser: () => Promise.resolve({ verified: false, uid: "123", email: "foo@bar.com" }),
     getSignedInUserProfile,
     hasLocalSession: () => Promise.resolve(false),
   };
 
   let state = await UIState.refresh();
 
   // No session should "win" over the unverified state.
   equal(state.status, UIState.STATUS_LOGIN_FAILED);
+  equal(state.uid, "123");
   equal(state.email, "foo@bar.com");
   equal(state.displayName, undefined);
   equal(state.avatarURL, undefined);
   equal(state.lastSync, undefined);
 
   ok(!getSignedInUserProfile.called);
 
   UIStateInternal.fxAccounts = fxAccountsOrig;
@@ -199,23 +204,24 @@ add_task(async function test_refreshStat
   UIState.reset();
   const fxAccountsOrig = UIStateInternal.fxAccounts;
 
   let loginFailed = sinon.stub(UIStateInternal, "_loginFailed");
   loginFailed.returns(true);
 
   let getSignedInUserProfile = sinon.spy();
   UIStateInternal.fxAccounts = {
-    getSignedInUser: () => Promise.resolve({ verified: true, email: "foo@bar.com" }),
+    getSignedInUser: () => Promise.resolve({ verified: true, uid: "123", email: "foo@bar.com" }),
     getSignedInUserProfile,
   };
 
   let state = await UIState.refresh();
 
   equal(state.status, UIState.STATUS_LOGIN_FAILED);
+  equal(state.uid, "123");
   equal(state.email, "foo@bar.com");
   equal(state.displayName, undefined);
   equal(state.avatarURL, undefined);
   equal(state.lastSync, undefined);
 
   ok(!getSignedInUserProfile.called);
 
   loginFailed.restore();
@@ -245,17 +251,17 @@ add_task(async function test_observer_re
 async function configureUIState(syncing, lastSync = new Date()) {
   UIState.reset();
   const fxAccountsOrig = UIStateInternal.fxAccounts;
 
   UIStateInternal._syncing = syncing;
   Services.prefs.setCharPref("services.sync.lastSync", lastSync.toString());
 
   UIStateInternal.fxAccounts = {
-    getSignedInUser: () => Promise.resolve({ verified: true, email: "foo@bar.com" }),
+    getSignedInUser: () => Promise.resolve({ verified: true, uid: "123", email: "foo@bar.com" }),
     getSignedInUserProfile: () => Promise.resolve({ displayName: "Foo Bar", avatar: "https://foo/bar" }),
     hasLocalSession: () => Promise.resolve(true),
   };
   await UIState.refresh();
   UIStateInternal.fxAccounts = fxAccountsOrig;
 }
 
 add_task(async function test_syncStarted() {
--- a/toolkit/components/passwordmgr/test/mochitest.ini
+++ b/toolkit/components/passwordmgr/test/mochitest.ini
@@ -1,16 +1,13 @@
 [DEFAULT]
 skip-if = e10s
 support-files =
   authenticate.sjs
   blank.html
   formsubmit.sjs
   prompt_common.js
   pwmgr_common.js
-  subtst_prompt_async.html
 
-[test_prompt_async.html]
-skip-if = toolkit == 'android' # Tests desktop prompts
 [test_xhr.html]
 skip-if = toolkit == 'android' # Tests desktop prompts
 [test_xml_load.html]
 skip-if = toolkit == 'android' # Tests desktop prompts
--- a/toolkit/components/passwordmgr/test/mochitest/mochitest.ini
+++ b/toolkit/components/passwordmgr/test/mochitest/mochitest.ini
@@ -1,22 +1,22 @@
 [DEFAULT]
 support-files =
   ../../../prompts/test/chromeScript.js
   ../../../prompts/test/prompt_common.js
   ../../../satchel/test/parent_utils.js
   ../../../satchel/test/satchel_common.js
-  ../authenticate.sjs
   ../blank.html
   ../browser/form_autofocus_js.html
   ../browser/form_basic.html
   ../browser/formless_basic.html
   ../browser/form_cross_origin_secure_action.html
   ../pwmgr_common.js
   auth2/authenticate.sjs
+  ../authenticate.sjs
 skip-if = toolkit == 'android' && !isFennec # Don't run on GeckoView
 
 [test_autocomplete_https_upgrade.html]
 skip-if = toolkit == 'android' # autocomplete
 [test_autocomplete_sandboxed.html]
 scheme = https
 skip-if = toolkit == 'android' # autocomplete
 [test_autofill_https_upgrade.html]
@@ -68,16 +68,19 @@ skip-if = toolkit == 'android' # Tests d
 support-files =
   chrome_timeout.js
   subtst_master_pass.html
 [test_maxlength.html]
 [test_onsubmit_value_change.html]
 [test_passwords_in_type_password.html]
 [test_prompt.html]
 skip-if = os == "linux" || toolkit == 'android' # Tests desktop prompts
+[test_prompt_async.html]
+skip-if = toolkit == 'android' # Tests desktop prompts
+support-files = subtst_prompt_async.html
 [test_prompt_http.html]
 skip-if = os == "linux" || toolkit == 'android' # Tests desktop prompts
 [test_prompt_noWindow.html]
 skip-if = e10s || toolkit == 'android' # Tests desktop prompts. e10s: bug 1217876
 [test_prompt_promptAuth.html]
 skip-if = os == "linux" || toolkit == 'android' # Tests desktop prompts
 [test_prompt_promptAuth_proxy.html]
 skip-if = e10s || os == "linux" || toolkit == 'android' # Tests desktop prompts
rename from toolkit/components/passwordmgr/test/subtst_prompt_async.html
rename to toolkit/components/passwordmgr/test/mochitest/subtst_prompt_async.html
--- a/toolkit/components/passwordmgr/test/subtst_prompt_async.html
+++ b/toolkit/components/passwordmgr/test/mochitest/subtst_prompt_async.html
@@ -1,12 +1,12 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <meta charset="utf-8">
   <title>Multiple auth request</title>
 </head>
 <body>
-  <iframe id="iframe1" src="http://example.com/tests/toolkit/components/passwordmgr/test/authenticate.sjs?r=1&user=user3name&pass=user3pass&realm=mochirealm3&proxy_user=proxy_user2&proxy_pass=proxy_pass2&proxy_realm=proxy_realm2"></iframe>
-  <iframe id="iframe2" src="http://example.com/tests/toolkit/components/passwordmgr/test/authenticate.sjs?r=2&user=user3name&pass=user3pass&realm=mochirealm3&proxy_user=proxy_user2&proxy_pass=proxy_pass2&proxy_realm=proxy_realm2"></iframe>
-  <iframe id="iframe3" src="http://example.com/tests/toolkit/components/passwordmgr/test/authenticate.sjs?r=3&user=user3name&pass=user3pass&realm=mochirealm3&proxy_user=proxy_user2&proxy_pass=proxy_pass2&proxy_realm=proxy_realm2"></iframe>
+  <iframe id="iframe1" src="authenticate.sjs?r=1&user=user3name&pass=user3pass&realm=mochirealm3&proxy_user=proxy_user2&proxy_pass=proxy_pass2&proxy_realm=proxy_realm2"></iframe>
+  <iframe id="iframe2" src="authenticate.sjs?r=2&user=user3name&pass=user3pass&realm=mochirealm3&proxy_user=proxy_user2&proxy_pass=proxy_pass2&proxy_realm=proxy_realm2"></iframe>
+  <iframe id="iframe3" src="authenticate.sjs?r=3&user=user3name&pass=user3pass&realm=mochirealm3&proxy_user=proxy_user2&proxy_pass=proxy_pass2&proxy_realm=proxy_realm2"></iframe>
 </body>
 </html>
rename from toolkit/components/passwordmgr/test/test_prompt_async.html
rename to toolkit/components/passwordmgr/test/mochitest/test_prompt_async.html
--- a/toolkit/components/passwordmgr/test/test_prompt_async.html
+++ b/toolkit/components/passwordmgr/test/mochitest/test_prompt_async.html
@@ -1,93 +1,48 @@
 <!DOCTYPE HTML>
 <html>
 <head>
     <meta charset="utf-8">
     <title>Test for Async Auth Prompt</title>
     <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
     <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+    <script type="text/javascript" src="/tests/SimpleTest/AddTask.js"></script>
+    <script type="text/javascript" src="pwmgr_common.js"></script>
     <script type="text/javascript" src="prompt_common.js"></script>
     <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 
     <script class="testbody" type="text/javascript">
-        /* eslint-disable mozilla/use-chromeutils-generateqi */
-        SimpleTest.waitForExplicitFinish();
-        SimpleTest.requestFlakyTimeout("untriaged");
-
-        const { NetUtil } = SpecialPowers.Cu.import("resource://gre/modules/NetUtil.jsm");
-
-        SpecialPowers.Services.prefs.setIntPref("network.auth.subresource-http-auth-allow", 2);
-        // Class monitoring number of open dialog windows
-        // It checks there is always open just a single dialog per application
-        function dialogMonitor() {
-          SpecialPowers.Services.obs.addObserver(this, "domwindowopened");
-          SpecialPowers.Services.obs.addObserver(this, "domwindowclosed");
-        }
+      const { NetUtil } = SpecialPowers.Cu.import("resource://gre/modules/NetUtil.jsm");
+      const { TestUtils } = SpecialPowers.Cu.import("resource://testing-common/TestUtils.jsm");
+      const EXAMPLE_COM = "http://example.com/tests/toolkit/components/passwordmgr/test/mochitest/";
+      const EXAMPLE_ORG = "http://example.org/tests/toolkit/components/passwordmgr/test/mochitest/";
+      let mozproxyOrigin;
 
-        /*
-         * As documented in Bug 718543, checking equality of objects pulled
-         * from SpecialPowers-wrapped objects is unreliable.  Because of that,
-         * `dialogMonitor` now tracks the number of open windows rather than
-         * specific window objects.
-         *
-         * NB: Because the constructor (above) adds |this| directly as an observer,
-         * we need to do SpecialPowers.wrapCallbackObject directly on the prototype.
-         */
-        dialogMonitor.prototype = SpecialPowers.wrapCallbackObject({
-          windowsOpen: 0,
-          windowsRegistered: 0,
+      // Force parent to not look for tab-modal prompts, as they're not used for auth prompts.
+      // Used by prompt_common.js.
+      isTabModal = false;
 
-          QueryInterface(iid) {
-            const interfaces = [Ci.nsIObserver, Ci.nsISupports];
-
-            if (!interfaces.some((v) => iid.equals(v))) {
-              throw SpecialPowers.Cr.NS_ERROR_NO_INTERFACE;
-            }
-            return this;
-          },
+      let chromeScript = runInParent(SimpleTest.getTestFileURL("pwmgr_common.js"));
 
-          observe(subject, topic, data) {
-            if (topic === "domwindowopened") {
-              this.windowsOpen++;
-              this.windowsRegistered++;
-            } else if (topic === "domwindowclosed") {
-              this.windowsOpen--;
-            }
-          },
-
-          shutdown() {
-            SpecialPowers.Services.obs.removeObserver(this, "domwindowopened");
-            SpecialPowers.Services.obs.removeObserver(this, "domwindowclosed");
-          },
+      /**
+       * Add a listener to add some logins to be autofilled in the HTTP/proxy auth. prompts later.
+       */
+      let pwmgrParent = runInParent(() => {
+        ChromeUtils.import("resource://gre/modules/Services.jsm");
 
-          reset() {
-            this.windowsOpen = 0;
-            this.windowsRegistered = 0;
-          },
-        });
-
-        var monitor = new dialogMonitor();
-
-        var pwmgr, logins = [];
+        Services.prefs.setIntPref("network.auth.subresource-http-auth-allow", 2);
 
-        function initLogins(pi) {
-          pwmgr = SpecialPowers.Services.logins;
-
+        function initLogins(mozproxy) {
           function addLogin(host, realm, user, pass) {
-            var login = SpecialPowers.Cc["@mozilla.org/login-manager/loginInfo;1"]
-                                     .createInstance(Ci.nsILoginInfo);
+            let login = Cc["@mozilla.org/login-manager/loginInfo;1"].createInstance(Ci.nsILoginInfo);
             login.init(host, null, realm, user, pass, "", "");
-            pwmgr.addLogin(login);
-            logins.push(login);
+            Services.logins.addLogin(login);
           }
 
-          var mozproxy = "moz-proxy://" + SpecialPowers.wrap(pi).host + ":" +
-                         SpecialPowers.wrap(pi).port;
-
           addLogin(mozproxy, "proxy_realm",
                    "proxy_user", "proxy_pass");
           addLogin(mozproxy, "proxy_realm2",
                    "proxy_user2", "proxy_pass2");
           addLogin(mozproxy, "proxy_realm3",
                    "proxy_user3", "proxy_pass3");
           addLogin(mozproxy, "proxy_realm4",
                    "proxy_user4", "proxy_pass4");
@@ -102,429 +57,516 @@
           addLogin("http://example.com", "mochirealm4",
                    "user4name", "user4pass");
           addLogin("http://example.com", "mochirealm5",
                    "user5name", "user5pass");
           addLogin("http://example.com", "mochirealm6",
                    "user6name", "user6pass");
         }
 
-        function finishTest() {
-          ok(true, "finishTest removing testing logins...");
-          for (i in logins) {
-            pwmgr.removeLogin(logins[i]);
-          }
+        addMessageListener("initLogins", function onMessage(msg) {
+          initLogins(msg.mozproxyOrigin);
+        });
+      }); // end runInParent
 
-          var authMgr = SpecialPowers.Cc["@mozilla.org/network/http-auth-manager;1"]
-                                     .getService(Ci.nsIHttpAuthManager);
-          authMgr.clearAll();
+      function promiseLoadedContentDoc(frame) {
+        return new Promise(resolve => {
+          frame.addEventListener("load", function onLoad(evt) {
+            resolve(SpecialPowers.wrap(frame).contentDocument);
+          }, { once: true });
+        });
+      }
 
-          monitor.shutdown();
-          SimpleTest.finish();
-        }
+      function promiseProxyErrorLoad(frame) {
+        return TestUtils.waitForCondition(() => {
+          return SpecialPowers.wrap(frame.contentWindow).document.documentURI.includes("proxyConnectFailure");
+        }, "Waiting for proxyConnectFailure documentURI");
+      }
 
-        var resolveCallback = SpecialPowers.wrapCallbackObject({
-          QueryInterface(iid) {
-            const interfaces = [Ci.nsIProtocolProxyCallback, Ci.nsISupports];
-
-            if (!interfaces.some(v => iid.equals(v))) {
-              throw SpecialPowers.Cr.NS_ERROR_NO_INTERFACE;
-            }
-            return this;
-          },
+      /**
+       * Make a channel to get the ProxyInfo used by the test harness so that we
+       * can add logins for the correct proxy origin.
+       */
+      add_task(async function setup_getProxyInfoForHarness() {
+        await new Promise(resolve => {
+          let resolveCallback = SpecialPowers.wrapCallbackObject({
+            // eslint-disable-next-line mozilla/use-chromeutils-generateqi
+            QueryInterface(iid) {
+              const interfaces = [Ci.nsIProtocolProxyCallback, Ci.nsISupports];
 
-          onProxyAvailable(req, uri, pi, status) {
-            initLogins(pi);
-            doTest(testNum);
-          },
-        });
+              if (!interfaces.some(v => iid.equals(v))) {
+                throw SpecialPowers.Cr.NS_ERROR_NO_INTERFACE;
+              }
+              return this;
+            },
 
-        function startup() {
+            onProxyAvailable(req, uri, pi, status) {
+              // Add logins using the proxy host and port used by the mochitest harness.
+              mozproxyOrigin = "moz-proxy://" + SpecialPowers.wrap(pi).host + ":" +
+                SpecialPowers.wrap(pi).port;
+
+              pwmgrParent.sendSyncMessage("initLogins", {mozproxyOrigin});
+              resolve();
+            },
+          });
+
           // Need to allow for arbitrary network servers defined in PAC instead of a hardcoded moz-proxy.
-          var channel = NetUtil.newChannel({
+          let channel = NetUtil.newChannel({
             uri: "http://example.com",
             loadUsingSystemPrincipal: true,
           });
 
-          var pps = SpecialPowers.Cc["@mozilla.org/network/protocol-proxy-service;1"]
+          let pps = SpecialPowers.Cc["@mozilla.org/network/protocol-proxy-service;1"]
                                  .getService();
 
           pps.asyncResolve(channel, 0, resolveCallback);
-        }
+        });
+      });
+
+      add_task(async function test_proxyAuthThenTwoHTTPAuth() {
+        // Load through a single proxy with authentication required 3 different
+        // pages, first with one login, other two with their own different login.
+        // We expect to show just a single dialog for proxy authentication and
+        // then two dialogs to authenticate to login 1 and then login 2.
+
+        let iframe1DocPromise = promiseLoadedContentDoc(iframe1);
+        let iframe2aDocPromise = promiseLoadedContentDoc(iframe2a);
+        let iframe2bDocPromise = promiseLoadedContentDoc(iframe2b);
 
-        // --------------- Test loop spin ----------------
-        var testNum = 1;
-        var iframe1;
-        var iframe2a;
-        var iframe2b;
-        window.onload = function() {
-          iframe1 = document.getElementById("iframe1");
-          iframe2a = document.getElementById("iframe2a");
-          iframe2b = document.getElementById("iframe2b");
-          iframe1.onload = onFrameLoad;
-          iframe2a.onload = onFrameLoad;
-          iframe2b.onload = onFrameLoad;
+        iframe1.src = EXAMPLE_COM + "authenticate.sjs?" +
+          "r=1&" +
+          "user=user1name&" +
+          "pass=user1pass&" +
+          "realm=mochirealm&" +
+          "proxy_user=proxy_user&" +
+          "proxy_pass=proxy_pass&" +
+          "proxy_realm=proxy_realm";
+        iframe2a.src = EXAMPLE_ORG + "authenticate.sjs?" +
+          "r=2&" +
+          "user=user2name&" +
+          "pass=user2pass&" +
+          "realm=mochirealm2&" +
+          "proxy_user=proxy_user&" +
+          "proxy_pass=proxy_pass&" +
+          "proxy_realm=proxy_realm";
+        iframe2b.src = EXAMPLE_ORG + "authenticate.sjs?" +
+          "r=3&" +
+          "user=user2name&" +
+          "pass=user2pass&" +
+          "realm=mochirealm2&" +
+          "proxy_user=proxy_user&" +
+          "proxy_pass=proxy_pass&" +
+          "proxy_realm=proxy_realm";
+
+        let state = {
+          msg: `The proxy ${mozproxyOrigin} is requesting a username and password. The site says: “proxy_realm”`,
+          title: "Authentication Required",
+          textValue: "proxy_user",
+          passValue: "proxy_pass",
+          iconClass: "authentication-icon question-icon",
+          titleHidden: true,
+          textHidden: false,
+          passHidden: false,
+          checkHidden: true,
+          checkMsg: "",
+          checked: false,
+          focused: "textField",
+          defButton: "button0",
+        };
+        let action = {
+          buttonClick: "ok",
+        };
+        await handlePrompt(state, action);
+
+        Object.assign(state, {
+          msg: "http://example.com is requesting your username and password. WARNING: Your password will not be sent to the website you are currently visiting!",
+          textValue: "user1name",
+          passValue: "user1pass",
+        });
+        await handlePrompt(state, action);
+
+        Object.assign(state, {
+          msg: "http://example.org is requesting your username and password. WARNING: Your password will not be sent to the website you are currently visiting!",
+          textValue: "user2name",
+          passValue: "user2pass",
+        });
+        await handlePrompt(state, action);
 
-          startup();
-        };
+        let iframe1Doc = await iframe1DocPromise;
+        let iframe2aDoc = await iframe2aDocPromise;
+        let iframe2bDoc = await iframe2bDocPromise;
+
+        authok1 = iframe1Doc.getElementById("ok").textContent;
+        proxyok1 = iframe1Doc.getElementById("proxy").textContent;
+
+        let authok2a = iframe2aDoc.getElementById("ok").textContent;
+        let proxyok2a = iframe2aDoc.getElementById("proxy").textContent;
+
+        let authok2b = iframe2bDoc.getElementById("ok").textContent;
+        let proxyok2b = iframe2bDoc.getElementById("proxy").textContent;
+
+        is(authok1, "PASS", "WWW Authorization OK, frame1");
+        is(authok2a, "PASS", "WWW Authorization OK, frame2a");
+        is(authok2b, "PASS", "WWW Authorization OK, frame2b");
+        is(proxyok1, "PASS", "Proxy Authorization OK, frame1");
+        is(proxyok2a, "PASS", "Proxy Authorization OK, frame2a");
+        is(proxyok2b, "PASS", "Proxy Authorization OK, frame2b");
+      });
+
+      add_task(async function test_threeSubframesWithSameProxyAndHTTPAuth() {
+        // Load an iframe with 3 subpages all requiring the same login through
+        // an authenticated proxy. We expect 2 dialogs, proxy authentication
+        // and web authentication.
+
+        let iframe1DocPromise = promiseLoadedContentDoc(iframe1);
+        let iframe2aDocPromise = promiseLoadedContentDoc(iframe2a);
+        let iframe2bDocPromise = promiseLoadedContentDoc(iframe2b);
+
+        iframe1.src = EXAMPLE_COM + "subtst_prompt_async.html";
+        iframe2a.src = "about:blank";
+        iframe2b.src = "about:blank";
 
-        var expectedLoads;
-        var expectedDialogs;
-        function onFrameLoad() {
-          if (--expectedLoads == 0) {
-            // All pages expected to load has loaded, continue with the next test
-            ok(true, "Expected frames loaded");
+        let state = {
+          msg: `The proxy ${mozproxyOrigin} is requesting a username and password. The site says: “proxy_realm2”`,
+          title: "Authentication Required",
+          textValue: "proxy_user2",
+          passValue: "proxy_pass2",
+          iconClass: "authentication-icon question-icon",
+          titleHidden: true,
+          textHidden: false,
+          passHidden: false,
+          checkHidden: true,
+          checkMsg: "",
+          checked: false,
+          focused: "textField",
+          defButton: "button0",
+        };
+        let action = {
+          buttonClick: "ok",
+        };
+        await handlePrompt(state, action);
 
-            doCheck(testNum);
-            monitor.reset();
+        Object.assign(state, {
+          msg: "http://example.com is requesting your username and password. WARNING: Your password will not be sent to the website you are currently visiting!",
+          textValue: "user3name",
+          passValue: "user3pass",
+        });
+        await handlePrompt(state, action);
+
+        let iframe1Doc = await iframe1DocPromise;
 
-            testNum++;
-            doTest(testNum);
-          }
+        function checkIframe(frame) {
+          let doc = SpecialPowers.wrap(frame).contentDocument;
+
+          let authok = doc.getElementById("ok").textContent;
+          let proxyok = doc.getElementById("proxy").textContent;
+
+          is(authok, "PASS", "WWW Authorization OK, " + frame.id);
+          is(proxyok, "PASS", "Proxy Authorization OK, " + frame.id);
         }
 
-        function doTest(testNumber) {
-          /*
-             * These contentDocument variables are located here,
-             * rather than in the global scope, because SpecialPowers threw
-             * errors (complaining that the objects were deleted)
-             * when these were in the global scope.
-             */
-          var iframe1Doc = SpecialPowers.wrap(iframe1).contentDocument;
-          var iframe2aDoc = SpecialPowers.wrap(iframe2a).contentDocument;
-          var iframe2bDoc = SpecialPowers.wrap(iframe2b).contentDocument;
-          var exampleCom = "http://example.com/tests/toolkit/components/passwordmgr/test/";
-          var exampleOrg = "http://example.org/tests/toolkit/components/passwordmgr/test/";
+        checkIframe(iframe1Doc.getElementById("iframe1"));
+        checkIframe(iframe1Doc.getElementById("iframe2"));
+        checkIframe(iframe1Doc.getElementById("iframe3"));
+      });
+
+      add_task(async function test_oneFrameWithUnauthenticatedProxy() {
+        // Load in the iframe page through unauthenticated proxy
+        // and discard the proxy authentication. We expect to see
+        // unauthenticated page content and just a single dialog.
+
+        iframe1.src = EXAMPLE_COM + "authenticate.sjs?" +
+          "user=user4name&" +
+          "pass=user4pass&" +
+          "realm=mochirealm4&" +
+          "proxy_user=proxy_user3&" +
+          "proxy_pass=proxy_pass3&" +
+          "proxy_realm=proxy_realm3";
 
-          switch (testNumber) {
-            case 1:
-              // Load through a single proxy with authentication required 3 different
-              // pages, first with one login, other two with their own different login.
-              // We expect to show just a single dialog for proxy authentication and
-              // then two dialogs to authenticate to login 1 and then login 2.
-              ok(true, "doTest testNum 1");
-              expectedLoads = 3;
-              expectedDialogs = 3;
-              iframe1.src = exampleCom + "authenticate.sjs?" +
-                            "r=1&" +
-                            "user=user1name&" +
-                            "pass=user1pass&" +
-                            "realm=mochirealm&" +
-                            "proxy_user=proxy_user&" +
-                            "proxy_pass=proxy_pass&" +
-                            "proxy_realm=proxy_realm";
-              iframe2a.src = exampleOrg + "authenticate.sjs?" +
-                             "r=2&" +
-                             "user=user2name&" +
-                             "pass=user2pass&" +
-                             "realm=mochirealm2&" +
-                             "proxy_user=proxy_user&" +
-                             "proxy_pass=proxy_pass&" +
-                             "proxy_realm=proxy_realm";
-              iframe2b.src = exampleOrg + "authenticate.sjs?" +
-                             "r=3&" +
-                             "user=user2name&" +
-                             "pass=user2pass&" +
-                             "realm=mochirealm2&" +
-                             "proxy_user=proxy_user&" +
-                             "proxy_pass=proxy_pass&" +
-                             "proxy_realm=proxy_realm";
-              break;
+        let state = {
+          msg: `The proxy ${mozproxyOrigin} is requesting a username and password. The site says: “proxy_realm3”`,
+          title: "Authentication Required",
+          textValue: "proxy_user3",
+          passValue: "proxy_pass3",
+          iconClass: "authentication-icon question-icon",
+          titleHidden: true,
+          textHidden: false,
+          passHidden: false,
+          checkHidden: true,
+          checkMsg: "",
+          checked: false,
+          focused: "textField",
+          defButton: "button0",
+        };
+        let action = {
+          buttonClick: "cancel",
+        };
+        await handlePrompt(state, action);
 
-            case 2:
-              // Load an iframe with 3 subpages all requiring the same login through
-              // anuthenticated proxy. We expect 2 dialogs, proxy authentication
-              // and web authentication.
-              ok(true, "doTest testNum 2");
-              expectedLoads = 3;
-              expectedDialogs = 2;
-              iframe1.src = exampleCom + "subtst_prompt_async.html";
-              iframe2a.src = "about:blank";
-              iframe2b.src = "about:blank";
-              break;
+        await promiseProxyErrorLoad(iframe1);
+      });
 
-            case 3:
-              // Load in the iframe page through unauthenticated proxy
-              // and discard the proxy authentication. We expect to see
-              // unauthenticated page content and just a single dialog.
-              ok(true, "doTest testNum 3");
-              expectedLoads = 1;
-              expectedDialogs = 1;
-              iframe1.src = exampleCom + "authenticate.sjs?" +
-                            "user=user4name&" +
-                            "pass=user4pass&" +
-                            "realm=mochirealm4&" +
-                            "proxy_user=proxy_user3&" +
-                            "proxy_pass=proxy_pass3&" +
-                            "proxy_realm=proxy_realm3";
-              break;
+      add_task(async function test_reloadReusingProxyAuthButCancellingHTTPAuth() {
+        // Reload the frame from previous step and pass the proxy authentication
+        // but cancel the WWW authentication. We should get the proxy=ok and WWW=fail
+        // content as a result.
+        let iframe1DocPromise = promiseLoadedContentDoc(iframe1);
+
+        iframe1.src = EXAMPLE_COM + "authenticate.sjs?" +
+          "user=user4name&" +
+          "pass=user4pass&" +
+          "realm=mochirealm4&" +
+          "proxy_user=proxy_user3&" +
+          "proxy_pass=proxy_pass3&" +
+          "proxy_realm=proxy_realm3";
 
-            case 4:
-              // Reload the frame from previous step and pass the proxy authentication
-              // but cancel the WWW authentication. We should get the proxy=ok and WWW=fail
-              // content as a result.
-              ok(true, "doTest testNum 4");
-              expectedLoads = 1;
-              expectedDialogs = 2;
-              iframe1.src = exampleCom + "authenticate.sjs?" +
-                            "user=user4name&" +
-                            "pass=user4pass&" +
-                            "realm=mochirealm4&" +
-                            "proxy_user=proxy_user3&" +
-                            "proxy_pass=proxy_pass3&" +
-                            "proxy_realm=proxy_realm3";
-
-
-              break;
+        let state = {
+          msg: `The proxy ${mozproxyOrigin} is requesting a username and password. The site says: “proxy_realm3”`,
+          title: "Authentication Required",
+          textValue: "proxy_user3",
+          passValue: "proxy_pass3",
+          iconClass: "authentication-icon question-icon",
+          titleHidden: true,
+          textHidden: false,
+          passHidden: false,
+          checkHidden: true,
+          checkMsg: "",
+          checked: false,
+          focused: "textField",
+          defButton: "button0",
+        };
+        let action = {
+          buttonClick: "ok",
+        };
+        await handlePrompt(state, action);
 
-            case 5:
-              // Same as the previous two steps but let the server generate
-              // huge content load to check http channel is capable to handle
-              // case when auth dialog is canceled or accepted before unauthenticated
-              // content data is load from the server. (This would be better to
-              // implement using delay of server response).
-              ok(true, "doTest testNum 5");
-              expectedLoads = 1;
-              expectedDialogs = 1;
-              iframe1.src = exampleCom + "authenticate.sjs?" +
-                            "user=user5name&" +
-                            "pass=user5pass&" +
-                            "realm=mochirealm5&" +
-                            "proxy_user=proxy_user4&" +
-                            "proxy_pass=proxy_pass4&" +
-                            "proxy_realm=proxy_realm4&" +
-                            "huge=1";
-              break;
+        Object.assign(state, {
+          msg: "http://example.com is requesting your username and password. WARNING: Your password will not be sent to the website you are currently visiting!",
+          textValue: "user4name",
+          passValue: "user4pass",
+        });
+        action = {
+          buttonClick: "cancel",
+        };
+        await handlePrompt(state, action);
+
+        let iframe1Doc = await iframe1DocPromise;
+
+        authok1 = iframe1Doc.getElementById("ok").textContent;
+        proxyok1 = iframe1Doc.getElementById("proxy").textContent;
+
+        is(authok1, "FAIL", "WWW Authorization FAILED, frame1");
+        is(proxyok1, "PASS", "Proxy Authorization OK, frame1");
+      });
 
-            case 6:
-              // Reload the frame from the previous step and let the proxy
-              // authentication pass but WWW fail. We expect two dialogs
-              // and an unathenticated page content load.
-              ok(true, "doTest testNum 6");
-              expectedLoads = 1;
-              expectedDialogs = 2;
-              iframe1.src = exampleCom + "authenticate.sjs?" +
-                            "user=user5name&" +
-                            "pass=user5pass&" +
-                            "realm=mochirealm5&" +
-                            "proxy_user=proxy_user4&" +
-                            "proxy_pass=proxy_pass4&" +
-                            "proxy_realm=proxy_realm4&" +
-                            "huge=1";
-              break;
-
-            case 7:
-              // Reload again and let pass all authentication dialogs.
-              // Check we get the authenticated content not broken by
-              // the unauthenticated content.
-              ok(true, "doTest testNum 7");
-              expectedLoads = 1;
-              expectedDialogs = 1;
-              iframe1Doc.location.reload();
-              break;
+      add_task(async function test_hugePayloadCancelled() {
+        // Same as the previous two steps but let the server generate
+        // huge content load to check http channel is capable to handle
+        // case when auth dialog is canceled or accepted before unauthenticated
+        // content data is load from the server. (This would be better to
+        // implement using delay of server response).
+        iframe1.src = EXAMPLE_COM + "authenticate.sjs?" +
+          "user=user5name&" +
+          "pass=user5pass&" +
+          "realm=mochirealm5&" +
+          "proxy_user=proxy_user4&" +
+          "proxy_pass=proxy_pass4&" +
+          "proxy_realm=proxy_realm4&" +
+          "huge=1";
 
-            case 8:
-              // Check we proccess all challenges sent by server when
-              // user cancels prompts
-              ok(true, "doTest testNum 8");
-              expectedLoads = 1;
-              expectedDialogs = 5;
-              iframe1.src = exampleCom + "authenticate.sjs?" +
-                            "user=user6name&" +
-                            "pass=user6pass&" +
-                            "realm=mochirealm6&" +
-                            "proxy_user=proxy_user5&" +
-                            "proxy_pass=proxy_pass5&" +
-                            "proxy_realm=proxy_realm5&" +
-                            "huge=1&" +
-                            "multiple=3";
-              break;
+        let state = {
+          msg: `The proxy ${mozproxyOrigin} is requesting a username and password. The site says: “proxy_realm4”`,
+          title: "Authentication Required",
+          textValue: "proxy_user4",
+          passValue: "proxy_pass4",
+          iconClass: "authentication-icon question-icon",
+          titleHidden: true,
+          textHidden: false,
+          passHidden: false,
+          checkHidden: true,
+          checkMsg: "",
+          checked: false,
+          focused: "textField",
+          defButton: "button0",
+        };
+        let action = {
+          buttonClick: "cancel",
+        };
+        await handlePrompt(state, action);
 
-            case 9:
-              finishTest();
-              return;
-          }
+        await promiseProxyErrorLoad(iframe1);
+      });
+
+      add_task(async function test_hugeProxySuccessWWWFail() {
+        // Reload the frame from the previous step and let the proxy
+        // authentication pass but WWW fail. We expect two dialogs
+        // and an unauthenticated page content load.
 
-          startCallbackTimer();
-        }
-
-        function handleDialog(doc, testNumber) {
-          var dialog        = doc.getElementById("commonDialog");
+        let iframe1DocPromise = promiseLoadedContentDoc(iframe1);
+        iframe1.src = EXAMPLE_COM + "authenticate.sjs?" +
+          "user=user5name&" +
+          "pass=user5pass&" +
+          "realm=mochirealm5&" +
+          "proxy_user=proxy_user4&" +
+          "proxy_pass=proxy_pass4&" +
+          "proxy_realm=proxy_realm4&" +
+          "huge=1";
 
-          switch (testNumber) {
-            case 1:
-            case 2:
-              dialog.acceptDialog();
-              break;
-
-            case 3:
-              dialog.cancelDialog();
-              setTimeout(onFrameLoad, 10); // there are no successful frames for test 3
-              break;
+        let state = {
+          msg: `The proxy ${mozproxyOrigin} is requesting a username and password. The site says: “proxy_realm4”`,
+          title: "Authentication Required",
+          textValue: "proxy_user4",
+          passValue: "proxy_pass4",
+          iconClass: "authentication-icon question-icon",
+          titleHidden: true,
+          textHidden: false,
+          passHidden: false,
+          checkHidden: true,
+          checkMsg: "",
+          checked: false,
+          focused: "textField",
+          defButton: "button0",
+        };
+        let action = {
+          buttonClick: "ok",
+        };
+        await handlePrompt(state, action);
 
-            case 4:
-              if (expectedDialogs == 2) {
-                dialog.acceptDialog();
-              } else {
-                dialog.cancelDialog();
-              }
-              break;
+        Object.assign(state, {
+          msg: "http://example.com is requesting your username and password. WARNING: Your password will not be sent to the website you are currently visiting!",
+          textValue: "user5name",
+          passValue: "user5pass",
+        });
+        action = {
+          buttonClick: "cancel",
+        };
+        await handlePrompt(state, action);
 
-            case 5:
-              dialog.cancelDialog();
-              setTimeout(onFrameLoad, 10); // there are no successful frames for test 5
-              break;
+        let iframe1Doc = await iframe1DocPromise;
 
-            case 6:
-              if (expectedDialogs == 2) {
-                dialog.acceptDialog();
-              } else {
-                dialog.cancelDialog();
-              }
-              break;
-
-            case 7:
-              dialog.acceptDialog();
-              break;
+        authok1 = iframe1Doc.getElementById("ok").textContent;
+        proxyok1 = iframe1Doc.getElementById("proxy").textContent;
+        footnote = iframe1Doc.getElementById("footnote").textContent;
 
-            case 8:
-              if (expectedDialogs == 3 || expectedDialogs == 1) {
-                dialog.acceptDialog();
-              } else {
-                dialog.cancelDialog();
-              }
-              break;
+        is(authok1, "FAIL", "WWW Authorization FAILED, frame1");
+        is(proxyok1, "PASS", "Proxy Authorization OK, frame1");
+        is(footnote, "This is a footnote after the huge content fill",
+           "Footnote present and loaded completely");
+      });
 
-            default:
-              ok(false, "Unhandled testNum " + testNumber + " in handleDialog");
-          }
+      add_task(async function test_hugeProxySuccessWWWSuccess() {
+        // Reload again and let pass all authentication dialogs.
+        // Check we get the authenticated content not broken by
+        // the unauthenticated content.
 
-          if (--expectedDialogs > 0) {
-            startCallbackTimer();
-          }
-        }
+        let iframe1DocPromise = promiseLoadedContentDoc(iframe1);
+        SpecialPowers.wrap(iframe1).contentDocument.location.reload();
 
-        function doCheck(testNumber) {
-          var iframe1Doc = SpecialPowers.wrap(iframe1).contentDocument;
-          var iframe2aDoc = SpecialPowers.wrap(iframe2a).contentDocument;
-          var iframe2bDoc = SpecialPowers.wrap(iframe2b).contentDocument;
-          var authok1;
-          var proxyok1;
-          var footnote;
-          switch (testNumber) {
-            case 1:
-              ok(true, "doCheck testNum 1");
-              is(monitor.windowsRegistered, 3, "Registered 3 open dialogs");
-
-              authok1 = iframe1Doc.getElementById("ok").textContent;
-              proxyok1 = iframe1Doc.getElementById("proxy").textContent;
+        let state = {
+          msg: "http://example.com is requesting your username and password. WARNING: Your password will not be sent to the website you are currently visiting!",
+          title: "Authentication Required",
+          textValue: "user5name",
+          passValue: "user5pass",
+          iconClass: "authentication-icon question-icon",
+          titleHidden: true,
+          textHidden: false,
+          passHidden: false,
+          checkHidden: true,
+          checkMsg: "",
+          checked: false,
+          focused: "textField",
+          defButton: "button0",
+        };
+        let action = {
+          buttonClick: "ok",
+        };
+        await handlePrompt(state, action);
 
-              var authok2a = iframe2aDoc.getElementById("ok").textContent;
-              var proxyok2a = iframe2aDoc.getElementById("proxy").textContent;
-
-              var authok2b = iframe2bDoc.getElementById("ok").textContent;
-              var proxyok2b = iframe2bDoc.getElementById("proxy").textContent;
-
-              is(authok1, "PASS", "WWW Authorization OK, frame1");
-              is(authok2a, "PASS", "WWW Authorization OK, frame2a");
-              is(authok2b, "PASS", "WWW Authorization OK, frame2b");
-              is(proxyok1, "PASS", "Proxy Authorization OK, frame1");
-              is(proxyok2a, "PASS", "Proxy Authorization OK, frame2a");
-              is(proxyok2b, "PASS", "Proxy Authorization OK, frame2b");
-              break;
-
-            case 2:
-              is(monitor.windowsRegistered, 2, "Registered 2 open dialogs");
-              ok(true, "doCheck testNum 2");
+        let iframe1Doc = await iframe1DocPromise;
+        authok1 = iframe1Doc.getElementById("ok").textContent;
+        proxyok1 = iframe1Doc.getElementById("proxy").textContent;
+        footnote = iframe1Doc.getElementById("footnote").textContent;
 
-              function checkIframe(frame) {
-                var doc = SpecialPowers.wrap(frame).contentDocument;
-
-                var authok = doc.getElementById("ok").textContent;
-                var proxyok = doc.getElementById("proxy").textContent;
-
-                is(authok, "PASS", "WWW Authorization OK, " + frame.id);
-                is(proxyok, "PASS", "Proxy Authorization OK, " + frame.id);
-              }
-
-              checkIframe(iframe1Doc.getElementById("iframe1"));
-              checkIframe(iframe1Doc.getElementById("iframe2"));
-              checkIframe(iframe1Doc.getElementById("iframe3"));
-              break;
-
-            case 3:
-              ok(true, "doCheck testNum 3");
-              is(monitor.windowsRegistered, 1, "Registered 1 open dialog");
+        is(authok1, "PASS", "WWW Authorization OK, frame1");
+        is(proxyok1, "PASS", "Proxy Authorization OK, frame1");
+        is(footnote, "This is a footnote after the huge content fill",
+           "Footnote present and loaded completely");
+      });
 
-              // ensure that the page content is not displayed on failed proxy auth
-              is(iframe1Doc.getElementById("ok"), null, "frame did not load");
-              break;
-
-            case 4:
-              ok(true, "doCheck testNum 4");
-              is(monitor.windowsRegistered, 2, "Registered 2 open dialogs");
-              authok1 = iframe1Doc.getElementById("ok").textContent;
-              proxyok1 = iframe1Doc.getElementById("proxy").textContent;
-
-              is(authok1, "FAIL", "WWW Authorization FAILED, frame1");
-              is(proxyok1, "PASS", "Proxy Authorization OK, frame1");
-              break;
-
-            case 5:
-              ok(true, "doCheck testNum 5");
-              is(monitor.windowsRegistered, 1, "Registered 1 open dialog");
-
-              // ensure that the page content is not displayed on failed proxy auth
-              is(iframe1Doc.getElementById("footnote"), null, "frame did not load");
-              break;
+      add_task(async function test_cancelSome() {
+        // Check we process all challenges sent by server when
+        // user cancels prompts
+        let iframe1DocPromise = promiseLoadedContentDoc(iframe1);
+        expectedDialogs = 5;
+        iframe1.src = EXAMPLE_COM + "authenticate.sjs?" +
+          "user=user6name&" +
+          "pass=user6pass&" +
+          "realm=mochirealm6&" +
+          "proxy_user=proxy_user5&" +
+          "proxy_pass=proxy_pass5&" +
+          "proxy_realm=proxy_realm5&" +
+          "huge=1&" +
+          "multiple=3";
 
-            case 6:
-              ok(true, "doCheck testNum 6");
-              is(monitor.windowsRegistered, 2, "Registered 2 open dialogs");
-              authok1 = iframe1Doc.getElementById("ok").textContent;
-              proxyok1 = iframe1Doc.getElementById("proxy").textContent;
-              footnote = iframe1Doc.getElementById("footnote").textContent;
+        let state = {
+          msg: `The proxy ${mozproxyOrigin} is requesting a username and password. The site says: “proxy_realm5”`,
+          title: "Authentication Required",
+          textValue: "proxy_user5",
+          passValue: "proxy_pass5",
+          iconClass: "authentication-icon question-icon",
+          titleHidden: true,
+          textHidden: false,
+          passHidden: false,
+          checkHidden: true,
+          checkMsg: "",
+          checked: false,
+          focused: "textField",
+          defButton: "button0",
+        };
+        let action = {
+          buttonClick: "cancel",
+        };
+        await handlePrompt(state, action);
 
-              is(authok1, "FAIL", "WWW Authorization FAILED, frame1");
-              is(proxyok1, "PASS", "Proxy Authorization OK, frame1");
-              is(footnote, "This is a footnote after the huge content fill",
-                 "Footnote present and loaded completely");
-              break;
-
-            case 7:
-              ok(true, "doCheck testNum 7");
-              is(monitor.windowsRegistered, 1, "Registered 1 open dialogs");
-              authok1 = iframe1Doc.getElementById("ok").textContent;
-              proxyok1 = iframe1Doc.getElementById("proxy").textContent;
-              footnote = iframe1Doc.getElementById("footnote").textContent;
+        action = {
+          buttonClick: "cancel",
+        };
+        await handlePrompt(state, action);
 
-              is(authok1, "PASS", "WWW Authorization OK, frame1");
-              is(proxyok1, "PASS", "Proxy Authorization OK, frame1");
-              is(footnote, "This is a footnote after the huge content fill",
-                 "Footnote present and loaded completely");
-              break;
+        action = {
+          buttonClick: "ok",
+        };
+        await handlePrompt(state, action);
+
+        Object.assign(state, {
+          msg: "http://example.com is requesting your username and password. WARNING: Your password will not be sent to the website you are currently visiting!",
+          textValue: "user6name",
+          passValue: "user6pass",
+        });
+
+        action = {
+          buttonClick: "cancel",
+        };
+        await handlePrompt(state, action);
 
-            case 8:
-              ok(true, "doCheck testNum 8");
-              is(monitor.windowsRegistered, 5, "Registered 5 open dialogs");
-              authok1 = iframe1Doc.getElementById("ok").textContent;
-              proxyok1 = iframe1Doc.getElementById("proxy").textContent;
-              footnote = iframe1Doc.getElementById("footnote").textContent;
+        action = {
+          buttonClick: "ok",
+        };
+        await handlePrompt(state, action);
 
-              is(authok1, "PASS", "WWW Authorization OK, frame1");
-              is(proxyok1, "PASS", "Proxy Authorization OK, frame1");
-              is(footnote, "This is a footnote after the huge content fill",
-                 "Footnote present and loaded completely");
-              break;
+        let iframe1Doc = await iframe1DocPromise;
+        authok1 = iframe1Doc.getElementById("ok").textContent;
+        proxyok1 = iframe1Doc.getElementById("proxy").textContent;
+        footnote = iframe1Doc.getElementById("footnote").textContent;
 
-            default:
-              ok(false, "Unhandled testNum " + testNumber + " in doCheck");
-          }
-        }
-
+        is(authok1, "PASS", "WWW Authorization OK, frame1");
+        is(proxyok1, "PASS", "Proxy Authorization OK, frame1");
+        is(footnote, "This is a footnote after the huge content fill",
+           "Footnote present and loaded completely");
+      });
     </script>
 </head>
 <body>
     <iframe id="iframe1"></iframe>
     <iframe id="iframe2a"></iframe>
     <iframe id="iframe2b"></iframe>
 </body>
 </html>
--- a/toolkit/components/prompts/test/prompt_common.js
+++ b/toolkit/components/prompts/test/prompt_common.js
@@ -31,16 +31,17 @@ function handlePrompt(state, action) {
       checkPromptState(msg.promptState, state);
       resolve(true);
     });
     gChromeScript.sendAsyncMessage("handlePrompt", { action, isTabModal});
   });
 }
 
 function checkPromptState(promptState, expectedState) {
+    info(`checkPromptState: ${expectedState.msg}`);
     // XXX check title? OS X has title in content
     is(promptState.msg, expectedState.msg, "Checking expected message");
     if (isOSX && !isTabModal)
       ok(!promptState.titleHidden, "Checking title always visible on OS X");
     else
       is(promptState.titleHidden, expectedState.titleHidden, "Checking title visibility");
     is(promptState.textHidden, expectedState.textHidden, "Checking textbox visibility");
     is(promptState.passHidden, expectedState.passHidden, "Checking passbox visibility");
--- a/toolkit/components/telemetry/app/TelemetryEnvironment.jsm
+++ b/toolkit/components/telemetry/app/TelemetryEnvironment.jsm
@@ -1412,45 +1412,45 @@ EnvironmentCache.prototype = {
     return buildData;
   },
 
   /**
    * Determine if we're the default browser.
    * @returns null on error, true if we are the default browser, or false otherwise.
    */
   _isDefaultBrowser() {
+    let isDefault = (service, ...args) => {
+      try {
+        return !!service.isDefaultBrowser(...args);
+      } catch (ex) {
+        this._log.error("_isDefaultBrowser - Could not determine if default browser", ex);
+        return null;
+      }
+    };
+
     if (!("@mozilla.org/browser/shell-service;1" in Cc)) {
       this._log.info("_isDefaultBrowser - Could not obtain browser shell service");
       return null;
     }
 
-    let shellService;
     try {
-      let scope = {};
-      ChromeUtils.import("resource:///modules/ShellService.jsm", scope);
-      shellService = scope.ShellService;
+      let { ShellService } = ChromeUtils.import("resource:///modules/ShellService.jsm", {});
+      // This uses the same set of flags used by the pref pane.
+      return isDefault(ShellService, false, true);
     } catch (ex) {
       this._log.error("_isDefaultBrowser - Could not obtain shell service JSM");
     }
 
-    if (!shellService) {
-      try {
-        shellService = Cc["@mozilla.org/browser/shell-service;1"]
-                         .getService(Ci.nsIShellService);
-      } catch (ex) {
-        this._log.error("_isDefaultBrowser - Could not obtain shell service", ex);
-        return null;
-      }
-    }
-
     try {
-      // This uses the same set of flags used by the pref pane.
-      return !!shellService.isDefaultBrowser(false, true);
+      let shellService = Cc["@mozilla.org/browser/shell-service;1"]
+                            .getService(Ci.nsIShellService);
+    // This uses the same set of flags used by the pref pane.
+      return isDefault(shellService, true);
     } catch (ex) {
-      this._log.error("_isDefaultBrowser - Could not determine if default browser", ex);
+      this._log.error("_isDefaultBrowser - Could not obtain shell service", ex);
       return null;
     }
   },
 
   _updateDefaultBrowser() {
     if (AppConstants.platform === "android") {
       return;
     }
--- a/toolkit/components/telemetry/pings/EventPing.jsm
+++ b/toolkit/components/telemetry/pings/EventPing.jsm
@@ -37,17 +37,16 @@ const MS_IN_A_MINUTE = 60 * 1000;
 const DEFAULT_EVENT_LIMIT = 1000;
 const DEFAULT_MIN_FREQUENCY_MS = 60 * MS_IN_A_MINUTE;
 const DEFAULT_MAX_FREQUENCY_MS = 10 * MS_IN_A_MINUTE;
 
 const LOGGER_NAME = "Toolkit.Telemetry";
 const LOGGER_PREFIX = "TelemetryEventPing::";
 
 const EVENT_LIMIT_REACHED_TOPIC = "event-telemetry-storage-limit-reached";
-const PROFILE_BEFORE_CHANGE_TOPIC = "profile-before-change";
 
 var Policy = {
   setTimeout: (callback, delayMs) => setTimeout(callback, delayMs),
   clearTimeout: (id) => clearTimeout(id),
   sendPing: (type, payload, options) => TelemetryController.submitExternalPing(type, payload, options),
 };
 
 var TelemetryEventPing = {
@@ -70,39 +69,40 @@ var TelemetryEventPing = {
     return Telemetry.canRecordPrereleaseData ? Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN
                                              : Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTOUT;
   },
 
   startup() {
     if (!Services.prefs.getBoolPref(Utils.Preferences.EventPingEnabled, true)) {
       return;
     }
+    this._log.trace("Starting up.");
     Services.obs.addObserver(this, EVENT_LIMIT_REACHED_TOPIC);
-    Services.obs.addObserver(this, PROFILE_BEFORE_CHANGE_TOPIC);
 
     XPCOMUtils.defineLazyPreferenceGetter(this, "maxEventsPerPing",
                                           Utils.Preferences.EventPingEventLimit,
                                           DEFAULT_EVENT_LIMIT);
     XPCOMUtils.defineLazyPreferenceGetter(this, "maxFrequency",
                                           Utils.Preferences.EventPingMaximumFrequency,
                                           DEFAULT_MAX_FREQUENCY_MS);
     XPCOMUtils.defineLazyPreferenceGetter(this, "minFrequency",
                                           Utils.Preferences.EventPingMinimumFrequency,
                                           DEFAULT_MIN_FREQUENCY_MS);
 
     this._startTimer();
   },
 
   shutdown() {
+    this._log.trace("Shutting down.");
     // removeObserver may throw, which could interrupt shutdown.
     try {
       Services.obs.removeObserver(this, EVENT_LIMIT_REACHED_TOPIC);
-      Services.obs.removeObserver(this, PROFILE_BEFORE_CHANGE_TOPIC);
     } catch (ex) {}
 
+    this._submitPing(this.Reason.SHUTDOWN, true /* discardLeftovers */);
     this._clearTimer();
   },
 
   observe(aSubject, aTopic, aData) {
     switch (aTopic) {
       case EVENT_LIMIT_REACHED_TOPIC:
         this._log.trace("event limit reached");
         let now = Utils.monotonicNow();
@@ -111,20 +111,16 @@ var TelemetryEventPing = {
           this._startTimer(this.maxFrequency - this._lastSendTime,
                            this.Reason.MAX,
                            true /* discardLeftovers*/);
         } else {
           this._log.trace("submitting ping immediately");
           this._submitPing(this.Reason.MAX);
         }
         break;
-      case PROFILE_BEFORE_CHANGE_TOPIC:
-        this._log.trace("profile before change");
-        this._submitPing(this.Reason.SHUTDOWN, true /* discardLeftovers */);
-        break;
     }
   },
 
   _startTimer(delay = this.minFrequency, reason = this.Reason.PERIODIC, discardLeftovers = false) {
     this._clearTimer();
     this._timeoutId =
       Policy.setTimeout(() => TelemetryEventPing._submitPing(reason, discardLeftovers), delay);
   },
--- a/toolkit/components/telemetry/tests/unit/test_EventPing.js
+++ b/toolkit/components/telemetry/tests/unit/test_EventPing.js
@@ -156,32 +156,16 @@ add_task(async function test_timers() {
 
   fakePolicy((callback, delay) => {
     Assert.ok(delay <= TelemetryEventPing.maxFrequency, "Timer should be at most the max frequency for a subsequent MAX ping.");
   }, pass, pass);
   recordEvents(1000);
 
 });
 
-add_task(async function test_shutdown() {
-  Telemetry.clearEvents();
-  TelemetryEventPing.testReset();
-
-  recordEvents(999);
-  fakePolicy(pass, pass, (type, payload, options) => {
-    Assert.ok(options.addClientId, "Adds the client id.");
-    Assert.ok(options.addEnvironment, "Adds the environment.");
-    Assert.ok(options.usePingSender, "Asks for pingsender.");
-    Assert.equal(payload.reason, TelemetryEventPing.Reason.SHUTDOWN, "Sending because we are shutting down");
-    Assert.equal(payload.events.parent.length, 999, "Has 999 events");
-    Assert.equal(payload.lostEventsCount, 0, "No lost events");
-  });
-  TelemetryEventPing.observe(null, "profile-before-change", null);
-});
-
 add_task(async function test_periodic() {
   Telemetry.clearEvents();
   TelemetryEventPing.testReset();
 
   fakePolicy((callback, delay) => {
     Assert.equal(delay, TelemetryEventPing.minFrequency, "Timer should default to the min frequency");
     fakePolicy(pass, pass, (type, payload, options) => {
       checkPingStructure(type, payload, options);
@@ -193,8 +177,25 @@ add_task(async function test_periodic() 
       Assert.equal(payload.lostEventsCount, 0, "Lost no events");
     });
     callback();
   }, pass, fail);
 
   recordEvents(1);
   TelemetryEventPing._startTimer();
 });
+
+// Ensure this is the final test in the suite, as it shuts things down.
+add_task(async function test_shutdown() {
+  Telemetry.clearEvents();
+  TelemetryEventPing.testReset();
+
+  recordEvents(999);
+  fakePolicy(pass, pass, (type, payload, options) => {
+    Assert.ok(options.addClientId, "Adds the client id.");
+    Assert.ok(options.addEnvironment, "Adds the environment.");
+    Assert.ok(options.usePingSender, "Asks for pingsender.");
+    Assert.equal(payload.reason, TelemetryEventPing.Reason.SHUTDOWN, "Sending because we are shutting down");
+    Assert.equal(payload.events.parent.length, 999, "Has 999 events");
+    Assert.equal(payload.lostEventsCount, 0, "No lost events");
+  });
+  TelemetryEventPing.shutdown();
+});
--- a/toolkit/content/license.html
+++ b/toolkit/content/license.html
@@ -5839,22 +5839,24 @@ WHETHER IN AN ACTION OF CONTRACT, TORT O
 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 OTHER DEALINGS IN THE SOFTWARE.
 </pre>
 
 <hr>
 
 <h1><a id="reselect"></a>Reselect License</h1>
 
-<p>This license applies to the file
-<code>devtools/client/shared/vendor/reselect.js</code>.</p>
+<p>This license applies to the files
+    <code>devtools/client/shared/vendor/reselect.js</code> and
+    <code>browser/components/newtab/data/content/activity-stream.bundle.js</code>.
+</p>
 <pre>
 The MIT License (MIT)
 
-Copyright (c) 2015-2016 Reselect Contributors
+Copyright (c) 2015-2018 Reselect Contributors
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:
 
--- a/toolkit/library/dependentlibs.py
+++ b/toolkit/library/dependentlibs.py
@@ -14,80 +14,47 @@ import mozpack.path as mozpath
 from collections import OrderedDict
 from mozpack.executables import (
     get_type,
     ELF,
     MACHO,
 )
 from buildconfig import substs
 
-def dependentlibs_dumpbin(lib):
-    '''Returns the list of dependencies declared in the given DLL'''
-    try:
-        proc = subprocess.Popen(['dumpbin', '-dependents', lib], stdout = subprocess.PIPE)
-    except OSError:
-        # dumpbin is missing, probably mingw compilation. Try using objdump.
-        return dependentlibs_mingw_objdump(lib)
-    deps = []
-    for line in proc.stdout:
-        # Each line containing an imported library name starts with 4 spaces
-        match = re.match('    (\S+)', line)
-        if match:
-             deps.append(match.group(1))
-        elif len(deps):
-             # There may be several groups of library names, but only the
-             # first one is interesting. The second one is for delayload-ed
-             # libraries.
-             break
-    proc.wait()
-    return deps
-
-def dependentlibs_mingw_objdump(lib):
-    try:
-        proc = subprocess.Popen(['objdump', '-x', lib], stdout = subprocess.PIPE)
-    except OSError:
-        # objdump is missing, try using llvm-objdump.
-        proc = subprocess.Popen(['llvm-objdump', '-private-headers', lib], stdout = subprocess.PIPE)
+def dependentlibs_win32_objdump(lib):
+    proc = subprocess.Popen([substs['LLVM_OBJDUMP'], '--private-headers', lib], stdout = subprocess.PIPE)
     deps = []
     for line in proc.stdout:
         match = re.match('\s+DLL Name: (\S+)', line)
         if match:
             deps.append(match.group(1))
     proc.wait()
     return deps
 
-def dependentlibs_readelf(lib):
+def dependentlibs_elf_objdump(lib):
     '''Returns the list of dependencies declared in the given ELF .so'''
-    proc = subprocess.Popen([substs.get('TOOLCHAIN_PREFIX', '') + 'readelf', '-d', lib], stdout = subprocess.PIPE)
+    proc = subprocess.Popen([substs['LLVM_OBJDUMP'], '--private-headers', lib], stdout = subprocess.PIPE)
     deps = []
     for line in proc.stdout:
-        # Each line has the following format:
-        #  tag (TYPE)          value
-        # or with BSD readelf:
-        #  tag TYPE            value
-        # Looking for NEEDED type entries
-        tmp = line.split(' ', 3)
-        if len(tmp) > 3 and 'NEEDED' in tmp[2]:
-            # NEEDED lines look like:
-            # 0x00000001 (NEEDED)             Shared library: [libname]
-            # or with BSD readelf:
-            # 0x00000001 NEEDED               Shared library: [libname]
-            match = re.search('\[(.*)\]', tmp[3])
-            if match:
-                deps.append(match.group(1))
+        # We are looking for lines with the format:
+        #   NEEDED             libname
+        tmp = line.split()
+        if len(tmp) == 2 and tmp[0] == 'NEEDED':
+            deps.append(tmp[1])
     proc.wait()
     return deps
 
-def dependentlibs_otool(lib):
+def dependentlibs_mac_objdump(lib):
     '''Returns the list of dependencies declared in the given MACH-O dylib'''
-    proc = subprocess.Popen([substs['OTOOL'], '-l', lib], stdout = subprocess.PIPE)
-    deps= []
+    proc = subprocess.Popen([substs['LLVM_OBJDUMP'], '--private-headers', lib], stdout = subprocess.PIPE)
+    deps = []
     cmd = None
     for line in proc.stdout:
-        # otool -l output contains many different things. The interesting data
+        # llvm-objdump --private-headers output contains many different
+        # things. The interesting data
         # is under "Load command n" sections, with the content:
         #           cmd LC_LOAD_DYLIB
         #       cmdsize 56
         #          name libname (offset 24)
         tmp = line.split()
         if len(tmp) < 2:
             continue
         if tmp[0] == 'cmd':
@@ -118,23 +85,23 @@ def dependentlibs(lib, libpaths, func):
                 break
 
     return deps
 
 def gen_list(output, lib):
     libpaths = [os.path.join(substs['DIST'], 'bin')]
     binary_type = get_type(lib)
     if binary_type == ELF:
-        func = dependentlibs_readelf
+        func = dependentlibs_elf_objdump
     elif binary_type == MACHO:
-        func = dependentlibs_otool
+        func = dependentlibs_mac_objdump
     else:
         ext = os.path.splitext(lib)[1]
         assert(ext == '.dll')
-        func = dependentlibs_dumpbin
+        func = dependentlibs_win32_objdump
 
     deps = dependentlibs(lib, libpaths, func)
     base_lib = mozpath.basename(lib)
     deps[base_lib] = mozpath.join(libpaths[0], base_lib)
     output.write('\n'.join(deps.keys()) + '\n')
 
     with open(output.name + ".gtest", 'w') as gtest_out:
         libs = deps.keys()
--- a/widget/gtk/nsWindow.cpp
+++ b/widget/gtk/nsWindow.cpp
@@ -2566,17 +2566,19 @@ void nsWindow::OnButtonPressEvent(GdkEve
 
   WidgetMouseEvent event(true, eMouseDown, this, WidgetMouseEvent::eReal);
   event.button = domButton;
   InitButtonEvent(event, aEvent);
   event.pressure = mLastMotionPressure;
 
   nsEventStatus eventStatus = DispatchInputEvent(&event);
 
-  if (mDraggableRegion.Contains(aEvent->x, aEvent->y) &&
+  LayoutDeviceIntPoint refPoint =
+      GdkEventCoordsToDevicePixels(aEvent->x, aEvent->y);
+  if (mDraggableRegion.Contains(refPoint.x, refPoint.y) &&
       domButton == WidgetMouseEvent::eLeftButton &&
       eventStatus != nsEventStatus_eConsumeNoDefault) {
     mWindowShouldStartDragging = true;
   }
 
   // right menu click on linux should also pop up a context menu
   if (!nsBaseWidget::ShowContextMenuAfterMouseUp()) {
     DispatchContextMenuEventFromMouseEvent(domButton, aEvent);