Merge mozilla-central to mozilla-inbound. a=merge CLOSED TREE
authorBogdan Tara <btara@mozilla.com>
Sat, 11 Aug 2018 01:01:18 +0300
changeset 431040 b4b17e9deb17e35ac6420741532fb78447171741
parent 431009 babb78f979b24ef5a6cbed39d6d4e9e2239814da (current diff)
parent 431039 9a6728f46269868c5f24f18c95cd2319b5b67a0a (diff)
child 431041 141dc7ae832e94ecd0c3b38a6a8ff04159b9bdf8
push id106334
push userbtara@mozilla.com
push dateFri, 10 Aug 2018 22:01:46 +0000
treeherdermozilla-inbound@b4b17e9deb17 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone63.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge mozilla-central to mozilla-inbound. a=merge CLOSED TREE
devtools/client/webconsole/test/mochitest/browser_jsterm_no_autocompletion_on_defined_variables.js
modules/libpref/init/all.js
testing/web-platform/meta/WebIDL/ecmascript-binding/legacy-platform-object.html.ini
testing/web-platform/meta/css/css-contain/contain-layout-006.html.ini
testing/web-platform/meta/css/css-contain/contain-layout-007.html.ini
testing/web-platform/meta/css/css-contain/contain-layout-008.html.ini
testing/web-platform/meta/css/css-contain/contain-layout-013.html.ini
testing/web-platform/meta/css/css-contain/contain-layout-014.html.ini
testing/web-platform/meta/css/css-contain/contain-layout-015.html.ini
testing/web-platform/meta/css/css-contain/contain-layout-016.html.ini
testing/web-platform/meta/css/css-contain/contain-layout-ifc-022.html.ini
testing/web-platform/meta/css/css-contain/contain-layout-ink-overflow-013.html.ini
testing/web-platform/meta/css/css-contain/contain-layout-ink-overflow-014.html.ini
testing/web-platform/meta/css/css-contain/contain-layout-ink-overflow-015.html.ini
testing/web-platform/meta/css/css-contain/contain-layout-ink-overflow-016.html.ini
testing/web-platform/meta/css/css-contain/contain-layout-ink-overflow-017.html.ini
testing/web-platform/meta/css/css-contain/contain-layout-ink-overflow-018.html.ini
testing/web-platform/meta/css/css-contain/contain-layout-ink-overflow-019.html.ini
testing/web-platform/meta/css/css-contain/contain-layout-ink-overflow-020.html.ini
testing/web-platform/meta/css/css-contain/contain-layout-size-003.html.ini
testing/web-platform/meta/xhr/responsetext-decoding.htm.ini
testing/web-platform/meta/xhr/send-receive-utf16.htm.ini
toolkit/library/gtest/rust/Makefile.in
--- a/browser/components/extensions/test/browser/browser_ext_sidebarAction_context.js
+++ b/browser/components/extensions/test/browser/browser_ext_sidebarAction_context.js
@@ -1,19 +1,14 @@
 /* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set sts=2 sw=2 et tw=80: */
 "use strict";
 
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 
-SpecialPowers.pushPrefEnv({
-  // Ignore toolbarbutton stuff, other test covers it.
-  set: [["extensions.sidebar-button.shown", true]],
-});
-
 async function runTests(options) {
   async function background(getTests) {
     async function checkDetails(expecting, details) {
       let title = await browser.sidebarAction.getTitle(details);
       browser.test.assertEq(expecting.title, title,
                             "expected value from getTitle in " + JSON.stringify(details));
 
       let panel = await browser.sidebarAction.getPanel(details);
--- a/browser/components/extensions/test/browser/browser_ext_sidebarAction_contextMenu.js
+++ b/browser/components/extensions/test/browser/browser_ext_sidebarAction_contextMenu.js
@@ -114,13 +114,8 @@ add_task(async function sidebar_image_co
   let item = contentAreaContextMenu.querySelector("#context-viewimageinfo");
   ok(!item.hidden);
   ok(!item.disabled);
 
   await closeContextMenu(contentAreaContextMenu);
 
   await extension.unload();
 });
-
-add_task(async function cleanup() {
-  // This is set on initial sidebar install.
-  Services.prefs.clearUserPref("extensions.sidebar-button.shown");
-});
--- a/browser/components/extensions/test/browser/browser_ext_sidebarAction_tabs.js
+++ b/browser/components/extensions/test/browser/browser_ext_sidebarAction_tabs.js
@@ -38,15 +38,9 @@ add_task(async function sidebar_tab_quer
       },
     },
   };
 
   let extension = ExtensionTestUtils.loadExtension(data);
   await extension.startup();
   await extension.awaitMessage("sidebar");
   await extension.unload();
-
-  // Move toolbar button back to customization.
-  CustomizableUI.removeWidgetFromArea("sidebar-button", CustomizableUI.AREA_NAVBAR);
-  ok(!document.getElementById("sidebar-button"), "sidebar button is not in UI");
-  // This is set on initial sidebar install.
-  Services.prefs.clearUserPref("extensions.sidebar-button.shown");
 });
--- a/browser/components/extensions/test/browser/browser_ext_sidebarAction_windows.js
+++ b/browser/components/extensions/test/browser/browser_ext_sidebarAction_windows.js
@@ -55,15 +55,9 @@ add_task(async function sidebar_windows(
   // Check that the menuitem has our image styling.
   elements = win.document.getElementsByClassName("webextension-menuitem");
   ok(elements.length > 0, "have a menuitem");
   style = elements[0].getAttribute("style");
   ok(style.includes("webextension-menuitem-image"), "this menu has style");
 
   await extension.unload();
   await BrowserTestUtils.closeWindow(win);
-
-  // Move toolbar button back to customization.
-  CustomizableUI.removeWidgetFromArea("sidebar-button", CustomizableUI.AREA_NAVBAR);
-  ok(!document.getElementById("sidebar-button"), "sidebar button is not in UI");
-  // This is set on initial sidebar install.
-  Services.prefs.clearUserPref("extensions.sidebar-button.shown");
 });
--- a/build/gecko_templates.mozbuild
+++ b/build/gecko_templates.mozbuild
@@ -102,33 +102,33 @@ def GeckoCppUnitTests(names, **kwargs):
     CppUnitTests(names)
 
     kwargs.setdefault('mozglue', 'program')
 
     GeckoBinary(**kwargs)
 
 
 @template
-def GeckoSharedLibrary(name, **kwargs):
+def GeckoSharedLibrary(name, output_category=None, **kwargs):
     '''Template for shared libraries related to Gecko.
 
     `name` identifies the library base name.
     See the documentation for `GeckoBinary` for other possible arguments.
     '''
-    SharedLibrary(name)
+    SharedLibrary(name, output_category)
 
     kwargs.setdefault('mozglue', 'library')
 
     GeckoBinary(**kwargs)
 
 
 @template
-def GeckoFramework(name, **kwargs):
+def GeckoFramework(name, output_category=None, **kwargs):
     '''Template for OSX frameworks related to Gecko.
 
     `name` identifies the library base name.
     See the documentation for `GeckoBinary` for other possible arguments.
     '''
-    Framework(name)
+    Framework(name, output_category)
 
     kwargs.setdefault('mozglue', 'library')
 
     GeckoBinary(**kwargs)
--- a/build/templates.mozbuild
+++ b/build/templates.mozbuild
@@ -53,45 +53,51 @@ def Library(name):
     '''Template for libraries.'''
     LIBRARY_NAME = name
 
 @template
 def AllowCompilerWarnings():
     COMPILE_FLAGS['WARNINGS_AS_ERRORS'] = []
 
 @template
-def RustLibrary(name, features=None, target_dir=None):
+def RustLibrary(name, features=None, target_dir=None, output_category=None):
     '''Template for Rust libraries.'''
     Library(name)
 
     IS_RUST_LIBRARY = True
     # Some Rust build scripts compile C/C++ sources, don't error on warnings for them.
     AllowCompilerWarnings()
 
     if features:
         RUST_LIBRARY_FEATURES = features
 
     if target_dir:
         RUST_LIBRARY_TARGET_DIR = target_dir
 
+    if output_category:
+        RUST_LIBRARY_OUTPUT_CATEGORY = output_category
+
 
 @template
-def SharedLibrary(name):
+def SharedLibrary(name, output_category=None):
     '''Template for shared libraries.'''
     Library(name)
 
     FORCE_SHARED_LIB = True
 
+    if output_category:
+        SHARED_LIBRARY_OUTPUT_CATEGORY = output_category
+
     Binary()
 
 
 @template
-def Framework(name):
+def Framework(name, output_category=None):
     '''Template for OSX Frameworks.'''
-    SharedLibrary(name)
+    SharedLibrary(name, output_category)
 
     IS_FRAMEWORK = True
 
 
 @template
 def HostProgram(name):
     '''Template for build tools executables.'''
     HOST_PROGRAM = name
--- a/config/makefiles/target_binaries.mk
+++ b/config/makefiles/target_binaries.mk
@@ -13,17 +13,19 @@ PROGRAMS_DEST ?= $(FINAL_TARGET)
 PROGRAMS_TARGET := target
 INSTALL_TARGETS += PROGRAMS
 endif
 
 
 ifdef SHARED_LIBRARY
 SHARED_LIBRARY_FILES = $(SHARED_LIBRARY)
 SHARED_LIBRARY_DEST ?= $(FINAL_TARGET)
+ifndef SHARED_LIBRARY_TARGET
 SHARED_LIBRARY_TARGET = target
+endif
 INSTALL_TARGETS += SHARED_LIBRARY
 endif # SHARED_LIBRARY
 
 ifneq (,$(strip $(HOST_SIMPLE_PROGRAMS)))
 HOST_PROGRAMS_EXECUTABLES = $(HOST_SIMPLE_PROGRAMS) $(HOST_RUST_PROGRAMS)
 HOST_PROGRAMS_DEST ?= $(DIST)/host/bin
 HOST_PROGRAMS_TARGET = host
 INSTALL_TARGETS += HOST_PROGRAMS
--- a/config/recurse.mk
+++ b/config/recurse.mk
@@ -36,17 +36,17 @@ include root.mk
 
 # Special rule that does install-manifests (cf. Makefile.in) + compile
 binaries::
 	+$(MAKE) recurse_compile
 
 # Carefully avoid $(eval) type of rule generation, which makes pymake slower
 # than necessary.
 # Get current tier and corresponding subtiers from the data in root.mk.
-CURRENT_TIER := $(filter $(foreach tier,$(TIERS),recurse_$(tier) $(tier)-deps),$(MAKECMDGOALS))
+CURRENT_TIER := $(filter $(foreach tier,$(TIERS) $(non_default_tiers),recurse_$(tier) $(tier)-deps),$(MAKECMDGOALS))
 ifneq (,$(filter-out 0 1,$(words $(CURRENT_TIER))))
 $(error $(CURRENT_TIER) not supported on the same make command line)
 endif
 CURRENT_TIER := $(subst recurse_,,$(CURRENT_TIER:-deps=))
 
 # The rules here are doing directory traversal, so we don't want further
 # recursion to happen when running make -C subdir $tier. But some make files
 # further call make -C something else, and sometimes expect recursion to
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -441,17 +441,17 @@ GLOBAL_DEPS += Makefile $(addprefix $(DE
 ##############################################
 ifdef COMPILE_ENVIRONMENT
 OBJ_TARGETS = $(OBJS) $(PROGOBJS) $(HOST_OBJS) $(HOST_PROGOBJS)
 
 compile:: host target
 
 host:: $(HOST_LIBRARY) $(HOST_PROGRAM) $(HOST_SIMPLE_PROGRAMS) $(HOST_RUST_PROGRAMS) $(HOST_RUST_LIBRARY_FILE) $(HOST_SHARED_LIBRARY)
 
-target:: $(LIBRARY) $(SHARED_LIBRARY) $(PROGRAM) $(SIMPLE_PROGRAMS) $(RUST_LIBRARY_FILE) $(RUST_PROGRAMS)
+target:: $(filter-out $(MOZBUILD_NON_DEFAULT_TARGETS),$(LIBRARY) $(SHARED_LIBRARY) $(PROGRAM) $(SIMPLE_PROGRAMS) $(RUST_LIBRARY_FILE) $(RUST_PROGRAMS))
 
 ifndef LIBRARY
 ifdef OBJS
 target:: $(OBJS)
 endif
 endif
 
 syms::
--- a/devtools/server/actors/webconsole.js
+++ b/devtools/server/actors/webconsole.js
@@ -1425,17 +1425,17 @@ WebConsoleActor.prototype =
     }
 
     const isCmd = isCommand(string);
     // we support Unix like syntax for commands if it is preceeded by `:`
     if (isCmd) {
       try {
         string = formatCommand(string);
       } catch (e) {
-        string = `throw "${e}"`;
+        string = `throw "${e.message || e}"`;
       }
     }
 
     // Add easter egg for console.mihai().
     if (trimmedString == "console.mihai()" || trimmedString == "console.mihai();") {
       string = "\"http://incompleteness.me/blog/2015/02/09/console-dot-mihai/\"";
     }
 
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -11431,16 +11431,22 @@ class CGDOMJSProxyHandler_defineProperty
 
         indexedSetter = self.descriptor.operations['IndexedSetter']
         if indexedSetter:
             set += fill(
                 """
                 uint32_t index = GetArrayIndexFromId(cx, id);
                 if (IsArrayIndex(index)) {
                   *defined = true;
+                  // https://heycam.github.io/webidl/#legacy-platform-object-defineownproperty
+                  // Step 1.1.  The no-indexed-setter case is handled by step 1.2.
+                  if (!desc.isDataDescriptor()) {
+                    return opresult.failNotDataDescriptor();
+                  }
+
                   $*{callSetter}
                   return opresult.succeed();
                 }
                 """,
                 callSetter=CGProxyIndexedSetter(self.descriptor).define())
         elif self.descriptor.supportsIndexedProperties():
             # We allow untrusted content to prevent Xrays from setting a
             # property if that property is an indexed property and we have no
--- a/dom/media/PeerConnection.js
+++ b/dom/media/PeerConnection.js
@@ -35,16 +35,20 @@ const PC_MANAGER_CID = Components.ID("{7
 const PC_STATS_CID = Components.ID("{7fe6e18b-0da3-4056-bf3b-440ef3809e06}");
 const PC_STATIC_CID = Components.ID("{0fb47c47-a205-4583-a9fc-cbadf8c95880}");
 const PC_SENDER_CID = Components.ID("{4fff5d46-d827-4cd4-a970-8fd53977440e}");
 const PC_RECEIVER_CID = Components.ID("{d974b814-8fde-411c-8c45-b86791b81030}");
 const PC_TRANSCEIVER_CID = Components.ID("{09475754-103a-41f5-a2d0-e1f27eb0b537}");
 const PC_COREQUEST_CID = Components.ID("{74b2122d-65a8-4824-aa9e-3d664cb75dc2}");
 const PC_DTMF_SENDER_CID = Components.ID("{3610C242-654E-11E6-8EC0-6D1BE389A607}");
 
+const TELEMETRY_PC_CONNECTED = "webrtc.peerconnection.connected";
+const TELEMETRY_PC_CALLBACK_GETSTATS = "webrtc.peerconnection.legacy_callback_stats_used";
+const TELEMETRY_PC_PROMISE_GETSTATS = "webrtc.peerconnection.promise_stats_used";
+const TELEMETRY_PC_PROMISE_AND_CALLBACK_GETSTATS = "webrtc.peerconnection.promise_and_callback_stats_used";
 function logMsg(msg, file, line, flag, winID) {
   let scriptErrorClass = Cc["@mozilla.org/scripterror;1"];
   let scriptError = scriptErrorClass.createInstance(Ci.nsIScriptError);
   scriptError.initWithWindowID(msg, file, null, line, 0, flag,
                                "content javascript", winID);
   Services.console.logMessage(scriptError);
 }
 
@@ -372,16 +376,42 @@ setupPrototype(RTCStatsReport, {
         "inbound-rtp": "inboundrtp",
         "outbound-rtp": "outboundrtp",
         "candidate-pair": "candidatepair",
         "local-candidate": "localcandidate",
         "remote-candidate": "remotecandidate"
   }
 });
 
+// This is its own class so that it does not need to be exposed to the client.
+class PeerConnectionTelemetry {
+  // Record which style(s) of invocation for getStats are used
+  recordPromiseAndCallbackGetStats(isCallback) {
+    if (!this._hasCallbackStatsBeenUsed && isCallback) {
+      this._hasCallbackStatsBeenUsed = true;
+      Services.telemetry.scalarAdd(TELEMETRY_PC_CALLBACK_GETSTATS, 1);
+    }
+    if (!this._hasPromiseStatsBeenUsed && !isCallback) {
+      this._hasPromiseStatsBeenUsed = true;
+      Services.telemetry.scalarAdd(TELEMETRY_PC_PROMISE_GETSTATS, 1);
+    }
+    if (this._hasCallbackStatsBeenUsed && this._hasPromiseStatsBeenUsed) {
+      Services.telemetry.scalarAdd(
+        TELEMETRY_PC_PROMISE_AND_CALLBACK_GETSTATS, 1);
+      // Everything that can be recorded has been at this point.
+      this.recordPromiseAndCallbackGetStats = () => {};
+    }
+  }
+  // ICE connection state enters connected or completed.
+  recordConnected() {
+    Services.telemetry.scalarAdd(TELEMETRY_PC_CONNECTED, 1);
+    this.recordConnected = () => {};
+  }
+}
+
 // Cache for RTPSourceEntries
 // Note: each cache is only valid for one JS event loop execution
 class RTCRtpSourceCache {
   constructor() {
     // The time in RTP source time (ms)
     this.tsNowInRtpSourceTime = null;
     // The time in JS
     this.jsTimestamp = null;
@@ -418,16 +448,18 @@ class RTCPeerConnection {
     this._iceGatheredRelayCandidates = false;
     // Stored webrtc timing information
     this._storedRtpSourceReferenceTime = null;
     // TODO: Remove legacy API eventually
     // see Bug 1328194
     this._onGetStatsIsLegacy = false;
     // Stores cached RTP sources state
     this._rtpSourceCache = new RTCRtpSourceCache();
+    // Records telemetry
+    this._pcTelemetry = new PeerConnectionTelemetry();
   }
 
   init(win) {
     this._win = win;
   }
 
   __init(rtcConfig) {
     this._winID = this._win.windowUtils.currentInnerWindowID;
@@ -1586,16 +1618,20 @@ class RTCPeerConnection {
       this._iceConnectionState = state;
       _globalPCList.notifyLifecycleObservers(this, "iceconnectionstatechange");
       this.dispatchEvent(new this._win.Event("iceconnectionstatechange"));
     }
   }
 
   getStats(selector, onSucc, onErr) {
     let isLegacy = (typeof onSucc) == "function";
+    if (this._iceConnectionState === "completed" ||
+        this._iceConnectionState === "connected") {
+      this._pcTelemetry.recordPromiseAndCallbackGetStats(isLegacy);
+    }
     if (isLegacy &&
         this._warnDeprecatedStatsCallbacksNullable.warn) {
       this._warnDeprecatedStatsCallbacksNullable.warn();
       this._warnDeprecatedStatsCallbacksNullable.warn = null;
     }
     return this._auto(onSucc, onErr, () => this._getStats(selector, isLegacy));
   }
 
@@ -1791,16 +1827,17 @@ class PeerConnectionObserver {
       } else if (iceConnectionState === "failed") {
         checking_histogram.add(false);
       }
     } else if (pc.iceConnectionState === "checking") {
       var success_histogram = Services.telemetry.getHistogramById("WEBRTC_ICE_SUCCESS_RATE");
       if (iceConnectionState === "completed" ||
           iceConnectionState === "connected") {
         success_histogram.add(true);
+        pc._pcTelemetry.recordConnected();
       } else if (iceConnectionState === "failed") {
         success_histogram.add(false);
       }
     }
 
     if (iceConnectionState === "failed") {
       if (!pc._hasStunServer) {
         pc.logError("ICE failed, add a STUN server and see about:webrtc for more details");
--- a/dom/tests/mochitest/general/test_interfaces.js
+++ b/dom/tests/mochitest/general/test_interfaces.js
@@ -203,16 +203,18 @@ var interfaceNamesInGlobalScope =
     {name: "ChannelMergerNode", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "ChannelSplitterNode", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "CharacterData", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "ChromeNodeList", insecureContext: true, xbl: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
+    {name: "Clipboard"},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "ClipboardEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "CloseEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "CommandEvent", insecureContext: true, xbl: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "Comment", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
--- a/dom/xhr/XMLHttpRequestMainThread.cpp
+++ b/dom/xhr/XMLHttpRequestMainThread.cpp
@@ -477,25 +477,35 @@ XMLHttpRequestMainThread::DetectCharset(
   if (mResponseType == XMLHttpRequestResponseType::Json &&
       encoding != UTF_8_ENCODING) {
     // The XHR spec says only UTF-8 is supported for responseType == "json"
     LogMessage("JSONCharsetWarning", GetOwner());
     encoding = UTF_8_ENCODING;
   }
 
   mResponseCharset = encoding;
-  mDecoder = encoding->NewDecoderWithBOMRemoval();
+
+  // Only sniff the BOM for non-JSON responseTypes
+  if (mResponseType == XMLHttpRequestResponseType::Json) {
+    mDecoder = encoding->NewDecoderWithBOMRemoval();
+  } else {
+    mDecoder = encoding->NewDecoder();
+  }
 
   return NS_OK;
 }
 
 nsresult
 XMLHttpRequestMainThread::AppendToResponseText(const char * aSrcBuffer,
-                                               uint32_t aSrcBufferLen)
+                                               uint32_t aSrcBufferLen,
+                                               bool aLast)
 {
+  // Call this with an empty buffer to send the decoder the signal
+  // that we have hit the end of the stream.
+
   NS_ENSURE_STATE(mDecoder);
 
   CheckedInt<size_t> destBufferLen =
     mDecoder->MaxUTF16BufferLength(aSrcBufferLen);
   if (!destBufferLen.isValid()) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
@@ -506,25 +516,24 @@ XMLHttpRequestMainThread::AppendToRespon
   }
 
   XMLHttpRequestStringWriterHelper helper(mResponseText);
 
   if (!helper.AddCapacity(destBufferLen.value())) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
-  // XXX there's no handling for incomplete byte sequences on EOF!
   uint32_t result;
   size_t read;
   size_t written;
   bool hadErrors;
   Tie(result, read, written, hadErrors) = mDecoder->DecodeToUTF16(
     AsBytes(MakeSpan(aSrcBuffer, aSrcBufferLen)),
     MakeSpan(helper.EndOfExistingData(), destBufferLen.value()),
-    false);
+    aLast);
   MOZ_ASSERT(result == kInputEmpty);
   MOZ_ASSERT(read == aSrcBufferLen);
   MOZ_ASSERT(written <= destBufferLen.value());
   Unused << hadErrors;
   helper.AddLength(written);
   return NS_OK;
 }
 
@@ -1506,16 +1515,17 @@ XMLHttpRequestMainThread::Open(const nsA
   mFlagSynchronous = !aAsync;
   mAuthorRequestHeaders.Clear();
   ResetResponse();
 
   // Gecko-specific
   mFlagHadUploadListenersOnSend = false;
   mFlagAborted = false;
   mFlagTimedOut = false;
+  mDecoder = nullptr;
 
   // Per spec we should only create the channel on send(), but we have internal
   // code that relies on the channel being created now, and that code is not
   // always IsSystemXHR(). However, we're not supposed to throw channel-creation
   // errors during open(), so we silently ignore those here.
   CreateChannel();
 
   // Step 12
@@ -1811,22 +1821,21 @@ XMLHttpRequestMainThread::OnStartRequest
     return NS_OK;
   }
 
   // Don't do anything if we have been aborted
   if (mState == XMLHttpRequest_Binding::UNSENT) {
     return NS_OK;
   }
 
-  /* Apparently, Abort() should set UNSENT.  See bug 361773.
-     XHR2 spec says this is correct. */
+  // Don't do anything if we're in mid-abort, but let the request
+  // know (this can happen due to race conditions in valid XHRs,
+  // see bz1070763 for info).
   if (mFlagAborted) {
-    NS_ERROR("Ugh, still getting data on an aborted XMLHttpRequest!");
-
-    return NS_ERROR_UNEXPECTED;
+    return NS_BINDING_ABORTED;
   }
 
   // Don't do anything if we have timed out.
   if (mFlagTimedOut) {
     return NS_OK;
   }
 
   nsCOMPtr<nsIChannel> channel(do_QueryInterface(request));
@@ -2070,16 +2079,22 @@ XMLHttpRequestMainThread::OnStopRequest(
 {
   AUTO_PROFILER_LABEL("XMLHttpRequestMainThread::OnStopRequest", NETWORK);
 
   if (request != mChannel) {
     // Can this still happen?
     return NS_OK;
   }
 
+  // Send the decoder the signal that we've hit the end of the stream,
+  // but only when parsing text (not XML, which does this already).
+  if (mDecoder && !mFlagParseBody) {
+    AppendToResponseText(nullptr, 0, true);
+  }
+
   mWaitingForOnStopRequest = false;
 
   if (mRequestObserver) {
     NS_ASSERTION(mFirstStartRequestSeen, "Inconsistent state!");
     mFirstStartRequestSeen = false;
     mRequestObserver->OnStopRequest(request, ctxt, status);
   }
 
@@ -2256,17 +2271,17 @@ XMLHttpRequestMainThread::OnBodyParseEnd
 
 void
 XMLHttpRequestMainThread::MatchCharsetAndDecoderToResponseDocument()
 {
   if (mResponseXML && mResponseCharset != mResponseXML->GetDocumentCharacterSet()) {
     mResponseCharset = mResponseXML->GetDocumentCharacterSet();
     TruncateResponseText();
     mResponseBodyDecodedPos = 0;
-    mDecoder = mResponseCharset->NewDecoderWithBOMRemoval();
+    mDecoder = mResponseCharset->NewDecoder();
   }
 }
 
 void
 XMLHttpRequestMainThread::ChangeStateToDone()
 {
   StopProgressEventTimer();
 
--- a/dom/xhr/XMLHttpRequestMainThread.h
+++ b/dom/xhr/XMLHttpRequestMainThread.h
@@ -475,17 +475,18 @@ public:
                           Blob* aBlob,
                           nsresult aResult) override;
 
   void
   LocalFileToBlobCompleted(Blob* aBlob);
 
 protected:
   nsresult DetectCharset();
-  nsresult AppendToResponseText(const char * aBuffer, uint32_t aBufferLen);
+  nsresult AppendToResponseText(const char * aBuffer, uint32_t aBufferLen,
+                                bool aLast = false);
   static nsresult StreamReaderFunc(nsIInputStream* in,
                                    void* closure,
                                    const char* fromRawSegment,
                                    uint32_t toOffset,
                                    uint32_t count,
                                    uint32_t *writeCount);
   nsresult CreateResponseParsedJSON(JSContext* aCx);
   // Change the state of the object with this. The broadcast argument
--- a/dom/xhr/tests/mochitest.ini
+++ b/dom/xhr/tests/mochitest.ini
@@ -62,16 +62,17 @@ support-files =
   worker_bug1300552.js
   sync_xhr_unload.sjs
   iframe_sync_xhr_unload.html
   empty.html
   file_sync_xhr_document_write_with_iframe.html
   slow.sjs
   !/dom/events/test/event_leak_utils.js
 
+[test_bug1070763.html]
 [test_bug1300552.html]
 [test_html_in_xhr.html]
 [test_relativeLoad.html]
 [test_sync_xhr_timer.xhtml]
 skip-if = toolkit == 'android'
 [test_sync_xhr_unload.html]
 [test_temporaryFileBlob.html]
 [test_worker_terminateSyncXHR.html]
new file mode 100644
--- /dev/null
+++ b/dom/xhr/tests/test_bug1070763.html
@@ -0,0 +1,58 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1405571
+-->
+<head>
+  <title>XMLHttpRequest send data and headers</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank"
+   href="https://bugzilla.mozilla.org/show_bug.cgi?id=1405571">Mozilla Bug 1405571</a>
+<p id="display">
+</p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="application/javascript">
+SimpleTest.waitForExplicitFinish();
+
+const url = "http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.text";
+
+function runTest(testName, testFn) {
+  return new Promise(resolve => {
+    const xhr = new XMLHttpRequest();
+    xhr.onloadend = () => {
+      xhr.onloadend = null;
+      xhr.onreadystatechange = () => {
+        if (xhr.readyState === 1) {
+          testFn(xhr);
+        } else if (xhr.readyState === 4) {
+          ok(true, testName);
+          resolve();
+        }
+      };
+      xhr.open("GET", url);
+      xhr.send(null);
+    };
+    xhr.open("GET", url);
+    xhr.send(null);
+  });
+}
+
+async function runTests() {
+  await runTest("Abort #1", xhr => { xhr.abort() });
+  await runTest("Abort #2", xhr => { setTimeout(() => xhr.abort(), 0) });
+  await runTest("Timeout",  xhr => { xhr.timeout = 1 });
+  SimpleTest.finish();
+}
+
+runTests();
+
+</script>
+</pre>
+</body>
+</html>
--- a/js/public/Class.h
+++ b/js/public/Class.h
@@ -197,16 +197,17 @@ class ObjectOpResult
     JS_PUBLIC_API(bool) failCantSetInterposed();
     JS_PUBLIC_API(bool) failCantDefineWindowElement();
     JS_PUBLIC_API(bool) failCantDeleteWindowElement();
     JS_PUBLIC_API(bool) failCantDeleteWindowNamedProperty();
     JS_PUBLIC_API(bool) failCantPreventExtensions();
     JS_PUBLIC_API(bool) failCantSetProto();
     JS_PUBLIC_API(bool) failNoNamedSetter();
     JS_PUBLIC_API(bool) failNoIndexedSetter();
+    JS_PUBLIC_API(bool) failNotDataDescriptor();
 
     uint32_t failureCode() const {
         MOZ_ASSERT(!ok());
         return uint32_t(code_);
     }
 
     /*
      * Report an error or warning if necessary; return true to proceed and
--- a/js/src/js.msg
+++ b/js/src/js.msg
@@ -583,16 +583,17 @@ MSG_DEF(JSMSG_ATOMICS_WAIT_NOT_ALLOWED, 
 // XPConnect wrappers and DOM bindings
 MSG_DEF(JSMSG_CANT_SET_INTERPOSED,       1, JSEXN_TYPEERR, "unable to set interposed data property '{0}'")
 MSG_DEF(JSMSG_CANT_DEFINE_WINDOW_ELEMENT, 0, JSEXN_TYPEERR, "can't define elements on a Window object")
 MSG_DEF(JSMSG_CANT_DELETE_WINDOW_ELEMENT, 0, JSEXN_TYPEERR, "can't delete elements from a Window object")
 MSG_DEF(JSMSG_CANT_DELETE_WINDOW_NAMED_PROPERTY, 1, JSEXN_TYPEERR, "can't delete property {0} from window's named properties object")
 MSG_DEF(JSMSG_CANT_PREVENT_EXTENSIONS,   0, JSEXN_TYPEERR, "can't prevent extensions on this proxy object")
 MSG_DEF(JSMSG_NO_NAMED_SETTER,           2, JSEXN_TYPEERR, "{0} doesn't have a named property setter for '{1}'")
 MSG_DEF(JSMSG_NO_INDEXED_SETTER,         2, JSEXN_TYPEERR, "{0} doesn't have an indexed property setter for '{1}'")
+MSG_DEF(JSMSG_NOT_DATA_DESCRIPTOR,       2, JSEXN_TYPEERR, "can't define a getter/setter for element '{1}' of {0} object")
 
 // Super
 MSG_DEF(JSMSG_CANT_DELETE_SUPER, 0, JSEXN_REFERENCEERR, "invalid delete involving 'super'")
 MSG_DEF(JSMSG_REINIT_THIS,       0, JSEXN_REFERENCEERR, "super() called twice in derived class constructor")
 
 // Modules
 MSG_DEF(JSMSG_BAD_DEFAULT_EXPORT,        0, JSEXN_SYNTAXERR, "default export cannot be provided by export *")
 MSG_DEF(JSMSG_MISSING_INDIRECT_EXPORT,   0, JSEXN_SYNTAXERR, "indirect export not found")
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -274,16 +274,22 @@ JS::ObjectOpResult::failNoNamedSetter()
 }
 
 JS_PUBLIC_API(bool)
 JS::ObjectOpResult::failNoIndexedSetter()
 {
     return fail(JSMSG_NO_INDEXED_SETTER);
 }
 
+JS_PUBLIC_API(bool)
+JS::ObjectOpResult::failNotDataDescriptor()
+{
+    return fail(JSMSG_NOT_DATA_DESCRIPTOR);
+}
+
 JS_PUBLIC_API(int64_t)
 JS_Now()
 {
     return PRMJ_Now();
 }
 
 JS_PUBLIC_API(Value)
 JS_GetNaNValue(JSContext* cx)
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -1785,78 +1785,112 @@ nsBlockFrame::ComputeFinalSize(const Ref
     printf(": WARNING: desired:%d,%d\n", aMetrics.Width(), aMetrics.Height());
   }
 #endif
 }
 
 static void
 ConsiderBlockEndEdgeOfChildren(const WritingMode aWritingMode,
                                nscoord aBEndEdgeOfChildren,
-                               nsOverflowAreas& aOverflowAreas)
+                               nsOverflowAreas& aOverflowAreas,
+                               const nsStyleDisplay* aDisplay)
 {
   // Factor in the block-end edge of the children.  Child frames will be added
   // to the overflow area as we iterate through the lines, but their margins
   // won't, so we need to account for block-end margins here.
   // REVIEW: For now, we do this for both visual and scrollable area,
   // although when we make scrollable overflow area not be a subset of
   // visual, we can change this.
   // XXX Currently, overflow areas are stored as physical rects, so we have
   // to handle writing modes explicitly here. If we change overflow rects
   // to be stored logically, this can be simplified again.
   if (aWritingMode.IsVertical()) {
     if (aWritingMode.IsVerticalLR()) {
       NS_FOR_FRAME_OVERFLOW_TYPES(otype) {
-        nsRect& o = aOverflowAreas.Overflow(otype);
-        o.width = std::max(o.XMost(), aBEndEdgeOfChildren) - o.x;
+        if (!(aDisplay->IsContainLayout() && otype == eScrollableOverflow)) {
+          // Layout containment should force all overflow to be ink (visual)
+          // overflow, so if we're layout-contained, we only add our children's
+          // block-end edge to the ink (visual) overflow -- not to the
+          // scrollable overflow.
+          nsRect& o = aOverflowAreas.Overflow(otype);
+          o.width = std::max(o.XMost(), aBEndEdgeOfChildren) - o.x;
+        }
       }
     } else {
       NS_FOR_FRAME_OVERFLOW_TYPES(otype) {
-        nsRect& o = aOverflowAreas.Overflow(otype);
-        nscoord xmost = o.XMost();
-        o.x = std::min(o.x, xmost - aBEndEdgeOfChildren);
-        o.width = xmost - o.x;
+        if (!(aDisplay->IsContainLayout() && otype == eScrollableOverflow)) {
+          nsRect& o = aOverflowAreas.Overflow(otype);
+          nscoord xmost = o.XMost();
+          o.x = std::min(o.x, xmost - aBEndEdgeOfChildren);
+          o.width = xmost - o.x;
+        }
       }
     }
   } else {
     NS_FOR_FRAME_OVERFLOW_TYPES(otype) {
-      nsRect& o = aOverflowAreas.Overflow(otype);
-      o.height = std::max(o.YMost(), aBEndEdgeOfChildren) - o.y;
+      if (!(aDisplay->IsContainLayout() && otype == eScrollableOverflow)) {
+        nsRect& o = aOverflowAreas.Overflow(otype);
+        o.height = std::max(o.YMost(), aBEndEdgeOfChildren) - o.y;
+      }
     }
   }
 }
 
 void
 nsBlockFrame::ComputeOverflowAreas(const nsRect&         aBounds,
                                    const nsStyleDisplay* aDisplay,
                                    nscoord               aBEndEdgeOfChildren,
                                    nsOverflowAreas&      aOverflowAreas)
 {
   // Compute the overflow areas of our children
   // XXX_perf: This can be done incrementally.  It is currently one of
   // the things that makes incremental reflow O(N^2).
   nsOverflowAreas areas(aBounds, aBounds);
+  if (mComputedStyle->GetPseudo() == nsCSSAnonBoxes::scrolledContent &&
+      mParent->StyleDisplay()->IsContainLayout()) {
+    // If we are a scrollframe's inner anonymous box and our parent
+    // has layout containment, we want to pass our parent's style to
+    // ConsiderBlockEndEdgeOfChildren to make sure all overflow from the
+    // layout contained element is processed as ink (visual) overflow.
+    aDisplay = mParent->StyleDisplay();
+  }
   if (!ShouldApplyOverflowClipping(this, aDisplay)) {
     for (LineIterator line = LinesBegin(), line_end = LinesEnd();
          line != line_end;
          ++line) {
-      areas.UnionWith(line->GetOverflowAreas());
+      if (aDisplay->IsContainLayout()) {
+        // If we have layout containment (or, per above, we are a scrollframe's
+        // inner anonymous box and our parent has layout containment), we should
+        // only consider our child's visual overflow, leaving the scrollable
+        // regions of the parent unaffected.
+        // Note: scrollable overflow is a subset of visual overflow,
+        // so this has the same affect as unioning the child's visual and
+        // scrollable overflow with its parent's visual overflow.
+        nsRect childVisualRect = line->GetVisualOverflowArea();
+        nsOverflowAreas childVisualArea = nsOverflowAreas(
+          childVisualRect,
+          nsRect());
+        areas.UnionWith(childVisualArea);
+      } else {
+        areas.UnionWith(line->GetOverflowAreas());
+      }
     }
 
     // Factor an outside bullet in; normally the bullet will be factored into
     // the line-box's overflow areas. However, if the line is a block
     // line then it won't; if there are no lines, it won't. So just
     // factor it in anyway (it can't hurt if it was already done).
     // XXXldb Can we just fix GetOverflowArea instead?
     nsIFrame* outsideBullet = GetOutsideBullet();
     if (outsideBullet) {
       areas.UnionAllWith(outsideBullet->GetRect());
     }
 
     ConsiderBlockEndEdgeOfChildren(GetWritingMode(),
-                                   aBEndEdgeOfChildren, areas);
+                                   aBEndEdgeOfChildren, areas, aDisplay);
   }
 
 #ifdef NOISY_COMBINED_AREA
   ListTag(stdout);
   const nsRect& vis = areas.VisualOverflow();
   printf(": VisualOverflowArea CA=%d,%d,%d,%d\n", vis.x, vis.y, vis.width, vis.height);
   const nsRect& scr = areas.ScrollableOverflow();
   printf(": ScrollableOverflowArea CA=%d,%d,%d,%d\n", scr.x, scr.y, scr.width, scr.height);
@@ -1904,17 +1938,18 @@ nsBlockFrame::UnionChildOverflow(nsOverf
 bool
 nsBlockFrame::ComputeCustomOverflow(nsOverflowAreas& aOverflowAreas)
 {
   bool found;
   nscoord blockEndEdgeOfChildren =
     GetProperty(BlockEndEdgeOfChildrenProperty(), &found);
   if (found) {
     ConsiderBlockEndEdgeOfChildren(GetWritingMode(),
-                                   blockEndEdgeOfChildren, aOverflowAreas);
+                                   blockEndEdgeOfChildren, aOverflowAreas,
+                                   StyleDisplay());
   }
 
   // Line cursor invariants depend on the overflow areas of the lines, so
   // we must clear the line cursor since those areas may have changed.
   ClearLineCursor();
   return nsContainerFrame::ComputeCustomOverflow(aOverflowAreas);
 }
 
@@ -7052,22 +7087,23 @@ nsBlockFrame::Init(nsIContent*       aCo
   }
 
   // A display:flow-root box establishes a block formatting context.
   // If a box has a different block flow direction than its containing block:
   // ...
   //   If the box is a block container, then it establishes a new block
   //   formatting context.
   // (http://dev.w3.org/csswg/css-writing-modes/#block-flow)
-  // If the box has contain: paint (or contain: strict), then it should also
-  // establish a formatting context.
+  // If the box has contain: paint or contain:layout (or contain:strict),
+  // then it should also establish a formatting context.
   if (StyleDisplay()->mDisplay == mozilla::StyleDisplay::FlowRoot ||
       (GetParent() && StyleVisibility()->mWritingMode !=
                       GetParent()->StyleVisibility()->mWritingMode) ||
-      StyleDisplay()->IsContainPaint()) {
+      StyleDisplay()->IsContainPaint() ||
+      StyleDisplay()->IsContainLayout()) {
     AddStateBits(NS_BLOCK_FORMATTING_CONTEXT_STATE_BITS);
   }
 
   if ((GetStateBits() &
        (NS_FRAME_FONT_INFLATION_CONTAINER | NS_BLOCK_FLOAT_MGR)) ==
       (NS_FRAME_FONT_INFLATION_CONTAINER | NS_BLOCK_FLOAT_MGR)) {
     AddStateBits(NS_FRAME_FONT_INFLATION_FLOW_ROOT);
   }
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -9673,18 +9673,42 @@ nsIFrame::GetDepthInFrameTree() const
   }
   return result;
 }
 
 void
 nsFrame::ConsiderChildOverflow(nsOverflowAreas& aOverflowAreas,
                                nsIFrame* aChildFrame)
 {
-  aOverflowAreas.UnionWith(aChildFrame->GetOverflowAreas() +
-                           aChildFrame->GetPosition());
+  const nsStyleDisplay* display = StyleDisplay();
+  if (mComputedStyle->GetPseudo() == nsCSSAnonBoxes::scrolledContent) {
+    // If we are a scrollframe's inner anonymous box, we'll want to check if
+    // our parent has contain:layout below, so we change the nsStyleDisplay we
+    // read from here.
+    display = mParent->StyleDisplay();
+  }
+  if (display->IsContainLayout() && IsFrameOfType(eSupportsContainLayoutAndPaint)) {
+    // If we have layout containment and are not a non-atomic, inline-level
+    // principal box (or, if we are a scrollframe's inner anonymous box and
+    // our parent has layout containment) we should only consider our child's
+    // visual (ink) overflow, leaving the scrollable regions of the parent
+    // unaffected.
+    // Note: scrollable overflow is a subset of visual overflow,
+    // so this has the same affect as unioning the child's visual and
+    // scrollable overflow with the parent's visual overflow.
+    // XXX doesn't work correctly for floats - bug 1481951
+    nsRect childVisual = aChildFrame->GetVisualOverflowRect();
+    nsOverflowAreas combined = nsOverflowAreas(
+      childVisual,
+      nsRect());
+    aOverflowAreas.UnionWith(combined + aChildFrame->GetPosition());
+  } else {
+    aOverflowAreas.UnionWith(aChildFrame->GetOverflowAreas() +
+                             aChildFrame->GetPosition());
+  }
 }
 
 bool
 nsFrame::ShouldAvoidBreakInside(const ReflowInput& aReflowInput) const
 {
   const auto* disp = StyleDisplay();
   return !aReflowInput.mFlags.mIsTopOfPage &&
     NS_STYLE_PAGE_BREAK_AVOID == disp->mBreakInside &&
@@ -10946,16 +10970,17 @@ nsIFrame::IsStackingContext(EffectSet* a
                             const nsStyleDisplay* aStyleDisplay,
                             const nsStylePosition* aStylePosition,
                             const nsStyleEffects* aStyleEffects,
                             bool aIsPositioned)
 {
   return HasOpacity(aEffectSet) ||
          IsTransformed(aStyleDisplay) ||
          aStyleDisplay->IsContainPaint() ||
+         aStyleDisplay->IsContainLayout() ||
          // strictly speaking, 'perspective' doesn't require visual atomicity,
          // but the spec says it acts like the rest of these
          ChildrenHavePerspective(aStyleDisplay) ||
          aStyleEffects->mMixBlendMode != NS_STYLE_BLEND_NORMAL ||
          nsSVGIntegrationUtils::UsingEffectsForFrame(this) ||
          (aIsPositioned && (aStyleDisplay->IsPositionForcingStackingContext() ||
                             aStylePosition->mZIndex.GetUnit() == eStyleUnit_Integer)) ||
          (aStyleDisplay->mWillChangeBitField & NS_STYLE_WILL_CHANGE_STACKING_CONTEXT) ||
copy from layout/reftests/w3c-css/submitted/contain/contain-paint-containing-block-absolute-001.html
copy to layout/reftests/w3c-css/submitted/contain/contain-layout-containing-block-absolute-001.html
--- a/layout/reftests/w3c-css/submitted/contain/contain-paint-containing-block-absolute-001.html
+++ b/layout/reftests/w3c-css/submitted/contain/contain-layout-containing-block-absolute-001.html
@@ -1,19 +1,20 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <meta charset="utf-8">
-  <title>CSS Test: 'contain: paint' element should contain absolute position elements.</title>
+  <title>CSS Test: 'contain: layout' element should contain absolute position elements.</title>
   <link rel="author" title="Kyle Zentner" href="mailto:zentner.kyle@gmail.com">
-  <link rel="help" href="http://www.w3.org/TR/css-containment-1/#containment-paint">
+  <link rel="author" title="Morgan Rae Reschenberg" href="mailto:mreschenberg@berkeley.edu">
+  <link rel="help" href="https://drafts.csswg.org/css-contain-1/#containment-layout">
   <link rel="match" href="contain-paint-containing-block-absolute-001-ref.html">
   <style>
   #a {
-      contain: paint;
+      contain: layout;
       width: 100px;
       height: 100px;
       background: red;
       margin: 50px;
   }
   #b {
       position: absolute;
       top: 0;
copy from layout/reftests/w3c-css/submitted/contain/contain-paint-containing-block-fixed-001.html
copy to layout/reftests/w3c-css/submitted/contain/contain-layout-containing-block-fixed-001.html
--- a/layout/reftests/w3c-css/submitted/contain/contain-paint-containing-block-fixed-001.html
+++ b/layout/reftests/w3c-css/submitted/contain/contain-layout-containing-block-fixed-001.html
@@ -1,19 +1,20 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <meta charset="utf-8">
-  <title>CSS Test: 'contain: paint' element should contain fixed position elements.</title>
+  <title>CSS Test: 'contain: layout' element should contain fixed position elements.</title>
   <link rel="author" title="Kyle Zentner" href="mailto:zentner.kyle@gmail.com">
-  <link rel="help" href="http://www.w3.org/TR/css-containment-1/#containment-paint">
+  <link rel="author" title="Morgan Rae Reschenberg" href="mailto:mreschenberg@berkeley.edu">
+  <link rel="help" href="https://drafts.csswg.org/css-contain-1/#containment-layout">
   <link rel="match" href="contain-paint-containing-block-fixed-001-ref.html">
   <style>
   #a {
-      contain: paint;
+      contain: layout;
       width: 100px;
       height: 100px;
       background: red;
       margin: 50px;
   }
   #b {
       position: fixed;
       top: 0;
copy from layout/reftests/w3c-css/submitted/contain/contain-paint-formatting-context-float-001.html
copy to layout/reftests/w3c-css/submitted/contain/contain-layout-formatting-context-float-001.html
--- a/layout/reftests/w3c-css/submitted/contain/contain-paint-formatting-context-float-001.html
+++ b/layout/reftests/w3c-css/submitted/contain/contain-layout-formatting-context-float-001.html
@@ -1,25 +1,26 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <meta charset="utf-8">
-  <title>CSS Test: 'contain: paint' should contain floats as a formatting context.</title>
+  <title>CSS Test: 'contain: layout' should contain floats as a formatting context.</title>
   <link rel="author" title="Kyle Zentner" href="mailto:zentner.kyle@gmail.com">
-  <link rel="help" href="http://www.w3.org/TR/css-containment-1/#containment-paint">
+  <link rel="author" title="Morgan Rae Reschenberg" href="mailto:mreschenberg@berkeley.edu">
+  <link rel="help" href="http://www.w3.org/TR/css-containment-1/#containment-layout">
   <link rel="match" href="contain-paint-formatting-context-float-001-ref.html">
   <style>
   #left {
     float: left;
     height: 50px;
     width: 10px;
     background: blue;
   }
   #a {
-    contain: paint;
+    contain: layout;
     background: red;
     margin: 10px;
     width: 50px;
     height: 50px;
   }
   #b {
     clear: left;
     width: 50px;
copy from layout/reftests/w3c-css/submitted/contain/contain-paint-formatting-context-margin-001-ref.html
copy to layout/reftests/w3c-css/submitted/contain/contain-layout-formatting-context-margin-001-ref.html
--- a/layout/reftests/w3c-css/submitted/contain/contain-paint-formatting-context-margin-001-ref.html
+++ b/layout/reftests/w3c-css/submitted/contain/contain-layout-formatting-context-margin-001-ref.html
@@ -1,30 +1,37 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <meta charset="utf-8">
   <title>CSS Reftest Test</title>
   <link rel="author" title="Kyle Zentner" href="mailto:zentner.kyle@gmail.com">
+  <link rel="author" title="Morgan Rae Reschenberg" href="mailto:mreschenberg@berkeley.edu">
   <style>
   #a {
       background: blue;
       margin: 10px;
       width: 50px;
       height: 50px;
   }
   #b {
       width: 50px;
       height: 40px;
       background: green;
   }
   #b-padding {
       height: 10px;
   }
+  #c {
+    width: 50px;
+    height: 10px;
+    background: lightblue;
+  }
   </style>
 </head>
 <body>
   <div id="a">
     <div id="b-padding"></div>
     <div id="b"></div>
+    <div id="c"></div>
   </div>
 </body>
 </html>
copy from layout/reftests/w3c-css/submitted/contain/contain-paint-formatting-context-margin-001.html
copy to layout/reftests/w3c-css/submitted/contain/contain-layout-formatting-context-margin-001.html
--- a/layout/reftests/w3c-css/submitted/contain/contain-paint-formatting-context-margin-001.html
+++ b/layout/reftests/w3c-css/submitted/contain/contain-layout-formatting-context-margin-001.html
@@ -1,32 +1,33 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <meta charset="utf-8">
-  <title>CSS Test: 'contain: paint' with a vertical margin child. Margin collapse should not occur.</title>
+  <title>CSS Test: 'contain: layout' with a vertical margin child. Margin collapse should not occur, and neither should overflow clipping.</title>
   <link rel="author" title="Kyle Zentner" href="mailto:zentner.kyle@gmail.com">
-  <link rel="help" href="http://www.w3.org/TR/css-containment-1/#containment-paint">
+  <link rel="author" title="Morgan Rae Reschenberg" href="mailto:mreschenberg@berkeley.edu">
+  <link rel="help" href="http://www.w3.org/TR/css-containment-1/#containment-layout">
   <link rel="match" href="contain-paint-formatting-context-margin-001-ref.html">
   <style>
   #a {
-      contain: paint;
+      contain:layout;
       background: blue;
       margin: 10px;
       width: 50px;
       height: 50px;
   }
   #b {
       width: 50px;
       height: 40px;
       background: green;
       margin-top: 10px;
   }
   #c {
-      background: red;
+      background: lightblue;
       width: 50px;
       height: 10px;
   }
   </style>
 </head>
 <body>
   <div id="a">
     <div id="b"></div>
copy from layout/reftests/w3c-css/submitted/contain/contain-paint-ignored-cases-no-principal-box-001.html
copy to layout/reftests/w3c-css/submitted/contain/contain-layout-ignored-cases-no-principal-box-001.html
--- a/layout/reftests/w3c-css/submitted/contain/contain-paint-ignored-cases-no-principal-box-001.html
+++ b/layout/reftests/w3c-css/submitted/contain/contain-layout-ignored-cases-no-principal-box-001.html
@@ -1,33 +1,33 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <meta charset="utf-8">
-  <title>CSS Test: 'contain: paint' with 'display: contents'.</title>
+  <title>CSS Test: 'contain: layout' should not create a stacking context when no principle box is generated.</title>
   <link rel="author" title="Yusuf Sermet" href="mailto:ysermet@mozilla.com">
-  <link rel="help" href="https://drafts.csswg.org/css-contain/#containment-paint">
+  <link rel="author" title="Morgan Rae Reschenberg" href="mailto:mreschenberg@berkeley.edu">
+  <link rel="help" href="https://drafts.csswg.org/css-contain/#containment-layout">
   <link rel="match" href="contain-paint-ignored-cases-no-principal-box-001-ref.html">
-  <meta name="assert" content="Contain:paint should have no effect when no principle box is generated.">
   <style>
     div {
       position: relative;
       width: 100px;
     }
     #div1,
     #div3 {
       background-color: #cfc;
       height: 100px;
     }
     #div1 {
       z-index: 5;
     }
     #div2 {
       display: contents;
-      contain: paint;
+      contain: layout;
       background-color: #fdd;
       height: 100px;
       top: -20px;
     }
     #div2_1 {
       background-color: #ffc;
       z-index: 6;
       top: -10px;
copy from layout/reftests/w3c-css/submitted/contain/contain-paint-containing-block-absolute-001-ref.html
copy to layout/reftests/w3c-css/submitted/contain/contain-layout-ignored-cases-no-principal-box-002-ref.html
--- a/layout/reftests/w3c-css/submitted/contain/contain-paint-containing-block-absolute-001-ref.html
+++ b/layout/reftests/w3c-css/submitted/contain/contain-layout-ignored-cases-no-principal-box-002-ref.html
@@ -1,19 +1,33 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <meta charset="utf-8">
   <title>CSS Reftest Reference</title>
   <link rel="author" title="Kyle Zentner" href="mailto:zentner.kyle@gmail.com">
+  <link rel="author" title="Morgan Rae Reschenberg" href="mailto:mreschenberg@berkeley.edu">
   <style>
   #a {
+      display: contents;
       width: 100px;
       height: 100px;
       background: green;
       margin: 50px;
   }
+ #b {
+      position: absolute;
+      top: 0;
+      left: 0;
+      width: 100px;
+      height: 100px;
+      background: green;
+  }
   </style>
 </head>
 <body>
-  <div id="a"></div>
+  <div id="a">
+    <div>
+      <div id="b"></div>
+    </div>
+  </div>
 </body>
-</html>
+</html>
\ No newline at end of file
copy from layout/reftests/w3c-css/submitted/contain/contain-paint-containing-block-absolute-001.html
copy to layout/reftests/w3c-css/submitted/contain/contain-layout-ignored-cases-no-principal-box-002.html
--- a/layout/reftests/w3c-css/submitted/contain/contain-paint-containing-block-absolute-001.html
+++ b/layout/reftests/w3c-css/submitted/contain/contain-layout-ignored-cases-no-principal-box-002.html
@@ -1,19 +1,21 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <meta charset="utf-8">
-  <title>CSS Test: 'contain: paint' element should contain absolute position elements.</title>
-  <link rel="author" title="Kyle Zentner" href="mailto:zentner.kyle@gmail.com">
-  <link rel="help" href="http://www.w3.org/TR/css-containment-1/#containment-paint">
-  <link rel="match" href="contain-paint-containing-block-absolute-001-ref.html">
+  <title>CSS Test: 'contain: layout' element should not contain absolute/fixed position elements when no principal box is generated.</title>
+  <link rel="author" title="Yusuf Sermet" href="mailto:ysermet@mozilla.com">
+  <link rel="author" title="Morgan Rae Reschenberg" href="mailto:mreschenberg@berkeley.edu">
+  <link rel="help" href="https://drafts.csswg.org/css-contain-1/#containment-layout">
+  <link rel="match" href="contain-layout-ignored-cases-no-principal-box-002-ref.html">
   <style>
   #a {
-      contain: paint;
+      contain: layout;
+      display: contents;
       width: 100px;
       height: 100px;
       background: red;
       margin: 50px;
   }
   #b {
       position: absolute;
       top: 0;
copy from layout/reftests/w3c-css/submitted/contain/contain-paint-containing-block-fixed-001-ref.html
copy to layout/reftests/w3c-css/submitted/contain/contain-layout-ignored-cases-no-principal-box-003-ref.html
--- a/layout/reftests/w3c-css/submitted/contain/contain-paint-containing-block-fixed-001-ref.html
+++ b/layout/reftests/w3c-css/submitted/contain/contain-layout-ignored-cases-no-principal-box-003-ref.html
@@ -1,19 +1,33 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <meta charset="utf-8">
   <title>CSS Reftest Reference</title>
   <link rel="author" title="Kyle Zentner" href="mailto:zentner.kyle@gmail.com">
+  <link rel="author" title="Morgan Rae Reschenberg" href="mailto:mreschenberg@berkeley.edu">
   <style>
   #a {
-      width: 100px;
-      height: 100px;
-      background: green;
-      margin: 50px;
+    display: contents;
+    width: 100px;
+    height: 100px;
+    background: red;
+    margin: 50px;
+  }
+  #b {
+    position: fixed;
+    top: 0;
+    left: 0;
+    width: 100px;
+    height: 100px;
+    background: green;
   }
   </style>
 </head>
 <body>
-  <div id="a"></div>
+  <div id="a">
+    <div>
+      <div id="b"></div>
+    </div>
+  </div>
 </body>
 </html>
copy from layout/reftests/w3c-css/submitted/contain/contain-paint-containing-block-fixed-001.html
copy to layout/reftests/w3c-css/submitted/contain/contain-layout-ignored-cases-no-principal-box-003.html
--- a/layout/reftests/w3c-css/submitted/contain/contain-paint-containing-block-fixed-001.html
+++ b/layout/reftests/w3c-css/submitted/contain/contain-layout-ignored-cases-no-principal-box-003.html
@@ -1,31 +1,33 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <meta charset="utf-8">
-  <title>CSS Test: 'contain: paint' element should contain fixed position elements.</title>
-  <link rel="author" title="Kyle Zentner" href="mailto:zentner.kyle@gmail.com">
-  <link rel="help" href="http://www.w3.org/TR/css-containment-1/#containment-paint">
-  <link rel="match" href="contain-paint-containing-block-fixed-001-ref.html">
+  <title>CSS Test: 'contain: layout' element should not contain absolute/fixed position elements when no principal box is generated.</title>
+  <link rel="author" title="Yusuf Sermet" href="mailto:ysermet@mozilla.com">
+  <link rel="author" title="Morgan Rae Reschenberg" href="mailto:mreschenberg@berkeley.edu">
+  <link rel="help" href="https://drafts.csswg.org/css-contain-1/#containment-layout">
+  <link rel="match" href="contain-layout-ignored-cases-no-principal-box-003-ref.html">
   <style>
   #a {
-      contain: paint;
-      width: 100px;
-      height: 100px;
-      background: red;
-      margin: 50px;
+    contain: layout;
+    display: contents;
+    width: 100px;
+    height: 100px;
+    background: red;
+    margin: 50px;
   }
   #b {
-      position: fixed;
-      top: 0;
-      left: 0;
-      width: 100px;
-      height: 100px;
-      background: green;
+    position: fixed;
+    top: 0;
+    left: 0;
+    width: 100px;
+    height: 100px;
+    background: green;
   }
   </style>
 </head>
 <body>
   <div id="a">
     <div>
       <div id="b"></div>
     </div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/w3c-css/submitted/contain/contain-layout-overflow-001-ref.html
@@ -0,0 +1,60 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>CSS Reftest Reference</title>
+  <link rel="author" title="Morgan Rae Reschenberg" href="mailto:mreschenberg@berkeley.edu">
+  <style>
+  .outer {
+    height: 100px;
+    width: 100px;
+  }
+  .auto {
+    overflow: auto;
+  }
+  .inner-sm {
+    height: 50px;
+    width: 50px;
+    background: lightblue;
+  }
+  .inner-md {
+    height: 100px;
+    width: 100px;
+    background: lightblue;
+  }
+  .inner-lg-1 {
+    height: 95px;
+    width: 95px;
+    background: lightblue;
+  }
+  .inner-lg-2 {
+    height: 200px;
+    width: 200px;
+  }
+  .pass {
+    background: green;
+  }
+  .border {
+    border: 5px solid green;
+  }
+
+  </style>
+</head>
+<body>
+  <div class="outer">
+    <div class="inner-sm"></div>
+  </div>
+  <br>
+
+  <div class="outer auto">
+    <div class="inner-lg-2 pass">
+    </div>
+  </div>
+  <br>
+
+  <div class="inner-sm border">
+    <div class="inner-lg-1">
+    </div>
+  </div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/w3c-css/submitted/contain/contain-layout-overflow-001.html
@@ -0,0 +1,71 @@
+
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>CSS Test: 'contain: layout' should force all overflow to be ink overflow.</title>
+  <link rel="author" title="Morgan Rae Reschenberg" href="mailto:mreschenberg@berkeley.edu">
+  <link rel="help" href="https://drafts.csswg.org/css-contain/#containment-layout">
+  <link rel="match" href="contain-layout-overflow-001-ref.html">
+  <style>
+  .contain {
+    contain: layout;
+  }
+  .outer {
+    height: 100px;
+    width: 100px;
+  }
+  .auto {
+    overflow: auto;
+  }
+  .inner-sm {
+    height: 50px;
+    width: 50px;
+    background: lightblue;
+  }
+  .inner-md {
+    height: 100px;
+    width: 100px;
+    background: lightblue;
+  }
+  .inner-lg {
+    height: 200px;
+    width: 200px;
+    background: lightblue;
+  }
+  .pass {
+    background: green;
+  }
+  .fail {
+    background: red;
+  }
+  .border {
+    border: 5px solid green;
+  }
+  </style>
+</head>
+<body>
+  <!--CSS Test: Elements with contain:layout that do not produce scrollable overflow should paint as if containment were not applied. -->
+  <div class="outer">
+    <div class="inner-sm contain"></div>
+  </div>
+  <br>
+
+  <!--CSS Test: Layout-contained elements that overflow their container and have children who overflow should produce the same amount of scrollable overflow as if there were no children. -->
+  <div class="outer auto">
+    <div class="inner-lg contain">
+      <div class="inner-lg pass"></div>
+      <div class="inner-lg fail"></div>
+    </div>
+  </div>
+  <br>
+
+  <!--CSS Test: Layout-contained elements that do not overflow their container, but have children who overflow, should not allow their children to affect the scrollable overflow regions of their parent. -->
+  <div class="outer auto">
+    <div class="inner-sm contain border">
+      <div class="inner-lg">
+      </div>
+    </div>
+  </div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/w3c-css/submitted/contain/contain-layout-overflow-002-ref.html
@@ -0,0 +1,62 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>CSS Reftest Reference</title>
+  <link rel="author" title="Morgan Rae Reschenberg" href="mailto:mreschenberg@berkeley.edu">
+  <style>
+  .outer {
+    height: 100px;
+    width: 100px;
+  }
+  .auto {
+    overflow: auto;
+  }
+  .inner-sm {
+    height: 50px;
+    width: 50px;
+    background: lightblue;
+  }
+  .inner-md {
+    height: 100px;
+    width: 100px;
+    background: lightblue;
+  }
+  .inner-lg-1 {
+    height: 95px;
+    width: 95px;
+    float:left;
+    background: lightblue;
+  }
+  .inner-lg-2 {
+    height: 200px;
+    width: 200px;
+    float:left;
+  }
+  .pass {
+    background: green;
+  }
+  .border {
+    border: 5px solid green;
+  }
+
+  </style>
+</head>
+<body>
+  <div class="outer">
+    <div class="inner-sm" style="float:left;"></div>
+  </div>
+  <br>
+
+  <div class="outer auto">
+    <div class="inner-lg-2 pass">
+    </div>
+  </div>
+  <br>
+
+  <div class="inner-sm border">
+    <div class="inner-lg-1">
+    </div>
+  </div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/w3c-css/submitted/contain/contain-layout-overflow-002.html
@@ -0,0 +1,73 @@
+
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>CSS Test: 'contain: layout' should force all overflow to be ink overflow.</title>
+  <link rel="author" title="Morgan Rae Reschenberg" href="mailto:mreschenberg@berkeley.edu">
+  <link rel="help" href="https://drafts.csswg.org/css-contain/#containment-layout">
+  <link rel="match" href="contain-layout-overflow-002-ref.html">
+  <style>
+  .contain {
+    contain: layout;
+  }
+  .outer {
+    height: 100px;
+    width: 100px;
+  }
+  .auto {
+    overflow: auto;
+  }
+  .inner-sm {
+    height: 50px;
+    width: 50px;
+    background: lightblue;
+  }
+  .inner-md {
+    height: 100px;
+    width: 100px;
+    background: lightblue;
+  }
+  .inner-lg {
+    height: 200px;
+    width: 200px;
+    background: lightblue;
+    float: left;
+  }
+  .pass {
+    background: green;
+  }
+  .fail {
+    background: red;
+  }
+  .border {
+    border: 5px solid green;
+  }
+  </style>
+</head>
+<body>
+  <!--CSS Test: Elements with contain:layout that do not produce scrollable overflow should paint as if containment were not applied. -->
+  <div class="outer">
+    <div class="inner-sm contain" style="float:left;"></div>
+  </div>
+  <br>
+
+  <!--CSS Test: Layout-contained elements that overflow their container and have children who overflow should produce the same amount of scrollable overflow as if there were no children. -->
+  <div class="outer auto">
+    <div class="outer contain">
+      <div class="inner-lg pass"></div>
+      <div class="inner-lg fail"></div>
+    </div>
+  </div>
+  <br>
+
+
+  <!--CSS Test: Layout-contained elements that do not overflow their container, but have children who overflow, should not allow their children to affect the scrollable overflow regions of their parent. -->
+  <div class="outer auto">
+    <div class="inner-sm contain border">
+      <div class="inner-lg">
+      </div>
+    </div>
+  </div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/w3c-css/submitted/contain/contain-layout-stacking-context-001.html
@@ -0,0 +1,66 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>CSS Test: 'contain: layout' with stacking contents. Z-index is defined only for siblings and children.</title>
+  <link rel="author" title="Yusuf Sermet" href="mailto:ysermet@mozilla.com">
+  <link rel="author" title="Morgan Rae Reschenberg" href="mailto:mreschenberg@berkeley.edu">
+  <link rel="help" href="https://drafts.csswg.org/css2/visuren.html#x43">
+  <link rel="help" href="https://drafts.csswg.org/css-contain/#containment-layout">
+  <link rel="match" href="contain-paint-stacking-context-001-ref.html">
+  <style>
+    div {
+      position: relative;
+      width: 100px;
+    }
+    #div1,
+    #div3 {
+      background-color: #cfc;
+    }
+    #div1 {
+      z-index: 5;
+    }
+    #div2 {
+      contain: layout;
+      background-color: #fdd;
+      height: 100px;
+      top: -20px;
+    }
+    #div2_1 {
+      background-color: #ffc;
+      z-index: 6;
+      top: -10px;
+    }
+    #div2_2 {
+      z-index: 3;
+      position: absolute;
+      top: -15px;
+      width: 40px;
+      height: 100px;
+      background-color: #ddf;
+    }
+    #div3 {
+      z-index: 2;
+      top: -50px;
+    }
+  </style>
+</head>
+<body>
+  <div id="div1">
+    <br/><br/>
+  </div>
+
+  <div id="div2">
+    <div id="div2_1">
+      <br/><br/>
+    </div>
+
+    <div id="div2_2">
+    </div>
+  </div>
+
+  <div id="div3">
+    <br/><br/>
+  </div>
+</body>
+</html>
--- a/layout/reftests/w3c-css/submitted/contain/reftest.list
+++ b/layout/reftests/w3c-css/submitted/contain/reftest.list
@@ -22,9 +22,19 @@ pref(layout.css.overflow-clip-box.enable
 == contain-size-inline-block-001.html contain-size-inline-block-001-ref.html
 == contain-size-flex-001.html contain-size-flex-001-ref.html
 fuzzy-if(webrender&&winWidget,0-3,0-2) == contain-size-inline-flex-001.html contain-size-inline-flex-001-ref.html # bug 1474093
 == contain-size-multicol-001.html contain-size-multicol-001-ref.html
 == contain-size-fieldset-001.html contain-size-fieldset-001-ref.html
 == contain-size-fieldset-002.html contain-size-fieldset-002-ref.html
 == contain-size-multicol-002.html contain-size-multicol-002-ref.html
 == contain-size-multicol-003.html contain-size-multicol-003-ref.html
+== contain-layout-overflow-001.html contain-layout-overflow-001-ref.html
+fails == contain-layout-overflow-002.html contain-layout-overflow-002-ref.html # bug 1481951
 == contain-size-table-caption-001.html contain-size-table-caption-001-ref.html
+== contain-layout-stacking-context-001.html contain-paint-stacking-context-001-ref.html
+== contain-layout-formatting-context-float-001.html contain-paint-formatting-context-float-001-ref.html
+== contain-layout-formatting-context-margin-001.html contain-layout-formatting-context-margin-001-ref.html
+== contain-layout-containing-block-fixed-001.html contain-paint-containing-block-fixed-001-ref.html
+== contain-layout-containing-block-absolute-001.html contain-paint-containing-block-absolute-001-ref.html
+== contain-layout-ignored-cases-no-principal-box-001.html contain-paint-ignored-cases-no-principal-box-001-ref.html
+== contain-layout-ignored-cases-no-principal-box-002.html contain-layout-ignored-cases-no-principal-box-002-ref.html
+== contain-layout-ignored-cases-no-principal-box-003.html contain-layout-ignored-cases-no-principal-box-003-ref.html
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -2342,16 +2342,29 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
   }
 
   bool IsContainPaint() const {
     return (NS_STYLE_CONTAIN_PAINT & mContain) &&
            !IsInternalRubyDisplayType() &&
            !IsInternalTableStyleExceptCell();
   }
 
+  bool IsContainLayout() const {
+    // Note: The spec for layout containment says it should
+    // have no effect on non-atomic, inline-level boxes. We
+    // don't check for these here because we don't know
+    // what type of element is involved. Callers are
+    // responsible for checking if the box in question is
+    // non-atomic and inline-level, and creating an
+    // exemption as necessary.
+    return (NS_STYLE_CONTAIN_LAYOUT & mContain) &&
+            !IsInternalRubyDisplayType() &&
+            !IsInternalTableStyleExceptCell();
+  }
+
   bool IsContainSize() const {
     // Note: The spec for size containment says it should
     // have no effect on non-atomic, inline-level boxes. We
     // don't check for these here because we don't know
     // what type of element is involved. Callers are
     // responsible for checking if the box in question is
     // non-atomic and inline-level, and creating an
     // exemption as necessary.
--- a/layout/style/nsStyleStructInlines.h
+++ b/layout/style/nsStyleStructInlines.h
@@ -166,19 +166,17 @@ nsStyleDisplay::IsFixedPosContainingBloc
   }
 
   return aStyle.ThreadsafeStyleEffects()->HasFilters();
 }
 
 bool
 nsStyleDisplay::IsFixedPosContainingBlockForContainLayoutAndPaintSupportingFrames() const
 {
-  // FIXME (bug 1472919): 'contain: layout' should also establish a
-  // containing block for fixed and absolute positioned elements.
-  return IsContainPaint();
+  return IsContainPaint() || IsContainLayout();
 }
 
 bool
 nsStyleDisplay::IsFixedPosContainingBlockForTransformSupportingFrames() const
 {
   // NOTE: Any CSS properties that influence the output of this function
   // should have the FIXPOS_CB flag set on them.
   return HasTransformStyle() || HasPerspectiveStyle();
--- a/mobile/android/base/java/org/mozilla/gecko/firstrun/LastPanel.java
+++ b/mobile/android/base/java/org/mozilla/gecko/firstrun/LastPanel.java
@@ -18,21 +18,21 @@ import org.mozilla.gecko.Telemetry;
 import org.mozilla.gecko.TelemetryContract;
 
 public class LastPanel extends FirstrunPanel {
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstance) {
         final ViewGroup root = (ViewGroup) inflater.inflate(R.layout.firstrun_basepanel_checkable_fragment, container, false);
         final Bundle args = getArguments();
         if (args != null) {
-            final Bitmap image = args.getParcelable(FirstrunPagerConfig.KEY_IMAGE);
+            final int image = args.getInt(FirstrunPagerConfig.KEY_IMAGE);
             final String message = args.getString(FirstrunPagerConfig.KEY_MESSAGE);
             final String subtext = args.getString(FirstrunPagerConfig.KEY_SUBTEXT);
 
-            ((ImageView) root.findViewById(R.id.firstrun_image)).setImageBitmap(image);
+            ((ImageView) root.findViewById(R.id.firstrun_image)).setImageDrawable(getResources().getDrawable(image));
             ((TextView) root.findViewById(R.id.firstrun_text)).setText(message);
             ((TextView) root.findViewById(R.id.firstrun_subtext)).setText(subtext);
             ((TextView) root.findViewById(R.id.firstrun_link)).setText(R.string.firstrun_welcome_button_browser);
         }
 
         root.findViewById(R.id.firstrun_link).setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
--- a/mobile/android/base/java/org/mozilla/gecko/firstrun/SyncPanel.java
+++ b/mobile/android/base/java/org/mozilla/gecko/firstrun/SyncPanel.java
@@ -20,21 +20,21 @@ import org.mozilla.gecko.fxa.FxAccountCo
 import org.mozilla.gecko.fxa.activities.FxAccountWebFlowActivity;
 
 public class SyncPanel extends FirstrunPanel {
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstance) {
         final ViewGroup root = (ViewGroup) inflater.inflate(R.layout.firstrun_sync_fragment, container, false);
         final Bundle args = getArguments();
         if (args != null) {
-            final Bitmap image = args.getParcelable(FirstrunPagerConfig.KEY_IMAGE);
+            final int image = args.getInt(FirstrunPagerConfig.KEY_IMAGE);
             final String message = args.getString(FirstrunPagerConfig.KEY_MESSAGE);
             final String subtext = args.getString(FirstrunPagerConfig.KEY_SUBTEXT);
 
-            ((ImageView) root.findViewById(R.id.firstrun_image)).setImageBitmap(image);
+            ((ImageView) root.findViewById(R.id.firstrun_image)).setImageDrawable(getResources().getDrawable(image));
             ((TextView) root.findViewById(R.id.firstrun_text)).setText(message);
             ((TextView) root.findViewById(R.id.firstrun_subtext)).setText(subtext);
         }
 
         root.findViewById(R.id.welcome_account).setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
                 Telemetry.sendUIEvent(TelemetryContract.Event.ACTION, TelemetryContract.Method.BUTTON, "firstrun-sync");
--- a/mobile/android/components/FilePicker.js
+++ b/mobile/android/components/FilePicker.js
@@ -67,21 +67,18 @@ FilePicker.prototype = {
     if (aFilterMask & Ci.nsIFilePicker.filterText) {
       this.appendFilter("*.txt; *.text");
     }
 
     if (aFilterMask & Ci.nsIFilePicker.filterXML) {
       this.appendFilter("*.xml");
     }
 
-    if (aFilterMask & Ci.nsIFilePicker.xulFilter) {
+    if (aFilterMask & Ci.nsIFilePicker.filterXUL) {
       this.appendFilter("*.xul");
-    }
-
-    if (aFilterMask & Ci.nsIFilePicker.xulFilter) {
       this.appendFilter("..apps");
     }
   },
 
   appendFilter: function(title, filter) {
     if (this._extensionsFilter)
         this._extensionsFilter += ", ";
     this._extensionsFilter += filter;
--- a/mobile/android/components/ImageBlockingPolicy.js
+++ b/mobile/android/components/ImageBlockingPolicy.js
@@ -71,17 +71,17 @@ ImageBlockingPolicy.prototype = {
 
             // For imageset (img + srcset) the "srcset" is used even after we reset the "src" causing a loop.
             // We are given the final image URL anyway, so it's OK to just remove the "srcset" value.
             node.removeAttribute("srcset");
           }, 0);
         }
 
         // Reject any image that is not associated with a DOM element
-        return Ci.nsIContentPolicy.REJECT;
+        return Ci.nsIContentPolicy.REJECT_REQUEST;
       }
     }
 
     // Accept all other content types
     return Ci.nsIContentPolicy.ACCEPT;
   },
 
   shouldProcess: function(contentLocation, loadInfo, mimeTypeGuess) {
--- a/mobile/android/tests/browser/chrome/test_device_search_engine.html
+++ b/mobile/android/tests/browser/chrome/test_device_search_engine.html
@@ -49,17 +49,18 @@ Migrated from Robocop: https://bugzilla.
     SimpleTest.finish();
   }
 
 SimpleTest.registerCleanupFunction(function() {
     Services.obs.removeObserver(search_observer, "browser-search-engine-modified");
   });
   Services.obs.addObserver(search_observer, "browser-search-engine-modified");
   info("Loading search engine");
-  Services.search.addEngine("http://mochi.test:8888/chrome/mobile/android/tests/browser/chrome/devicesearch.xml", Ci.nsISearchEngine.DATA_XML, null, false);
+  Services.search.addEngine("http://mochi.test:8888/chrome/mobile/android/tests/browser/chrome/devicesearch.xml",
+                            null, null, false);
 
   </script>
 </head>
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=861164">Mozilla Bug 861164</a>
 <br>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1184186">Migrated from Robocop testDeviceSearchEngine</a>
 <p id="display"></p>
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -5890,18 +5890,19 @@ pref("general.document_open_conversion_d
 pref("dom.event.default_to_passive_touch_listeners", true);
 
 // Enable FastBlock?
 pref("browser.fastblock.enabled", false);
 // The timeout (ms) since navigation start, all tracker connections been made
 // after this timeout will be canceled.
 pref("browser.fastblock.timeout", 5000);
 
-// Disables clipboard reads and writes by default.
-pref("dom.events.asyncClipboard", false);
+// Enable clipboard readText() and writeText() by default
+pref("dom.events.asyncClipboard", true);
+// Disable clipboard read() and write() by default
 pref("dom.events.asyncClipboard.dataTransfer", false);
 // Should only be enabled in tests
 pref("dom.events.testing.asyncClipboard", false);
 
 #ifdef NIGHTLY_BUILD
 // Disable moz* APIs in DataTransfer
 pref("dom.datatransfer.mozAtAPIs", false);
 #else
--- a/old-configure.in
+++ b/old-configure.in
@@ -2701,31 +2701,31 @@ if test -n "$MOZ_ANGLE_RENDERER"; then
 
   if test -z "$CROSS_COMPILE"; then
     if test -z "MOZ_FOUND_A_D3D_COMPILER"; then
       AC_MSG_ERROR([Couldn't find an acceptable D3D compiler DLL.])
     fi
   fi
 fi # MOZ_ANGLE_RENDERER
 
-fi # COMPILE_ENVIRONMENT
-
-
 dnl ========================================================
 dnl Gamepad support
 dnl ========================================================
 
 dnl Moved gamepad platform check to moz.build, linux header check still needed here.
 if test "$OS_TARGET" = "Linux"; then
     MOZ_CHECK_HEADER([linux/joystick.h])
     if test "$ac_cv_header_linux_joystick_h" != "yes"; then
       AC_MSG_ERROR([Can't find header linux/joystick.h, needed for gamepad support. Please install Linux kernel headers.])
     fi
 fi
 
+fi # COMPILE_ENVIRONMENT
+
+
 dnl ========================================================
 dnl = Breakpad crash reporting (on by default on supported platforms)
 dnl ========================================================
 
 case $target in
 i?86-*-mingw*|x86_64-*-mingw*)
   MOZ_CRASHREPORTER=1
   ;;
--- a/python/mozbuild/mozbuild/backend/recursivemake.py
+++ b/python/mozbuild/mozbuild/backend/recursivemake.py
@@ -805,37 +805,73 @@ class RecursiveMakeBackend(CommonBackend
         #   they all end up rooting to nodes from the above category. But the
         #   way make works[1] is such that there can be benefits listing them
         #   as direct dependencies of the top recursion target, to somehow
         #   prioritize them.
         #   1. See bug 1262241 comment 5.
         compile_roots = [t for t, deps in self._compile_graph.iteritems()
                          if not deps or t not in all_compile_deps]
 
-        rule = root_deps_mk.create_rule(['recurse_compile'])
-        rule.add_dependencies(compile_roots)
-        for target, deps in sorted(self._compile_graph.items()):
-            if deps:
-                rule = root_deps_mk.create_rule([target])
-                rule.add_dependencies(deps)
+        def add_category_rules(category, roots, graph):
+            rule = root_deps_mk.create_rule(['recurse_%s' % category])
+            rule.add_dependencies(roots)
+            for target, deps in sorted(graph.items()):
+                if deps:
+                    rule = root_deps_mk.create_rule([target])
+                    rule.add_dependencies(deps)
+
+        non_default_roots = defaultdict(list)
+        non_default_graphs = defaultdict(lambda: OrderedDefaultDict(set))
+
+        default_root_dirs = set()
+        for root in compile_roots:
+            # If this is a non-default target, separate the root from the
+            # rest of the compile graph.
+            target_name = mozpath.basename(root)
+
+            if target_name not in ('target', 'host'):
+                non_default_roots[target_name].append(root)
+                compile_roots.remove(root)
+                non_default_graphs[target_name][root] = self._compile_graph[root]
+                del self._compile_graph[root]
+            else:
+                dir_name = mozpath.dirname(root)
+                default_root_dirs.add(dir_name)
+
+        # If a directory only contains non-default compile targets, we don't
+        # attempt to dump symbols there.
+        self._no_skip['syms'] &= default_root_dirs
+
+        add_category_rules('compile', compile_roots, self._compile_graph)
+        for category, graph in non_default_graphs.iteritems():
+            add_category_rules(category, non_default_roots[category], graph)
 
         root_mk = Makefile()
 
         # Fill root.mk with the convenience variables.
         for tier, filter in filters:
             all_dirs = self._traversal.traverse('', filter)
             root_mk.add_statement('%s_dirs := %s' % (tier, ' '.join(all_dirs)))
 
         # Need a list of compile targets because we can't use pattern rules:
         # https://savannah.gnu.org/bugs/index.php?42833
         root_mk.add_statement('compile_targets := %s' % ' '.join(sorted(
             set(self._compile_graph.keys()) | all_compile_deps)))
         root_mk.add_statement('syms_targets := %s' % ' '.join(sorted(
             set('%s/syms' % d for d in self._no_skip['syms']))))
 
+        root_mk.add_statement('non_default_tiers := %s' % ' '.join(sorted(
+            non_default_roots.keys())))
+
+        for category, graphs in non_default_graphs.iteritems():
+            category_dirs = [mozpath.dirname(target)
+                             for target in graphs.keys()]
+            root_mk.add_statement('%s_dirs := %s' % (category,
+                                                     ' '.join(category_dirs)))
+
         root_mk.add_statement('include root-deps.mk')
 
         with self._write_file(
                 mozpath.join(self.environment.topobjdir, 'root.mk')) as root:
             root_mk.dump(root, removal_guard=False)
 
         with self._write_file(
                 mozpath.join(self.environment.topobjdir, 'root-deps.mk')) as root_deps:
@@ -1247,27 +1283,39 @@ class RecursiveMakeBackend(CommonBackend
         for flag in per_source_flag.flags:
             backend_file.write('%s_FLAGS += %s\n' % (mozpath.basename(per_source_flag.file_name), flag))
 
     def _process_computed_flags(self, computed_flags, backend_file):
         for var, flags in computed_flags.get_flags():
             backend_file.write('COMPUTED_%s += %s\n' % (var,
                                                         ' '.join(make_quote(shell_quote(f)) for f in flags)))
 
+    def _process_non_default_target(self, libdef, target_name, backend_file):
+        backend_file.write("%s:: %s\n" % (libdef.output_category, target_name))
+        backend_file.write('MOZBUILD_NON_DEFAULT_TARGETS += %s\n' % target_name)
+
     def _process_shared_library(self, libdef, backend_file):
         backend_file.write_once('LIBRARY_NAME := %s\n' % libdef.basename)
         backend_file.write('FORCE_SHARED_LIB := 1\n')
         backend_file.write('IMPORT_LIBRARY := %s\n' % libdef.import_name)
         backend_file.write('SHARED_LIBRARY := %s\n' % libdef.lib_name)
         if libdef.soname:
             backend_file.write('DSO_SONAME := %s\n' % libdef.soname)
         if libdef.symbols_file:
             backend_file.write('SYMBOLS_FILE := %s\n' % libdef.symbols_file)
         if not libdef.cxx_link:
             backend_file.write('LIB_IS_C_ONLY := 1\n')
+        if libdef.output_category:
+            self._process_non_default_target(libdef, libdef.lib_name,
+                                             backend_file)
+            # Override the install rule target for this library. This is hacky,
+            # but can go away as soon as we start building libraries in their
+            # final location (bug 1459764).
+            backend_file.write('SHARED_LIBRARY_TARGET := %s\n' %
+                               libdef.output_category)
 
     def _process_static_library(self, libdef, backend_file):
         backend_file.write_once('LIBRARY_NAME := %s\n' % libdef.basename)
         backend_file.write('FORCE_STATIC_LIB := 1\n')
         backend_file.write('REAL_LIBRARY := %s\n' % libdef.lib_name)
         if libdef.no_expand_lib:
             backend_file.write('NO_EXPAND_LIBS := 1\n')
 
@@ -1278,26 +1326,31 @@ class RecursiveMakeBackend(CommonBackend
         # possible invocations of Cargo with this CARGO_TARGET_DIR.  Otherwise,
         # Cargo's dependency calculations don't work as we expect and we wind
         # up recompiling lots of things.
         target_dir = mozpath.join(backend_file.objdir, libdef.target_dir)
         target_dir = mozpath.normpath(target_dir)
         backend_file.write('CARGO_TARGET_DIR := %s\n' % target_dir)
         if libdef.features:
             backend_file.write('%s := %s\n' % (libdef.FEATURES_VAR, ' '.join(libdef.features)))
+        if libdef.output_category:
+            self._process_non_default_target(libdef, libdef.import_name, backend_file)
 
     def _process_host_library(self, libdef, backend_file):
         backend_file.write('HOST_LIBRARY_NAME = %s\n' % libdef.basename)
 
     def _process_host_shared_library(self, libdef, backend_file):
         backend_file.write('HOST_SHARED_LIBRARY = %s\n' % libdef.lib_name)
 
     def _build_target_for_obj(self, obj):
+        target_name = obj.KIND
+        if hasattr(obj, 'output_category') and obj.output_category:
+            target_name = obj.output_category
         return '%s/%s' % (mozpath.relpath(obj.objdir,
-            self.environment.topobjdir), obj.KIND)
+            self.environment.topobjdir), target_name)
 
     def _process_linked_libraries(self, obj, backend_file):
         def pretty_relpath(lib, name):
             return os.path.normpath(mozpath.join(mozpath.relpath(lib.objdir, obj.objdir),
                                                  name))
 
         topobjdir = mozpath.normsep(obj.topobjdir)
         # This will create the node even if there aren't any linked libraries.
--- a/python/mozbuild/mozbuild/backend/tup.py
+++ b/python/mozbuild/mozbuild/backend/tup.py
@@ -251,33 +251,39 @@ class TupBackend(CommonBackend):
             '*.inc',
             '*.msg',
             '*.py',
             '*.rs',
         )
 
         # These are 'group' dependencies - All rules that list these as an output
         # will be built before any rules that list this as an input.
-        self._installed_idls = '$(MOZ_OBJ_ROOT)/<installed-idls>'
-        self._installed_files = '$(MOZ_OBJ_ROOT)/<installed-files>'
-        self._rust_libs = '$(MOZ_OBJ_ROOT)/<rust-libs>'
+        self._installed_idls = self._output_group('installed-idls')
+        self._installed_files = self._output_group('installed-files')
+        self._rust_libs = self._output_group('rust-libs')
         # The preprocessor including source-repo.h and buildid.h creates
         # dependencies that aren't specified by moz.build and cause errors
         # in Tup. Express these as a group dependency.
-        self._early_generated_files = '$(MOZ_OBJ_ROOT)/<early-generated-files>'
+        self._early_generated_files = self._output_group('early-generated-files')
 
-        self._shlibs = '$(MOZ_OBJ_ROOT)/<shlibs>'
-        self._gtests = '$(MOZ_OBJ_ROOT)/<gtest>'
-        self._default_group = '$(MOZ_OBJ_ROOT)/<default>'
+        self._shlibs = self._output_group('shlibs')
+        self._default_group = self._output_group('default')
 
         self._rust_cmds = set()
 
         self._built_in_addons = set()
         self._built_in_addons_file = 'dist/bin/browser/chrome/browser/content/browser/built_in_addons.json'
 
+    def _output_group(self, label):
+        if label:
+            return '$(MOZ_OBJ_ROOT)/<%s>' % label
+
+    def _rust_output_group(self, label):
+        if label:
+            return self._output_group('rust-' + label)
 
     def _get_mozconfig_env(self, config):
         env = {}
         loader = MozconfigLoader(config.topsrcdir)
         mozconfig = loader.read_mozconfig(config.substs['MOZCONFIG'])
         make_extra = mozconfig['make_extra'] or []
         env = {}
         for line in make_extra:
@@ -338,18 +344,18 @@ class TupBackend(CommonBackend):
     def _lib_paths(self, objdir, libs):
         return [mozpath.relpath(mozpath.join(l.objdir, l.import_name), objdir)
                 for l in libs]
 
     def _gen_shared_library(self, backend_file):
         shlib = backend_file.shared_lib
 
         output_group = self._shlibs
-        if 'toolkit/library/gtest' in backend_file.objdir:
-            output_group = self._gtests
+        if shlib.output_category:
+            output_group = self._output_group(shlib.output_category)
 
         if shlib.cxx_link:
             mkshlib = (
                 [backend_file.environment.substs['CXX']] +
                 backend_file.local_flags['CXX_LDFLAGS']
             )
         else:
             mkshlib = (
@@ -366,26 +372,26 @@ class TupBackend(CommonBackend):
 
         objs, _, _, shared_libs, os_libs, static_libs = self._expand_libs(shlib)
         static_libs = self._lib_paths(backend_file.objdir, static_libs)
         shared_libs = self._lib_paths(backend_file.objdir, shared_libs)
 
         list_file_name = '%s.list' % shlib.name.replace('.', '_')
         list_file = self._make_list_file(backend_file.objdir, objs, list_file_name)
 
-        rust_linked = self._lib_paths(backend_file.objdir,
-                                      (l for l in backend_file.shared_lib.linked_libraries
-                                       if isinstance(l, RustLibrary)))
+        rust_linked = [l for l in backend_file.shared_lib.linked_libraries
+                       if isinstance(l, RustLibrary)]
 
         inputs = objs + static_libs + shared_libs
 
         extra_inputs = []
         if rust_linked:
-            extra_inputs = [self._rust_libs]
-            static_libs += rust_linked
+            extra_inputs = [self._rust_output_group(rust_linked[0].output_category) or
+                            self._rust_libs]
+            static_libs += self._lib_paths(backend_file.objdir, rust_linked)
 
         symbols_file = []
         if (shlib.symbols_file and
             backend_file.environment.substs.get('GCC_USE_GNU_LD')):
             inputs.append(shlib.symbols_file)
             symbols_file = ['-Wl,--version-script,%s' % shlib.symbols_file]
 
         cmd = (
@@ -734,17 +740,17 @@ class TupBackend(CommonBackend):
         if os.environ.get('MOZ_AUTOMATION'):
             # Build scripts generally read environment variables that are set
             # by cargo, however, some may rely on MOZ_AUTOMATION. We may need
             # to audit for others as well.
             env['MOZ_AUTOMATION'] = os.environ['MOZ_AUTOMATION']
 
         return env
 
-    def _gen_cargo_rules(self, backend_file, build_plan, cargo_env):
+    def _gen_cargo_rules(self, backend_file, build_plan, cargo_env, output_group):
         invocations = build_plan['invocations']
         processed = set()
 
         def get_libloading_outdir():
             for invocation in invocations:
                 if (invocation['package_name'] == 'libloading' and
                     invocation['outputs'][0].endswith('.rlib')):
                     return invocation['env']['OUT_DIR']
@@ -826,24 +832,24 @@ class TupBackend(CommonBackend):
                 # The two rust libraries in the tree share many prerequisites,
                 # so we need to prune common dependencies and therefore build
                 # all rust from the same Tupfile.
                 rust_backend_file = self._get_backend_file('toolkit/library/rust')
                 rust_backend_file.rule(
                     command,
                     inputs=sorted(inputs),
                     outputs=outputs,
-                    output_group=self._rust_libs,
+                    output_group=output_group,
                     extra_inputs=[self._installed_files],
                     display='%s %s' % (header, display_name(invocation)),
                     check_unchanged=check_unchanged,
                 )
 
                 for dst, link in invocation['links'].iteritems():
-                    rust_backend_file.symlink_rule(link, dst, self._rust_libs)
+                    rust_backend_file.symlink_rule(link, dst, output_group)
 
         for val in enumerate(invocations):
             _process(*val)
 
 
     def _gen_rust_rules(self, obj, backend_file):
         cargo_flags = self._get_cargo_flags(obj)
         cargo_env = self._get_cargo_env(obj, backend_file)
@@ -857,17 +863,20 @@ class TupBackend(CommonBackend):
             line_handler=accumulate_output,
             ensure_exit_code=False,
             explicit_env=cargo_env)
         if cargo_status:
             raise Exception("cargo --build-plan failed with output:\n%s" %
                             '\n'.join(output_lines))
 
         cargo_plan = json.loads(''.join(output_lines))
-        self._gen_cargo_rules(backend_file, cargo_plan, cargo_env)
+
+        self._gen_cargo_rules(backend_file, cargo_plan, cargo_env,
+                              self._rust_output_group(obj.output_category) or
+                              self._rust_libs)
         self.backend_input_files |= set(cargo_plan['inputs'])
 
 
     def _process_generated_file(self, backend_file, obj):
         if obj.script and obj.method:
             backend_file.export_shell()
             cmd = self._py_action('file_generate')
             if obj.localized:
--- a/python/mozbuild/mozbuild/frontend/context.py
+++ b/python/mozbuild/mozbuild/frontend/context.py
@@ -1547,16 +1547,28 @@ VARIABLES = {
 
     'SHARED_LIBRARY_NAME': (unicode, unicode,
         """The name of the static library generated for a directory, if it needs to
         differ from the library code name.
 
         Implies FORCE_SHARED_LIB.
         """),
 
+    'SHARED_LIBRARY_OUTPUT_CATEGORY': (unicode, unicode,
+        """The output category for this context's shared library. If set this will
+        correspond to the build command that will build this shared library, and
+        the library will not be built as part of the default build.
+        """),
+
+    'RUST_LIBRARY_OUTPUT_CATEGORY': (unicode, unicode,
+        """The output category for this context's rust library. If set this will
+        correspond to the build command that will build this rust library, and
+        the library will not be built as part of the default build.
+        """),
+
     'IS_FRAMEWORK': (bool, bool,
         """Whether the library to build should be built as a framework on OSX.
 
         This implies the name of the library won't be prefixed nor suffixed.
         Implies FORCE_SHARED_LIB.
         """),
 
     'STATIC_LIBRARY_NAME': (unicode, unicode,
--- a/python/mozbuild/mozbuild/frontend/data.py
+++ b/python/mozbuild/mozbuild/frontend/data.py
@@ -668,16 +668,17 @@ class RustLibrary(StaticLibrary):
     """Context derived container object for a static library"""
     __slots__ = (
         'cargo_file',
         'crate_type',
         'dependencies',
         'deps_path',
         'features',
         'target_dir',
+        'output_category',
     )
     TARGET_SUBST_VAR = 'RUST_TARGET'
     FEATURES_VAR = 'RUST_LIBRARY_FEATURES'
     LIB_FILE_VAR = 'RUST_LIBRARY_FILE'
 
     def __init__(self, context, basename, cargo_file, crate_type, dependencies,
                  features, target_dir, **args):
         StaticLibrary.__init__(self, context, basename, **args)
@@ -689,16 +690,17 @@ class RustLibrary(StaticLibrary):
         # many other things in the build system depend on that.
         assert self.crate_type == 'staticlib'
         self.lib_name = '%s%s%s' % (context.config.rust_lib_prefix,
                                      basename.replace('-', '_'),
                                      context.config.rust_lib_suffix)
         self.dependencies = dependencies
         self.features = features
         self.target_dir = target_dir
+        self.output_category = context.get('RUST_LIBRARY_OUTPUT_CATEGORY')
         # Skip setting properties below which depend on cargo
         # when we don't have a compile environment. The required
         # config keys won't be available, but the instance variables
         # that we don't set should never be accessed by the actual
         # build in that case.
         if not context.config.substs.get('COMPILE_ENVIRONMENT'):
             return
         build_dir = mozpath.join(target_dir,
@@ -708,16 +710,17 @@ class RustLibrary(StaticLibrary):
 
 
 class SharedLibrary(Library):
     """Context derived container object for a shared library"""
     __slots__ = (
         'soname',
         'variant',
         'symbols_file',
+        'output_category',
     )
 
     DICT_ATTRS = {
         'basename',
         'import_name',
         'install_target',
         'lib_name',
         'relobjdir',
@@ -728,16 +731,17 @@ class SharedLibrary(Library):
     MAX_VARIANT = 2
 
     def __init__(self, context, basename, real_name=None,
                  soname=None, variant=None, symbols_file=False):
         assert(variant in range(1, self.MAX_VARIANT) or variant is None)
         Library.__init__(self, context, basename, real_name)
         self.variant = variant
         self.lib_name = real_name or basename
+        self.output_category = context.get('SHARED_LIBRARY_OUTPUT_CATEGORY')
         assert self.lib_name
 
         if variant == self.FRAMEWORK:
             self.import_name = self.lib_name
         else:
             self.import_name = '%s%s%s' % (
                 context.config.import_prefix,
                 self.lib_name,
--- a/python/mozbuild/mozbuild/mach_commands.py
+++ b/python/mozbuild/mozbuild/mach_commands.py
@@ -596,29 +596,22 @@ class GTestCommands(MachCommandBase):
         try:
             config = self.config_environment
         except Exception:
             print("Please run |./mach build| before |./mach gtest|.")
             return 1
 
         active_backend = config.substs.get('BUILD_BACKENDS', [None])[0]
         if 'Tup' in active_backend:
-            gtest_build_path = mozpath.join(self.topobjdir, '<gtest>')
+            gtest_build_target = mozpath.join(self.topobjdir, '<gtest>')
         else:
-            # This path happens build the necessary parts of the tree in the
-            # Make backend due to the odd nature of partial tree builds.
-            gtest_build_path = mozpath.relpath(mozpath.join(self.topobjdir,
-                                                            'toolkit', 'library',
-                                                            'gtest', 'rust'),
-                                               self.topsrcdir)
-
-        os.environ[b'LINK_GTEST_DURING_COMPILE'] = b'1'
+            gtest_build_target = 'recurse_gtest'
+
         res = self._mach_context.commands.dispatch('build', self._mach_context,
-                                                   what=[gtest_build_path])
-        del os.environ[b'LINK_GTEST_DURING_COMPILE']
+                                                   what=[gtest_build_target])
         if res:
             print("Could not build xul-gtest")
             return res
 
         if self.substs.get('MOZ_WIDGET_TOOLKIT') == 'cocoa':
             self._run_make(directory='browser/app', target='repackage',
                            ensure_exit_code=True)
 
--- a/taskcluster/ci/fetch/benchmarks.yml
+++ b/taskcluster/ci/fetch/benchmarks.yml
@@ -1,8 +1,17 @@
 unity-webgl:
   description: unity-webgl benchmark
   fetch:
     type: static-url
     artifact-name: unity-webgl.zip
     url: https://github.com/mozilla/perf-automation/releases/download/unity-webgl-v1/unity-webgl-6beb3d3e22ab.zip
     sha256: f71ee3a3f5b9513f041e1dd01c032d51f2071e1ad130e8ac2cf0c553c468b9ea
     size: 27062962
+
+assorted-dom:
+  description: assorted-dom benchmark
+  fetch:
+    type: static-url
+    artifact-name: assorted-dom.zip
+    url: https://github.com/mozilla/perf-automation/releases/download/assorted-dom-v1/assorted-dom-4befd28725c6.zip
+    sha256: e4eafe4a8e70c7ae6d42d668d3b1640b9fd9b696c486ff35aab754c368f78c2c
+    size: 402665
deleted file mode 100644
--- a/testing/web-platform/meta/WebIDL/ecmascript-binding/legacy-platform-object.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[legacy-platform-object.html]
-  [Test [[DefineOwnProperty\]\] with indexed property setter support.]
-    expected: FAIL
-
deleted file mode 100644
--- a/testing/web-platform/meta/css/css-contain/contain-layout-006.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[contain-layout-006.html]
-  expected: FAIL
deleted file mode 100644
--- a/testing/web-platform/meta/css/css-contain/contain-layout-007.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[contain-layout-007.html]
-  expected: FAIL
deleted file mode 100644
--- a/testing/web-platform/meta/css/css-contain/contain-layout-008.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[contain-layout-008.html]
-  expected: FAIL
deleted file mode 100644
--- a/testing/web-platform/meta/css/css-contain/contain-layout-013.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[contain-layout-013.html]
-  expected: FAIL
deleted file mode 100644
--- a/testing/web-platform/meta/css/css-contain/contain-layout-014.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[contain-layout-014.html]
-  expected: FAIL
deleted file mode 100644
--- a/testing/web-platform/meta/css/css-contain/contain-layout-015.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[contain-layout-015.html]
-  expected: FAIL
deleted file mode 100644
--- a/testing/web-platform/meta/css/css-contain/contain-layout-016.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[contain-layout-016.html]
-  expected: FAIL
deleted file mode 100644
--- a/testing/web-platform/meta/css/css-contain/contain-layout-ifc-022.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[contain-layout-ifc-022.html]
-  expected: FAIL
deleted file mode 100644
--- a/testing/web-platform/meta/css/css-contain/contain-layout-ink-overflow-013.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[contain-layout-ink-overflow-013.html]
-  expected: FAIL
deleted file mode 100644
--- a/testing/web-platform/meta/css/css-contain/contain-layout-ink-overflow-014.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[contain-layout-ink-overflow-014.html]
-  expected: FAIL
deleted file mode 100644
--- a/testing/web-platform/meta/css/css-contain/contain-layout-ink-overflow-015.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[contain-layout-ink-overflow-015.html]
-  expected: FAIL
deleted file mode 100644
--- a/testing/web-platform/meta/css/css-contain/contain-layout-ink-overflow-016.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[contain-layout-ink-overflow-016.html]
-  expected: FAIL
deleted file mode 100644
--- a/testing/web-platform/meta/css/css-contain/contain-layout-ink-overflow-017.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[contain-layout-ink-overflow-017.html]
-  expected: FAIL
deleted file mode 100644
--- a/testing/web-platform/meta/css/css-contain/contain-layout-ink-overflow-018.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[contain-layout-ink-overflow-018.html]
-  expected: FAIL
deleted file mode 100644
--- a/testing/web-platform/meta/css/css-contain/contain-layout-ink-overflow-019.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[contain-layout-ink-overflow-019.html]
-  expected: FAIL
deleted file mode 100644
--- a/testing/web-platform/meta/css/css-contain/contain-layout-ink-overflow-020.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[contain-layout-ink-overflow-020.html]
-  expected: FAIL
deleted file mode 100644
--- a/testing/web-platform/meta/css/css-contain/contain-layout-size-003.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[contain-layout-size-003.html]
-  expected: FAIL
--- a/testing/web-platform/meta/encoding/unsupported-encodings.any.js.ini
+++ b/testing/web-platform/meta/encoding/unsupported-encodings.any.js.ini
@@ -1,39 +1,15 @@
 [unsupported-encodings.any.html]
-  [UTF-32 with BOM should decode as UTF-16LE]
-    expected: FAIL
-
-  [utf-32 with BOM should decode as UTF-16LE]
-    expected: FAIL
-
-  [UTF-32LE with BOM should decode as UTF-16LE]
-    expected: FAIL
-
-  [utf-32le with BOM should decode as UTF-16LE]
-    expected: FAIL
-
   [UTF-32be with BOM should decode as windows-1252]
     expected: FAIL
 
   [utf-32be with BOM should decode as windows-1252]
     expected: FAIL
 
 
 [unsupported-encodings.any.worker.html]
-  [UTF-32 with BOM should decode as UTF-16LE]
-    expected: FAIL
-
-  [utf-32 with BOM should decode as UTF-16LE]
-    expected: FAIL
-
-  [UTF-32LE with BOM should decode as UTF-16LE]
-    expected: FAIL
-
-  [utf-32le with BOM should decode as UTF-16LE]
-    expected: FAIL
-
   [UTF-32be with BOM should decode as windows-1252]
     expected: FAIL
 
   [utf-32be with BOM should decode as windows-1252]
     expected: FAIL
 
deleted file mode 100644
--- a/testing/web-platform/meta/xhr/responsetext-decoding.htm.ini
+++ /dev/null
@@ -1,37 +0,0 @@
-[responsetext-decoding.htm]
-  [XMLHttpRequest: responseText decoding (text/plain %FE%FF)]
-    expected: FAIL
-
-  [XMLHttpRequest: responseText decoding (text/plain %FE%FF%FE%FF)]
-    expected: FAIL
-
-  [XMLHttpRequest: responseText decoding (text/plain %C2)]
-    expected: FAIL
-
-  [XMLHttpRequest: responseText decoding (text/plain %FE%FF empty)]
-    expected: FAIL
-
-  [XMLHttpRequest: responseText decoding (text/plain %FE%FF%FE%FF empty)]
-    expected: FAIL
-
-  [XMLHttpRequest: responseText decoding (text/plain %C2 empty)]
-    expected: FAIL
-
-  [XMLHttpRequest: responseText decoding (text/plain %FE%FF  text)]
-    expected: FAIL
-
-  [XMLHttpRequest: responseText decoding (text/plain %FE%FF%FE%FF  text)]
-    expected: FAIL
-
-  [XMLHttpRequest: responseText decoding (text/plain %C2  text)]
-    expected: FAIL
-
-  [XMLHttpRequest: responseText decoding (text/xml %FE%FF  text)]
-    expected: FAIL
-
-  [XMLHttpRequest: responseText decoding (text/xml %FE%FF%FE%FF  text)]
-    expected: FAIL
-
-  [XMLHttpRequest: responseText decoding (text/plain;charset=bogus %C2  text)]
-    expected: FAIL
-
deleted file mode 100644
--- a/testing/web-platform/meta/xhr/send-receive-utf16.htm.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[send-receive-utf16.htm]
-  [UTF-16 with BOM, no encoding in content-type]
-    expected: FAIL
-
--- a/testing/web-platform/tests/xhr/overridemimetype-edge-cases.window.js
+++ b/testing/web-platform/tests/xhr/overridemimetype-edge-cases.window.js
@@ -1,16 +1,16 @@
 const testURL = "resources/status.py?type=" + encodeURIComponent("text/plain;charset=windows-1252") + "&content=%C2%F0";
 
 async_test(t => {
   const client = new XMLHttpRequest();
   let secondTime = false;
   client.onload = t.step_func(() => {
     if(!secondTime) {
-      assert_equals(client.responseText, "\uFFFD");
+      assert_equals(client.responseText, "\uFFFD\uFFFD");
       secondTime = true;
       client.open("GET", testURL);
       client.send();
     } else {
       assert_equals(client.responseText, "Âð");
       t.done();
     }
   });
@@ -27,14 +27,14 @@ async_test(t => {
   client.open("GET", testURL);
   client.overrideMimeType("text/xml");
   client.send();
 }, "If charset is not overridden by overrideMimeType() the original continues to be used");
 
 async_test(t => {
   const client = new XMLHttpRequest();
   client.onload = t.step_func_done(() => {
-    assert_equals(client.responseText, "\uFFFD")
+    assert_equals(client.responseText, "\uFFFD\uFFFD")
   });
   client.open("GET", testURL);
   client.overrideMimeType("text/plain;charset=342");
   client.send();
 }, "Charset can be overridden by overrideMimeType() with a bogus charset");
--- a/toolkit/components/extensions/test/xpcshell/test_ext_storage_idb_data_migration.js
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_storage_idb_data_migration.js
@@ -82,16 +82,25 @@ add_task(async function setup() {
   Services.prefs.setBoolPref(ExtensionStorageIDB.BACKEND_ENABLED_PREF, true);
   setLowDiskMode(false);
 
   await promiseStartupManager();
 
   // Telemetry test setup needed to ensure that the builtin events are defined
   // and they can be collected and verified.
   await TelemetryController.testSetup();
+
+  // This is actually only needed on Android, because it does not properly support unified telemetry
+  // and so, if not enabled explicitly here, it would make these tests to fail when running on a
+  // non-Nightly build.
+  const oldCanRecordBase = Services.telemetry.canRecordBase;
+  Services.telemetry.canRecordBase = true;
+  registerCleanupFunction(() => {
+    Services.telemetry.canRecordBase = oldCanRecordBase;
+  });
 });
 
 // Test that the old data is migrated successfully to the new storage backend
 // and that the original JSONFile has been renamed.
 add_task(async function test_storage_local_data_migration() {
   const EXTENSION_ID = "extension-to-be-migrated@mozilla.org";
 
   // Keep the extension storage and the uuid on uninstall, to verify that no telemetry events
--- a/toolkit/components/telemetry/Scalars.yaml
+++ b/toolkit/components/telemetry/Scalars.yaml
@@ -632,16 +632,89 @@ preferences:
     expires: "62"
     kind: boolean
     notification_emails:
       - yzenevich@mozilla.com
     release_channel_collection: opt-out
     record_in_processes:
       - 'main'
 
+# The following section contains WebRTC JS API scalars
+# For more information on WebRTC, see https://www.w3.org/TR/webrtc/
+# For more info on ICE, see https://tools.ietf.org/html/rfc5245
+webrtc.peerconnection:
+  connected:
+    bug_numbers:
+      - 1455724
+    description: >
+      The number of RTCPeerConnection objects that established connections.
+      This is incremented the first time a RTCPeerConnection object's
+      iceConnectionState becomes "connected" or "complete".
+      For more information on WebRTC, see https://www.w3.org/TR/webrtc/
+    expires: "65"
+    kind: uint
+    notification_emails:
+      - ngrunbaum@mozilla.com
+    release_channel_collection: opt-in
+    record_in_processes:
+      - 'main'
+      - 'content'
+
+  legacy_callback_stats_used:
+    bug_numbers:
+      - 1455724
+    description: >
+      The number of RTCPeerConnections in which the current statistics
+      API is called. Recorded the first time getStats is called using the
+      deprecated callback based API on a RTCPeerConnection that has an
+      iceConnectionState of "complete" or "connected".
+    expires: "65"
+    kind: uint
+    notification_emails:
+      - ngrunbaum@mozilla.com
+    release_channel_collection: opt-in
+    record_in_processes:
+      - 'main'
+      - 'content'
+
+  promise_stats_used:
+    bug_numbers:
+      - 1455724
+    description: >
+      The number of RTCPeerConnection objects in which the current statistics
+      API is called. This is recorded the first time getStats is called using
+      the promise based API on a RTCPeerConnection that has an
+      iceConnectionState of "complete" or "connected".
+    expires: "65"
+    kind: uint
+    notification_emails:
+      - ngrunbaum@mozilla.com
+    release_channel_collection: opt-in
+    record_in_processes:
+      - 'main'
+      - 'content'
+
+  promise_and_callback_stats_used:
+    bug_numbers:
+      - 1455724
+    description: >
+      The number of RTCPeerConnection objects in which both the legacy callback
+      statistics API and the modern promise statistics API are used. This is
+      recorded once for each RTCPeerConnection after the callback and promise
+      getStats API has been called on a RTCPeerConnection that has an
+      iceConnectionState of "complete" or "connected".
+    expires: "65"
+    kind: uint
+    notification_emails:
+      - ngrunbaum@mozilla.com
+    release_channel_collection: opt-in
+    record_in_processes:
+      - 'main'
+      - 'content'
+
 # The following section contains WebRTC nICEr scalars
 # For more info on ICE, see https://tools.ietf.org/html/rfc5245
 # For more info on STUN, see https://tools.ietf.org/html/rfc5389
 # For more info on TURN, see https://tools.ietf.org/html/rfc5766
 webrtc.nicer:
   stun_retransmits:
     bug_numbers:
       - 1325536
--- a/toolkit/content/widgets/remote-browser.xml
+++ b/toolkit/content/widgets/remote-browser.xml
@@ -396,18 +396,16 @@
           this._contentPrincipal = ssm.getLoadContextCodebasePrincipal(aboutBlank, this.loadContext);
 
           this.messageManager.addMessageListener("Browser:Init", this);
           this.messageManager.addMessageListener("DOMTitleChanged", this);
           this.messageManager.addMessageListener("ImageDocumentLoaded", this);
           this.messageManager.addMessageListener("FullZoomChange", this);
           this.messageManager.addMessageListener("TextZoomChange", this);
           this.messageManager.addMessageListener("ZoomChangeUsingMouseWheel", this);
-          this.messageManager.addMessageListener("DOMFullscreen:RequestExit", this);
-          this.messageManager.addMessageListener("DOMFullscreen:RequestRollback", this);
           this.messageManager.addMessageListener("MozApplicationManifest", this);
 
           // browser-child messages, such as Content:LocationChange, are handled in
           // RemoteWebProgress, ensure it is loaded and ready.
           let jsm = "resource://gre/modules/RemoteWebProgress.jsm";
           let { RemoteWebProgressManager } = ChromeUtils.import(jsm, {});
           this._remoteWebProgressManager = new RemoteWebProgressManager(this);
           this._remoteWebProgress = this._remoteWebProgressManager.topLevelWebProgress;
@@ -527,28 +525,16 @@
 
             case "ZoomChangeUsingMouseWheel": {
               let event = document.createEvent("Events");
               event.initEvent("ZoomChangeUsingMouseWheel", true, false);
               this.dispatchEvent(event);
               break;
             }
 
-            case "DOMFullscreen:RequestExit": {
-              let windowUtils = window.windowUtils;
-              windowUtils.exitFullscreen();
-              break;
-            }
-
-            case "DOMFullscreen:RequestRollback": {
-              let windowUtils = window.windowUtils;
-              windowUtils.remoteFrameFullscreenReverted();
-              break;
-            }
-
             case "MozApplicationManifest":
               this._manifestURI = aMessage.data.manifest;
               break;
 
             default:
               // Delegate to browser.xml.
               return this._receiveMessage(aMessage);
           }
--- a/toolkit/library/gtest/Makefile.in
+++ b/toolkit/library/gtest/Makefile.in
@@ -1,28 +1,7 @@
 # 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/.
 
-# Enforce that the clean/distclean rules removes everything that needs
-# to be removed from this directory.
-ifneq (,$(filter clean distclean,$(MAKECMDGOALS)))
-LINK_GTEST_DURING_COMPILE = 1
-endif
-
-# Don't link the gtest xul during MOZ_PROFILE_GENERATE, it doesn't get
-# used during profiling anyway.
-ifdef MOZ_PROFILE_GENERATE
-LINK_GTEST_DURING_COMPILE =
-endif
-
-ifndef LINK_GTEST_DURING_COMPILE
-# Force to not include backend.mk unless LINK_GTEST_DURING_COMPILE is set.
-# Not including backend.mk makes traversing this directory do nothing.
-STANDALONE_MAKEFILE = 1
-
-else
-
 include $(topsrcdir)/toolkit/library/libxul.mk
 
 include $(topsrcdir)/config/config.mk
-
-endif
--- a/toolkit/library/gtest/moz.build
+++ b/toolkit/library/gtest/moz.build
@@ -27,13 +27,14 @@ if CONFIG['OS_ARCH'] == 'Linux' and CONF
     GENERATED_FILES['symverscript'].inputs = ['../symverscript.in']
     GENERATED_FILES['symverscript'].flags = [
         'xul%s' % CONFIG['MOZILLA_SYMBOLVERSION']
     ]
     SYMBOLS_FILE = '!symverscript'
 
 # This needs to come after static:xul to avoid things like libfallible coming
 # before StaticXULComponentStart.
-Libxul('xul-gtest-real')
+Libxul('xul-gtest-real',
+       output_category=None if CONFIG['LINK_GTEST_DURING_COMPILE'] else 'gtest')
 
 DIRS += [
     'static',
 ]
deleted file mode 100644
--- a/toolkit/library/gtest/rust/Makefile.in
+++ /dev/null
@@ -1,29 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this file,
-# You can obtain one at http://mozilla.org/MPL/2.0/.
-
-# This file looks quite similar to toolkit/library/gtest/Makefile.in.
-# We only want to build gkrust-gtest when we are building libxul-gtest.
-
-# Enforce that the clean/distclean rules removes everything that needs
-# to be removed from this directory.
-ifneq (,$(filter clean distclean,$(MAKECMDGOALS)))
-LINK_GTEST_DURING_COMPILE = 1
-endif
-
-# Don't build gkrust-gtest during MOZ_PROFILE_GENERATE, it doesn't get
-# used during profiling anyway.
-ifdef MOZ_PROFILE_GENERATE
-LINK_GTEST_DURING_COMPILE =
-endif
-
-ifndef LINK_GTEST_DURING_COMPILE
-# Force to not include backend.mk unless LINK_GTEST_DURING_COMPILE is set.
-# Not including backend.mk makes traversing this directory do nothing.
-STANDALONE_MAKEFILE = 1
-
-else
-
-include $(topsrcdir)/config/config.mk
-
-endif
--- a/toolkit/library/gtest/rust/moz.build
+++ b/toolkit/library/gtest/rust/moz.build
@@ -1,9 +1,10 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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('../../rust/gkrust-features.mozbuild')
 
-RustLibrary('gkrust-gtest', gkrust_features, '../..')
+RustLibrary('gkrust-gtest', gkrust_features, '../..',
+            output_category=None if CONFIG['LINK_GTEST_DURING_COMPILE'] else 'gtest')
--- a/toolkit/library/moz.build
+++ b/toolkit/library/moz.build
@@ -7,24 +7,24 @@
 @template
 def Libxul_defines():
     LIBRARY_DEFINES['MOZILLA_INTERNAL_API'] = True
     LIBRARY_DEFINES['IMPL_LIBXUL'] = True
     if not CONFIG['JS_SHARED_LIBRARY']:
         LIBRARY_DEFINES['STATIC_EXPORTABLE_JS_API'] = True
 
 @template
-def Libxul(name):
+def Libxul(name, output_category=None):
     if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('cocoa', 'uikit'):
         # This is going to be a framework named "XUL", not an ordinary library named
         # "libxul.dylib"
-        GeckoFramework(name, linkage=None)
+        GeckoFramework(name, output_category=output_category, linkage=None)
         SHARED_LIBRARY_NAME = 'XUL'
     else:
-        GeckoSharedLibrary(name, linkage=None)
+        GeckoSharedLibrary(name, output_category=output_category, linkage=None)
         SHARED_LIBRARY_NAME = 'xul'
 
     DELAYLOAD_DLLS += [
         'comdlg32.dll',
         'hid.dll',
         'msimg32.dll',
         'netapi32.dll',
         'secur32.dll',
--- a/toolkit/modules/addons/WebRequest.jsm
+++ b/toolkit/modules/addons/WebRequest.jsm
@@ -223,61 +223,34 @@ function serializeRequestData(eventName)
 }
 
 var HttpObserverManager;
 
 var nextFakeRequestId = 1;
 
 var ContentPolicyManager = {
   policyData: new Map(),
-  policies: new Map(),
   idMap: new Map(),
   nextId: 0,
 
   init() {
     Services.ppmm.initialProcessData.webRequestContentPolicies = this.policyData;
 
     Services.ppmm.addMessageListener("WebRequest:ShouldLoad", this);
     Services.mm.addMessageListener("WebRequest:ShouldLoad", this);
   },
 
   receiveMessage(msg) {
     let browser = ChromeUtils.getClassName(msg.target) == "XULFrameElement" ? msg.target : null;
 
     let requestId = `fakeRequest-${++nextFakeRequestId}`;
-    for (let id of msg.data.ids) {
-      let callback = this.policies.get(id);
-      if (!callback) {
-        // It's possible that this listener has been removed and the
-        // child hasn't learned yet.
-        continue;
-      }
-      let response = null;
-      let listenerKind = "onStop";
-      let data = Object.assign({requestId, browser, serialize: serializeRequestData}, msg.data);
+    let data = Object.assign({requestId, browser, serialize: serializeRequestData}, msg.data);
 
-      delete data.ids;
-      try {
-        response = callback(data);
-        if (response) {
-          if (response.cancel) {
-            listenerKind = "onError";
-            data.error = "NS_ERROR_ABORT";
-            return {cancel: true};
-          }
-          // FIXME: Need to handle redirection here (for non-HTTP URIs only)
-        }
-      } catch (e) {
-        Cu.reportError(e);
-      } finally {
-        runLater(() => this.runChannelListener(listenerKind, data));
-      }
-    }
-
-    return {};
+    this.runChannelListener("opening", data);
+    runLater(() => this.runChannelListener("onStop", data));
   },
 
   shouldRunListener(policyType, url, opts) {
     let {filter} = opts;
 
     if (filter.types && !filter.types.includes(policyType)) {
       return false;
     }
@@ -293,17 +266,21 @@ var ContentPolicyManager = {
 
     return true;
   },
 
   runChannelListener(kind, data) {
     let listeners = HttpObserverManager.listeners[kind];
     for (let [callback, opts] of listeners.entries()) {
       if (this.shouldRunListener(data.type, data.url, opts)) {
-        callback(data);
+        try {
+          callback(data);
+        } catch (e) {
+          Cu.reportError(e);
+        }
       }
     }
   },
 
   addListener(callback, opts) {
     // Clone opts, since we're going to modify them for IPC.
     opts = Object.assign({}, opts);
     let id = this.nextId++;
@@ -311,27 +288,25 @@ var ContentPolicyManager = {
     if (opts.filter.urls) {
       opts.filter = Object.assign({}, opts.filter);
       opts.filter.urls = opts.filter.urls.patterns.map(url => url.pattern);
     }
     Services.ppmm.broadcastAsyncMessage("WebRequest:AddContentPolicy", opts);
 
     this.policyData.set(id, opts);
 
-    this.policies.set(id, callback);
     this.idMap.set(callback, id);
   },
 
   removeListener(callback) {
     let id = this.idMap.get(callback);
     Services.ppmm.broadcastAsyncMessage("WebRequest:RemoveContentPolicy", {id});
 
     this.policyData.delete(id);
     this.idMap.delete(callback);
-    this.policies.delete(id);
   },
 };
 ContentPolicyManager.init();
 
 var ChannelEventSink = {
   _classDescription: "WebRequest channel event sink",
   _classID: Components.ID("115062f8-92f1-11e5-8b7f-080027b0f7ec"),
   _contractID: "@mozilla.org/webrequest/channel-event-sink;1",
--- a/toolkit/modules/addons/WebRequestContent.js
+++ b/toolkit/modules/addons/WebRequestContent.js
@@ -96,25 +96,27 @@ var ContentPolicy = {
       return Ci.nsIContentPolicy.ACCEPT;
     }
     let url = contentLocation.spec;
     if (IS_HTTP.test(url)) {
       // We'll handle this in our parent process HTTP observer.
       return Ci.nsIContentPolicy.ACCEPT;
     }
 
-    let ids = [];
-    for (let [id, {filter}] of this.contentPolicies.entries()) {
+    // Break out early if there are no extension listeners.
+    let haveListeners = false;
+    for (let {filter} of this.contentPolicies.values()) {
       if (WebRequestCommon.typeMatches(policyType, filter.types) &&
           WebRequestCommon.urlMatches(contentLocation, filter.urls)) {
-        ids.push(id);
+        haveListeners = true;
+        break;
       }
     }
 
-    if (!ids.length) {
+    if (!haveListeners) {
       return Ci.nsIContentPolicy.ACCEPT;
     }
 
     let windowId = 0;
     let parentWindowId = -1;
     let frameAncestors = [];
     let mm = Services.cpmm;
 
@@ -166,18 +168,17 @@ var ContentPolicy = {
       }
 
       let windowMM = window.docShell.messageManager;
       if (windowMM) {
         mm = windowMM;
       }
     }
 
-    let data = {ids,
-                url,
+    let data = {url,
                 type: WebRequestCommon.typeForPolicyType(policyType),
                 windowId,
                 parentWindowId};
     if (frameAncestors.length > 0) {
       data.frameAncestors = frameAncestors;
     }
     if (requestOrigin) {
       data.documentUrl = requestOrigin.spec;