Merge inbound to mozilla-central. a=merge
authorshindli <shindli@mozilla.com>
Wed, 09 Jan 2019 23:42:10 +0200
changeset 453099 8e746f670f430ceb0cb85fa8eebfe97cbe42ff01
parent 453072 47ced8013922dad7c08afd513cf07b00c22672a1 (current diff)
parent 453098 89ca00a3e30767aaf57562ac8c2e2b3994123de3 (diff)
child 453147 aa289d489496689509b460e8d27b3da6bb4d9d44
child 453182 d033029954abe5a902d20e841020bc4aa1ab5542
push id35345
push usershindli@mozilla.com
push dateWed, 09 Jan 2019 21:42:48 +0000
treeherdermozilla-central@8e746f670f43 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone66.0a1
first release with
nightly linux32
8e746f670f43 / 66.0a1 / 20190109214248 / files
nightly linux64
8e746f670f43 / 66.0a1 / 20190109214248 / files
nightly mac
8e746f670f43 / 66.0a1 / 20190109214248 / files
nightly win32
8e746f670f43 / 66.0a1 / 20190109214248 / files
nightly win64
8e746f670f43 / 66.0a1 / 20190109214248 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge inbound to mozilla-central. a=merge
dom/webidl/TreeBoxObject.webidl
layout/xul/tree/TreeBoxObject.cpp
layout/xul/tree/TreeBoxObject.h
layout/xul/tree/nsITreeBoxObject.idl
toolkit/components/perfmonitoring/PerformanceWatcher-content.js
toolkit/components/perfmonitoring/PerformanceWatcher.jsm
toolkit/components/perfmonitoring/tests/browser/browser_webpagePerformanceAlerts.js
--- a/browser/base/content/browser-sets.inc
+++ b/browser/base/content/browser-sets.inc
@@ -177,18 +177,18 @@
          key="&copyCmd.key;"
          modifiers="accel"/>
     <key id="key_paste"
          key="&pasteCmd.key;"
          modifiers="accel"/>
     <key id="key_delete" keycode="VK_DELETE" command="cmd_delete"/>
     <key id="key_selectAll" key="&selectAllCmd.key;" modifiers="accel"/>
 
-    <key keycode="VK_BACK" command="cmd_handleBackspace"/>
-    <key keycode="VK_BACK" command="cmd_handleShiftBackspace" modifiers="shift"/>
+    <key keycode="VK_BACK" command="cmd_handleBackspace" reserved="false"/>
+    <key keycode="VK_BACK" command="cmd_handleShiftBackspace" modifiers="shift" reserved="false"/>
 #ifndef XP_MACOSX
     <key id="goBackKb"  keycode="VK_LEFT" command="Browser:Back" modifiers="alt"/>
     <key id="goForwardKb"  keycode="VK_RIGHT" command="Browser:Forward" modifiers="alt"/>
 #else
     <key id="goBackKb" keycode="VK_LEFT" command="Browser:Back" modifiers="accel" />
     <key id="goForwardKb" keycode="VK_RIGHT" command="Browser:Forward" modifiers="accel" />
 #endif
 #ifdef XP_UNIX
--- a/browser/base/content/test/permissions/browser_reservedkey.js
+++ b/browser/base/content/test/permissions/browser_reservedkey.js
@@ -112,8 +112,48 @@ if (!navigator.platform.includes("Mac"))
 
     popupHidden = BrowserTestUtils.waitForEvent(filePopup, "popuphidden");
     filePopup.hidePopup();
     await popupHidden;
 
     BrowserTestUtils.removeTab(tab1);
   });
 }
+
+// There is a <key> element for Backspace with reserved="false", so make sure that it is not
+// treated as a blocked shortcut key.
+add_task(async function test_backspace() {
+  await new Promise(resolve => {
+    SpecialPowers.pushPrefEnv({"set": [["permissions.default.shortcuts", 2]]}, resolve);
+  });
+
+  // The input field is autofocused. If this test fails, backspace can go back
+  // in history so cancel the beforeunload event and adjust the field to make the test fail.
+  const uri = "data:text/html,<body onbeforeunload='document.getElementById(\"field\").value = \"failed\";'>" +
+                 "<input id='field' value='something'></body>";
+  let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, uri);
+
+  await ContentTask.spawn(tab.linkedBrowser, { }, async function() {
+    content.document.getElementById("field").focus();
+
+    // Add a promise that resolves when the backspace key gets received
+    // so we can ensure the key gets received before checking the result.
+    content.keysPromise = new Promise(resolve => {
+      content.addEventListener("keyup", event => {
+        if (event.code == "Backspace") {
+          resolve(content.document.getElementById("field").value);
+        }
+      });
+    });
+  });
+
+  // Move the caret so backspace will delete the first character.
+  EventUtils.synthesizeKey("KEY_ArrowRight", {});
+  EventUtils.synthesizeKey("KEY_Backspace", {});
+
+  let fieldValue = await ContentTask.spawn(tab.linkedBrowser, { }, async function() {
+    return content.keysPromise;
+  });
+  is(fieldValue, "omething", "backspace not prevented");
+
+  BrowserTestUtils.removeTab(tab);
+});
+
--- a/devtools/client/debugger/new/test/mochitest/browser.ini
+++ b/devtools/client/debugger/new/test/mochitest/browser.ini
@@ -699,16 +699,17 @@ skip-if = (os == "win" && ccov) # Bug 14
 [browser_dbg-editor-gutter.js]
 [browser_dbg-editor-select.js]
 [browser_dbg-editor-highlight.js]
 [browser_dbg-ember-quickstart.js]
 [browser_dbg-expressions.js]
 [browser_dbg-expressions-error.js]
 [browser_dbg-iframes.js]
 [browser_dbg-inline-cache.js]
+skip-if = ccov && os == 'win' # Bug 1443132
 [browser_dbg-inspector-integration.js]
 [browser_dbg-keyboard-navigation.js]
 [browser_dbg-keyboard-shortcuts.js]
 skip-if = os == "linux" # bug 1351952
 [browser_dbg-layout-changes.js]
 [browser_dbg-outline.js]
 skip-if = verify
 [browser_dbg-outline-pretty.js]
--- a/dom/media/webaudio/blink/ReverbConvolver.cpp
+++ b/dom/media/webaudio/blink/ReverbConvolver.cpp
@@ -59,17 +59,17 @@ const size_t MaxRealtimeFFTSize = 4096;
 ReverbConvolver::ReverbConvolver(const float* impulseResponseData,
                                  size_t impulseResponseLength,
                                  size_t maxFFTSize, size_t convolverRenderPhase,
                                  bool useBackgroundThreads)
     : m_impulseResponseLength(impulseResponseLength),
       m_accumulationBuffer(impulseResponseLength + WEBAUDIO_BLOCK_SIZE),
       m_inputBuffer(InputBufferSize),
       m_backgroundThread("ConvolverWorker"),
-      m_backgroundThreadCondition(&m_backgroundThreadLock),
+      m_backgroundThreadMonitor("ConvolverMonitor"),
       m_useBackgroundThreads(useBackgroundThreads),
       m_wantsToExit(false),
       m_moreInputBuffered(false) {
   // For the moment, a good way to know if we have real-time constraint is to
   // check if we're using background threads. Otherwise, assume we're being run
   // from a command-line tool.
   bool hasRealtimeConstraint = useBackgroundThreads;
 
@@ -161,19 +161,19 @@ ReverbConvolver::ReverbConvolver(const f
 
 ReverbConvolver::~ReverbConvolver() {
   // Wait for background thread to stop
   if (useBackgroundThreads() && m_backgroundThread.IsRunning()) {
     m_wantsToExit = true;
 
     // Wake up thread so it can return
     {
-      AutoLock locker(m_backgroundThreadLock);
+      MonitorAutoLock locker(m_backgroundThreadMonitor);
       m_moreInputBuffered = true;
-      m_backgroundThreadCondition.Signal();
+      m_backgroundThreadMonitor.Notify();
     }
 
     m_backgroundThread.Stop();
   }
 }
 
 size_t ReverbConvolver::sizeOfIncludingThis(
     mozilla::MallocSizeOf aMallocSizeOf) const {
@@ -194,29 +194,28 @@ size_t ReverbConvolver::sizeOfIncludingT
 
   // NB: The buffer sizes are static, so even though they might be accessed
   //     in another thread it's safe to measure them.
   amount += m_accumulationBuffer.sizeOfExcludingThis(aMallocSizeOf);
   amount += m_inputBuffer.sizeOfExcludingThis(aMallocSizeOf);
 
   // Possible future measurements:
   // - m_backgroundThread
-  // - m_backgroundThreadLock
-  // - m_backgroundThreadCondition
+  // - m_backgroundThreadMonitor
   return amount;
 }
 
 void ReverbConvolver::backgroundThreadEntry() {
   while (!m_wantsToExit) {
     // Wait for realtime thread to give us more input
     m_moreInputBuffered = false;
     {
-      AutoLock locker(m_backgroundThreadLock);
+      MonitorAutoLock locker(m_backgroundThreadMonitor);
       while (!m_moreInputBuffered && !m_wantsToExit)
-        m_backgroundThreadCondition.Wait();
+        m_backgroundThreadMonitor.Wait();
     }
 
     // Process all of the stages until their read indices reach the input
     // buffer's write index
     int writeIndex = m_inputBuffer.writeIndex();
 
     // Even though it doesn't seem like every stage needs to maintain its own
     // version of readIndex we do this in case we want to run in more than one
@@ -246,23 +245,23 @@ void ReverbConvolver::process(const floa
   // Accumulate contributions from each stage
   for (size_t i = 0; i < m_stages.Length(); ++i) m_stages[i]->process(source);
 
   // Finally read from accumulation buffer
   m_accumulationBuffer.readAndClear(destination, WEBAUDIO_BLOCK_SIZE);
 
   // Now that we've buffered more input, wake up our background thread.
 
-  // Not using a MutexLocker looks strange, but we use a tryLock() instead
+  // Not using a MonitorAutoLock looks strange, but we use a TryLock() instead
   // because this is run on the real-time thread where it is a disaster for the
   // lock to be contended (causes audio glitching).  It's OK if we fail to
   // signal from time to time, since we'll get to it the next time we're called.
   // We're called repeatedly and frequently (around every 3ms).  The background
   // thread is processing well into the future and has a considerable amount of
   // leeway here...
-  if (m_backgroundThreadLock.Try()) {
+  if (m_backgroundThreadMonitor.TryLock()) {
     m_moreInputBuffered = true;
-    m_backgroundThreadCondition.Signal();
-    m_backgroundThreadLock.Release();
+    m_backgroundThreadMonitor.Notify();
+    m_backgroundThreadMonitor.Unlock();
   }
 }
 
 }  // namespace WebCore
--- a/dom/media/webaudio/blink/ReverbConvolver.h
+++ b/dom/media/webaudio/blink/ReverbConvolver.h
@@ -28,21 +28,20 @@
 
 #ifndef ReverbConvolver_h
 #define ReverbConvolver_h
 
 #include "ReverbAccumulationBuffer.h"
 #include "ReverbInputBuffer.h"
 #include "nsAutoPtr.h"
 #include "mozilla/MemoryReporting.h"
+#include "mozilla/Monitor.h"
 #ifdef LOG
 #undef LOG
 #endif
-#include "base/condition_variable.h"
-#include "base/lock.h"
 #include "base/thread.h"
 
 namespace WebCore {
 
 class ReverbConvolverStage;
 
 class ReverbConvolver {
  public:
@@ -75,18 +74,17 @@ class ReverbConvolver {
   ReverbAccumulationBuffer m_accumulationBuffer;
 
   // One or more background threads read from this input buffer which is fed
   // from the realtime thread.
   ReverbInputBuffer m_inputBuffer;
 
   // Background thread and synchronization
   base::Thread m_backgroundThread;
-  Lock m_backgroundThreadLock;
-  ConditionVariable m_backgroundThreadCondition;
+  mozilla::Monitor m_backgroundThreadMonitor;
   bool m_useBackgroundThreads;
   bool m_wantsToExit;
   bool m_moreInputBuffered;
 };
 
 }  // namespace WebCore
 
 #endif  // ReverbConvolver_h
--- a/ipc/chromium/src/base/at_exit.cc
+++ b/ipc/chromium/src/base/at_exit.cc
@@ -10,22 +10,25 @@
 namespace base {
 
 // Keep a stack of registered AtExitManagers.  We always operate on the most
 // recent, and we should never have more than one outside of testing, when we
 // use the shadow version of the constructor.  We don't protect this for
 // thread-safe access, since it will only be modified in testing.
 static AtExitManager* g_top_manager = NULL;
 
-AtExitManager::AtExitManager() : next_manager_(NULL) {
+AtExitManager::AtExitManager() : lock_("AtExitManager"),
+                                 next_manager_(NULL) {
   DCHECK(!g_top_manager);
   g_top_manager = this;
 }
 
-AtExitManager::AtExitManager(bool shadow) : next_manager_(g_top_manager) {
+AtExitManager::AtExitManager(bool shadow) : lock_("AtExitManager"),
+                                            next_manager_(g_top_manager)
+ {
   DCHECK(shadow || !g_top_manager);
   g_top_manager = this;
 }
 
 AtExitManager::~AtExitManager() {
   if (!g_top_manager) {
     NOTREACHED() << "Tried to ~AtExitManager without an AtExitManager";
     return;
@@ -40,28 +43,28 @@ AtExitManager::~AtExitManager() {
 void AtExitManager::RegisterCallback(AtExitCallbackType func, void* param) {
   if (!g_top_manager) {
     NOTREACHED() << "Tried to RegisterCallback without an AtExitManager";
     return;
   }
 
   DCHECK(func);
 
-  AutoLock lock(g_top_manager->lock_);
+  mozilla::MutexAutoLock lock(g_top_manager->lock_);
   g_top_manager->stack_.push(CallbackAndParam(func, param));
 }
 
 // static
 void AtExitManager::ProcessCallbacksNow() {
   if (!g_top_manager) {
     NOTREACHED() << "Tried to ProcessCallbacksNow without an AtExitManager";
     return;
   }
 
-  AutoLock lock(g_top_manager->lock_);
+  mozilla::MutexAutoLock lock(g_top_manager->lock_);
 
   while (!g_top_manager->stack_.empty()) {
     CallbackAndParam callback_and_param = g_top_manager->stack_.top();
     g_top_manager->stack_.pop();
 
     callback_and_param.func_(callback_and_param.param_);
   }
 }
--- a/ipc/chromium/src/base/at_exit.h
+++ b/ipc/chromium/src/base/at_exit.h
@@ -5,17 +5,18 @@
 // found in the LICENSE file.
 
 #ifndef BASE_AT_EXIT_H_
 #define BASE_AT_EXIT_H_
 
 #include <stack>
 
 #include "base/basictypes.h"
-#include "base/lock.h"
+
+#include "mozilla/Mutex.h"
 
 namespace base {
 
 // This class provides a facility similar to the CRT atexit(), except that
 // we control when the callbacks are executed. Under Windows for a DLL they
 // happen at a really bad time and under the loader lock. This facility is
 // mostly used by base::Singleton.
 //
@@ -58,17 +59,17 @@ class AtExitManager {
  private:
   struct CallbackAndParam {
     CallbackAndParam(AtExitCallbackType func, void* param)
         : func_(func), param_(param) {}
     AtExitCallbackType func_;
     void* param_;
   };
 
-  Lock lock_;
+  mozilla::Mutex lock_;
   std::stack<CallbackAndParam> stack_;
   AtExitManager* next_manager_;  // Stack of managers to allow shadowing.
 
   DISALLOW_COPY_AND_ASSIGN(AtExitManager);
 };
 
 }  // namespace base
 
--- a/ipc/chromium/src/base/histogram.cc
+++ b/ipc/chromium/src/base/histogram.cc
@@ -21,18 +21,16 @@
 #include "base/string_util.h"
 #include "base/logging.h"
 
 namespace base {
 
 #define DVLOG(x) CHROMIUM_LOG(ERROR)
 #define CHECK_GT DCHECK_GT
 #define CHECK_LT DCHECK_LT
-typedef ::Lock Lock;
-typedef ::AutoLock AutoLock;
 
 // Static table of checksums for all possible 8 bit bytes.
 const uint32_t Histogram::kCrcTable[256] = {
     0x0,         0x77073096L, 0xee0e612cL, 0x990951baL, 0x76dc419L,
     0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0xedb8832L,  0x79dcb8a4L,
     0xe0d5e91eL, 0x97d2d988L, 0x9b64c2bL,  0x7eb17cbdL, 0xe7b82d07L,
     0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
     0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
--- a/ipc/chromium/src/base/histogram.h
+++ b/ipc/chromium/src/base/histogram.h
@@ -45,17 +45,16 @@
 
 #include "mozilla/Atomics.h"
 #include "mozilla/MemoryReporting.h"
 
 #include <map>
 #include <string>
 
 #include "base/time.h"
-#include "base/lock.h"
 
 #include "nsTArray.h"
 
 namespace base {
 
 //------------------------------------------------------------------------------
 
 class BooleanHistogram;
--- a/ipc/chromium/src/base/message_loop.cc
+++ b/ipc/chromium/src/base/message_loop.cc
@@ -166,16 +166,17 @@ void MessageLoop::set_current(MessageLoo
 
 static mozilla::Atomic<int32_t> message_loop_id_seq(0);
 
 MessageLoop::MessageLoop(Type type, nsIEventTarget* aEventTarget)
     : type_(type),
       id_(++message_loop_id_seq),
       nestable_tasks_allowed_(true),
       exception_restoration_(false),
+      incoming_queue_lock_("MessageLoop Incoming Queue Lock"),
       state_(NULL),
       run_depth_base_(1),
       shutting_down_(false),
 #ifdef OS_WIN
       os_modal_loop_(false),
 #endif  // OS_WIN
       transient_hang_timeout_(0),
       permanent_hang_timeout_(0),
@@ -395,17 +396,17 @@ void MessageLoop::PostTask_Helper(alread
   }
 
   // Warning: Don't try to short-circuit, and handle this thread's tasks more
   // directly, as it could starve handling of foreign threads.  Put every task
   // into this queue.
 
   RefPtr<base::MessagePump> pump;
   {
-    AutoLock locked(incoming_queue_lock_);
+    mozilla::MutexAutoLock locked(incoming_queue_lock_);
     incoming_queue_.push(std::move(pending_task));
     pump = pump_;
   }
   // Since the incoming_queue_ may contain a task that destroys this message
   // loop, we cannot exit incoming_queue_lock_ until we are done with |this|.
   // We use a stack-based reference to the message pump so that we can call
   // ScheduleWork outside of incoming_queue_lock_.
 
@@ -473,17 +474,17 @@ void MessageLoop::ReloadWorkQueue() {
   // work_queue_ by waiting until the last minute (work_queue_ is empty) to
   // load.  That reduces the number of locks-per-task significantly when our
   // queues get large.
   if (!work_queue_.empty())
     return;  // Wait till we *really* need to lock and load.
 
   // Acquire all we can from the inter-thread queue with one lock acquisition.
   {
-    AutoLock lock(incoming_queue_lock_);
+    mozilla::MutexAutoLock lock(incoming_queue_lock_);
     if (incoming_queue_.empty()) return;
     std::swap(incoming_queue_, work_queue_);
     DCHECK(incoming_queue_.empty());
   }
 }
 
 bool MessageLoop::DeletePendingTasks() {
   MOZ_ASSERT(work_queue_.empty());
--- a/ipc/chromium/src/base/message_loop.h
+++ b/ipc/chromium/src/base/message_loop.h
@@ -8,20 +8,21 @@
 #define BASE_MESSAGE_LOOP_H_
 
 #include <deque>
 #include <queue>
 #include <string>
 #include <vector>
 #include <map>
 
-#include "base/lock.h"
 #include "base/message_pump.h"
 #include "base/observer_list.h"
 
+#include "mozilla/Mutex.h"
+
 #if defined(OS_WIN)
 // We need this to declare base::MessagePumpWin::Dispatcher, which we should
 // really just eliminate.
 #include "base/message_pump_win.h"
 #elif defined(OS_POSIX)
 #include "base/message_pump_libevent.h"
 #endif
 
@@ -418,17 +419,17 @@ class MessageLoop : public base::Message
   std::string thread_name_;
 
   // A null terminated list which creates an incoming_queue of tasks that are
   // aquired under a mutex for processing on this instance's thread. These tasks
   // have not yet been sorted out into items for our work_queue_ vs items that
   // will be handled by the TimerManager.
   TaskQueue incoming_queue_;
   // Protect access to incoming_queue_.
-  Lock incoming_queue_lock_;
+  mozilla::Mutex incoming_queue_lock_;
 
   RunState* state_;
   int run_depth_base_;
   bool shutting_down_;
 
 #if defined(OS_WIN)
   // Should be set to true before calling Windows APIs like TrackPopupMenu, etc
   // which enter a modal message loop.
--- a/ipc/chromium/src/base/message_pump_win.h
+++ b/ipc/chromium/src/base/message_pump_win.h
@@ -6,17 +6,16 @@
 
 #ifndef BASE_MESSAGE_PUMP_WIN_H_
 #define BASE_MESSAGE_PUMP_WIN_H_
 
 #include <windows.h>
 
 #include <list>
 
-#include "base/lock.h"
 #include "base/message_pump.h"
 #include "base/observer_list.h"
 #include "base/scoped_handle.h"
 #include "base/time.h"
 
 namespace base {
 
 // MessagePumpWin serves as the base for specialized versions of the MessagePump
--- a/ipc/chromium/src/base/time_win.cc
+++ b/ipc/chromium/src/base/time_win.cc
@@ -39,19 +39,19 @@
 
 #ifndef __MINGW32__
 #pragma comment(lib, "winmm.lib")
 #endif
 #include <windows.h>
 #include <mmsystem.h>
 
 #include "base/basictypes.h"
-#include "base/lock.h"
 #include "base/logging.h"
 #include "mozilla/Casting.h"
+#include "mozilla/StaticMutex.h"
 
 using base::Time;
 using base::TimeDelta;
 using base::TimeTicks;
 using mozilla::BitwiseCast;
 
 namespace {
 
@@ -211,37 +211,51 @@ DWORD (*tick_function)(void) = &timeGetT
 
 // We use timeGetTime() to implement TimeTicks::Now().  This can be problematic
 // because it returns the number of milliseconds since Windows has started,
 // which will roll over the 32-bit value every ~49 days.  We try to track
 // rollover ourselves, which works if TimeTicks::Now() is called at least every
 // 49 days.
 class NowSingleton {
  public:
-  NowSingleton() : rollover_(TimeDelta::FromMilliseconds(0)), last_seen_(0) {}
-
   TimeDelta Now() {
-    AutoLock locked(lock_);
+    mozilla::StaticMutexAutoLock locked(lock_);
     // We should hold the lock while calling tick_function to make sure that
     // we keep our last_seen_ stay correctly in sync.
     DWORD now = tick_function();
     if (now < last_seen_)
       rollover_ +=
           TimeDelta::FromMilliseconds(GG_LONGLONG(0x100000000));  // ~49.7 days.
     last_seen_ = now;
     return TimeDelta::FromMilliseconds(now) + rollover_;
   }
 
   static NowSingleton& instance() {
-    static NowSingleton now;
+    // This setup is a little gross: the `now` instance lives until libxul is
+    // unloaded, but leak checking runs prior to that, and would see a Mutex
+    // instance contained in NowSingleton as still live.  Said instance would
+    // be reported as a leak...but it's not, really.  To avoid that, we need
+    // to use StaticMutex (which is not leak-checked), but StaticMutex can't
+    // be a member variable.  So we have to have this separate variable and
+    // pass it into the NowSingleton constructor.
+    static mozilla::StaticMutex mutex;
+    static NowSingleton now(mutex);
     return now;
   }
 
  private:
-  Lock lock_;           // To protected last_seen_ and rollover_.
+  explicit NowSingleton(mozilla::StaticMutex& aMutex)
+    : lock_(aMutex)
+    , rollover_(TimeDelta::FromMilliseconds(0))
+    , last_seen_(0)
+  {
+  }
+  ~NowSingleton() = default;
+
+  mozilla::StaticMutex& lock_;  // To protected last_seen_ and rollover_.
   TimeDelta rollover_;  // Accumulation of time lost due to rollover.
   DWORD last_seen_;  // The last timeGetTime value we saw, to detect rollover.
 
   DISALLOW_COPY_AND_ASSIGN(NowSingleton);
 };
 
 }  // namespace
 
--- a/ipc/chromium/src/chrome/common/ipc_channel_posix.cc
+++ b/ipc/chromium/src/chrome/common/ipc_channel_posix.cc
@@ -20,24 +20,24 @@
 #include <sys/un.h>
 #include <sys/uio.h>
 
 #include <string>
 #include <map>
 
 #include "base/command_line.h"
 #include "base/eintr_wrapper.h"
-#include "base/lock.h"
 #include "base/logging.h"
 #include "base/process_util.h"
 #include "base/string_util.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/file_descriptor_set_posix.h"
 #include "chrome/common/ipc_message_utils.h"
 #include "mozilla/ipc/ProtocolUtils.h"
+#include "mozilla/StaticMutex.h"
 #include "mozilla/UniquePtr.h"
 
 #ifdef FUZZING
 #include "mozilla/ipc/Faulty.h"
 #endif
 
 // Use OS specific iovec array limit where it's possible.
 #if defined(IOV_MAX)
@@ -103,54 +103,64 @@ namespace {
 //
 // TODO(port): a client process cannot connect to multiple IPC channels with
 // this scheme.
 
 class PipeMap {
  public:
   // Lookup a given channel id. Return -1 if not found.
   int Lookup(const std::string& channel_id) {
-    AutoLock locked(lock_);
+    mozilla::StaticMutexAutoLock locked(lock_);
 
     ChannelToFDMap::const_iterator i = map_.find(channel_id);
     if (i == map_.end()) return -1;
     return i->second;
   }
 
   // Remove the mapping for the given channel id. No error is signaled if the
   // channel_id doesn't exist
   void Remove(const std::string& channel_id) {
-    AutoLock locked(lock_);
+    mozilla::StaticMutexAutoLock locked(lock_);
 
     ChannelToFDMap::iterator i = map_.find(channel_id);
     if (i != map_.end()) map_.erase(i);
   }
 
   // Insert a mapping from @channel_id to @fd. It's a fatal error to insert a
   // mapping if one already exists for the given channel_id
   void Insert(const std::string& channel_id, int fd) {
-    AutoLock locked(lock_);
+    mozilla::StaticMutexAutoLock locked(lock_);
     DCHECK(fd != -1);
 
     ChannelToFDMap::const_iterator i = map_.find(channel_id);
     CHECK(i == map_.end()) << "Creating second IPC server for '" << channel_id
                            << "' while first still exists";
     map_[channel_id] = fd;
   }
 
   static PipeMap& instance() {
-    static PipeMap map;
+    // This setup is a little gross: the `map` instance lives until libxul is
+    // unloaded, but leak checking runs prior to that, and would see a Mutex
+    // instance contained in PipeMap as still live.  Said instance would be
+    // reported as a leak...but it's not, really.  To avoid that, we need to
+    // use StaticMutex (which is not leak-checked), but StaticMutex can't be
+    // a member variable.  So we have to have this separate variable and pass
+    // it into the PipeMap constructor.
+    static mozilla::StaticMutex mutex;
+    static PipeMap map(mutex);
     return map;
   }
 
  private:
-  PipeMap() = default;
+  explicit PipeMap(mozilla::StaticMutex& aMutex)
+    : lock_(aMutex)
+  {}
   ~PipeMap() = default;
 
-  Lock lock_;
+  mozilla::StaticMutex& lock_;
   typedef std::map<std::string, int> ChannelToFDMap;
   ChannelToFDMap map_;
 };
 
 // This is the file descriptor number that a client process expects to find its
 // IPC socket.
 static int gClientChannelFd =
 #if defined(MOZ_WIDGET_ANDROID)
--- a/js/public/PropertySpec.h
+++ b/js/public/PropertySpec.h
@@ -101,21 +101,19 @@ struct JSPropertySpec {
   static_assert(offsetof(SelfHostedWrapper, funname) ==
                     offsetof(JSNativeWrapper, info),
                 "JS_SELF_HOSTED* macros below require that "
                 "SelfHostedWrapper::funname overlay "
                 "JSNativeWrapper::info");
 
  private:
   void checkAccessorsAreNative() const {
-    MOZ_ASSERT(accessors.getter.native.op);
-    // We may not have a setter at all.  So all we can assert here, for the
-    // native case is that if we have a jitinfo for the setter then we have
-    // a setter op too.  This is good enough to make sure we don't have a
-    // SelfHostedWrapper for the setter.
+    // We may have a getter or a setter or both.  And whichever ones we have
+    // should not have a SelfHostedWrapper for the accessor.
+    MOZ_ASSERT_IF(accessors.getter.native.info, accessors.getter.native.op);
     MOZ_ASSERT_IF(accessors.setter.native.info, accessors.setter.native.op);
   }
 
   void checkAccessorsAreSelfHosted() const {
     MOZ_ASSERT(!accessors.getter.selfHosted.unused);
     MOZ_ASSERT(!accessors.setter.selfHosted.unused);
   }
 };
--- a/media/mtransport/test/webrtcproxychannel_unittest.cpp
+++ b/media/mtransport/test/webrtcproxychannel_unittest.cpp
@@ -106,16 +106,20 @@ class FakeSocketTransportProvider : publ
   NS_IMETHOD GetTimeout(uint32_t aType, uint32_t *_retval) override {
     MOZ_ASSERT(false);
     return NS_OK;
   }
   NS_IMETHOD SetTimeout(uint32_t aType, uint32_t aValue) override {
     MOZ_ASSERT(false);
     return NS_OK;
   }
+  NS_IMETHOD SetLinger(bool aPolarity, int16_t aTimeout) override {
+    MOZ_ASSERT(false);
+    return NS_OK;
+  }
   NS_IMETHOD SetReuseAddrPort(bool reuseAddrPort) override {
     MOZ_ASSERT(false);
     return NS_OK;
   }
   NS_IMETHOD GetConnectionFlags(uint32_t *aConnectionFlags) override {
     MOZ_ASSERT(false);
     return NS_OK;
   }
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
@@ -6,16 +6,17 @@
 #include <cstdlib>
 #include <cerrno>
 #include <deque>
 #include <set>
 #include <sstream>
 #include <vector>
 
 #include "CSFLog.h"
+#include "base/histogram.h"
 #include "timecard.h"
 
 #include "jsapi.h"
 #include "nspr.h"
 #include "nss.h"
 #include "pk11pub.h"
 
 #include "nsNetCID.h"
--- a/media/webrtc/trunk/webrtc/modules/video_capture/objc/device_info.mm
+++ b/media/webrtc/trunk/webrtc/modules/video_capture/objc/device_info.mm
@@ -37,17 +37,19 @@ static NSArray* camera_presets = @[
 VideoCaptureModule::DeviceInfo* VideoCaptureImpl::CreateDeviceInfo() {
   return new DeviceInfoIos();
 }
 
 DeviceInfoIos::DeviceInfoIos() {
   this->Init();
 }
 
-DeviceInfoIos::~DeviceInfoIos() {}
+DeviceInfoIos::~DeviceInfoIos() {
+  [_captureInfo registerOwner:nil];
+}
 
 int32_t DeviceInfoIos::Init() {
   _captureInfo = [[DeviceInfoIosObjC alloc] init];
   [_captureInfo registerOwner:this];
 
   // Fill in all device capabilities.
   int deviceCount = [DeviceInfoIosObjC captureDeviceCount];
 
--- a/mozglue/misc/Mutex_posix.cpp
+++ b/mozglue/misc/Mutex_posix.cpp
@@ -122,32 +122,32 @@ mozilla::detail::MutexImpl::~MutexImpl()
 }
 
 inline void mozilla::detail::MutexImpl::mutexLock() {
   TRY_CALL_PTHREADS(
       pthread_mutex_lock(&platformData()->ptMutex),
       "mozilla::detail::MutexImpl::mutexLock: pthread_mutex_lock failed");
 }
 
-#ifdef XP_DARWIN
-inline bool mozilla::detail::MutexImpl::mutexTryLock() {
+bool mozilla::detail::MutexImpl::tryLock() { return mutexTryLock(); }
+
+bool mozilla::detail::MutexImpl::mutexTryLock() {
   int result = pthread_mutex_trylock(&platformData()->ptMutex);
   if (result == 0) {
     return true;
   }
 
   if (result == EBUSY) {
     return false;
   }
 
   REPORT_PTHREADS_ERROR(
       result,
       "mozilla::detail::MutexImpl::mutexTryLock: pthread_mutex_trylock failed");
 }
-#endif
 
 void mozilla::detail::MutexImpl::lock() {
 #ifndef XP_DARWIN
   mutexLock();
 #else
   // Mutex performance on OSX can be very poor if there's a lot of contention as
   // this causes excessive context switching. On Linux/FreeBSD we use the
   // adaptive mutex type (PTHREAD_MUTEX_ADAPTIVE_NP) to address this, but this
--- a/mozglue/misc/Mutex_windows.cpp
+++ b/mozglue/misc/Mutex_windows.cpp
@@ -17,16 +17,22 @@ mozilla::detail::MutexImpl::MutexImpl(re
 }
 
 mozilla::detail::MutexImpl::~MutexImpl() {}
 
 void mozilla::detail::MutexImpl::lock() {
   AcquireSRWLockExclusive(&platformData()->lock);
 }
 
+bool mozilla::detail::MutexImpl::tryLock() { return mutexTryLock(); }
+
+bool mozilla::detail::MutexImpl::mutexTryLock() {
+  return !!TryAcquireSRWLockExclusive(&platformData()->lock);
+}
+
 void mozilla::detail::MutexImpl::unlock() {
   ReleaseSRWLockExclusive(&platformData()->lock);
 }
 
 mozilla::detail::MutexImpl::PlatformData*
 mozilla::detail::MutexImpl::platformData() {
   static_assert(sizeof(platformData_) >= sizeof(PlatformData),
                 "platformData_ is too small");
--- a/mozglue/misc/PlatformMutex.h
+++ b/mozglue/misc/PlatformMutex.h
@@ -28,28 +28,29 @@ class MutexImpl {
 
   explicit MFBT_API MutexImpl(
       recordreplay::Behavior aRecorded = recordreplay::Behavior::Preserve);
   MFBT_API ~MutexImpl();
 
  protected:
   MFBT_API void lock();
   MFBT_API void unlock();
+  // We have a separate, forwarding API so internal uses don't have to go
+  // through the PLT.
+  MFBT_API bool tryLock();
 
  private:
   MutexImpl(const MutexImpl&) = delete;
   void operator=(const MutexImpl&) = delete;
   MutexImpl(MutexImpl&&) = delete;
   void operator=(MutexImpl&&) = delete;
   bool operator==(const MutexImpl& rhs) = delete;
 
   void mutexLock();
-#ifdef XP_DARWIN
   bool mutexTryLock();
-#endif
 
   PlatformData* platformData();
 
 #if !defined(XP_WIN)
   void* platformData_[sizeof(pthread_mutex_t) / sizeof(void*)];
   static_assert(sizeof(pthread_mutex_t) / sizeof(void*) != 0 &&
                     sizeof(pthread_mutex_t) % sizeof(void*) == 0,
                 "pthread_mutex_t must have pointer alignment");
--- a/netwerk/base/nsISocketTransport.idl
+++ b/netwerk/base/nsISocketTransport.idl
@@ -120,16 +120,23 @@ interface nsISocketTransport : nsITransp
      * Socket timeouts in seconds.  To specify no timeout, pass UINT32_MAX
      * as aValue to setTimeout.  The implementation may truncate timeout values
      * to a smaller range of values (e.g., 0 to 0xFFFF).
      */
     unsigned long getTimeout(in unsigned long aType);
     void          setTimeout(in unsigned long aType, in unsigned long aValue);
 
     /**
+     * Sets the SO_LINGER option with the specified values for the l_onoff and
+     * l_linger parameters. This applies PR_SockOpt_Linger before PR_Close and
+     * can be used with a timeout of zero to send an RST packet when closing.
+     */
+    void setLinger(in boolean aPolarity, in short aTimeout);
+
+    /**
      * True to set addr and port reuse socket options.
      */
     void setReuseAddrPort(in bool reuseAddrPort);
 
     /**
      * Values for the aType parameter passed to get/setTimeout.
      */
     const unsigned long TIMEOUT_CONNECT    = 0;
--- a/netwerk/base/nsSocketTransport2.cpp
+++ b/netwerk/base/nsSocketTransport2.cpp
@@ -712,16 +712,18 @@ nsSocketTransport::nsSocketTransport()
       mLock("nsSocketTransport.mLock"),
       mFD(this),
       mFDref(0),
       mFDconnected(false),
       mFDFastOpenInProgress(false),
       mSocketTransportService(gSocketTransportService),
       mInput(this),
       mOutput(this),
+      mLingerPolarity(false),
+      mLingerTimeout(0),
       mQoSBits(0x00),
       mKeepaliveEnabled(false),
       mKeepaliveIdleTimeS(-1),
       mKeepaliveRetryIntervalS(-1),
       mKeepaliveProbeCount(-1),
       mFastOpenCallback(nullptr),
       mFastOpenLayerHasBufferedData(false),
       mFastOpenStatus(TFO_NOT_SET),
@@ -1973,17 +1975,18 @@ class ThunkPRClose : public Runnable {
         mFD, gSocketTransportService->IsTelemetryEnabledAndNotSleepPhase());
     return NS_OK;
   }
 
  private:
   PRFileDesc *mFD;
 };
 
-void STS_PRCloseOnSocketTransport(PRFileDesc *fd) {
+void STS_PRCloseOnSocketTransport(PRFileDesc *fd, bool lingerPolarity,
+                                  int16_t lingerTimeout) {
   if (gSocketTransportService) {
     // Can't PR_Close() a socket off STS thread. Thunk it to STS to die
     gSocketTransportService->Dispatch(new ThunkPRClose(fd), NS_DISPATCH_NORMAL);
   } else {
     // something horrible has happened
     NS_ASSERTION(gSocketTransportService, "No STS service");
   }
 }
@@ -1994,23 +1997,32 @@ void nsSocketTransport::ReleaseFD_Locked
   NS_ASSERTION(mFD == fd, "wrong fd");
 
   if (--mFDref == 0) {
     if (gIOService->IsNetTearingDown() &&
         ((PR_IntervalNow() - gIOService->NetTearingDownStarted()) >
          gSocketTransportService->MaxTimeForPrClosePref())) {
       // If shutdown last to long, let the socket leak and do not close it.
       SOCKET_LOG(("Intentional leak"));
-    } else if (OnSocketThread()) {
-      SOCKET_LOG(("nsSocketTransport: calling PR_Close [this=%p]\n", this));
-      CloseSocket(
-          mFD, mSocketTransportService->IsTelemetryEnabledAndNotSleepPhase());
     } else {
-      // Can't PR_Close() a socket off STS thread. Thunk it to STS to die
-      STS_PRCloseOnSocketTransport(mFD);
+      if (mLingerPolarity || mLingerTimeout) {
+        PRSocketOptionData socket_linger;
+        socket_linger.option = PR_SockOpt_Linger;
+        socket_linger.value.linger.polarity = mLingerPolarity;
+        socket_linger.value.linger.linger = mLingerTimeout;
+        PR_SetSocketOption(mFD, &socket_linger);
+      }
+      if (OnSocketThread()) {
+        SOCKET_LOG(("nsSocketTransport: calling PR_Close [this=%p]\n", this));
+        CloseSocket(
+            mFD, mSocketTransportService->IsTelemetryEnabledAndNotSleepPhase());
+      } else {
+        // Can't PR_Close() a socket off STS thread. Thunk it to STS to die
+        STS_PRCloseOnSocketTransport(mFD, mLingerPolarity, mLingerTimeout);
+      }
     }
     mFD = nullptr;
   }
 }
 
 //-----------------------------------------------------------------------------
 // socket event handler impl
 
@@ -2752,16 +2764,26 @@ nsSocketTransport::SetTimeout(uint32_t t
 
 NS_IMETHODIMP
 nsSocketTransport::SetReuseAddrPort(bool reuseAddrPort) {
   mReuseAddrPort = reuseAddrPort;
   return NS_OK;
 }
 
 NS_IMETHODIMP
+nsSocketTransport::SetLinger(bool aPolarity, int16_t aTimeout) {
+  MutexAutoLock lock(mLock);
+
+  mLingerPolarity = aPolarity;
+  mLingerTimeout = aTimeout;
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 nsSocketTransport::SetQoSBits(uint8_t aQoSBits) {
   // Don't do any checking here of bits.  Why?  Because as of RFC-4594
   // several different Class Selector and Assured Forwarding values
   // have been defined, but that isn't to say more won't be added later.
   // In that case, any checking would be an impediment to interoperating
   // with newer QoS definitions.
 
   mQoSBits = aQoSBits;
--- a/netwerk/base/nsSocketTransport2.h
+++ b/netwerk/base/nsSocketTransport2.h
@@ -393,16 +393,20 @@ class nsSocketTransport final : public n
   nsSocketOutputStream mOutput;
 
   friend class nsSocketInputStream;
   friend class nsSocketOutputStream;
 
   // socket timeouts are not protected by any lock.
   uint16_t mTimeouts[2];
 
+  // linger options to use when closing
+  bool mLingerPolarity;
+  int16_t mLingerTimeout;
+
   // QoS setting for socket
   uint8_t mQoSBits;
 
   //
   // mFD access methods: called with mLock held.
   //
   PRFileDesc *GetFD_Locked();
   PRFileDesc *GetFD_LockedAlsoDuringFastOpen();
--- a/netwerk/cache2/CacheIOThread.cpp
+++ b/netwerk/cache2/CacheIOThread.cpp
@@ -591,17 +591,16 @@ NS_IMETHODIMP CacheIOThread::AfterProces
 
 // Memory reporting
 
 size_t CacheIOThread::SizeOfExcludingThis(
     mozilla::MallocSizeOf mallocSizeOf) const {
   MonitorAutoLock lock(const_cast<CacheIOThread*>(this)->mMonitor);
 
   size_t n = 0;
-  n += mallocSizeOf(mThread);
   for (const auto& event : mEventQueue) {
     n += event.ShallowSizeOfExcludingThis(mallocSizeOf);
     // Events referenced by the queues are arbitrary objects we cannot be sure
     // are reported elsewhere as well as probably not implementing nsISizeOf
     // interface.  Deliberatly omitting them from reporting here.
   }
 
   return n;
--- a/netwerk/protocol/http/TunnelUtils.cpp
+++ b/netwerk/protocol/http/TunnelUtils.cpp
@@ -1885,16 +1885,21 @@ SocketTransportShim::SetTimeout(uint32_t
 }
 
 NS_IMETHODIMP
 SocketTransportShim::SetReuseAddrPort(bool aReuseAddrPort) {
   return mWrapped->SetReuseAddrPort(aReuseAddrPort);
 }
 
 NS_IMETHODIMP
+SocketTransportShim::SetLinger(bool aPolarity, int16_t aTimeout) {
+  return mWrapped->SetLinger(aPolarity, aTimeout);
+}
+
+NS_IMETHODIMP
 SocketTransportShim::GetQoSBits(uint8_t *aQoSBits) {
   return mWrapped->GetQoSBits(aQoSBits);
 }
 
 NS_IMETHODIMP
 SocketTransportShim::SetQoSBits(uint8_t aQoSBits) {
   return mWrapped->SetQoSBits(aQoSBits);
 }
--- a/netwerk/test/httpserver/httpd.js
+++ b/netwerk/test/httpserver/httpd.js
@@ -393,17 +393,17 @@ nsHttpServer.prototype =
       trans.close(Cr.NS_BINDING_ABORTED);
       return;
     }
 
     var connectionNumber = ++this._connectionGen;
 
     try {
       var conn = new Connection(input, output, this, socket.port, trans.port,
-                                connectionNumber);
+                                connectionNumber, trans);
       var reader = new RequestReader(conn);
 
       // XXX add request timeout functionality here!
 
       // Note: must use main thread here, or we might get a GC that will cause
       //       threadsafety assertions.  We really need to fix XPConnect so that
       //       you can actually do things in multi-threaded JS.  :-(
       input.asyncWait(reader, 0, 0, gThreadManager.mainThread);
@@ -1062,17 +1062,18 @@ ServerIdentity.prototype =
  *   the server handling the connection
  * @param port : int
  *   the port on which the server is running
  * @param outgoingPort : int
  *   the outgoing port used by this connection
  * @param number : uint
  *   a serial number used to uniquely identify this connection
  */
-function Connection(input, output, server, port, outgoingPort, number) {
+function Connection(input, output, server, port, outgoingPort, number,
+                    transport) {
   dumpn("*** opening new connection " + number + " on port " + outgoingPort);
 
   /** Stream of incoming data. */
   this.input = input;
 
   /** Stream for outgoing data. */
   this.output = output;
 
@@ -1083,16 +1084,19 @@ function Connection(input, output, serve
   this.port = port;
 
   /** The outgoing poort used by this connection. */
   this._outgoingPort = outgoingPort;
 
   /** The serial number of this connection. */
   this.number = number;
 
+  /** Reference to the underlying transport. */
+  this.transport = transport;
+
   /**
    * The request for which a response is being generated, null if the
    * incoming request has not been fully received or if it had errors.
    */
   this.request = null;
 
   /** This allows a connection to disambiguate between a peer initiating a
    *  close and the socket being forced closed on shutdown.
@@ -3554,20 +3558,29 @@ Response.prototype =
    * response) because data may already have been sent (or because the response
    * might be expected to have been generated asynchronously or completely from
    * scratch by the handler), we stop processing this response and abruptly
    * close the connection.
    *
    * @param e : Error
    *   the exception which precipitated this abort, or null if no such exception
    *   was generated
+   * @param truncateConnection : Boolean
+   *   ensures that we truncate the connection using an RST packet, so the
+   *   client testing code is aware that an error occurred, otherwise it may
+   *   consider the response as valid.
    */
-  abort(e) {
+  abort(e, truncateConnection = false) {
     dumpn("*** abort(<" + e + ">)");
 
+    if (truncateConnection) {
+      dumpn("*** truncate connection");
+      this._connection.transport.setLinger(true, 0);
+    }
+
     // This response will be ended by the processor if one was created.
     var copier = this._asyncCopier;
     if (copier) {
       // We dispatch asynchronously here so that any pending writes of data to
       // the connection will be deterministically written.  This makes it easier
       // to specify exact behavior, and it makes observable behavior more
       // predictable for clients.  Note that the correctness of this depends on
       // callbacks in response to _waitToReadData in WriteThroughCopier
--- a/old-configure.in
+++ b/old-configure.in
@@ -2207,22 +2207,27 @@ if test -n "$MOZ_ANGLE_RENDERER"; then
     AC_MSG_ERROR([Couldn't determine MOZ_D3D_CPU_SUFFIX.])
   fi
 
   ######################################
   # Find _46+ for use by Vista+.
 
   # Find a D3D compiler DLL in a Windows SDK.
   MOZ_D3DCOMPILER_VISTA_DLL=
-  case "$MOZ_WINSDK_MAXVER" in
-  0x0603*|0x0A00*)
+  if test "$OS_ARCH" != "$HOST_OS_ARCH"; then
     MOZ_D3DCOMPILER_VISTA_DLL=d3dcompiler_47.dll
-    AC_MSG_RESULT([Found D3D compiler in Windows SDK.])
-  ;;
-  esac
+    AC_MSG_RESULT([Assuming D3D compiler will be in fxc2.])
+  else
+    case "$MOZ_WINSDK_MAXVER" in
+    0x0603*|0x0A00*)
+      MOZ_D3DCOMPILER_VISTA_DLL=d3dcompiler_47.dll
+      AC_MSG_RESULT([Found D3D compiler in Windows SDK.])
+    ;;
+    esac
+  fi
 
   if test -n "$MOZ_D3DCOMPILER_VISTA_DLL"; then
     # We have a name, now track down the path.
     if test -n "$WINDOWSSDKDIR"; then
       MOZ_D3DCOMPILER_VISTA_DLL_PATH="$WINDOWSSDKDIR/Redist/D3D/$MOZ_D3D_CPU_SUFFIX/$MOZ_D3DCOMPILER_VISTA_DLL"
       if test -f "$MOZ_D3DCOMPILER_VISTA_DLL_PATH"; then
         AC_MSG_RESULT([Found MOZ_D3DCOMPILER_VISTA_DLL_PATH: $MOZ_D3DCOMPILER_VISTA_DLL_PATH])
         MOZ_HAS_WINSDK_WITH_D3D=1
@@ -2230,23 +2235,30 @@ if test -n "$MOZ_ANGLE_RENDERER"; then
         AC_MSG_RESULT([AArch64 Windows includes d3dcompiler DLLs])
         MOZ_D3DCOMPILER_VISTA_DLL_PATH=
       else
         AC_MSG_RESULT([MOZ_D3DCOMPILER_VISTA_DLL_PATH doesn't exist: $MOZ_D3DCOMPILER_VISTA_DLL_PATH])
         AC_MSG_ERROR([Windows SDK at "$WINDOWSSDKDIR" appears broken. Try updating to MozillaBuild 1.9 final or higher.])
         MOZ_D3DCOMPILER_VISTA_DLL_PATH=
       fi
     else
-      AC_MSG_RESULT([Windows SDK not found.])
+      MOZ_D3DCOMPILER_VISTA_DLL_PATH="$(dirname $FXC)/$MOZ_D3DCOMPILER_VISTA_DLL"
+      if test -f "$MOZ_D3DCOMPILER_VISTA_DLL_PATH"; then
+        AC_MSG_RESULT([Found MOZ_D3DCOMPILER_VISTA_DLL_PATH: $MOZ_D3DCOMPILER_VISTA_DLL_PATH])
+      else
+        AC_MSG_RESULT([MOZ_D3DCOMPILER_VISTA_DLL_PATH doesn't exist: $MOZ_D3DCOMPILER_VISTA_DLL_PATH])
+        AC_MSG_ERROR([fxc2 or "$MOZ_D3DCOMPILER_VISTA_DLL" seem to be missing from the expected location.])
+        MOZ_D3DCOMPILER_VISTA_DLL_PATH=
+      fi
     fi
   else
     if test "$OS_ARCH" = "$HOST_OS_ARCH"; then
       AC_MSG_ERROR([Couldn't find Windows SDK 8.1 or higher needed for ANGLE.])
     else
-      AC_MSG_RESULT([Windows SDK not needed for ANGLE in Linux MinGW build.])
+      AC_MSG_ERROR([We should need "$MOZ_D3DCOMPILER_VISTA_DLL" for ANGLE in Linux MinGW build, but we didn't look for it.])
     fi
   fi
 
   if test -z "$MOZ_D3DCOMPILER_VISTA_DLL_PATH"; then
     MOZ_D3DCOMPILER_VISTA_DLL=
   fi
 
   # On mingw, check if headers are provided by toolchain.
@@ -2258,20 +2270,18 @@ if test -n "$MOZ_ANGLE_RENDERER"; then
   # Check that we found what we needed.
   MOZ_FOUND_A_D3D_COMPILER=
 
   if test -n "$MOZ_D3DCOMPILER_VISTA_DLL"; then
     MOZ_FOUND_A_D3D_COMPILER=1
     AC_MSG_RESULT([Found d3dcompiler DLL for Vista+: $MOZ_D3DCOMPILER_VISTA_DLL])
   fi
 
-  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
+  if test -z "MOZ_FOUND_A_D3D_COMPILER"; then
+    AC_MSG_ERROR([Couldn't find an acceptable D3D compiler DLL.])
   fi
 fi # MOZ_ANGLE_RENDERER
 
 dnl ========================================================
 dnl Gamepad support
 dnl ========================================================
 
 dnl Moved gamepad platform check to moz.build, linux header check still needed here.
--- a/testing/marionette/capture.js
+++ b/testing/marionette/capture.js
@@ -67,24 +67,22 @@ capture.element = function(node, highlig
  * @param {Array.<Node>=} highlights
  *     Optional array of nodes, around which a border will be marked to
  *     highlight them in the screenshot.
  *
  * @return {HTMLCanvasElement}
  *     The canvas element where the viewport has been painted on.
  */
 capture.viewport = function(win, highlights = []) {
-  let rootNode = win.document.documentElement;
-
   return capture.canvas(
       win,
       win.pageXOffset,
       win.pageYOffset,
-      rootNode.clientWidth,
-      rootNode.clientHeight,
+      win.innerWidth,
+      win.innerHeight,
       {highlights});
 };
 
 /**
  * Low-level interface to draw a rectangle off the framebuffer.
  *
  * @param {DOMWindow} win
  *     The DOM window used for the framebuffer, and providing the interfaces
--- a/testing/marionette/harness/marionette_harness/tests/unit/test_screenshot.py
+++ b/testing/marionette/harness/marionette_harness/tests/unit/test_screenshot.py
@@ -62,20 +62,17 @@ class ScreenCaptureTestCase(MarionetteTe
         return self.marionette.find_element(By.CSS_SELECTOR, ":root")
 
     @property
     def page_y_offset(self):
         return self.marionette.execute_script("return window.pageYOffset")
 
     @property
     def viewport_dimensions(self):
-        return self.marionette.execute_script("""
-            return [arguments[0].clientWidth,
-                    arguments[0].clientHeight];
-            """, script_args=[self.document_element])
+        return self.marionette.execute_script("return [window.innerWidth, window.innerHeight];")
 
     def assert_png(self, screenshot):
         """Test that screenshot is a Base64 encoded PNG file."""
         image = base64.decodestring(screenshot)
         self.assertEqual(imghdr.what("", image), "png")
 
     def assert_formats(self, element=None):
         if element is None:
--- a/testing/web-platform/tests/webdriver/tests/take_screenshot/__init__.py
+++ b/testing/web-platform/tests/webdriver/tests/take_screenshot/__init__.py
@@ -1,6 +1,2 @@
 def document_dimensions(session):
-    return tuple(session.execute_script("""
-        let devicePixelRatio = window.devicePixelRatio;
-        let rect = document.documentElement.getBoundingClientRect();
-        return [Math.floor(rect.width * devicePixelRatio), Math.floor(rect.height * devicePixelRatio)];
-        """))
+    return tuple(session.execute_script("return [window.innerWidth, window.innerHeight];"))
--- a/toolkit/components/downloads/test/unit/common_test_Download.js
+++ b/toolkit/components/downloads/test/unit/common_test_Download.js
@@ -1447,16 +1447,61 @@ add_task(async function test_error_sourc
   Assert.equal(download.error.result, Cr.NS_ERROR_NET_PARTIAL_TRANSFER);
 
   Assert.equal(false, await OS.File.exists(download.target.path));
   Assert.ok(!download.target.exists);
   Assert.equal(download.target.size, 0);
 });
 
 /**
+ * Ensures a download error is reported when an RST packet is received.
+ */
+add_task(async function test_error_source_netreset() {
+  if (AppConstants.platform == "win") {
+    return;
+  }
+
+  let download;
+  try {
+    if (!gUseLegacySaver) {
+      // When testing DownloadCopySaver, we want to check that the promise
+      // returned by the "start" method is rejected.
+      download = await promiseNewDownload(httpUrl("netreset.txt"));
+
+      Assert.ok(download.error === null);
+
+      await download.start();
+    } else {
+      // When testing DownloadLegacySaver, we cannot be sure whether we are
+      // testing the promise returned by the "start" method or we are testing
+      // the "error" property checked by promiseDownloadStopped.  This happens
+      // because we don't have control over when the download is started.
+      download = await promiseStartLegacyDownload(httpUrl("netreset.txt"));
+      await promiseDownloadStopped(download);
+    }
+    do_throw("The download should have failed.");
+  } catch (ex) {
+    if (!(ex instanceof Downloads.Error) || !ex.becauseSourceFailed) {
+      throw ex;
+    }
+    // A specific error object is thrown when reading from the source fails.
+  }
+
+  // Check the properties now that the download stopped.
+  Assert.ok(download.stopped);
+  Assert.ok(!download.canceled);
+  Assert.ok(download.error !== null);
+  Assert.ok(download.error.becauseSourceFailed);
+  Assert.ok(!download.error.becauseTargetFailed);
+  Assert.equal(download.error.result, Cr.NS_ERROR_NET_RESET);
+
+  Assert.equal(false, await OS.File.exists(download.target.path));
+});
+
+/**
  * Ensures download error details are reported on local writing failures.
  */
 add_task(async function test_error_target() {
   // Create a file without write access permissions before downloading.
   let targetFile = getTempFile(TEST_TARGET_FILE_NAME);
   targetFile.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0);
   try {
     let download;
--- a/toolkit/components/downloads/test/unit/head.js
+++ b/toolkit/components/downloads/test/unit/head.js
@@ -6,16 +6,17 @@
 /**
  * Provides infrastructure for automated download components tests.
  */
 
 "use strict";
 
 // Globals
 
+ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
 ChromeUtils.import("resource://gre/modules/Integration.jsm");
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 
 ChromeUtils.defineModuleGetter(this, "DownloadPaths",
                                "resource://gre/modules/DownloadPaths.jsm");
 ChromeUtils.defineModuleGetter(this, "Downloads",
                                "resource://gre/modules/Downloads.jsm");
 ChromeUtils.defineModuleGetter(this, "FileUtils",
@@ -713,16 +714,30 @@ add_task(function test_common_initialize
 
   // This URL will emulate being blocked by Windows Parental controls
   gHttpServer.registerPathHandler("/parentalblocked.zip",
     function(aRequest, aResponse) {
       aResponse.setStatusLine(aRequest.httpVersion, 450,
                               "Blocked by Windows Parental Controls");
     });
 
+  // This URL sends some data followed by an RST packet
+  gHttpServer.registerPathHandler("/netreset.txt",
+    function(aRequest, aResponse) {
+      info("Starting response that will be aborted.");
+      aResponse.processAsync();
+      aResponse.setHeader("Content-Type", "text/plain", false);
+      aResponse.write(TEST_DATA_SHORT);
+      promiseExecuteSoon().then(() => {
+        aResponse.abort(null, true);
+        aResponse.finish();
+        info("Aborting response with network reset.");
+      }).then(null, Cu.reportError);
+    });
+
   // During unit tests, most of the functions that require profile access or
   // operating system features will be disabled. Individual tests may override
   // them again to check for specific behaviors.
   Integration.downloads.register(base => ({
     __proto__: base,
     loadPublicDownloadListFromStore: () => Promise.resolve(),
     shouldKeepBlockedData: () => Promise.resolve(false),
     shouldBlockForParentalControls: () => Promise.resolve(false),
--- a/toolkit/components/downloads/test/unit/test_DownloadPaths.js
+++ b/toolkit/components/downloads/test/unit/test_DownloadPaths.js
@@ -1,17 +1,15 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 /**
  * Tests for the "DownloadPaths.jsm" JavaScript module.
  */
 
-ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
-
 function testSanitize(leafName, expectedLeafName) {
   Assert.equal(DownloadPaths.sanitize(leafName), expectedLeafName);
 }
 
 function testSplitBaseNameAndExtension(aLeafName, [aBase, aExt]) {
   var [base, ext] = DownloadPaths.splitBaseNameAndExtension(aLeafName);
   Assert.equal(base, aBase);
   Assert.equal(ext, aExt);
--- a/toolkit/content/widgets/popup.xml
+++ b/toolkit/content/widgets/popup.xml
@@ -18,16 +18,143 @@
         <children/>
       </xul:arrowscrollbox>
     </content>
 
     <implementation>
       <field name="scrollBox" readonly="true">
         document.getAnonymousElementByAttribute(this, "class", "popup-internal-box");
       </field>
+
+      <field name="AUTOSCROLL_INTERVAL">25</field>
+      <field name="NOT_DRAGGING">0</field>
+      <field name="DRAG_OVER_BUTTON">-1</field>
+      <field name="DRAG_OVER_POPUP">1</field>
+
+      <field name="_draggingState">this.NOT_DRAGGING</field>
+      <field name="_scrollTimer">0</field>
+
+      <method name="_enableDragScrolling">
+        <!-- when overItem is true, drag started over menuitem; when false, drag
+             started while the popup was opening.
+          -->
+        <parameter name="overItem"/>
+        <body>
+        <![CDATA[
+          if (!this._draggingState) {
+            this.setCaptureAlways();
+            this._draggingState = overItem ? this.DRAG_OVER_POPUP : this.DRAG_OVER_BUTTON;
+          }
+        ]]>
+        </body>
+      </method>
+
+      <method name="_clearScrollTimer">
+        <body>
+        <![CDATA[
+          if (this._scrollTimer) {
+            this.ownerGlobal.clearInterval(this._scrollTimer);
+            this._scrollTimer = 0;
+          }
+        ]]>
+        </body>
+      </method>
+
+      <constructor><![CDATA[
+        // Enable the drag-to-scroll events only in menulist popups.
+        if (!this.parentNode || this.parentNode.localName != "menulist") {
+          return;
+        }
+
+        // XBL bindings might be constructed more than once.
+        if (this.eventListenersAdded) {
+          return;
+        }
+        this.eventListenersAdded = true;
+
+        this.addEventListener("popupshown", () => {
+          // Enable drag scrolling even when the mouse wasn't used. The
+          // mousemove handler will remove it if the mouse isn't down.
+          this._enableDragScrolling(false);
+        });
+
+        this.addEventListener("popuphidden", () => {
+          this._draggingState = this.NOT_DRAGGING;
+          this._clearScrollTimer();
+          this.releaseCapture();
+        });
+
+        this.addEventListener("mousedown", event => {
+          if (event.button != 0) {
+            return;
+          }
+
+          if (this.state == "open" &&
+            (event.target.localName == "menuitem" ||
+              event.target.localName == "menu" ||
+              event.target.localName == "menucaption")) {
+            this._enableDragScrolling(true);
+          }
+        });
+
+        this.addEventListener("mouseup", event => {
+          if (event.button != 0) {
+            return;
+          }
+
+          this._draggingState = this.NOT_DRAGGING;
+          this._clearScrollTimer();
+        });
+
+        this.addEventListener("mousemove", event => {
+          if (!this._draggingState) {
+            return;
+          }
+
+          this._clearScrollTimer();
+
+          // If the user released the mouse before the popup opens, we will
+          // still be capturing, so check that the button is still pressed. If
+          // not, release the capture and do nothing else. This also handles if
+          // the dropdown was opened via the keyboard.
+          if (!(event.buttons & 1)) {
+            this._draggingState = this.NOT_DRAGGING;
+            this.releaseCapture();
+            return;
+          }
+
+          // If dragging outside the top or bottom edge of the popup, but within
+          // the popup area horizontally, scroll the list in that direction. The
+          // _draggingState flag is used to ensure that scrolling does not start
+          // until the mouse has moved over the popup first, preventing
+          // scrolling while over the dropdown button.
+          let popupRect = this.getOuterScreenRect();
+          if (event.screenX >= popupRect.left &&
+              event.screenX <= popupRect.right) {
+            if (this._draggingState == this.DRAG_OVER_BUTTON) {
+              if (event.screenY > popupRect.top &&
+                  event.screenY < popupRect.bottom) {
+                this._draggingState = this.DRAG_OVER_POPUP;
+              }
+            }
+
+            if (this._draggingState == this.DRAG_OVER_POPUP &&
+                (event.screenY <= popupRect.top ||
+                 event.screenY >= popupRect.bottom)) {
+              let scrollAmount = event.screenY <= popupRect.top ? -1 : 1;
+              this.scrollBox.scrollByIndex(scrollAmount, true);
+
+              let win = this.ownerGlobal;
+              this._scrollTimer = win.setInterval(() => {
+                this.scrollBox.scrollByIndex(scrollAmount, true);
+              }, this.AUTOSCROLL_INTERVAL);
+            }
+          }
+        });
+      ]]></constructor>
     </implementation>
 
     <handlers>
       <handler event="popupshowing" phase="target">
         <![CDATA[
           var array = [];
           var width = 0;
           for (var menuitem = this.firstElementChild; menuitem; menuitem = menuitem.nextElementSibling) {
@@ -257,129 +384,9 @@
           this.removeAttribute("animate");
         }
       </handler>
       <handler event="popuppositioned" phase="target">
         this.adjustArrowPosition();
       </handler>
     </handlers>
   </binding>
-
-  <binding id="popup-scrollbars" extends="chrome://global/content/bindings/popup.xml#popup">
-    <content>
-      <xul:arrowscrollbox class="popup-internal-box" flex="1" orient="vertical"
-                          smoothscroll="false">
-        <children/>
-      </xul:arrowscrollbox>
-    </content>
-    <implementation>
-      <field name="AUTOSCROLL_INTERVAL">25</field>
-      <field name="NOT_DRAGGING">0</field>
-      <field name="DRAG_OVER_BUTTON">-1</field>
-      <field name="DRAG_OVER_POPUP">1</field>
-
-      <field name="_draggingState">this.NOT_DRAGGING</field>
-      <field name="_scrollTimer">0</field>
-
-      <method name="enableDragScrolling">
-        <!-- when overItem is true, drag started over menuitem; when false, drag
-             started while the popup was opening.
-          -->
-        <parameter name="overItem"/>
-        <body>
-        <![CDATA[
-          if (!this._draggingState) {
-            this.setCaptureAlways();
-            this._draggingState = overItem ? this.DRAG_OVER_POPUP : this.DRAG_OVER_BUTTON;
-          }
-        ]]>
-        </body>
-      </method>
-      <method name="_clearScrollTimer">
-        <body>
-        <![CDATA[
-          if (this._scrollTimer) {
-            this.ownerGlobal.clearInterval(this._scrollTimer);
-            this._scrollTimer = 0;
-          }
-        ]]>
-        </body>
-      </method>
-    </implementation>
-    <handlers>
-      <handler event="popupshown">
-        // Enable drag scrolling even when the mouse wasn't used. The mousemove
-        // handler will remove it if the mouse isn't down.
-        this.enableDragScrolling(false);
-      </handler>
-
-      <handler event="popuphidden">
-      <![CDATA[
-        this._draggingState = this.NOT_DRAGGING;
-        this._clearScrollTimer();
-        this.releaseCapture();
-      ]]>
-      </handler>
-
-      <handler event="mousedown" button="0">
-      <![CDATA[
-        if (this.state == "open" &&
-            (event.target.localName == "menuitem" ||
-             event.target.localName == "menu" ||
-             event.target.localName == "menucaption")) {
-          this.enableDragScrolling(true);
-        }
-      ]]>
-      </handler>
-      <handler event="mouseup" button="0">
-      <![CDATA[
-        this._draggingState = this.NOT_DRAGGING;
-        this._clearScrollTimer();
-      ]]>
-      </handler>
-      <handler event="mousemove">
-      <![CDATA[
-        if (!this._draggingState) {
-          return;
-        }
-
-        this._clearScrollTimer();
-
-        // If the user released the mouse before the popup opens, we will
-        // still be capturing, so check that the button is still pressed. If
-        // not, release the capture and do nothing else. This also handles if
-        // the dropdown was opened via the keyboard.
-        if (!(event.buttons & 1)) {
-          this._draggingState = this.NOT_DRAGGING;
-          this.releaseCapture();
-          return;
-        }
-
-        // If dragging outside the top or bottom edge of the popup, but within
-        // the popup area horizontally, scroll the list in that direction. The
-        // _draggingState flag is used to ensure that scrolling does not start
-        // until the mouse has moved over the popup first, preventing scrolling
-        // while over the dropdown button.
-        let popupRect = this.getOuterScreenRect();
-        if (event.screenX >= popupRect.left && event.screenX <= popupRect.right) {
-          if (this._draggingState == this.DRAG_OVER_BUTTON) {
-            if (event.screenY > popupRect.top && event.screenY < popupRect.bottom) {
-              this._draggingState = this.DRAG_OVER_POPUP;
-            }
-          }
-
-          if (this._draggingState == this.DRAG_OVER_POPUP &&
-              (event.screenY <= popupRect.top || event.screenY >= popupRect.bottom)) {
-            let scrollAmount = event.screenY <= popupRect.top ? -1 : 1;
-            this.scrollBox.scrollByIndex(scrollAmount, true);
-
-            let win = this.ownerGlobal;
-            this._scrollTimer = win.setInterval(() => {
-              this.scrollBox.scrollByIndex(scrollAmount, true);
-            }, this.AUTOSCROLL_INTERVAL);
-          }
-        }
-      ]]>
-      </handler>
-    </handlers>
-  </binding>
-
 </bindings>
--- a/toolkit/moz.configure
+++ b/toolkit/moz.configure
@@ -1288,16 +1288,17 @@ set_config('MOZ_LAYOUT_DEBUGGER', depend
 
 
 # Shader Compiler for Windows (and MinGW Cross Compile)
 # ==============================================================
 
 with only_when(compile_environment):
     fxc = check_prog('FXC', ('fxc.exe', 'fxc2.exe'), when=depends(target)
                      (lambda t: t.kernel == 'WINNT'))
+    add_old_configure_assignment('FXC', fxc)
     wine = check_prog('WINE', ['wine'], when=depends(target, host)
                       (lambda t, h: t.kernel == 'WINNT' and h.kernel == 'Linux'))
 
 
 # VPX
 # ===
 
 with only_when(compile_environment):
--- a/toolkit/mozapps/update/nsIUpdateService.idl
+++ b/toolkit/mozapps/update/nsIUpdateService.idl
@@ -23,32 +23,32 @@ webidl Document;
 interface nsIUpdatePatch : nsISupports
 {
   /**
    * The type of this patch:
    * "partial"      A binary difference between two application versions
    * "complete"     A complete patch containing all of the replacement files
    *                to update to the new version
    */
-  attribute AString type;
+  readonly attribute AString type;
 
   /**
    * The URL this patch was being downloaded from
    */
-  attribute AString URL;
+  readonly attribute AString URL;
 
   /**
    * The final URL this patch was being downloaded from
    */
   attribute AString finalURL;
 
   /**
    * The size of this file, in bytes.
    */
-  attribute unsigned long size;
+  readonly attribute unsigned long size;
 
   /**
    * The state of this patch
    */
   attribute AString state;
 
   /**
    * A numeric error code that conveys additional information about the state of
@@ -87,69 +87,69 @@ interface nsIUpdatePatch : nsISupports
 [scriptable, uuid(e094c045-f4ff-41fd-92da-cd2effd2c7c9)]
 interface nsIUpdate : nsISupports
 {
   /**
    * The type of update:
    *   "major"  A major new version of the Application
    *   "minor"  A minor update to the Application (e.g. security update)
    */
-  attribute AString type;
+  readonly attribute AString type;
 
   /**
    * The name of the update, or "<Application Name> <Update Version>"
    */
-  attribute AString name;
+  readonly attribute AString name;
 
   /**
    * The string to display in the user interface for the version. If you want
    * a real version number use appVersion.
    */
-  attribute AString displayVersion;
+  readonly attribute AString displayVersion;
 
   /**
    * The Application version of this update.
    */
-  attribute AString appVersion;
+  readonly attribute AString appVersion;
 
   /**
    * The Application version prior to the application being updated.
    */
-  attribute AString previousAppVersion;
+  readonly attribute AString previousAppVersion;
 
   /**
    * The Build ID of this update. Used to determine a particular build, down
    * to the hour, minute and second of its creation. This allows the system
    * to differentiate between several nightly builds with the same |version|
    * for example.
    */
-  attribute AString buildID;
+  readonly attribute AString buildID;
 
   /**
    * The URL to a page which offers details about the content of this
    * update. Ideally, this page is not the release notes but some other page
    * that summarizes the differences between this update and the previous,
    * which also links to the release notes.
    */
-  attribute AString detailsURL;
+  readonly attribute AString detailsURL;
 
   /**
    * The URL to the Update Service that supplied this update.
    */
-  attribute AString serviceURL;
+  readonly attribute AString serviceURL;
 
   /**
    * The channel used to retrieve this update from the Update Service.
    */
-  attribute AString channel;
+  readonly attribute AString channel;
 
   /**
    * Whether the update is no longer supported on this system.
    */
-  attribute boolean unsupported;
+  readonly attribute boolean unsupported;
   
   /**
    * Allows overriding the default amount of time in seconds before prompting the
    * user to apply an update. If not specified, the value of
    * app.update.promptWaitTime will be used.
    */
   attribute long long promptWaitTime;
 
--- a/toolkit/themes/linux/global/global.css
+++ b/toolkit/themes/linux/global/global.css
@@ -12,20 +12,16 @@
 
 @namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
 @namespace html url("http://www.w3.org/1999/xhtml");
 
 %include ../../shared/global.inc.css
 
 /* ::::: XBL bindings ::::: */
 
-menulist > menupopup {
-  -moz-binding: url("chrome://global/content/bindings/popup.xml#popup-scrollbars");
-}
-
 @media (-moz-menubar-drag) {
   toolbar[type="menubar"] {
     -moz-binding: url("chrome://global/content/bindings/toolbar.xml#toolbar-drag");
   }
 }
 
 /* ::::: Variables ::::: */
 :root {
--- a/toolkit/themes/osx/global/global.css
+++ b/toolkit/themes/osx/global/global.css
@@ -6,22 +6,16 @@
 @import url("chrome://global/locale/intl.css");
 @import url("chrome://global/content/widgets.css");
 
 %include shared.inc
 @namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
 
 %include ../../shared/global.inc.css
 
-/* ::::: XBL bindings ::::: */
-
-menulist > menupopup {
-  -moz-binding: url("chrome://global/content/bindings/popup.xml#popup-scrollbars");
-}
-
 /* ::::: Variables ::::: */
 :root {
   --arrowpanel-padding: 16px;
   --default-arrowpanel-background: #fff;
   --default-arrowpanel-color: hsl(0,0%,10%);
   --default-arrowpanel-border-color: hsla(210,4%,10%,.05);
   --arrowpanel-background: var(--default-arrowpanel-background);
   --arrowpanel-color: var(--default-arrowpanel-color);
--- a/toolkit/themes/windows/global/global.css
+++ b/toolkit/themes/windows/global/global.css
@@ -10,22 +10,16 @@
 @import url("chrome://global/locale/intl.css");
 @import url("chrome://global/content/widgets.css");
 
 @namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
 @namespace html url("http://www.w3.org/1999/xhtml");
 
 %include ../../shared/global.inc.css
 
-/* ::::: XBL bindings ::::: */
-
-menulist > menupopup {
-  -moz-binding: url("chrome://global/content/bindings/popup.xml#popup-scrollbars");
-}
-
 /* ::::: Variables ::::: */
 :root {
   --arrowpanel-padding: 10px;
   --default-arrowpanel-background: -moz-field;
   --default-arrowpanel-color: -moz-fieldText;
   --default-arrowpanel-border-color: ThreeDShadow;
   --arrowpanel-background: var(--default-arrowpanel-background);
   --arrowpanel-color: var(--default-arrowpanel-color);
--- a/xpcom/threads/BlockingResourceBase.cpp
+++ b/xpcom/threads/BlockingResourceBase.cpp
@@ -344,16 +344,26 @@ void BlockingResourceBase::Release() {
 // Debug implementation of (OffTheBooks)Mutex
 void OffTheBooksMutex::Lock() {
   CheckAcquire();
   this->lock();
   mOwningThread = PR_GetCurrentThread();
   Acquire();
 }
 
+bool OffTheBooksMutex::TryLock() {
+  CheckAcquire();
+  bool locked = this->tryLock();
+  if (locked) {
+    mOwningThread = PR_GetCurrentThread();
+    Acquire();
+  }
+  return locked;
+}
+
 void OffTheBooksMutex::Unlock() {
   Release();
   mOwningThread = nullptr;
   this->unlock();
 }
 
 void OffTheBooksMutex::AssertCurrentThreadOwns() const {
   MOZ_ASSERT(IsAcquired() && mOwningThread == PR_GetCurrentThread());
--- a/xpcom/threads/Monitor.h
+++ b/xpcom/threads/Monitor.h
@@ -25,16 +25,17 @@ class Monitor {
  public:
   explicit Monitor(const char* aName, recordreplay::Behavior aRecorded =
                                           recordreplay::Behavior::Preserve)
       : mMutex(aName, aRecorded), mCondVar(mMutex, "[Monitor.mCondVar]") {}
 
   ~Monitor() {}
 
   void Lock() { mMutex.Lock(); }
+  bool TryLock() { return mMutex.TryLock(); }
   void Unlock() { mMutex.Unlock(); }
 
   void Wait() { mCondVar.Wait(); }
   CVStatus Wait(TimeDuration aDuration) { return mCondVar.Wait(aDuration); }
 
   nsresult Notify() { return mCondVar.Notify(); }
   nsresult NotifyAll() { return mCondVar.NotifyAll(); }
 
--- a/xpcom/threads/Mutex.h
+++ b/xpcom/threads/Mutex.h
@@ -61,16 +61,21 @@ class OffTheBooksMutex : public detail::
 
 #ifndef DEBUG
   /**
    * Lock this mutex.
    **/
   void Lock() { this->lock(); }
 
   /**
+   * Try to lock this mutex, returning true if we were successful.
+   **/
+  bool TryLock() { return this->tryLock(); }
+
+  /**
    * Unlock this mutex.
    **/
   void Unlock() { this->unlock(); }
 
   /**
    * Assert that the current thread owns this mutex in debug builds.
    *
    * Does nothing in non-debug builds.
@@ -84,16 +89,17 @@ class OffTheBooksMutex : public detail::
    * non-debug builds due to difficulties in dealing with memory ordering.
    *
    * It is therefore mostly useful as documentation.
    **/
   void AssertNotCurrentThreadOwns() const {}
 
 #else
   void Lock();
+  bool TryLock();
   void Unlock();
 
   void AssertCurrentThreadOwns() const;
 
   void AssertNotCurrentThreadOwns() const {
     // FIXME bug 476536
   }