Merge mozilla-central to fx-team
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Fri, 25 Sep 2015 14:42:13 +0200
changeset 264533 841c0c9779d2b97df0cad60b701d4e25e655e2f2
parent 264532 efd51878d60c2632c654cdc95907eaf6e15d3620 (current diff)
parent 264409 543e1b3a25887258a70d1f2dab3cb287d0d500e4 (diff)
child 264534 4b20c11bc86014538dca678e7bccbdbeea8b472f
push id65658
push userkwierso@gmail.com
push dateSat, 26 Sep 2015 01:02:44 +0000
treeherdermozilla-inbound@1fa901135ac9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone44.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 fx-team
js/public/UbiNodeTraverse.h
testing/web-platform/meta/XMLHttpRequest/setrequestheader-content-type.htm.ini
--- a/accessible/base/DocManager.h
+++ b/accessible/base/DocManager.h
@@ -82,16 +82,19 @@ public:
     MOZ_ASSERT(result, "Why didn't we find the document!");
   }
 
   /*
    * Notify of a new top level document in a content process.
    */
   static void RemoteDocAdded(DocAccessibleParent* aDoc);
 
+  static const nsTArray<DocAccessibleParent*>* TopLevelRemoteDocs()
+    { return sRemoteDocuments; }
+
 #ifdef DEBUG
   bool IsProcessingRefreshDriverNotification() const;
 #endif
 
 protected:
   DocManager();
   virtual ~DocManager() { }
 
--- a/accessible/ipc/DocAccessibleParent.h
+++ b/accessible/ipc/DocAccessibleParent.h
@@ -118,16 +118,20 @@ public:
 
     ProxyEntry* e = mAccessibles.GetEntry(aID);
     return e ? e->mProxy : nullptr;
   }
 
   const ProxyAccessible* GetAccessible(uintptr_t aID) const
     { return const_cast<DocAccessibleParent*>(this)->GetAccessible(aID); }
 
+  size_t ChildDocCount() const { return mChildDocs.Length(); }
+  const DocAccessibleParent* ChildDocAt(size_t aIdx) const
+    { return mChildDocs[aIdx]; }
+
 private:
 
   class ProxyEntry : public PLDHashEntryHdr
   {
   public:
     explicit ProxyEntry(const void*) : mProxy(nullptr) {}
     ProxyEntry(ProxyEntry&& aOther) :
       mProxy(aOther.mProxy) { aOther.mProxy = nullptr; }
--- a/accessible/windows/msaa/AccessibleWrap.cpp
+++ b/accessible/windows/msaa/AccessibleWrap.cpp
@@ -1407,53 +1407,73 @@ GetAccessibleInSubtree(DocAccessible* aD
     if (child)
       return child;
   }
 
     return nullptr;
   }
 #endif
 
+static AccessibleWrap*
+GetProxiedAccessibleInSubtree(const DocAccessibleParent* aDoc, uint32_t aID)
+{
+  auto wrapper = static_cast<DocProxyAccessibleWrap*>(WrapperFor(aDoc));
+  AccessibleWrap* child = wrapper->GetAccessibleByID(aID);
+  if (child) {
+    return child;
+  }
+
+  size_t childDocs = aDoc->ChildDocCount();
+  for (size_t i = 0; i < childDocs; i++) {
+    const DocAccessibleParent* childDoc = aDoc->ChildDocAt(i);
+    child = GetProxiedAccessibleInSubtree(childDoc, aID);
+    if (child) {
+      return child;
+    }
+  }
+
+  return nullptr;
+}
+
 Accessible*
 AccessibleWrap::GetXPAccessibleFor(const VARIANT& aVarChild)
 {
   if (aVarChild.vt != VT_I4)
     return nullptr;
 
   // if its us real easy - this seems to always be the case
   if (aVarChild.lVal == CHILDID_SELF)
     return this;
 
-  if (IsProxy()) {
-    if (Proxy()->MustPruneChildren())
-      return nullptr;
-
-    if (aVarChild.lVal > 0)
-      return WrapperFor(Proxy()->ChildAt(aVarChild.lVal - 1));
-
-    // XXX Don't implement negative child ids for now because annoying, and
-    // doesn't seem to be speced.
+  if (IsProxy() ? Proxy()->MustPruneChildren() : nsAccUtils::MustPrune(this)) {
     return nullptr;
   }
 
-  if (nsAccUtils::MustPrune(this))
-    return nullptr;
+  if (aVarChild.lVal > 0) {
+    // Gecko child indices are 0-based in contrast to indices used in MSAA.
+    if (IsProxy()) {
+      return WrapperFor(Proxy()->ChildAt(aVarChild.lVal - 1));
+    } else {
+      return GetChildAt(aVarChild.lVal - 1);
+    }
+  }
 
   // If lVal negative then it is treated as child ID and we should look for
   // accessible through whole accessible subtree including subdocuments.
   // Otherwise we treat lVal as index in parent.
-
-  if (aVarChild.lVal < 0) {
-    // Convert child ID to unique ID.
+  // Convert child ID to unique ID.
+  // First handle the case that both this accessible and the id'd one are in
+  // this process.
+  if (!IsProxy()) {
     void* uniqueID = reinterpret_cast<void*>(-aVarChild.lVal);
 
     DocAccessible* document = Document();
     Accessible* child =
 #ifdef _WIN64
-    GetAccessibleInSubtree(document, static_cast<uint32_t>(aVarChild.lVal));
+      GetAccessibleInSubtree(document, static_cast<uint32_t>(aVarChild.lVal));
 #else
       document->GetAccessibleByUniqueIDInSubtree(uniqueID);
 #endif
 
     // If it is a document then just return an accessible.
     if (IsDoc())
       return child;
 
@@ -1461,22 +1481,75 @@ AccessibleWrap::GetXPAccessibleFor(const
     // ARIA documents and popups).
     Accessible* parent = child;
     while (parent && parent != document) {
       if (parent == this)
         return child;
 
       parent = parent->Parent();
     }
+  }
+
+  // Now see about the case that both this accessible and the target one are
+  // proxied.
+  uint32_t id = aVarChild.lVal;
+  if (IsProxy()) {
+    DocAccessibleParent* proxyDoc = Proxy()->Document();
+    AccessibleWrap* wrapper = GetProxiedAccessibleInSubtree(proxyDoc, id);
+    MOZ_ASSERT(wrapper->IsProxy());
+
+    ProxyAccessible* parent = wrapper->Proxy();
+    while (parent && parent != proxyDoc) {
+      if (parent == this->Proxy()) {
+        return wrapper;
+      }
+
+      parent = parent->Parent();
+    }
 
     return nullptr;
   }
 
-  // Gecko child indices are 0-based in contrast to indices used in MSAA.
-  return GetChildAt(aVarChild.lVal - 1);
+  // Finally we need to handle the case that this accessible is in the main
+  // process, but the target is proxied.  This is the case when the target
+  // accessible is in a child document of this one.
+  DocAccessibleParent* proxyDoc = nullptr;
+  DocAccessible* doc = Document();
+  const nsTArray<DocAccessibleParent*>* remoteDocs =
+    DocManager::TopLevelRemoteDocs();
+  if (!remoteDocs) {
+    return nullptr;
+  }
+
+  size_t docCount = remoteDocs->Length();
+  for (size_t i = 0; i < docCount; i++) {
+    Accessible* outerDoc = remoteDocs->ElementAt(i)->OuterDocOfRemoteBrowser();
+    if (!outerDoc) {
+      continue;
+    }
+
+    if (outerDoc->Document() != doc) {
+      continue;
+    }
+
+    Accessible* parent = outerDoc;
+    while (parent && parent != doc) {
+      if (parent == this) {
+        AccessibleWrap* proxyWrapper =
+          GetProxiedAccessibleInSubtree(remoteDocs->ElementAt(i), id);
+        if (proxyWrapper) {
+          return proxyWrapper;
+        }
+      }
+
+      parent = parent->Parent();
+    }
+  }
+
+  return nullptr;
 }
 
 void
 AccessibleWrap::UpdateSystemCaretFor(Accessible* aAccessible)
 {
   // Move the system caret so that Windows Tablet Edition and tradional ATs with 
   // off-screen model can follow the caret
   ::DestroyCaret();
--- a/accessible/windows/msaa/AccessibleWrap.h
+++ b/accessible/windows/msaa/AccessibleWrap.h
@@ -227,17 +227,17 @@ protected:
     NAVRELATION_NODE_PARENT_OF = 0x1010,
     NAVRELATION_CONTAINING_DOCUMENT = 0x1011,
     NAVRELATION_CONTAINING_TAB_PANE = 0x1012,
     NAVRELATION_CONTAINING_APPLICATION = 0x1014
   };
 };
 
 static inline AccessibleWrap*
-WrapperFor(ProxyAccessible* aProxy)
+WrapperFor(const ProxyAccessible* aProxy)
 {
   return reinterpret_cast<AccessibleWrap*>(aProxy->GetWrapper());
 }
 
 } // namespace a11y
 } // namespace mozilla
 
 #ifdef XP_WIN
--- a/b2g/config/aries/sources.xml
+++ b/b2g/config/aries/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="f1cb3089ee2a77dd779408ca86dbb5e4ed5af0b3"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="5a0a1bb1a863b07528ebc1a04652ed656d8333b3"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="828317e64d28138f24d578ab340c2a0ff8552df0"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="48d8c7c950745f1b166b42125e6f0d3293d71636"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f004530b30a63c08a16d82536858600446b2abf5"/>
@@ -121,17 +121,17 @@
   <project name="platform/hardware/libhardware_legacy" path="hardware/libhardware_legacy" revision="76c4bf4bc430a1b8317f2f21ef735867733e50cc"/>
   <project name="platform/system/media" path="system/media" revision="c1332c21c608f4932a6d7e83450411cde53315ef"/>
   <default remote="caf" revision="LNX.LA.3.5.2.1.1" sync-j="4"/>
   <!-- Platform common things -->
   <project name="device-shinano-common" path="device/sony/shinano-common" remote="b2g" revision="df3d2ae4345ca5d32bce717bb7b3dac18a3afa18"/>
   <project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="1bb28abbc215f45220620af5cd60a8ac1be93722"/>
   <project name="device/qcom/common" path="device/qcom/common" revision="2501e5940ba69ece7654ff85611c76ae5bda299c"/>
   <project name="codeaurora_kernel_msm" path="kernel" remote="b2g" revision="d620691cad7aee780018e98159ff03bf99840317"/>
-  <project name="init_sh" path="external/init_sh" remote="b2g" revision="0634405632190765881347500a982221b86a1766"/>
+  <project name="init_sh" path="external/init_sh" remote="b2g" revision="feb58d2b397e45ead9b904d5c4d9255df408db56"/>
   <project name="platform_external_bluetooth_bluedroid" path="external/bluetooth/bluedroid" remote="b2g" revision="70f536bd97d901b96b94669ae1aa2fd0fb54b258"/>
   <project name="platform/external/libnfc-nci" path="external/libnfc-nci" revision="0a01977f34d6e86fe23d6c0ec75e96ba988bbebb"/>
   <project name="platform_external_libnfc-pn547" path="external/libnfc-pn547" remote="b2g" revision="5bb999b84b8adc14f6bea004d523ba258dea8188"/>
   <project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="5b71e40213f650459e95d35b6f14af7e88d8ab62"/>
   <project name="platform_frameworks_av" path="frameworks/av" remote="b2g" revision="a920312eb6299b6cc11f7136254c4b0ba7a663be"/>
   <project name="platform/frameworks/base" path="frameworks/base" revision="da8e6bc53c8bc669da0bb627904d08aa293f2497"/>
   <project name="platform/frameworks/native" path="frameworks/native" revision="a46a9f1ac0ed5662d614c277cbb14eb3f332f365"/>
   <project name="platform/hardware/libhardware" path="hardware/libhardware" revision="7196881a0e9dd7bfbbcf0af64c8064e70f0fa094"/>
--- a/b2g/config/dolphin/sources.xml
+++ b/b2g/config/dolphin/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="f1cb3089ee2a77dd779408ca86dbb5e4ed5af0b3"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="5a0a1bb1a863b07528ebc1a04652ed656d8333b3"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="828317e64d28138f24d578ab340c2a0ff8552df0"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="48d8c7c950745f1b166b42125e6f0d3293d71636"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f004530b30a63c08a16d82536858600446b2abf5"/>
--- a/b2g/config/emulator-ics/sources.xml
+++ b/b2g/config/emulator-ics/sources.xml
@@ -14,17 +14,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="1b0db93fb6b870b03467aff50d6419771ba0d88c">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="f1cb3089ee2a77dd779408ca86dbb5e4ed5af0b3"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="5a0a1bb1a863b07528ebc1a04652ed656d8333b3"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="27eb2f04e149fc2c9976d881b1b5984bbe7ee089"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="12ff7481566587aa4198cf1287598acb3a999973"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="828317e64d28138f24d578ab340c2a0ff8552df0"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="34ea6163f9f0e0122fb0bb03607eccdca31ced7a"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/emulator-jb/sources.xml
+++ b/b2g/config/emulator-jb/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="660169a3d7e034a892359e39135e8c2785a6ad6f">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="f1cb3089ee2a77dd779408ca86dbb5e4ed5af0b3"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="5a0a1bb1a863b07528ebc1a04652ed656d8333b3"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="828317e64d28138f24d578ab340c2a0ff8552df0"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f004530b30a63c08a16d82536858600446b2abf5"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="48d8c7c950745f1b166b42125e6f0d3293d71636"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
--- a/b2g/config/emulator-kk/sources.xml
+++ b/b2g/config/emulator-kk/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="f1cb3089ee2a77dd779408ca86dbb5e4ed5af0b3"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="5a0a1bb1a863b07528ebc1a04652ed656d8333b3"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="828317e64d28138f24d578ab340c2a0ff8552df0"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="48d8c7c950745f1b166b42125e6f0d3293d71636"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f004530b30a63c08a16d82536858600446b2abf5"/>
--- a/b2g/config/emulator-l/sources.xml
+++ b/b2g/config/emulator-l/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="c9d4fe680662ee44a4bdea42ae00366f5df399cf">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="f1cb3089ee2a77dd779408ca86dbb5e4ed5af0b3"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="5a0a1bb1a863b07528ebc1a04652ed656d8333b3"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="828317e64d28138f24d578ab340c2a0ff8552df0"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="48d8c7c950745f1b166b42125e6f0d3293d71636"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f004530b30a63c08a16d82536858600446b2abf5"/>
--- a/b2g/config/emulator/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -14,17 +14,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="1b0db93fb6b870b03467aff50d6419771ba0d88c">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="f1cb3089ee2a77dd779408ca86dbb5e4ed5af0b3"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="5a0a1bb1a863b07528ebc1a04652ed656d8333b3"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="27eb2f04e149fc2c9976d881b1b5984bbe7ee089"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="12ff7481566587aa4198cf1287598acb3a999973"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="828317e64d28138f24d578ab340c2a0ff8552df0"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="34ea6163f9f0e0122fb0bb03607eccdca31ced7a"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/flame-kk/sources.xml
+++ b/b2g/config/flame-kk/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="f1cb3089ee2a77dd779408ca86dbb5e4ed5af0b3"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="5a0a1bb1a863b07528ebc1a04652ed656d8333b3"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="828317e64d28138f24d578ab340c2a0ff8552df0"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="48d8c7c950745f1b166b42125e6f0d3293d71636"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f004530b30a63c08a16d82536858600446b2abf5"/>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,9 +1,9 @@
 {
     "git": {
-        "git_revision": "f1cb3089ee2a77dd779408ca86dbb5e4ed5af0b3", 
+        "git_revision": "5a0a1bb1a863b07528ebc1a04652ed656d8333b3", 
         "remote": "https://git.mozilla.org/releases/gaia.git", 
         "branch": ""
     }, 
-    "revision": "754c41de25dcb48c7b1f18f13900d0212ed7fb07", 
+    "revision": "e3fe2ebe9defdb65b56c3e7a3d655f4e1229fe09", 
     "repo_path": "integration/gaia-central"
 }
--- a/b2g/config/nexus-4-kk/sources.xml
+++ b/b2g/config/nexus-4-kk/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="f1cb3089ee2a77dd779408ca86dbb5e4ed5af0b3"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="5a0a1bb1a863b07528ebc1a04652ed656d8333b3"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="828317e64d28138f24d578ab340c2a0ff8552df0"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="48d8c7c950745f1b166b42125e6f0d3293d71636"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f004530b30a63c08a16d82536858600446b2abf5"/>
--- a/b2g/config/nexus-4/sources.xml
+++ b/b2g/config/nexus-4/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="660169a3d7e034a892359e39135e8c2785a6ad6f">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="f1cb3089ee2a77dd779408ca86dbb5e4ed5af0b3"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="5a0a1bb1a863b07528ebc1a04652ed656d8333b3"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="828317e64d28138f24d578ab340c2a0ff8552df0"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f004530b30a63c08a16d82536858600446b2abf5"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="48d8c7c950745f1b166b42125e6f0d3293d71636"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
--- a/b2g/config/nexus-5-l/sources.xml
+++ b/b2g/config/nexus-5-l/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="c9d4fe680662ee44a4bdea42ae00366f5df399cf">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="f1cb3089ee2a77dd779408ca86dbb5e4ed5af0b3"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="5a0a1bb1a863b07528ebc1a04652ed656d8333b3"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="828317e64d28138f24d578ab340c2a0ff8552df0"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="48d8c7c950745f1b166b42125e6f0d3293d71636"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f004530b30a63c08a16d82536858600446b2abf5"/>
--- a/devtools/shared/heapsnapshot/HeapSnapshot.cpp
+++ b/devtools/shared/heapsnapshot/HeapSnapshot.cpp
@@ -7,17 +7,17 @@
 
 #include <google/protobuf/io/coded_stream.h>
 #include <google/protobuf/io/gzip_stream.h>
 #include <google/protobuf/io/zero_copy_stream_impl_lite.h>
 
 #include "js/Debug.h"
 #include "js/TypeDecls.h"
 #include "js/UbiNodeCensus.h"
-#include "js/UbiNodeTraverse.h"
+#include "js/UbiNodeBreadthFirst.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/devtools/AutoMemMap.h"
 #include "mozilla/devtools/CoreDump.pb.h"
 #include "mozilla/devtools/DeserializedNode.h"
 #include "mozilla/devtools/FileDescriptorOutputStream.h"
 #include "mozilla/devtools/HeapSnapshotTempFileHelperChild.h"
 #include "mozilla/devtools/ZeroCopyNSIOutputStream.h"
 #include "mozilla/dom/ChromeUtils.h"
--- a/devtools/shared/heapsnapshot/tests/gtest/moz.build
+++ b/devtools/shared/heapsnapshot/tests/gtest/moz.build
@@ -19,11 +19,11 @@ UNIFIED_SOURCES = [
     'SerializesEverythingInHeapGraphOnce.cpp',
     'SerializesTypeNames.cpp',
     'UniqueStringHashPolicy.cpp',
 ]
 
 # THE MOCK_METHOD2 macro from gtest triggers this clang warning and it's hard
 # to work around, so we just ignore it.
 if CONFIG['CLANG_CXX']:
-  CXXFLAGS += ['-Wno-error=inconsistent-missing-override']
+  CXXFLAGS += ['-Wno-inconsistent-missing-override']
 
 FINAL_LIBRARY = 'xul-gtest'
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -1503,17 +1503,17 @@ nsDocShell::LoadURI(nsIURI* aURI,
       // Don't inherit from the current page.  Just do the safe thing
       // and pretend that we were loaded by a nullprincipal.
       owner = nsNullPrincipal::Create();
       inheritOwner = false;
     }
   }
   if (!owner && !inheritOwner && !ownerIsExplicit) {
     // See if there's system or chrome JS code running
-    inheritOwner = nsContentUtils::IsCallerChrome();
+    inheritOwner = nsContentUtils::LegacyIsCallerChromeOrNativeCode();
   }
 
   if (aLoadFlags & LOAD_FLAGS_DISALLOW_INHERIT_OWNER) {
     inheritOwner = false;
     owner = nsNullPrincipal::Create();
   }
 
   uint32_t flags = 0;
--- a/dom/base/BarProps.cpp
+++ b/dom/base/BarProps.cpp
@@ -271,17 +271,17 @@ ScrollbarsProp::GetVisible(ErrorResult& 
   scroller->GetDefaultScrollbarPreferences(
               nsIScrollable::ScrollOrientation_X, &prefValue);
   return prefValue != nsIScrollable::Scrollbar_Never;
 }
 
 void
 ScrollbarsProp::SetVisible(bool aVisible, ErrorResult& aRv)
 {
-  if (!nsContentUtils::IsCallerChrome()) {
+  if (!nsContentUtils::LegacyIsCallerChromeOrNativeCode()) {
     return;
   }
 
   /* Scrollbars, unlike the other barprops, implement visibility directly
      rather than handing off to the superclass (and from there to the
      chrome window) because scrollbar visibility uniquely applies only
      to the window making the change (arguably. it does now, anyway.)
      and because embedding apps have no interface for implementing this
--- a/dom/base/File.cpp
+++ b/dom/base/File.cpp
@@ -700,17 +700,17 @@ BlobImplBase::GetPath(nsAString& aPath, 
 void
 BlobImplBase::GetMozFullPath(nsAString& aFileName, ErrorResult& aRv) const
 {
   NS_ASSERTION(mIsFile, "Should only be called on files");
 
   aFileName.Truncate();
 
   if (NS_IsMainThread()) {
-    if (nsContentUtils::IsCallerChrome()) {
+    if (nsContentUtils::LegacyIsCallerChromeOrNativeCode()) {
       GetMozFullPathInternal(aFileName, aRv);
     }
 
     return;
   }
 
   workers::WorkerPrivate* workerPrivate =
     workers::GetCurrentThreadWorkerPrivate();
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -1950,19 +1950,16 @@ nsContentUtils::CheckSameOrigin(const ns
 }
 
 nsresult
 nsContentUtils::CheckSameOrigin(const nsINode* aTrustedNode,
                                 const nsINode* unTrustedNode)
 {
   MOZ_ASSERT(aTrustedNode);
   MOZ_ASSERT(unTrustedNode);
-  if (IsCallerChrome()) {
-    return NS_OK;
-  }
 
   /*
    * Get hold of each node's principal
    */
 
   nsIPrincipal* trustedPrincipal = aTrustedNode->NodePrincipal();
   nsIPrincipal* unTrustedPrincipal = unTrustedNode->NodePrincipal();
 
@@ -2708,17 +2705,17 @@ nsContentUtils::GenerateStateKey(nsICont
 // static
 nsIPrincipal*
 nsContentUtils::SubjectPrincipal()
 {
   MOZ_ASSERT(IsInitialized());
   MOZ_ASSERT(NS_IsMainThread());
   JSContext* cx = GetCurrentJSContext();
   if (!cx) {
-    return GetSystemPrincipal();
+    MOZ_CRASH("Accessing the Subject Principal without an AutoJSAPI on the stack is forbidden");
   }
 
   JSCompartment *compartment = js::GetContextCompartment(cx);
 
   // When an AutoJSAPI is instantiated, we are in a null compartment until the
   // first JSAutoCompartment, which is kind of a purgatory as far as permissions
   // go. It would be nice to just hard-abort if somebody does a security check
   // in this purgatory zone, but that would be too fragile, since it could be
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -190,16 +190,57 @@ class nsContentUtils
 
 public:
   static nsresult Init();
 
   static bool     IsCallerChrome();
   static bool     ThreadsafeIsCallerChrome();
   static bool     IsCallerContentXBL();
 
+  // In the traditional Gecko architecture, both C++ code and untrusted JS code
+  // needed to rely on the same XPCOM method/getter/setter to get work done.
+  // This required lots of security checks in the various exposed methods, which
+  // in turn created difficulty in determining whether the caller was script
+  // (whose access needed to be checked) and internal C++ platform code (whose
+  // access did not need to be checked). To address this problem, Gecko had a
+  // convention whereby the absence of script on the stack was interpretted as
+  // "System Caller" and always granted unfettered access.
+  //
+  // Unfortunately, this created a bunch of footguns. For example, when the
+  // implementation of a DOM method wanted to perform a privileged
+  // sub-operation, it needed to "hide" the presence of script on the stack in
+  // order for that sub-operation to be allowed. Additionally, if script could
+  // trigger an API entry point to be invoked in some asynchronous way without
+  // script on the stack, it could potentially perform privilege escalation.
+  //
+  // In the modern world, untrusted script should interact with the platform
+  // exclusively over WebIDL APIs, and platform code has a lot more flexibility
+  // in deciding whether or not to use XPCOM. This gives us the flexibility to
+  // do something better.
+  //
+  // Going forward, APIs should be designed such that any security checks that
+  // ask the question "is my caller allowed to do this?" should live in WebIDL
+  // API entry points, with a separate method provided for internal callers
+  // that just want to get the job done.
+  //
+  // To enforce this and catch bugs, nsContentUtils::SubjectPrincipal will crash
+  // if it is invoked without script on the stack. To land that transition, it
+  // was necessary to go through and whitelist a bunch of callers that were
+  // depending on the old behavior. Those callers should be fixed up, and these
+  // methods should not be used by new code without review from bholley or bz.
+  static bool     LegacyIsCallerNativeCode() { return !GetCurrentJSContext(); }
+  static bool     LegacyIsCallerChromeOrNativeCode() { return LegacyIsCallerNativeCode() || IsCallerChrome(); }
+  static nsIPrincipal* SubjectPrincipalOrSystemIfNativeCaller()
+  {
+    if (!GetCurrentJSContext()) {
+      return GetSystemPrincipal();
+    }
+    return SubjectPrincipal();
+  }
+
   static bool     IsImageSrcSetDisabled();
 
   static bool LookupBindingMember(JSContext* aCx, nsIContent *aContent,
                                   JS::Handle<jsid> aId,
                                   JS::MutableHandle<JSPropertyDescriptor> aDesc);
 
   // Check whether we should avoid leaking distinguishing information to JS/CSS.
   static bool ShouldResistFingerprinting(nsIDocShell* aDocShell);
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -405,17 +405,17 @@ nsDOMWindowUtils::SetDisplayPortForEleme
 NS_IMETHODIMP
 nsDOMWindowUtils::SetDisplayPortMarginsForElement(float aLeftMargin,
                                                   float aTopMargin,
                                                   float aRightMargin,
                                                   float aBottomMargin,
                                                   nsIDOMElement* aElement,
                                                   uint32_t aPriority)
 {
-  MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
+  MOZ_RELEASE_ASSERT(nsContentUtils::LegacyIsCallerChromeOrNativeCode());
 
   nsIPresShell* presShell = GetPresShell();
   if (!presShell) {
     return NS_ERROR_FAILURE;
   }
 
   if (!aElement) {
     return NS_ERROR_INVALID_ARG;
@@ -476,17 +476,17 @@ nsDOMWindowUtils::SetDisplayPortBaseForE
   nsLayoutUtils::SetDisplayPortBase(content, nsRect(aX, aY, aWidth, aHeight));
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::SetResolution(float aResolution)
 {
-  if (!nsContentUtils::IsCallerChrome()) {
+  if (!nsContentUtils::LegacyIsCallerChromeOrNativeCode()) {
     return NS_ERROR_DOM_SECURITY_ERR;
   }
 
   nsIPresShell* presShell = GetPresShell();
   if (!presShell) {
     return NS_ERROR_FAILURE;
   }
 
@@ -542,47 +542,47 @@ nsDOMWindowUtils::GetIsResolutionSet(boo
   *aIsResolutionSet = sf && sf->IsResolutionSet();
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::SetIsFirstPaint(bool aIsFirstPaint)
 {
-  if (!nsContentUtils::IsCallerChrome()) {
+  if (!nsContentUtils::LegacyIsCallerChromeOrNativeCode()) {
     return NS_ERROR_DOM_SECURITY_ERR;
   }
 
   nsIPresShell* presShell = GetPresShell();
   if (presShell) {
     presShell->SetIsFirstPaint(aIsFirstPaint);
     return NS_OK;
   }
   return NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::GetIsFirstPaint(bool *aIsFirstPaint)
 {
-  if (!nsContentUtils::IsCallerChrome()) {
+  if (!nsContentUtils::LegacyIsCallerChromeOrNativeCode()) {
     return NS_ERROR_DOM_SECURITY_ERR;
   }
 
   nsIPresShell* presShell = GetPresShell();
   if (presShell) {
     *aIsFirstPaint = presShell->GetIsFirstPaint();
     return NS_OK;
   }
   return NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::GetPresShellId(uint32_t *aPresShellId)
 {
-  MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
+  MOZ_RELEASE_ASSERT(nsContentUtils::LegacyIsCallerChromeOrNativeCode());
 
   nsIPresShell* presShell = GetPresShell();
   if (presShell) {
     *aPresShellId = presShell->GetPresShellId();
     return NS_OK;
   }
   return NS_ERROR_FAILURE;
 }
@@ -1031,17 +1031,17 @@ nsDOMWindowUtils::SendKeyEvent(const nsA
 NS_IMETHODIMP
 nsDOMWindowUtils::SendNativeKeyEvent(int32_t aNativeKeyboardLayout,
                                      int32_t aNativeKeyCode,
                                      int32_t aModifiers,
                                      const nsAString& aCharacters,
                                      const nsAString& aUnmodifiedCharacters,
                                      nsIObserver* aObserver)
 {
-  MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
+  MOZ_RELEASE_ASSERT(nsContentUtils::LegacyIsCallerChromeOrNativeCode());
 
   // get the widget to send the event to
   nsCOMPtr<nsIWidget> widget = GetWidget();
   if (!widget)
     return NS_ERROR_FAILURE;
 
   NS_DispatchToMainThread(NS_NewRunnableMethodWithArgs
     <int32_t, int32_t, uint32_t, nsString, nsString, nsIObserver*>
@@ -1717,17 +1717,19 @@ nsDOMWindowUtils::GetBoundsWithoutFlushi
 
   rect.forget(aResult);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::GetRootBounds(nsIDOMClientRect** aResult)
 {
-  MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
+  // Unfortunately, this is called from AndroidBridge.cpp and the logic here is
+  // nontrivial, so we need to allow non-scripted callers.
+  MOZ_RELEASE_ASSERT(nsContentUtils::LegacyIsCallerChromeOrNativeCode());
 
   nsIDocument* doc = GetDocument();
   NS_ENSURE_STATE(doc);
 
   nsRect bounds(0, 0, 0, 0);
   nsIPresShell* presShell = doc->GetShell();
   if (presShell) {
     nsIScrollableFrame* sf = presShell->GetRootScrollFrameAsScrollable();
@@ -3145,17 +3147,17 @@ nsDOMWindowUtils::GetPlugins(JSContext* 
 
   aPlugins.setObject(*jsPlugins);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::SetScrollPositionClampingScrollPortSize(float aWidth, float aHeight)
 {
-  MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
+  MOZ_RELEASE_ASSERT(nsContentUtils::LegacyIsCallerChromeOrNativeCode());
 
   if (!(aWidth >= 0.0 && aHeight >= 0.0)) {
     return NS_ERROR_ILLEGAL_VALUE;
   }
 
   nsIPresShell* presShell = GetPresShell();
   if (!presShell) {
     return NS_ERROR_FAILURE;
--- a/dom/base/nsFocusManager.cpp
+++ b/dom/base/nsFocusManager.cpp
@@ -1216,17 +1216,17 @@ nsFocusManager::SetFocusInner(nsIContent
       do_QueryInterface(newWindow);
     nsIPrincipal* focusedPrincipal = focused->GetPrincipal();
     nsIPrincipal* newPrincipal = newFocus->GetPrincipal();
     if (!focusedPrincipal || !newPrincipal) {
       return;
     }
     bool subsumes = false;
     focusedPrincipal->Subsumes(newPrincipal, &subsumes);
-    if (!subsumes && !nsContentUtils::IsCallerChrome()) {
+    if (!subsumes && !nsContentUtils::LegacyIsCallerChromeOrNativeCode()) {
       NS_WARNING("Not allowed to focus the new window!");
       return;
     }
   }
 
   // to check if the new element is in the active window, compare the
   // new root docshell for the new element with the active window's docshell.
   bool isElementInActiveWindow = false;
@@ -1270,17 +1270,17 @@ nsFocusManager::SetFocusInner(nsIContent
   bool sendFocusEvent =
     isElementInActiveWindow && allowFrameSwitch && IsWindowVisible(newWindow);
 
   // When the following conditions are true:
   //  * an element has focus
   //  * isn't called by trusted event (i.e., called by untrusted event or by js)
   //  * the focus is moved to another document's element
   // we need to check the permission.
-  if (sendFocusEvent && mFocusedContent &&
+  if (sendFocusEvent && mFocusedContent && !nsContentUtils::LegacyIsCallerNativeCode() &&
       mFocusedContent->OwnerDoc() != aNewContent->OwnerDoc()) {
     // If the caller cannot access the current focused node, the caller should
     // not be able to steal focus from it. E.g., When the current focused node
     // is in chrome, any web contents should not be able to steal the focus.
     nsCOMPtr<nsIDOMNode> domNode(do_QueryInterface(mFocusedContent));
     sendFocusEvent = nsContentUtils::CanCallerAccess(domNode);
     if (!sendFocusEvent && mMouseButtonEventHandlingDocument) {
       // However, while mouse button event is handling, the handling document's
@@ -1448,18 +1448,20 @@ nsFocusManager::AdjustWindowFocus(nsPIDO
       // likely moved up and out from a hidden tab to the browser window, or a
       // similar such arrangement. Stop adjusting the current nodes.
       if (IsWindowVisible(window) != isVisible)
         break;
 
       // When aCheckPermission is true, we should check whether the caller can
       // access the window or not.  If it cannot access, we should stop the
       // adjusting.
-      if (aCheckPermission && !nsContentUtils::CanCallerAccess(window))
+      if (aCheckPermission && !nsContentUtils::LegacyIsCallerNativeCode() &&
+          !nsContentUtils::CanCallerAccess(window)) {
         break;
+      }
 
       window->SetFocusedNode(frameElement);
     }
   }
 }
 
 bool
 nsFocusManager::IsWindowVisible(nsPIDOMWindow* aWindow)
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -2080,17 +2080,17 @@ nsGlobalWindow::WouldReuseInnerWindow(ns
 }
 
 void
 nsGlobalWindow::SetInitialPrincipalToSubject()
 {
   MOZ_ASSERT(IsOuterWindow());
 
   // First, grab the subject principal.
-  nsCOMPtr<nsIPrincipal> newWindowPrincipal = nsContentUtils::SubjectPrincipal();
+  nsCOMPtr<nsIPrincipal> newWindowPrincipal = nsContentUtils::SubjectPrincipalOrSystemIfNativeCaller();
 
   // Now, if we're about to use the system principal or an nsExpandedPrincipal,
   // make sure we're not using it for a content docshell.
   if (nsContentUtils::IsSystemOrExpandedPrincipal(newWindowPrincipal) &&
       GetDocShell()->ItemType() != nsIDocShellTreeItem::typeChrome) {
     newWindowPrincipal = nullptr;
   }
 
@@ -4544,17 +4544,17 @@ nsGlobalWindow::GetOpenerWindowOuter()
   nsCOMPtr<nsPIDOMWindow> opener = do_QueryReferent(mOpener);
   if (!opener) {
     return nullptr;
   }
 
   nsGlobalWindow* win = static_cast<nsGlobalWindow*>(opener.get());
 
   // First, check if we were called from a privileged chrome script
-  if (nsContentUtils::IsCallerChrome()) {
+  if (nsContentUtils::LegacyIsCallerChromeOrNativeCode()) {
     // Catch the case where we're chrome but the opener is not...
     if (GetPrincipal() == nsContentUtils::GetSystemPrincipal() &&
         win->GetPrincipal() != nsContentUtils::GetSystemPrincipal()) {
       return nullptr;
     }
     return opener;
   }
 
@@ -6508,17 +6508,17 @@ nsGlobalWindow::SetFullscreenInternal(Fu
   NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE);
 
   MOZ_ASSERT(aReason != eForForceExitFullscreen || !aFullScreen,
              "FullscreenReason::eForForceExitFullscreen can "
              "only be used with exiting fullscreen");
 
   // Only chrome can change our fullscreen mode. Otherwise, the state
   // can only be changed for DOM fullscreen.
-  if (aReason == eForFullscreenMode && !nsContentUtils::IsCallerChrome()) {
+  if (aReason == eForFullscreenMode && !nsContentUtils::LegacyIsCallerChromeOrNativeCode()) {
     return NS_OK;
   }
 
   // SetFullScreen needs to be called on the root window, so get that
   // via the DocShell tree, and if we are not already the root,
   // call SetFullScreen on that window instead.
   nsCOMPtr<nsIDocShellTreeItem> rootItem;
   mDocShell->GetRootTreeItem(getter_AddRefs(rootItem));
@@ -8244,17 +8244,17 @@ static void FirePopupWindowEvent(nsIDocu
                                        true, true);
 }
 
 // static
 bool
 nsGlobalWindow::CanSetProperty(const char *aPrefName)
 {
   // Chrome can set any property.
-  if (nsContentUtils::IsCallerChrome()) {
+  if (nsContentUtils::LegacyIsCallerChromeOrNativeCode()) {
     return true;
   }
 
   // If the pref is set to true, we can not set the property
   // and vice versa.
   return !Preferences::GetBool(aPrefName, true);
 }
 
@@ -10049,16 +10049,17 @@ nsGlobalWindow::AddSystemEventListener(c
                                        uint8_t aOptionalArgc)
 {
   NS_ASSERTION(!aWantsUntrusted || aOptionalArgc > 1,
                "Won't check if this is chrome, you want to set "
                "aWantsUntrusted to false or make the aWantsUntrusted "
                "explicit by making optional_argc non-zero.");
 
   if (IsOuterWindow() && mInnerWindow &&
+      !nsContentUtils::LegacyIsCallerNativeCode() &&
       !nsContentUtils::CanCallerAccess(mInnerWindow)) {
     return NS_ERROR_DOM_SECURITY_ERR;
   }
 
   if (!aWantsUntrusted &&
       (aOptionalArgc < 2 && !nsContentUtils::IsChromeDoc(mDoc))) {
     aWantsUntrusted = true;
   }
@@ -12176,17 +12177,17 @@ nsGlobalWindow::OpenInternal(const nsASt
 
   // Popups from apps are never blocked.
   bool isApp = false;
   if (mDoc) {
     isApp = mDoc->NodePrincipal()->GetAppStatus() >=
               nsIPrincipal::APP_STATUS_INSTALLED;
   }
 
-  const bool checkForPopup = !nsContentUtils::IsCallerChrome() &&
+  const bool checkForPopup = !nsContentUtils::LegacyIsCallerChromeOrNativeCode() &&
     !isApp && !aDialog && !WindowExists(aName, !aCalledNoScript);
 
   // Note: it's very important that this be an nsXPIDLCString, since we want
   // .get() on it to return nullptr until we write stuff to it.  The window
   // watcher expects a null URL string if there is no URL to load.
   nsXPIDLCString url;
   nsresult rv = NS_OK;
 
--- a/dom/base/nsObjectLoadingContent.cpp
+++ b/dom/base/nsObjectLoadingContent.cpp
@@ -1151,17 +1151,17 @@ nsObjectLoadingContent::OnStopRequest(ns
   if (aStatusCode == NS_ERROR_TRACKING_URI) {
     nsCOMPtr<nsIContent> thisNode =
       do_QueryInterface(static_cast<nsIObjectLoadingContent*>(this));
     if (thisNode && thisNode->IsInComposedDoc()) {
       thisNode->GetComposedDoc()->AddBlockedTrackingNode(thisNode);
     }
   }
 
-  NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_NOT_AVAILABLE);
+  NS_ENSURE_TRUE(nsContentUtils::LegacyIsCallerChromeOrNativeCode(), NS_ERROR_NOT_AVAILABLE);
 
   if (aRequest != mChannel) {
     return NS_BINDING_ABORTED;
   }
 
   mChannel = nullptr;
 
   if (mFinalListener) {
@@ -1178,17 +1178,17 @@ nsObjectLoadingContent::OnStopRequest(ns
 
 // nsIStreamListener
 NS_IMETHODIMP
 nsObjectLoadingContent::OnDataAvailable(nsIRequest *aRequest,
                                         nsISupports *aContext,
                                         nsIInputStream *aInputStream,
                                         uint64_t aOffset, uint32_t aCount)
 {
-  NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_NOT_AVAILABLE);
+  NS_ENSURE_TRUE(nsContentUtils::LegacyIsCallerChromeOrNativeCode(), NS_ERROR_NOT_AVAILABLE);
 
   if (aRequest != mChannel) {
     return NS_BINDING_ABORTED;
   }
 
   if (mFinalListener) {
     // This may re-enter in the case of plugin listeners
     nsCOMPtr<nsIStreamListener> listenerGrip(mFinalListener);
@@ -2820,17 +2820,18 @@ nsObjectLoadingContent::ScriptRequestPlu
 {
   // The below methods pull the cx off the stack, so make sure they match.
   //
   // NB: Sometimes there's a null cx on the stack, in which case |cx| is the
   // safe JS context. But in that case, IsCallerChrome() will return true,
   // so the ensuing expression is short-circuited.
   MOZ_ASSERT_IF(nsContentUtils::GetCurrentJSContext(),
                 aCx == nsContentUtils::GetCurrentJSContext());
-  bool callerIsContentJS = (!nsContentUtils::IsCallerChrome() &&
+  bool callerIsContentJS = (nsContentUtils::GetCurrentJSContext() &&
+                            !nsContentUtils::IsCallerChrome() &&
                             !nsContentUtils::IsCallerContentXBL() &&
                             JS_IsRunning(aCx));
 
   nsCOMPtr<nsIContent> thisContent =
     do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
 
   *aResult = nullptr;
 
--- a/dom/base/nsRange.cpp
+++ b/dom/base/nsRange.cpp
@@ -1133,17 +1133,18 @@ nsRange::IsValidBoundary(nsINode* aNode)
 
   // We allow this because of backward compatibility.
   return root;
 }
 
 void
 nsRange::SetStart(nsINode& aNode, uint32_t aOffset, ErrorResult& aRv)
 {
- if (!nsContentUtils::CanCallerAccess(&aNode)) {
+ if (!nsContentUtils::LegacyIsCallerNativeCode() &&
+     !nsContentUtils::CanCallerAccess(&aNode)) {
     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     return;
   }
 
   AutoInvalidateSelection atEndOfBlock(this);
   aRv = SetStart(&aNode, aOffset);
 }
 
@@ -1185,17 +1186,18 @@ nsRange::SetStart(nsINode* aParent, int3
   DoSetRange(aParent, aOffset, mEndParent, mEndOffset, mRoot);
 
   return NS_OK;
 }
 
 void
 nsRange::SetStartBefore(nsINode& aNode, ErrorResult& aRv)
 {
-  if (!nsContentUtils::CanCallerAccess(&aNode)) {
+  if (!nsContentUtils::LegacyIsCallerNativeCode() &&
+      !nsContentUtils::CanCallerAccess(&aNode)) {
     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     return;
   }
 
   AutoInvalidateSelection atEndOfBlock(this);
   aRv = SetStart(aNode.GetParentNode(), IndexOf(&aNode));
 }
 
@@ -1210,17 +1212,18 @@ nsRange::SetStartBefore(nsIDOMNode* aSib
   ErrorResult rv;
   SetStartBefore(*sibling, rv);
   return rv.StealNSResult();
 }
 
 void
 nsRange::SetStartAfter(nsINode& aNode, ErrorResult& aRv)
 {
-  if (!nsContentUtils::CanCallerAccess(&aNode)) {
+  if (!nsContentUtils::LegacyIsCallerNativeCode() &&
+      !nsContentUtils::CanCallerAccess(&aNode)) {
     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     return;
   }
 
   AutoInvalidateSelection atEndOfBlock(this);
   aRv = SetStart(aNode.GetParentNode(), IndexOf(&aNode) + 1);
 }
 
@@ -1235,17 +1238,18 @@ nsRange::SetStartAfter(nsIDOMNode* aSibl
   ErrorResult rv;
   SetStartAfter(*sibling, rv);
   return rv.StealNSResult();
 }
 
 void
 nsRange::SetEnd(nsINode& aNode, uint32_t aOffset, ErrorResult& aRv)
 {
- if (!nsContentUtils::CanCallerAccess(&aNode)) {
+ if (!nsContentUtils::LegacyIsCallerNativeCode() &&
+     !nsContentUtils::CanCallerAccess(&aNode)) {
     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     return;
   }
   AutoInvalidateSelection atEndOfBlock(this);
   aRv = SetEnd(&aNode, aOffset);
 }
 
 NS_IMETHODIMP
@@ -1286,17 +1290,18 @@ nsRange::SetEnd(nsINode* aParent, int32_
   DoSetRange(mStartParent, mStartOffset, aParent, aOffset, mRoot);
 
   return NS_OK;
 }
 
 void
 nsRange::SetEndBefore(nsINode& aNode, ErrorResult& aRv)
 {
-  if (!nsContentUtils::CanCallerAccess(&aNode)) {
+  if (!nsContentUtils::LegacyIsCallerNativeCode() &&
+      !nsContentUtils::CanCallerAccess(&aNode)) {
     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     return;
   }
 
   AutoInvalidateSelection atEndOfBlock(this);
   aRv = SetEnd(aNode.GetParentNode(), IndexOf(&aNode));
 }
 
@@ -1311,17 +1316,18 @@ nsRange::SetEndBefore(nsIDOMNode* aSibli
   ErrorResult rv;
   SetEndBefore(*sibling, rv);
   return rv.StealNSResult();
 }
 
 void
 nsRange::SetEndAfter(nsINode& aNode, ErrorResult& aRv)
 {
-  if (!nsContentUtils::CanCallerAccess(&aNode)) {
+  if (!nsContentUtils::LegacyIsCallerNativeCode() &&
+      !nsContentUtils::CanCallerAccess(&aNode)) {
     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     return;
   }
 
   AutoInvalidateSelection atEndOfBlock(this);
   aRv = SetEnd(aNode.GetParentNode(), IndexOf(&aNode) + 1);
 }
 
@@ -1362,17 +1368,18 @@ nsRange::SelectNode(nsIDOMNode* aN)
   ErrorResult rv;
   SelectNode(*node, rv);
   return rv.StealNSResult();
 }
 
 void
 nsRange::SelectNode(nsINode& aNode, ErrorResult& aRv)
 {
-  if (!nsContentUtils::CanCallerAccess(&aNode)) {
+  if (!nsContentUtils::LegacyIsCallerNativeCode() &&
+      !nsContentUtils::CanCallerAccess(&aNode)) {
     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     return;
   }
 
   nsINode* parent = aNode.GetParentNode();
   nsINode* newRoot = IsValidBoundary(parent);
   if (!newRoot) {
     aRv.Throw(NS_ERROR_DOM_INVALID_NODE_TYPE_ERR);
@@ -1398,17 +1405,18 @@ nsRange::SelectNodeContents(nsIDOMNode* 
   ErrorResult rv;
   SelectNodeContents(*node, rv);
   return rv.StealNSResult();
 }
 
 void
 nsRange::SelectNodeContents(nsINode& aNode, ErrorResult& aRv)
 {
-  if (!nsContentUtils::CanCallerAccess(&aNode)) {
+  if (!nsContentUtils::LegacyIsCallerNativeCode() &&
+      !nsContentUtils::CanCallerAccess(&aNode)) {
     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     return;
   }
 
   nsINode* newRoot = IsValidBoundary(&aNode);
   if (!newRoot) {
     aRv.Throw(NS_ERROR_DOM_INVALID_NODE_TYPE_ERR);
     return;
@@ -2446,17 +2454,18 @@ nsRange::InsertNode(nsIDOMNode* aNode)
   ErrorResult rv;
   InsertNode(*node, rv);
   return rv.StealNSResult();
 }
 
 void
 nsRange::InsertNode(nsINode& aNode, ErrorResult& aRv)
 {
-  if (!nsContentUtils::CanCallerAccess(&aNode)) {
+  if (!nsContentUtils::LegacyIsCallerNativeCode() &&
+      !nsContentUtils::CanCallerAccess(&aNode)) {
     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     return;
   }
 
   int32_t tStartOffset = StartOffset();
 
   nsCOMPtr<nsINode> tStartContainer = GetStartContainer(aRv);
   if (aRv.Failed()) {
@@ -2543,17 +2552,18 @@ nsRange::SurroundContents(nsIDOMNode* aN
   ErrorResult rv;
   SurroundContents(*node, rv);
   return rv.StealNSResult();
 }
 
 void
 nsRange::SurroundContents(nsINode& aNewParent, ErrorResult& aRv)
 {
-  if (!nsContentUtils::CanCallerAccess(&aNewParent)) {
+  if (!nsContentUtils::LegacyIsCallerNativeCode() &&
+      !nsContentUtils::CanCallerAccess(&aNewParent)) {
     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     return;
   }
 
   if (!mRoot) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
--- a/dom/base/nsXMLHttpRequest.cpp
+++ b/dom/base/nsXMLHttpRequest.cpp
@@ -2695,18 +2695,17 @@ nsXMLHttpRequest::Send(nsIVariant* aVari
       net::InScriptableRange(size_u64) ? static_cast<int64_t>(size_u64) : -1;
 
     if (postDataStream) {
       // If no content type header was set by the client, we set it to
       // application/xml.
       nsAutoCString contentType;
       if (NS_FAILED(httpChannel->
                       GetRequestHeader(NS_LITERAL_CSTRING("Content-Type"),
-                                       contentType)) ||
-          contentType.IsEmpty()) {
+                                       contentType))) {
         contentType = defaultContentType;
 
         if (!charset.IsEmpty()) {
           // If we are providing the default content type, then we also need to
           // provide a charset declaration.
           contentType.Append(NS_LITERAL_CSTRING(";charset="));
           contentType.Append(charset);
         }
--- a/dom/bindings/CallbackObject.cpp
+++ b/dom/bindings/CallbackObject.cpp
@@ -62,17 +62,17 @@ CallbackObject::CallSetup::CallSetup(Cal
   if (mIsMainThread) {
     nsContentUtils::EnterMicroTask();
   }
 
   // Compute the caller's subject principal (if necessary) early, before we
   // do anything that might perturb the relevant state.
   nsIPrincipal* webIDLCallerPrincipal = nullptr;
   if (aIsJSImplementedWebIDL) {
-    webIDLCallerPrincipal = nsContentUtils::SubjectPrincipal();
+    webIDLCallerPrincipal = nsContentUtils::SubjectPrincipalOrSystemIfNativeCaller();
   }
 
   // We need to produce a useful JSContext here.  Ideally one that the callback
   // is in some sense associated with, so that we can sort of treat it as a
   // "script entry point".  Though once we actually have script entry points,
   // we'll need to do the script entry point bits once we have an actual
   // callable.
 
--- a/dom/camera/CameraPreviewMediaStream.cpp
+++ b/dom/camera/CameraPreviewMediaStream.cpp
@@ -132,17 +132,17 @@ CameraPreviewMediaStream::Invalidate()
 
 void
 CameraPreviewMediaStream::RateLimit(bool aLimit)
 {
   mRateLimit = aLimit;
 }
 
 void
-CameraPreviewMediaStream::SetCurrentFrame(const gfxIntSize& aIntrinsicSize, Image* aImage)
+CameraPreviewMediaStream::SetCurrentFrame(const gfx::IntSize& aIntrinsicSize, Image* aImage)
 {
   {
     MutexAutoLock lock(mMutex);
 
     if (mInvalidatePending > 0) {
       if (mRateLimit || mInvalidatePending > MAX_INVALIDATE_PENDING) {
         ++mDiscardedFrames;
         DOM_CAMERA_LOGW("Discard preview frame %d, %d invalidation(s) pending",
--- a/dom/camera/CameraPreviewMediaStream.h
+++ b/dom/camera/CameraPreviewMediaStream.h
@@ -53,17 +53,17 @@ public:
   virtual void AddListener(MediaStreamListener* aListener) override;
   virtual void RemoveListener(MediaStreamListener* aListener) override;
   virtual void Destroy() override;
   void OnPreviewStateChange(bool aActive);
 
   void Invalidate();
 
   // Call these on any thread.
-  void SetCurrentFrame(const gfxIntSize& aIntrinsicSize, Image* aImage);
+  void SetCurrentFrame(const gfx::IntSize& aIntrinsicSize, Image* aImage);
   void ClearCurrentFrame();
   void RateLimit(bool aLimit);
 
 protected:
   // mMutex protects all the class' fields.
   // This class is not registered to MediaStreamGraph.
   // It needs to protect all the fields.
   Mutex mMutex;
--- a/dom/camera/DOMCameraControlListener.cpp
+++ b/dom/camera/DOMCameraControlListener.cpp
@@ -306,17 +306,17 @@ DOMCameraControlListener::OnRateLimitPre
   mStream->RateLimit(aLimit);
 }
 
 bool
 DOMCameraControlListener::OnNewPreviewFrame(layers::Image* aImage, uint32_t aWidth, uint32_t aHeight)
 {
   DOM_CAMERA_LOGI("OnNewPreviewFrame: got %d x %d frame\n", aWidth, aHeight);
 
-  mStream->SetCurrentFrame(gfxIntSize(aWidth, aHeight), aImage);
+  mStream->SetCurrentFrame(gfx::IntSize(aWidth, aHeight), aImage);
   return true;
 }
 
 void
 DOMCameraControlListener::OnAutoFocusComplete(bool aAutoFocusSucceeded)
 {
   class Callback : public DOMCallback
   {
--- a/dom/canvas/CanvasImageCache.cpp
+++ b/dom/canvas/CanvasImageCache.cpp
@@ -48,17 +48,17 @@ struct ImageCacheEntryData {
 
   // Key
   nsRefPtr<Element> mImage;
   nsIImageLoadingContent* mILC;
   nsRefPtr<HTMLCanvasElement> mCanvas;
   // Value
   nsCOMPtr<imgIRequest> mRequest;
   RefPtr<SourceSurface> mSourceSurface;
-  gfxIntSize mSize;
+  IntSize mSize;
   nsExpirationState mState;
 };
 
 class ImageCacheEntry : public PLDHashEntryHdr {
 public:
   typedef ImageCacheKey KeyType;
   typedef const ImageCacheKey* KeyTypePointer;
 
@@ -232,17 +232,17 @@ ImageCache::~ImageCache() {
   mImageCacheObserver->Destroy();
 }
 
 void
 CanvasImageCache::NotifyDrawImage(Element* aImage,
                                   HTMLCanvasElement* aCanvas,
                                   imgIRequest* aRequest,
                                   SourceSurface* aSource,
-                                  const gfxIntSize& aSize)
+                                  const IntSize& aSize)
 {
   if (!gImageCache) {
     gImageCache = new ImageCache();
     nsContentUtils::RegisterShutdownObserver(new CanvasImageCacheShutdownObserver());
   }
 
   ImageCacheEntry* entry = gImageCache->mCache.PutEntry(ImageCacheKey(aImage, aCanvas));
   if (entry) {
--- a/dom/canvas/CanvasImageCache.h
+++ b/dom/canvas/CanvasImageCache.h
@@ -28,17 +28,17 @@ public:
    * Notify that image element aImage was (or is about to be) drawn to aCanvas
    * using the first frame of aRequest's image. The data for the surface is
    * in aSurface, and the image size is in aSize.
    */
   static void NotifyDrawImage(dom::Element* aImage,
                               dom::HTMLCanvasElement* aCanvas,
                               imgIRequest* aRequest,
                               SourceSurface* aSource,
-                              const gfxIntSize& aSize);
+                              const gfx::IntSize& aSize);
 
   /**
    * Check whether aImage has recently been drawn into aCanvas. If we return
    * a non-null surface, then the image was recently drawn into the canvas
    * (with the same image request) and the returned surface contains the image
    * data, and the image size will be returned in aSize.
    */
   static SourceSurface* Lookup(dom::Element* aImage,
--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -4782,17 +4782,17 @@ CanvasRenderingContext2D::GetGlobalCompo
 void
 CanvasRenderingContext2D::DrawWindow(nsGlobalWindow& window, double x,
                                      double y, double w, double h,
                                      const nsAString& bgColor,
                                      uint32_t flags, ErrorResult& error)
 {
   // protect against too-large surfaces that will cause allocation
   // or overflow issues
-  if (!gfxASurface::CheckSurfaceSize(gfxIntSize(int32_t(w), int32_t(h)),
+  if (!gfxASurface::CheckSurfaceSize(gfx::IntSize(int32_t(w), int32_t(h)),
                                      0xffff)) {
     error.Throw(NS_ERROR_FAILURE);
     return;
   }
 
   EnsureTarget();
   // We can't allow web apps to call this until we fix at least the
   // following potential security issues:
@@ -4971,17 +4971,17 @@ CanvasRenderingContext2D::AsyncDrawXULEl
       return;
     }
 
     return DrawWindow(window, x, y, w, h, bgColor, flags);
   }
 
   // protect against too-large surfaces that will cause allocation
   // or overflow issues
-  if (!gfxASurface::CheckSurfaceSize(gfxIntSize(w, h), 0xffff)) {
+  if (!gfxASurface::CheckSurfaceSize(gfx::IntSize(w, h), 0xffff)) {
     error.Throw(NS_ERROR_FAILURE);
     return;
   }
 
   bool flush =
     (flags & nsIDOMCanvasRenderingContext2D::DRAWWINDOW_DO_NOT_FLUSH) == 0;
 
   uint32_t renderDocFlags = nsIPresShell::RENDER_IGNORE_VIEWPORT_SCROLLING;
@@ -5396,17 +5396,17 @@ CanvasRenderingContext2D::PutImageData_e
 
   uint32_t len = w * h * 4;
   if (dataLen != len) {
     return NS_ERROR_DOM_INVALID_STATE_ERR;
   }
 
   uint32_t copyWidth = dirtyRect.Width();
   uint32_t copyHeight = dirtyRect.Height();
-  nsRefPtr<gfxImageSurface> imgsurf = new gfxImageSurface(gfxIntSize(copyWidth, copyHeight),
+  nsRefPtr<gfxImageSurface> imgsurf = new gfxImageSurface(gfx::IntSize(copyWidth, copyHeight),
                                                           gfxImageFormat::ARGB32,
                                                           false);
   if (!imgsurf || imgsurf->CairoStatus()) {
     return NS_ERROR_FAILURE;
   }
 
   uint32_t copyX = dirtyRect.x - x;
   uint32_t copyY = dirtyRect.y - y;
--- a/dom/canvas/WebGLContext.cpp
+++ b/dom/canvas/WebGLContext.cpp
@@ -212,16 +212,17 @@ WebGLContextOptions::WebGLContextOptions
         alpha = false;
 }
 
 WebGLContext::WebGLContext()
     : WebGLContextUnchecked(nullptr)
     , mBypassShaderValidation(false)
     , mGLMaxSamples(1)
     , mNeedsFakeNoAlpha(false)
+    , mNeedsFakeNoDepth(false)
     , mNeedsFakeNoStencil(false)
 {
     mGeneration = 0;
     mInvalidated = false;
     mCapturedFrameInvalidated = false;
     mShouldPresent = true;
     mResetLayer = true;
     mOptionsFrozen = false;
@@ -248,16 +249,17 @@ WebGLContext::WebGLContext()
     mViewportX = 0;
     mViewportY = 0;
     mViewportWidth = 0;
     mViewportHeight = 0;
 
     mDitherEnabled = 1;
     mRasterizerDiscardEnabled = 0; // OpenGL ES 3.0 spec p244
     mScissorTestEnabled = 0;
+    mDepthTestEnabled = 0;
     mStencilTestEnabled = 0;
 
     // initialize some GL values: we're going to get them from the GL and use them as the sizes of arrays,
     // so in case glGetIntegerv leaves them uninitialized because of a GL bug, we would have very weird crashes.
     mGLMaxVertexAttribs = 0;
     mGLMaxTextureUnits = 0;
     mGLMaxTextureSize = 0;
     mGLMaxTextureSizeLog2 = 0;
@@ -538,251 +540,244 @@ HasAcceleratedLayers(const nsCOMPtr<nsIG
         return true;
     gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_OPENGL_LAYERS, &status);
     if (status)
         return true;
 
     return false;
 }
 
-static already_AddRefed<GLContext>
-CreateHeadlessNativeGL(CreateContextFlags flags, const nsCOMPtr<nsIGfxInfo>& gfxInfo,
-                       WebGLContext* webgl)
-{
-    if (!(flags & CreateContextFlags::FORCE_ENABLE_HARDWARE) &&
-        IsFeatureInBlacklist(gfxInfo, nsIGfxInfo::FEATURE_WEBGL_OPENGL))
-    {
-        webgl->GenerateWarning("Refused to create native OpenGL context"
-                               " because of blacklisting.");
-        return nullptr;
-    }
-
-    nsRefPtr<GLContext> gl = gl::GLContextProvider::CreateHeadless(flags);
-    if (!gl) {
-        webgl->GenerateWarning("Error during native OpenGL init.");
-        return nullptr;
-    }
-    MOZ_ASSERT(!gl->IsANGLE());
-
-    return gl.forget();
-}
-
-// Note that we have a separate call for ANGLE and EGL, even though
-// right now, we get ANGLE implicitly by using EGL on Windows.
-// Eventually, we want to be able to pick ANGLE-EGL or native EGL.
-static already_AddRefed<GLContext>
-CreateHeadlessANGLE(CreateContextFlags flags, const nsCOMPtr<nsIGfxInfo>& gfxInfo,
-                    WebGLContext* webgl)
-{
-    nsRefPtr<GLContext> gl;
-
-#ifdef XP_WIN
-    gl = gl::GLContextProviderEGL::CreateHeadless(flags);
-    if (!gl) {
-        webgl->GenerateWarning("Error during ANGLE OpenGL init.");
-        return nullptr;
-    }
-    MOZ_ASSERT(gl->IsANGLE());
-#endif
-
-    return gl.forget();
-}
-
-static already_AddRefed<GLContext>
-CreateHeadlessEGL(CreateContextFlags flags, WebGLContext* webgl)
-{
-    nsRefPtr<GLContext> gl;
-
-#ifdef ANDROID
-    gl = gl::GLContextProviderEGL::CreateHeadless(flags);
-    if (!gl) {
-        webgl->GenerateWarning("Error during EGL OpenGL init.");
-        return nullptr;
-    }
-    MOZ_ASSERT(!gl->IsANGLE());
-#endif
-
-    return gl.forget();
-}
-
-static already_AddRefed<GLContext>
-CreateHeadlessGL(CreateContextFlags flags, const nsCOMPtr<nsIGfxInfo>& gfxInfo,
-                 WebGLContext* webgl)
-{
-    bool preferEGL = PR_GetEnv("MOZ_WEBGL_PREFER_EGL");
-    bool disableANGLE = Preferences::GetBool("webgl.disable-angle", false);
-
-    if (PR_GetEnv("MOZ_WEBGL_FORCE_OPENGL"))
-        disableANGLE = true;
-
-    if (!webgl->IsWebGL2()) {
-        flags |= CreateContextFlags::REQUIRE_COMPAT_PROFILE;
-    }
-
-    nsRefPtr<GLContext> gl;
-
-    if (preferEGL)
-        gl = CreateHeadlessEGL(flags, webgl);
-
-    if (!gl && !disableANGLE) {
-        gl = CreateHeadlessANGLE(flags, gfxInfo, webgl);
-    }
-
-    if (!gl) {
-        gl = CreateHeadlessNativeGL(flags, gfxInfo, webgl);
-    }
-
-    return gl.forget();
-}
-
-// Try to create a dummy offscreen with the given caps.
-static bool
-CreateOffscreenWithCaps(GLContext* gl, const SurfaceCaps& caps)
-{
-    gfx::IntSize dummySize(16, 16);
-    return gl->InitOffscreen(dummySize, caps);
-}
-
 static void
-PopulateCapFallbackQueue(const SurfaceCaps& baseCaps,
-                         std::queue<SurfaceCaps>* out_fallbackCaps)
+PopulateCapFallbackQueue(const gl::SurfaceCaps& baseCaps,
+                         std::queue<gl::SurfaceCaps>* out_fallbackCaps)
 {
     out_fallbackCaps->push(baseCaps);
 
     // Dropping antialias drops our quality, but not our correctness.
     // The user basically doesn't have to handle if this fails, they
     // just get reduced quality.
     if (baseCaps.antialias) {
-        SurfaceCaps nextCaps(baseCaps);
+        gl::SurfaceCaps nextCaps(baseCaps);
         nextCaps.antialias = false;
         PopulateCapFallbackQueue(nextCaps, out_fallbackCaps);
     }
 
     // If we have to drop one of depth or stencil, we'd prefer to keep
     // depth. However, the client app will need to handle if this
     // doesn't work.
     if (baseCaps.stencil) {
-        SurfaceCaps nextCaps(baseCaps);
+        gl::SurfaceCaps nextCaps(baseCaps);
         nextCaps.stencil = false;
         PopulateCapFallbackQueue(nextCaps, out_fallbackCaps);
     }
 
     if (baseCaps.depth) {
-        SurfaceCaps nextCaps(baseCaps);
+        gl::SurfaceCaps nextCaps(baseCaps);
         nextCaps.depth = false;
         PopulateCapFallbackQueue(nextCaps, out_fallbackCaps);
     }
 }
 
-static bool
-CreateOffscreen(GLContext* gl, const WebGLContextOptions& options,
-                const nsCOMPtr<nsIGfxInfo>& gfxInfo, WebGLContext* webgl,
-                layers::LayersBackend layersBackend,
-                layers::ISurfaceAllocator* surfAllocator)
+static gl::SurfaceCaps
+BaseCaps(const WebGLContextOptions& options, WebGLContext* webgl)
 {
-    SurfaceCaps baseCaps;
+    gl::SurfaceCaps baseCaps;
 
     baseCaps.color = true;
     baseCaps.alpha = options.alpha;
     baseCaps.antialias = options.antialias;
     baseCaps.depth = options.depth;
     baseCaps.premultAlpha = options.premultipliedAlpha;
     baseCaps.preserve = options.preserveDrawingBuffer;
     baseCaps.stencil = options.stencil;
 
     if (!baseCaps.alpha)
         baseCaps.premultAlpha = true;
 
-    if (gl->IsANGLE() ||
-        (gl->GetContextType() == GLContextType::GLX &&
-         layersBackend == LayersBackend::LAYERS_OPENGL))
-    {
-        // We can't use no-alpha formats on ANGLE yet because of:
-        // https://code.google.com/p/angleproject/issues/detail?id=764
-        // GLX only supports GL_RGBA pixmaps as well. Since we can't blit from
-        // an RGB FB to GLX's RGBA FB, force RGBA when surface sharing.
-        baseCaps.alpha = true;
-    }
-
     // we should really have this behind a
     // |gfxPlatform::GetPlatform()->GetScreenDepth() == 16| check, but
     // for now it's just behind a pref for testing/evaluation.
     baseCaps.bpp16 = Preferences::GetBool("webgl.prefer-16bpp", false);
 
 #ifdef MOZ_WIDGET_GONK
-    baseCaps.surfaceAllocator = surfAllocator;
+    do {
+        auto canvasElement = webgl->GetCanvas();
+        auto ownerDoc = canvasElement->OwnerDoc();
+        nsIWidget* docWidget = nsContentUtils::WidgetForDocument(ownerDoc);
+        if (!docWidget)
+            break;
+
+        layers::LayerManager* layerManager = docWidget->GetLayerManager();
+        if (!layerManager)
+            break;
+
+        // XXX we really want "AsSurfaceAllocator" here for generality
+        layers::ShadowLayerForwarder* forwarder = layerManager->AsShadowForwarder();
+        if (!forwarder)
+            break;
+
+        baseCaps.surfaceAllocator = static_cast<layers::ISurfaceAllocator*>(forwarder);
+    } while (false);
 #endif
 
     // Done with baseCaps construction.
 
     bool forceAllowAA = Preferences::GetBool("webgl.msaa-force", false);
+    nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
     if (!forceAllowAA &&
         IsFeatureInBlacklist(gfxInfo, nsIGfxInfo::FEATURE_WEBGL_MSAA))
     {
         webgl->GenerateWarning("Disallowing antialiased backbuffers due"
                                " to blacklisting.");
         baseCaps.antialias = false;
     }
 
-    std::queue<SurfaceCaps> fallbackCaps;
+    return baseCaps;
+}
+
+////////////////////////////////////////
+
+static already_AddRefed<gl::GLContext>
+CreateGLWithEGL(const gl::SurfaceCaps& caps, gl::CreateContextFlags flags,
+                WebGLContext* webgl)
+{
+    RefPtr<GLContext> gl;
+#ifndef XP_MACOSX // Mac doesn't have GLContextProviderEGL.
+    gfx::IntSize dummySize(16, 16);
+    gl = gl::GLContextProviderEGL::CreateOffscreen(dummySize, caps,
+                                                                     flags);
+    if (!gl) {
+        webgl->GenerateWarning("Error during EGL OpenGL init.");
+        return nullptr;
+    }
+
+    if (gl->IsANGLE())
+        return nullptr;
+#endif // XP_MACOSX
+    return gl.forget();
+}
+
+static already_AddRefed<GLContext>
+CreateGLWithANGLE(const gl::SurfaceCaps& caps, gl::CreateContextFlags flags,
+                  WebGLContext* webgl)
+{
+    RefPtr<GLContext> gl;
+
+#ifdef XP_WIN
+    gfx::IntSize dummySize(16, 16);
+    gl = gl::GLContextProviderEGL::CreateOffscreen(dummySize, caps, flags);
+    if (!gl) {
+        webgl->GenerateWarning("Error during ANGLE OpenGL init.");
+        return nullptr;
+    }
+
+    if (!gl->IsANGLE())
+        return nullptr;
+#endif
+
+    return gl.forget();
+}
+
+static already_AddRefed<gl::GLContext>
+CreateGLWithDefault(const gl::SurfaceCaps& caps, gl::CreateContextFlags flags,
+                    WebGLContext* webgl)
+{
+    nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
+
+    if (!(flags & CreateContextFlags::FORCE_ENABLE_HARDWARE) &&
+        IsFeatureInBlacklist(gfxInfo, nsIGfxInfo::FEATURE_WEBGL_OPENGL))
+    {
+        webgl->GenerateWarning("Refused to create native OpenGL context because of"
+                               " blacklisting.");
+        return nullptr;
+    }
+
+    gfx::IntSize dummySize(16, 16);
+    RefPtr<GLContext> gl = gl::GLContextProvider::CreateOffscreen(dummySize, caps, flags);
+    if (!gl) {
+        webgl->GenerateWarning("Error during native OpenGL init.");
+        return nullptr;
+    }
+
+    if (gl->IsANGLE())
+        return nullptr;
+
+    return gl.forget();
+}
+
+////////////////////////////////////////
+
+bool
+WebGLContext::CreateAndInitGLWith(FnCreateGL_T fnCreateGL,
+                                  const gl::SurfaceCaps& baseCaps,
+                                  gl::CreateContextFlags flags)
+{
+    MOZ_ASSERT(!gl);
+
+    std::queue<gl::SurfaceCaps> fallbackCaps;
     PopulateCapFallbackQueue(baseCaps, &fallbackCaps);
 
-    bool created = false;
+    gl = nullptr;
     while (!fallbackCaps.empty()) {
-        SurfaceCaps& caps = fallbackCaps.front();
+        gl::SurfaceCaps& caps = fallbackCaps.front();
 
-        created = CreateOffscreenWithCaps(gl, caps);
-        if (created)
+        gl = fnCreateGL(caps, flags, this);
+        if (gl)
             break;
 
         fallbackCaps.pop();
     }
+    if (!gl)
+        return false;
 
-    return created;
+    if (!InitAndValidateGL()) {
+        gl = nullptr;
+        return false;
+    }
+
+    return true;
 }
 
 bool
-WebGLContext::CreateOffscreenGL(bool forceEnabled)
+WebGLContext::CreateAndInitGL(bool forceEnabled)
 {
-    nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
+    bool preferEGL = PR_GetEnv("MOZ_WEBGL_PREFER_EGL");
+    bool disableANGLE = Preferences::GetBool("webgl.disable-angle", false);
+
+    if (PR_GetEnv("MOZ_WEBGL_FORCE_OPENGL"))
+        disableANGLE = true;
 
-    layers::ISurfaceAllocator* surfAllocator = nullptr;
-#ifdef MOZ_WIDGET_GONK
-    nsIWidget* docWidget = nsContentUtils::WidgetForDocument(mCanvasElement->OwnerDoc());
-    if (docWidget) {
-        layers::LayerManager* layerManager = docWidget->GetLayerManager();
-        if (layerManager) {
-            // XXX we really want "AsSurfaceAllocator" here for generality
-            layers::ShadowLayerForwarder* forwarder = layerManager->AsShadowForwarder();
-            if (forwarder)
-                surfAllocator = static_cast<layers::ISurfaceAllocator*>(forwarder);
-        }
-    }
-#endif
+    gl::CreateContextFlags flags = gl::CreateContextFlags::NONE;
+    if (forceEnabled) flags |= gl::CreateContextFlags::FORCE_ENABLE_HARDWARE;
+    if (!IsWebGL2())  flags |= gl::CreateContextFlags::REQUIRE_COMPAT_PROFILE;
+
+    const gl::SurfaceCaps baseCaps = BaseCaps(mOptions, this);
+
+    MOZ_ASSERT(!gl);
 
-    CreateContextFlags flags = forceEnabled ? CreateContextFlags::FORCE_ENABLE_HARDWARE :
-                                              CreateContextFlags::NONE;
+    if (preferEGL) {
+        if (CreateAndInitGLWith(CreateGLWithEGL, baseCaps, flags))
+            return true;
+    }
 
-    gl = CreateHeadlessGL(flags, gfxInfo, this);
-
-    do {
-        if (!gl)
-            break;
+    MOZ_ASSERT(!gl);
 
-        if (!CreateOffscreen(gl, mOptions, gfxInfo, this,
-                             GetCompositorBackendType(), surfAllocator))
-            break;
+    if (!disableANGLE) {
+        if (CreateAndInitGLWith(CreateGLWithANGLE, baseCaps, flags))
+            return true;
+    }
+
+    MOZ_ASSERT(!gl);
 
-        if (!InitAndValidateGL())
-            break;
-
+    if (CreateAndInitGLWith(CreateGLWithDefault, baseCaps, flags))
         return true;
-    } while (false);
 
+    MOZ_ASSERT(!gl);
     gl = nullptr;
+
     return false;
 }
 
 // Fallback for resizes:
 bool
 WebGLContext::ResizeBackbuffer(uint32_t requestedWidth,
                                uint32_t requestedHeight)
 {
@@ -936,22 +931,25 @@ WebGLContext::SetDimensions(int32_t sign
             return NS_ERROR_FAILURE;
         }
     }
 
     // Alright, now let's start trying.
     bool forceEnabled = Preferences::GetBool("webgl.force-enabled", false);
     ScopedGfxFeatureReporter reporter("WebGL", forceEnabled);
 
-    if (!CreateOffscreenGL(forceEnabled)) {
+    MOZ_ASSERT(!gl);
+    if (!CreateAndInitGL(forceEnabled)) {
         GenerateWarning("WebGL creation failed.");
         return NS_ERROR_FAILURE;
     }
     MOZ_ASSERT(gl);
 
+    MOZ_ASSERT_IF(mOptions.alpha, gl->Caps().alpha);
+
     if (!ResizeBackbuffer(width, height)) {
         GenerateWarning("Initializing WebGL backbuffer failed.");
         return NS_ERROR_FAILURE;
     }
 
 #ifdef DEBUG
     if (gl->DebugMode())
         printf_stderr("--- WebGL context created: %p\n", gl.get());
@@ -960,24 +958,30 @@ WebGLContext::SetDimensions(int32_t sign
     mResetLayer = true;
     mOptionsFrozen = true;
 
     // Update our internal stuff:
     if (gl->WorkAroundDriverBugs()) {
         if (!mOptions.alpha && gl->Caps().alpha)
             mNeedsFakeNoAlpha = true;
 
-        // ANGLE doesn't quite handle this properly.
-        if (gl->Caps().depth && !gl->Caps().stencil && gl->IsANGLE())
+        if (!mOptions.depth && gl->Caps().depth)
+            mNeedsFakeNoDepth = true;
+
+        if (!mOptions.stencil && gl->Caps().stencil)
             mNeedsFakeNoStencil = true;
     }
 
     // Update mOptions.
-    mOptions.depth = gl->Caps().depth;
-    mOptions.stencil = gl->Caps().stencil;
+    if (!gl->Caps().depth)
+        mOptions.depth = false;
+
+    if (!gl->Caps().stencil)
+        mOptions.stencil = false;
+
     mOptions.antialias = gl->Caps().antialias;
 
     MakeContextCurrent();
 
     gl->fViewport(0, 0, mWidth, mHeight);
     mViewportWidth = mWidth;
     mViewportHeight = mHeight;
 
@@ -993,20 +997,26 @@ WebGLContext::SetDimensions(int32_t sign
     // Clear immediately, because we need to present the cleared initial
     // buffer.
     mBackbufferNeedsClear = true;
     ClearBackbufferIfNeeded();
 
     mShouldPresent = true;
 
     MOZ_ASSERT(gl->Caps().color);
+
     MOZ_ASSERT_IF(!mNeedsFakeNoAlpha, gl->Caps().alpha == mOptions.alpha);
     MOZ_ASSERT_IF(mNeedsFakeNoAlpha, !mOptions.alpha && gl->Caps().alpha);
-    MOZ_ASSERT(gl->Caps().depth == mOptions.depth);
-    MOZ_ASSERT(gl->Caps().stencil == mOptions.stencil);
+
+    MOZ_ASSERT_IF(!mNeedsFakeNoDepth, gl->Caps().depth == mOptions.depth);
+    MOZ_ASSERT_IF(mNeedsFakeNoDepth, !mOptions.depth && gl->Caps().depth);
+
+    MOZ_ASSERT_IF(!mNeedsFakeNoStencil, gl->Caps().stencil == mOptions.stencil);
+    MOZ_ASSERT_IF(mNeedsFakeNoStencil, !mOptions.stencil && gl->Caps().stencil);
+
     MOZ_ASSERT(gl->Caps().antialias == mOptions.antialias);
     MOZ_ASSERT(gl->Caps().preserve == mOptions.preserveDrawingBuffer);
 
     AssertCachedBindings();
     AssertCachedState();
 
     reporter.SetSuccessful();
     return NS_OK;
@@ -1871,37 +1881,44 @@ RoundedToNextMultipleOf(CheckedUint32 x,
     return ((x + y - 1) / y) * y;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 
 WebGLContext::ScopedMaskWorkaround::ScopedMaskWorkaround(WebGLContext& webgl)
     : mWebGL(webgl)
     , mFakeNoAlpha(ShouldFakeNoAlpha(webgl))
+    , mFakeNoDepth(ShouldFakeNoDepth(webgl))
     , mFakeNoStencil(ShouldFakeNoStencil(webgl))
 {
     if (mFakeNoAlpha) {
         mWebGL.gl->fColorMask(mWebGL.mColorWriteMask[0],
                               mWebGL.mColorWriteMask[1],
                               mWebGL.mColorWriteMask[2],
                               false);
     }
+    if (mFakeNoDepth) {
+        mWebGL.gl->fDisable(LOCAL_GL_DEPTH_TEST);
+    }
     if (mFakeNoStencil) {
         mWebGL.gl->fDisable(LOCAL_GL_STENCIL_TEST);
     }
 }
 
 WebGLContext::ScopedMaskWorkaround::~ScopedMaskWorkaround()
 {
     if (mFakeNoAlpha) {
         mWebGL.gl->fColorMask(mWebGL.mColorWriteMask[0],
                               mWebGL.mColorWriteMask[1],
                               mWebGL.mColorWriteMask[2],
                               mWebGL.mColorWriteMask[3]);
     }
+    if (mFakeNoDepth) {
+        mWebGL.gl->fEnable(LOCAL_GL_DEPTH_TEST);
+    }
     if (mFakeNoStencil) {
         mWebGL.gl->fEnable(LOCAL_GL_STENCIL_TEST);
     }
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // XPCOM goop
 
--- a/dom/canvas/WebGLContext.h
+++ b/dom/canvas/WebGLContext.h
@@ -3,32 +3,34 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef WEBGLCONTEXT_H_
 #define WEBGLCONTEXT_H_
 
 #include <stdarg.h>
 
+#include "GLContextTypes.h"
 #include "GLDefs.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/CheckedInt.h"
 #include "mozilla/dom/HTMLCanvasElement.h"
 #include "mozilla/dom/TypedArray.h"
 #include "mozilla/EnumeratedArray.h"
 #include "mozilla/ErrorResult.h"
 #include "mozilla/gfx/2D.h"
 #include "mozilla/LinkedList.h"
 #include "mozilla/UniquePtr.h"
 #include "mozilla/WeakPtr.h"
 #include "nsCycleCollectionNoteChild.h"
 #include "nsICanvasRenderingContextInternal.h"
 #include "nsLayoutUtils.h"
 #include "nsTArray.h"
 #include "nsWrapperCache.h"
+#include "SurfaceTypes.h"
 
 #ifdef XP_MACOSX
 #include "ForceDiscreteGPUHelperCGL.h"
 #endif
 
 // Local
 #include "WebGLContextUnchecked.h"
 #include "WebGLFormats.h"
@@ -807,16 +809,17 @@ public:
                              JS::MutableHandle<JS::Value> retval);
     bool IsEnabled(GLenum cap);
 
 private:
     // State tracking slots
     realGLboolean mDitherEnabled;
     realGLboolean mRasterizerDiscardEnabled;
     realGLboolean mScissorTestEnabled;
+    realGLboolean mDepthTestEnabled;
     realGLboolean mStencilTestEnabled;
 
     bool ValidateCapabilityEnum(GLenum cap, const char* info);
     realGLboolean* GetStateTrackingSlot(GLenum cap);
 
 // -----------------------------------------------------------------------------
 // Texture funcions (WebGLContextTextures.cpp)
 public:
@@ -1148,21 +1151,29 @@ protected:
     // -------------------------------------------------------------------------
     // WebGL 2 specifics (implemented in WebGL2Context.cpp)
 public:
     virtual bool IsWebGL2() const = 0;
 
 protected:
     bool InitWebGL2();
 
+    bool CreateAndInitGL(bool forceEnabled);
+    bool ResizeBackbuffer(uint32_t width, uint32_t height);
+
+    typedef already_AddRefed<gl::GLContext> FnCreateGL_T(const gl::SurfaceCaps& caps,
+                                                         gl::CreateContextFlags flags,
+                                                         WebGLContext* webgl);
+
+    bool CreateAndInitGLWith(FnCreateGL_T fnCreateGL, const gl::SurfaceCaps& baseCaps,
+                             gl::CreateContextFlags flags);
+
     // -------------------------------------------------------------------------
     // Validation functions (implemented in WebGLContextValidate.cpp)
-    bool CreateOffscreenGL(bool forceEnabled);
     bool InitAndValidateGL();
-    bool ResizeBackbuffer(uint32_t width, uint32_t height);
     bool ValidateBlendEquationEnum(GLenum cap, const char* info);
     bool ValidateBlendFuncDstEnum(GLenum mode, const char* info);
     bool ValidateBlendFuncSrcEnum(GLenum mode, const char* info);
     bool ValidateBlendFuncEnumsCompatibility(GLenum sfactor, GLenum dfactor,
                                              const char* info);
     bool ValidateDataOffsetSize(WebGLintptr offset, WebGLsizeiptr size, WebGLsizeiptr bufferSize, const char* info);
     bool ValidateDataRanges(WebGLintptr readOffset, WebGLintptr writeOffset, WebGLsizeiptr size, const char* info);
     bool ValidateTextureTargetEnum(GLenum target, const char* info);
@@ -1438,31 +1449,40 @@ protected:
     int mMaxWarnings;
     bool mAlreadyWarnedAboutFakeVertexAttrib0;
 
     bool ShouldGenerateWarnings() const;
 
     uint64_t mLastUseIndex;
 
     bool mNeedsFakeNoAlpha;
+    bool mNeedsFakeNoDepth;
     bool mNeedsFakeNoStencil;
 
     struct ScopedMaskWorkaround {
         WebGLContext& mWebGL;
         const bool mFakeNoAlpha;
+        const bool mFakeNoDepth;
         const bool mFakeNoStencil;
 
         static bool ShouldFakeNoAlpha(WebGLContext& webgl) {
             // We should only be doing this if we're about to draw to the backbuffer, but
             // the backbuffer needs to have this fake-no-alpha workaround.
             return !webgl.mBoundDrawFramebuffer &&
                    webgl.mNeedsFakeNoAlpha &&
                    webgl.mColorWriteMask[3] != false;
         }
 
+        static bool ShouldFakeNoDepth(WebGLContext& webgl) {
+            // We should only be doing this if we're about to draw to the backbuffer.
+            return !webgl.mBoundDrawFramebuffer &&
+                   webgl.mNeedsFakeNoDepth &&
+                   webgl.mDepthTestEnabled;
+        }
+
         static bool ShouldFakeNoStencil(WebGLContext& webgl) {
             // We should only be doing this if we're about to draw to the backbuffer.
             return !webgl.mBoundDrawFramebuffer &&
                    webgl.mNeedsFakeNoStencil &&
                    webgl.mStencilTestEnabled;
         }
 
         explicit ScopedMaskWorkaround(WebGLContext& webgl);
--- a/dom/canvas/WebGLContextState.cpp
+++ b/dom/canvas/WebGLContextState.cpp
@@ -355,20 +355,26 @@ WebGLContext::GetParameter(JSContext* cx
         case LOCAL_GL_SAMPLE_BUFFERS:
         case LOCAL_GL_SAMPLES:
         case LOCAL_GL_MAX_VERTEX_ATTRIBS:
         case LOCAL_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
         case LOCAL_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
         case LOCAL_GL_MAX_TEXTURE_IMAGE_UNITS:
         case LOCAL_GL_RED_BITS:
         case LOCAL_GL_GREEN_BITS:
-        case LOCAL_GL_BLUE_BITS:
+        case LOCAL_GL_BLUE_BITS: {
+            GLint i = 0;
+            gl->fGetIntegerv(pname, &i);
+            return JS::Int32Value(i);
+        }
         case LOCAL_GL_DEPTH_BITS: {
             GLint i = 0;
-            gl->fGetIntegerv(pname, &i);
+            if (!mNeedsFakeNoDepth) {
+                gl->fGetIntegerv(pname, &i);
+            }
             return JS::Int32Value(i);
         }
         case LOCAL_GL_ALPHA_BITS: {
             GLint i = 0;
             if (!mNeedsFakeNoAlpha) {
                 gl->fGetIntegerv(pname, &i);
             }
             return JS::Int32Value(i);
@@ -617,16 +623,18 @@ WebGLContext::ValidateCapabilityEnum(GLe
             return false;
     }
 }
 
 realGLboolean*
 WebGLContext::GetStateTrackingSlot(GLenum cap)
 {
     switch (cap) {
+        case LOCAL_GL_DEPTH_TEST:
+            return &mDepthTestEnabled;
         case LOCAL_GL_DITHER:
             return &mDitherEnabled;
         case LOCAL_GL_RASTERIZER_DISCARD:
             return &mRasterizerDiscardEnabled;
         case LOCAL_GL_SCISSOR_TEST:
             return &mScissorTestEnabled;
         case LOCAL_GL_STENCIL_TEST:
             return &mStencilTestEnabled;
--- a/dom/canvas/WebGLContextUtils.cpp
+++ b/dom/canvas/WebGLContextUtils.cpp
@@ -1170,16 +1170,17 @@ WebGLContext::AssertCachedState()
 
     // extensions
     if (IsExtensionEnabled(WebGLExtensionID::WEBGL_draw_buffers)) {
         AssertUintParamCorrect(gl, LOCAL_GL_MAX_COLOR_ATTACHMENTS, mGLMaxColorAttachments);
         AssertUintParamCorrect(gl, LOCAL_GL_MAX_DRAW_BUFFERS, mGLMaxDrawBuffers);
     }
 
     // Draw state
+    MOZ_ASSERT(gl->fIsEnabled(LOCAL_GL_DEPTH_TEST) == mDepthTestEnabled);
     MOZ_ASSERT(gl->fIsEnabled(LOCAL_GL_DITHER) == mDitherEnabled);
     MOZ_ASSERT_IF(IsWebGL2(),
                   gl->fIsEnabled(LOCAL_GL_RASTERIZER_DISCARD) == mRasterizerDiscardEnabled);
     MOZ_ASSERT(gl->fIsEnabled(LOCAL_GL_SCISSOR_TEST) == mScissorTestEnabled);
     MOZ_ASSERT(gl->fIsEnabled(LOCAL_GL_STENCIL_TEST) == mStencilTestEnabled);
 
     realGLboolean colorWriteMask[4] = {0, 0, 0, 0};
     gl->fGetBooleanv(LOCAL_GL_COLOR_WRITEMASK, colorWriteMask);
--- a/dom/events/Event.cpp
+++ b/dom/events/Event.cpp
@@ -899,17 +899,17 @@ Event::Shutdown()
   }
 }
 
 LayoutDeviceIntPoint
 Event::GetScreenCoords(nsPresContext* aPresContext,
                        WidgetEvent* aEvent,
                        LayoutDeviceIntPoint aPoint)
 {
-  if (!nsContentUtils::IsCallerChrome() &&
+  if (!nsContentUtils::LegacyIsCallerChromeOrNativeCode() &&
       nsContentUtils::ResistFingerprinting()) {
     // When resisting fingerprinting, return client coordinates instead.
     CSSIntPoint clientCoords = GetClientCoords(aPresContext, aEvent, aPoint, CSSIntPoint(0, 0));
     return LayoutDeviceIntPoint(clientCoords.x, clientCoords.y);
   }
 
   if (EventStateManager::sIsPointerLocked) {
     return EventStateManager::sLastScreenPoint;
--- a/dom/events/EventDispatcher.cpp
+++ b/dom/events/EventDispatcher.cpp
@@ -31,16 +31,17 @@
 #include "mozilla/dom/ScrollAreaEvent.h"
 #include "mozilla/dom/SimpleGestureEvent.h"
 #include "mozilla/dom/StorageEvent.h"
 #include "mozilla/dom/SVGZoomEvent.h"
 #include "mozilla/dom/TimeEvent.h"
 #include "mozilla/dom/TouchEvent.h"
 #include "mozilla/dom/TransitionEvent.h"
 #include "mozilla/dom/WheelEvent.h"
+#include "mozilla/dom/WorkerPrivate.h"
 #include "mozilla/dom/XULCommandEvent.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/EventListenerManager.h"
 #include "mozilla/InternalMutationEvent.h"
 #include "mozilla/ipc/MessageChannel.h"
 #include "mozilla/MiscEvents.h"
 #include "mozilla/MouseEvents.h"
 #include "mozilla/TextEvents.h"
@@ -704,17 +705,19 @@ EventDispatcher::DispatchDOMEvent(nsISup
       innerEvent->target = nullptr;
       innerEvent->originalTarget = nullptr;
     } else {
       aDOMEvent->GetIsTrusted(&dontResetTrusted);
     }
 
     if (!dontResetTrusted) {
       //Check security state to determine if dispatcher is trusted
-      aDOMEvent->SetTrusted(nsContentUtils::ThreadsafeIsCallerChrome());
+      bool trusted = NS_IsMainThread() ? nsContentUtils::LegacyIsCallerChromeOrNativeCode()
+                                       : mozilla::dom::workers::IsCurrentThreadRunningChromeWorker();
+      aDOMEvent->SetTrusted(trusted);
     }
 
     return EventDispatcher::Dispatch(aTarget, aPresContext, innerEvent,
                                      aDOMEvent, aEventStatus);
   } else if (aEvent) {
     return EventDispatcher::Dispatch(aTarget, aPresContext, aEvent,
                                      aDOMEvent, aEventStatus);
   }
--- a/dom/events/Touch.cpp
+++ b/dom/events/Touch.cpp
@@ -88,16 +88,17 @@ NS_INTERFACE_MAP_END
 NS_IMPL_CYCLE_COLLECTING_ADDREF(Touch)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(Touch)
 
 EventTarget*
 Touch::GetTarget() const
 {
   nsCOMPtr<nsIContent> content = do_QueryInterface(mTarget);
   if (content && content->ChromeOnlyAccess() &&
+      !nsContentUtils::LegacyIsCallerNativeCode() &&
       !nsContentUtils::CanAccessNativeAnon()) {
     return content->FindFirstNonChromeOnlyAccessContent();
   }
 
   return mTarget;
 }
 
 void
--- a/dom/events/test/test_bug607464.html
+++ b/dom/events/test/test_bug607464.html
@@ -2,16 +2,17 @@
 <html>
 <!--
 https://bugzilla.mozilla.org/show_bug.cgi?id=607464
 -->
 <head>
   <title>Test for Bug 607464</title>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+  <script type="text/javascript" src="/tests/gfx/layers/apz/test/mochitest/apz_test_utils.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=607464">Mozilla Bug 607464</a>
 <p id="display"></p>
 <div id="content" style="display: none">
 
 </div>
@@ -58,17 +59,19 @@ function runTest() {
          "scroll position " + scrollbox.scrollTop + " in this sequence of wheel " +
          "events should be a multiple of 30.");
       if (scrollbox.scrollTop == 150) {
         win.close();
         SimpleTest.finish();
       }
     }, true);
 
-    scrollDown150PxWithPixelScrolling(scrollbox);
+    flushApzRepaints(function() {
+      scrollDown150PxWithPixelScrolling(scrollbox);
+    }, win);
   }, win);
 }
 
 window.onload = function() {
   SpecialPowers.pushPrefEnv({
     "set":[["general.smoothScroll", true],
            ["mousewheel.acceleration.start", -1],
            ["mousewheel.system_scroll_override_on_root_content.enabled", false]]}, runTest);
--- a/dom/geolocation/nsGeolocation.cpp
+++ b/dom/geolocation/nsGeolocation.cpp
@@ -1414,17 +1414,17 @@ Geolocation::GetCurrentPosition(GeoPosit
                                                                     false);
 
   if (!sGeoEnabled) {
     nsCOMPtr<nsIRunnable> ev = new RequestAllowEvent(false, request);
     NS_DispatchToMainThread(ev);
     return NS_OK;
   }
 
-  if (!mOwner && !nsContentUtils::IsCallerChrome()) {
+  if (!mOwner && !nsContentUtils::LegacyIsCallerChromeOrNativeCode()) {
     return NS_ERROR_FAILURE;
   }
 
   if (sGeoInitPending) {
     mPendingRequests.AppendElement(request);
     return NS_OK;
   }
 
@@ -1437,17 +1437,17 @@ Geolocation::GetCurrentPositionReady(nsG
   if (mOwner) {
     if (!RegisterRequestWithPrompt(aRequest)) {
       return NS_ERROR_NOT_AVAILABLE;
     }
 
     return NS_OK;
   }
 
-  if (!nsContentUtils::IsCallerChrome()) {
+  if (!nsContentUtils::LegacyIsCallerChromeOrNativeCode()) {
     return NS_ERROR_FAILURE;
   }
 
   nsCOMPtr<nsIRunnable> ev = new RequestAllowEvent(true, aRequest);
   NS_DispatchToMainThread(ev);
 
   return NS_OK;
 }
@@ -1508,17 +1508,17 @@ Geolocation::WatchPosition(GeoPositionCa
 
   if (!sGeoEnabled) {
     GPSLOG("request allow event");
     nsCOMPtr<nsIRunnable> ev = new RequestAllowEvent(false, request);
     NS_DispatchToMainThread(ev);
     return NS_OK;
   }
 
-  if (!mOwner && !nsContentUtils::IsCallerChrome()) {
+  if (!mOwner && !nsContentUtils::LegacyIsCallerChromeOrNativeCode()) {
     return NS_ERROR_FAILURE;
   }
 
   if (sGeoInitPending) {
     mPendingRequests.AppendElement(request);
     return NS_OK;
   }
 
@@ -1530,17 +1530,17 @@ Geolocation::WatchPositionReady(nsGeoloc
 {
   if (mOwner) {
     if (!RegisterRequestWithPrompt(aRequest))
       return NS_ERROR_NOT_AVAILABLE;
 
     return NS_OK;
   }
 
-  if (!nsContentUtils::IsCallerChrome()) {
+  if (!nsContentUtils::LegacyIsCallerChromeOrNativeCode()) {
     return NS_ERROR_FAILURE;
   }
 
   aRequest->Allow(JS::UndefinedHandleValue);
 
   return NS_OK;
 }
 
--- a/dom/html/HTMLInputElement.cpp
+++ b/dom/html/HTMLInputElement.cpp
@@ -1412,17 +1412,17 @@ HTMLInputElement::GetValueInternal(nsASt
       if (IsSingleLineTextControl(false)) {
         mInputData.mState->GetValue(aValue, true);
       } else {
         aValue.Assign(mInputData.mValue);
       }
       return NS_OK;
 
     case VALUE_MODE_FILENAME:
-      if (nsContentUtils::IsCallerChrome()) {
+      if (nsContentUtils::LegacyIsCallerChromeOrNativeCode()) {
 #ifndef MOZ_CHILD_PERMISSIONS
         aValue.Assign(mFirstFilePath);
 #else
         // XXX We'd love to assert that this can't happen, but some mochitests
         // use SpecialPowers to circumvent our more sane security model.
         if (!mFiles.IsEmpty()) {
           ErrorResult rv;
           mFiles[0]->GetMozFullPath(aValue, rv);
@@ -2989,17 +2989,17 @@ HTMLInputElement::Select()
 
 bool
 HTMLInputElement::DispatchSelectEvent(nsPresContext* aPresContext)
 {
   nsEventStatus status = nsEventStatus_eIgnore;
 
   // If already handling select event, don't dispatch a second.
   if (!mHandlingSelectEvent) {
-    WidgetEvent event(nsContentUtils::IsCallerChrome(), eFormSelect);
+    WidgetEvent event(nsContentUtils::LegacyIsCallerChromeOrNativeCode(), eFormSelect);
 
     mHandlingSelectEvent = true;
     EventDispatcher::Dispatch(static_cast<nsIContent*>(this),
                               aPresContext, &event, nullptr, &status);
     mHandlingSelectEvent = false;
   }
 
   // If the DOM event was not canceled (e.g. by a JS event handler
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -1467,17 +1467,17 @@ HTMLMediaElement::Seek(double aTime,
                        SeekTarget::Type aSeekType,
                        ErrorResult& aRv)
 {
   // aTime should be non-NaN.
   MOZ_ASSERT(!mozilla::IsNaN(aTime));
 
   // Detect if user has interacted with element by seeking so that
   // play will not be blocked when initiated by a script.
-  if (EventStateManager::IsHandlingUserInput() || nsContentUtils::IsCallerChrome()) {
+  if (EventStateManager::IsHandlingUserInput() || nsContentUtils::LegacyIsCallerChromeOrNativeCode()) {
     mHasUserInteraction = true;
   }
 
   StopSuspendingAfterFirstFrame();
 
   if (mSrcStream) {
     // do nothing since streams aren't seekable; we effectively clamp to
     // the current time.
@@ -3037,52 +3037,52 @@ public:
   {}
   void Forget() { mElement = nullptr; }
 
   void ReceivedSize()
   {
     if (!mElement) {
       return;
     }
-    gfxIntSize size;
+    gfx::IntSize size;
     {
       MutexAutoLock lock(mMutex);
       size = mInitialSize;
     }
     nsRefPtr<HTMLMediaElement> deathGrip = mElement;
     mElement->UpdateInitialMediaSize(size);
   }
   virtual void NotifyQueuedTrackChanges(MediaStreamGraph* aGraph, TrackID aID,
                                         StreamTime aTrackOffset,
                                         uint32_t aTrackEvents,
                                         const MediaSegment& aQueuedMedia) override
   {
     MutexAutoLock lock(mMutex);
-    if (mInitialSize != gfxIntSize(0,0) ||
+    if (mInitialSize != gfx::IntSize(0,0) ||
         aQueuedMedia.GetType() != MediaSegment::VIDEO) {
       return;
     }
     const VideoSegment& video = static_cast<const VideoSegment&>(aQueuedMedia);
     for (VideoSegment::ConstChunkIterator c(video); !c.IsEnded(); c.Next()) {
-      if (c->mFrame.GetIntrinsicSize() != gfxIntSize(0,0)) {
+      if (c->mFrame.GetIntrinsicSize() != gfx::IntSize(0,0)) {
         mInitialSize = c->mFrame.GetIntrinsicSize();
         nsCOMPtr<nsIRunnable> event =
           NS_NewRunnableMethod(this, &StreamSizeListener::ReceivedSize);
         aGraph->DispatchToMainThreadAfterStreamStateUpdate(event.forget());
       }
     }
   }
 
 private:
   // These fields may only be accessed on the main thread
   HTMLMediaElement* mElement;
 
   // mMutex protects the fields below; they can be accessed on any thread
   Mutex mMutex;
-  gfxIntSize mInitialSize;
+  gfx::IntSize mInitialSize;
 };
 
 class HTMLMediaElement::MediaStreamTracksAvailableCallback:
     public DOMMediaStream::OnTracksAvailableCallback
 {
 public:
   explicit MediaStreamTracksAvailableCallback(HTMLMediaElement* aElement):
       DOMMediaStream::OnTracksAvailableCallback(),
--- a/dom/html/nsGenericHTMLElement.cpp
+++ b/dom/html/nsGenericHTMLElement.cpp
@@ -2787,17 +2787,18 @@ nsGenericHTMLElement::InternalGetExistin
   return mAttrsAndChildren.GetExistingAttrNameFromQName(aStr);
 }
 
 nsresult
 nsGenericHTMLElement::GetEditor(nsIEditor** aEditor)
 {
   *aEditor = nullptr;
 
-  if (!nsContentUtils::IsCallerChrome()) {
+  // See also HTMLTextFieldAccessible::GetEditor.
+  if (!nsContentUtils::LegacyIsCallerChromeOrNativeCode()) {
     return NS_ERROR_DOM_SECURITY_ERR;
   }
 
   NS_IF_ADDREF(*aEditor = GetEditorInternal());
   return NS_OK;
 }
 
 already_AddRefed<nsIEditor>
--- a/dom/html/nsHTMLDocument.cpp
+++ b/dom/html/nsHTMLDocument.cpp
@@ -2924,17 +2924,17 @@ nsHTMLDocument::SetDesignMode(const nsAS
   ErrorResult rv;
   SetDesignMode(aDesignMode, rv);
   return rv.StealNSResult();
 }
 
 void
 nsHTMLDocument::SetDesignMode(const nsAString& aDesignMode, ErrorResult& rv)
 {
-  if (!nsContentUtils::SubjectPrincipal()->Subsumes(NodePrincipal())) {
+  if (!nsContentUtils::LegacyIsCallerNativeCode() && !nsContentUtils::SubjectPrincipal()->Subsumes(NodePrincipal())) {
     rv.Throw(NS_ERROR_DOM_PROP_ACCESS_DENIED);
     return;
   }
   bool editableMode = HasFlag(NODE_IS_EDITABLE);
   if (aDesignMode.LowerCaseEqualsASCII(editableMode ? "off" : "on")) {
     SetEditableFlag(!editableMode);
 
     rv = EditingStateChanged();
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -2172,17 +2172,17 @@ ContentChild::RecvAddPermission(const IP
                                    nsPermissionManager::eNotify,
                                    nsPermissionManager::eNoDBOperation);
 #endif
 
     return true;
 }
 
 bool
-ContentChild::RecvScreenSizeChanged(const gfxIntSize& size)
+ContentChild::RecvScreenSizeChanged(const gfx::IntSize& size)
 {
 #ifdef ANDROID
     mScreenSize = size;
 #else
     NS_RUNTIMEABORT("Message currently only expected on android");
 #endif
     return true;
 }
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -327,17 +327,17 @@ public:
     virtual bool RecvGeolocationUpdate(const GeoPosition& somewhere) override;
 
     virtual bool RecvGeolocationError(const uint16_t& errorCode) override;
 
     virtual bool RecvUpdateDictionaryList(InfallibleTArray<nsString>&& aDictionaries) override;
 
     virtual bool RecvAddPermission(const IPC::Permission& permission) override;
 
-    virtual bool RecvScreenSizeChanged(const gfxIntSize &size) override;
+    virtual bool RecvScreenSizeChanged(const gfx::IntSize &size) override;
 
     virtual bool RecvFlushMemory(const nsString& reason) override;
 
     virtual bool RecvActivateA11y() override;
 
     virtual bool RecvGarbageCollect() override;
     virtual bool RecvCycleCollect() override;
 
@@ -402,17 +402,17 @@ public:
     virtual bool RecvShutdown() override;
 
     virtual bool
     RecvInvokeDragSession(nsTArray<IPCDataTransfer>&& aTransfers,
                           const uint32_t& aAction) override;
     virtual bool RecvEndDragSession(const bool& aDoneDrag,
                                     const bool& aUserCancelled) override;
 #ifdef ANDROID
-    gfxIntSize GetScreenSize() { return mScreenSize; }
+    gfx::IntSize GetScreenSize() { return mScreenSize; }
 #endif
 
     // Get the directory for IndexedDB files. We query the parent for this and
     // cache the value
     nsString &GetIndexedDBPath();
 
     ContentParentId GetID() { return mID; }
 
@@ -497,17 +497,17 @@ private:
      * We expect our content parent to set this ID immediately after opening a
      * channel to us.
      */
     ContentParentId mID;
 
     AppInfo mAppInfo;
 
 #ifdef ANDROID
-    gfxIntSize mScreenSize;
+    gfx::IntSize mScreenSize;
 #endif
 
     bool mIsForApp;
     bool mIsForBrowser;
     bool mCanOverrideProcessName;
     bool mIsAlive;
     nsString mProcessName;
 
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -2722,17 +2722,17 @@ ContentParent::RecvSetClipboard(const IP
         NS_ENSURE_SUCCESS(rv, true);
       } else if (item.data().type() == IPCDataTransferData::TnsCString) {
         if (item.flavor().EqualsLiteral(kNativeImageMime) ||
             item.flavor().EqualsLiteral(kJPEGImageMime) ||
             item.flavor().EqualsLiteral(kJPGImageMime) ||
             item.flavor().EqualsLiteral(kPNGImageMime) ||
             item.flavor().EqualsLiteral(kGIFImageMime)) {
           const IPCDataTransferImage& imageDetails = item.imageDetails();
-          const gfxIntSize size(imageDetails.width(), imageDetails.height());
+          const gfx::IntSize size(imageDetails.width(), imageDetails.height());
           if (!size.width || !size.height) {
             return true;
           }
 
           nsCString text = item.data().get_nsCString();
           mozilla::RefPtr<gfx::DataSourceSurface> image =
             new mozilla::gfx::SourceSurfaceRawData();
           mozilla::gfx::SourceSurfaceRawData* raw =
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -79,17 +79,17 @@ using base::ChildPrivileges from "base/p
 using base::ProcessId from "base/process.h";
 using struct IPC::Permission from "mozilla/net/NeckoMessageUtils.h";
 using class IPC::Principal from "mozilla/dom/PermissionMessageUtils.h";
 using struct mozilla::null_t from "ipc/IPCMessageUtils.h";
 using struct mozilla::void_t from "ipc/IPCMessageUtils.h";
 using mozilla::dom::NativeThreadId from "mozilla/dom/TabMessageUtils.h";
 using mozilla::dom::quota::PersistenceType from "mozilla/dom/quota/PersistenceType.h";
 using mozilla::hal::ProcessPriority from "mozilla/HalTypes.h";
-using gfxIntSize from "nsSize.h";
+using mozilla::gfx::IntSize from "mozilla/gfx/2D.h";
 using mozilla::dom::TabId from "mozilla/dom/ipc/IdType.h";
 using mozilla::dom::ContentParentId from "mozilla/dom/ipc/IdType.h";
 using struct LookAndFeelInt from "mozilla/widget/WidgetMessageUtils.h";
 using class mozilla::dom::ipc::StructuredCloneData from "ipc/IPCMessageUtils.h";
 
 union ChromeRegistryItem
 {
     ChromePackage;
@@ -541,17 +541,17 @@ child:
 
     GeolocationError(uint16_t errorCode);
 
     UpdateDictionaryList(nsString[] dictionaries);
 
     // nsIPermissionManager messages
     AddPermission(Permission permission);
 
-    ScreenSizeChanged(gfxIntSize size);
+    ScreenSizeChanged(IntSize size);
 
     Volumes(VolumeInfo[] volumes);
 
     FlushMemory(nsString reason);
 
     GarbageCollect();
     CycleCollect();
 
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -1974,17 +1974,17 @@ TabParent::RecvSetCustomCursor(const nsC
 
   nsCOMPtr<nsIWidget> widget = GetWidget();
   if (widget) {
     if (aForce) {
       widget->ClearCachedCursor();
     }
 
     if (mTabSetsCursor) {
-      const gfxIntSize size(aWidth, aHeight);
+      const gfx::IntSize size(aWidth, aHeight);
 
       mozilla::RefPtr<gfx::DataSourceSurface> customCursor = new mozilla::gfx::SourceSurfaceRawData();
       mozilla::gfx::SourceSurfaceRawData* raw = static_cast<mozilla::gfx::SourceSurfaceRawData*>(customCursor.get());
       raw->InitWrappingData(
         reinterpret_cast<uint8_t*>(const_cast<nsCString&>(aCursorData).BeginWriting()),
         size, aStride, static_cast<mozilla::gfx::SurfaceFormat>(aFormat), false);
       raw->GuaranteePersistance();
 
--- a/dom/media/VideoFrameContainer.cpp
+++ b/dom/media/VideoFrameContainer.cpp
@@ -24,39 +24,39 @@ VideoFrameContainer::VideoFrameContainer
 {
   NS_ASSERTION(aElement, "aElement must not be null");
   NS_ASSERTION(mImageContainer, "aContainer must not be null");
 }
 
 VideoFrameContainer::~VideoFrameContainer()
 {}
 
-void VideoFrameContainer::SetCurrentFrame(const gfxIntSize& aIntrinsicSize,
+void VideoFrameContainer::SetCurrentFrame(const gfx::IntSize& aIntrinsicSize,
                                           Image* aImage,
                                           const TimeStamp& aTargetTime)
 {
   if (aImage) {
     MutexAutoLock lock(mMutex);
     nsAutoTArray<ImageContainer::NonOwningImage,1> imageList;
     imageList.AppendElement(
         ImageContainer::NonOwningImage(aImage, aTargetTime, ++mFrameID));
     SetCurrentFramesLocked(aIntrinsicSize, imageList);
   } else {
     ClearCurrentFrame(aIntrinsicSize);
   }
 }
 
-void VideoFrameContainer::SetCurrentFrames(const gfxIntSize& aIntrinsicSize,
+void VideoFrameContainer::SetCurrentFrames(const gfx::IntSize& aIntrinsicSize,
                                            const nsTArray<ImageContainer::NonOwningImage>& aImages)
 {
   MutexAutoLock lock(mMutex);
   SetCurrentFramesLocked(aIntrinsicSize, aImages);
 }
 
-void VideoFrameContainer::SetCurrentFramesLocked(const gfxIntSize& aIntrinsicSize,
+void VideoFrameContainer::SetCurrentFramesLocked(const gfx::IntSize& aIntrinsicSize,
                                                  const nsTArray<ImageContainer::NonOwningImage>& aImages)
 {
   mMutex.AssertCurrentThreadOwns();
 
   if (aIntrinsicSize != mIntrinsicSize) {
     mIntrinsicSize = aIntrinsicSize;
     mIntrinsicSizeChanged = true;
   }
--- a/dom/media/VideoFrameContainer.h
+++ b/dom/media/VideoFrameContainer.h
@@ -37,21 +37,21 @@ public:
   typedef layers::Image Image;
 
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VideoFrameContainer)
 
   VideoFrameContainer(dom::HTMLMediaElement* aElement,
                       already_AddRefed<ImageContainer> aContainer);
 
   // Call on any thread
-  B2G_ACL_EXPORT void SetCurrentFrame(const gfxIntSize& aIntrinsicSize, Image* aImage,
+  B2G_ACL_EXPORT void SetCurrentFrame(const gfx::IntSize& aIntrinsicSize, Image* aImage,
                        const TimeStamp& aTargetTime);
-  void SetCurrentFrames(const gfxIntSize& aIntrinsicSize,
+  void SetCurrentFrames(const gfx::IntSize& aIntrinsicSize,
                         const nsTArray<ImageContainer::NonOwningImage>& aImages);
-  void ClearCurrentFrame(const gfxIntSize& aIntrinsicSize)
+  void ClearCurrentFrame(const gfx::IntSize& aIntrinsicSize)
   {
     SetCurrentFrames(aIntrinsicSize, nsTArray<ImageContainer::NonOwningImage>());
   }
 
   void ClearCurrentFrame();
   // Make the current frame the only frame in the container, i.e. discard
   // all future frames.
   void ClearFutureFrames();
@@ -74,32 +74,32 @@ public:
     INVALIDATE_FORCE
   };
   void Invalidate() { InvalidateWithFlags(INVALIDATE_DEFAULT); }
   B2G_ACL_EXPORT void InvalidateWithFlags(uint32_t aFlags);
   B2G_ACL_EXPORT ImageContainer* GetImageContainer();
   void ForgetElement() { mElement = nullptr; }
 
 protected:
-  void SetCurrentFramesLocked(const gfxIntSize& aIntrinsicSize,
+  void SetCurrentFramesLocked(const gfx::IntSize& aIntrinsicSize,
                               const nsTArray<ImageContainer::NonOwningImage>& aImages);
 
   // Non-addreffed pointer to the element. The element calls ForgetElement
   // to clear this reference when the element is destroyed.
   dom::HTMLMediaElement* mElement;
   nsRefPtr<ImageContainer> mImageContainer;
 
   // mMutex protects all the fields below.
   Mutex mMutex;
   // The intrinsic size is the ideal size which we should render the
   // ImageContainer's current Image at.
   // This can differ from the Image's actual size when the media resource
   // specifies that the Image should be stretched to have the correct aspect
   // ratio.
-  gfxIntSize mIntrinsicSize;
+  gfx::IntSize mIntrinsicSize;
   // We maintain our own mFrameID which is auto-incremented at every
   // SetCurrentFrame() or NewFrameID() call.
   ImageContainer::FrameID mFrameID;
   // True when the intrinsic size has been changed by SetCurrentFrame() since
   // the last call to Invalidate().
   // The next call to Invalidate() will recalculate
   // and update the intrinsic size on the element, request a frame reflow and
   // then reset this flag.
--- a/dom/media/VideoSegment.cpp
+++ b/dom/media/VideoSegment.cpp
@@ -9,44 +9,44 @@
 #include "ImageContainer.h"
 #include "Layers.h"
 
 namespace mozilla {
 
 using namespace layers;
 
 VideoFrame::VideoFrame(already_AddRefed<Image>& aImage,
-                       const gfxIntSize& aIntrinsicSize)
+                       const gfx::IntSize& aIntrinsicSize)
   : mImage(aImage), mIntrinsicSize(aIntrinsicSize), mForceBlack(false)
 {}
 
 VideoFrame::VideoFrame()
   : mIntrinsicSize(0, 0), mForceBlack(false)
 {}
 
 VideoFrame::~VideoFrame()
 {}
 
 void
 VideoFrame::SetNull() {
   mImage = nullptr;
-  mIntrinsicSize = gfxIntSize(0, 0);
+  mIntrinsicSize = gfx::IntSize(0, 0);
 }
 
 void
 VideoFrame::TakeFrom(VideoFrame* aFrame)
 {
   mImage = aFrame->mImage.forget();
   mIntrinsicSize = aFrame->mIntrinsicSize;
   mForceBlack = aFrame->GetForceBlack();
 }
 
 #if !defined(MOZILLA_XPCOMRT_API)
 /* static */ already_AddRefed<Image>
-VideoFrame::CreateBlackImage(const gfxIntSize& aSize)
+VideoFrame::CreateBlackImage(const gfx::IntSize& aSize)
 {
   nsRefPtr<ImageContainer> container;
   nsRefPtr<Image> image;
   container = LayerManager::CreateImageContainer();
   image = container->CreateImage(ImageFormat::PLANAR_YCBCR);
   if (!image) {
     MOZ_ASSERT(false);
     return nullptr;
--- a/dom/media/VideoSegment.h
+++ b/dom/media/VideoSegment.h
@@ -25,17 +25,17 @@ class Image;
 class VideoFrame {
 public:
 #if defined(MOZILLA_XPCOMRT_API)
   typedef mozilla::SimpleImageBuffer Image;
 #else
   typedef mozilla::layers::Image Image;
 #endif
 
-  VideoFrame(already_AddRefed<Image>& aImage, const gfxIntSize& aIntrinsicSize);
+  VideoFrame(already_AddRefed<Image>& aImage, const gfx::IntSize& aIntrinsicSize);
   VideoFrame();
   ~VideoFrame();
 
   bool operator==(const VideoFrame& aFrame) const
   {
     return mIntrinsicSize == aFrame.mIntrinsicSize &&
            mForceBlack == aFrame.mForceBlack &&
            ((mForceBlack && aFrame.mForceBlack) || mImage == aFrame.mImage);
@@ -43,31 +43,31 @@ public:
   bool operator!=(const VideoFrame& aFrame) const
   {
     return !operator==(aFrame);
   }
 
   Image* GetImage() const { return mImage; }
   void SetForceBlack(bool aForceBlack) { mForceBlack = aForceBlack; }
   bool GetForceBlack() const { return mForceBlack; }
-  const gfxIntSize& GetIntrinsicSize() const { return mIntrinsicSize; }
+  const gfx::IntSize& GetIntrinsicSize() const { return mIntrinsicSize; }
   void SetNull();
   void TakeFrom(VideoFrame* aFrame);
 
 #if !defined(MOZILLA_XPCOMRT_API)
   // Create a planar YCbCr black image.
-  static already_AddRefed<Image> CreateBlackImage(const gfxIntSize& aSize);
+  static already_AddRefed<Image> CreateBlackImage(const gfx::IntSize& aSize);
 #endif // !defined(MOZILLA_XPCOMRT_API)
 
 protected:
   // mImage can be null to indicate "no video" (aka "empty frame"). It can
   // still have an intrinsic size in this case.
   nsRefPtr<Image> mImage;
   // The desired size to render the video frame at.
-  gfxIntSize mIntrinsicSize;
+  gfx::IntSize mIntrinsicSize;
   bool mForceBlack;
 };
 
 struct VideoChunk {
   VideoChunk();
   ~VideoChunk();
   void SliceTo(StreamTime aStart, StreamTime aEnd)
   {
--- a/dom/media/android/AndroidMediaReader.cpp
+++ b/dom/media/android/AndroidMediaReader.cpp
@@ -74,17 +74,17 @@ nsresult AndroidMediaReader::ReadMetadat
 
     // Video track's frame sizes will not overflow. Activate the video track.
     mHasVideo = true;
     mInfo.mVideo.mDisplay = displaySize;
     mPicture = pictureRect;
     mInitialFrame = frameSize;
     VideoFrameContainer* container = mDecoder->GetVideoFrameContainer();
     if (container) {
-      container->ClearCurrentFrame(gfxIntSize(displaySize.width, displaySize.height));
+      container->ClearCurrentFrame(IntSize(displaySize.width, displaySize.height));
     }
   }
 
   if (mPlugin->HasAudio(mPlugin)) {
     int32_t numChannels, sampleRate;
     mPlugin->GetAudioParameters(mPlugin, &numChannels, &sampleRate);
     mHasAudio = true;
     mInfo.mAudio.mChannels = numChannels;
--- a/dom/media/eme/MediaKeySystemAccessManager.cpp
+++ b/dom/media/eme/MediaKeySystemAccessManager.cpp
@@ -73,28 +73,23 @@ MediaKeySystemAccessManager::Request(Det
   Sequence<MediaKeySystemOptions> optionsNotPassed;
   const auto& options = aOptions.WasPassed() ? aOptions.Value() : optionsNotPassed;
   Request(aPromise, aKeySystem, options, RequestType::Initial);
 }
 
 static bool
 ShouldTrialCreateGMP(const nsAString& aKeySystem)
 {
-  // Trial create where the CDM has a decoder;
-  // * ClearKey and Primetime on Windows Vista and later.
-  // * Primetime on MacOSX Lion and later.
-  return
-    Preferences::GetBool("media.gmp.trial-create.enabled", false) &&
+  // Trial create where the CDM has a Windows Media Foundation decoder.
 #ifdef XP_WIN
-    IsVistaOrLater();
-#elif defined(XP_MACOSX)
-    aKeySystem.EqualsLiteral("com.adobe.primetime") &&
-    nsCocoaFeatures::OnLionOrLater();
+  return Preferences::GetBool("media.gmp.trial-create.enabled", false) &&
+         aKeySystem.EqualsLiteral("org.w3.clearkey") &&
+         IsVistaOrLater();
 #else
-    false;
+  return false;
 #endif
 }
 
 void
 MediaKeySystemAccessManager::Request(DetailedPromise* aPromise,
                                      const nsAString& aKeySystem,
                                      const Sequence<MediaKeySystemOptions>& aOptions,
                                      RequestType aType)
--- a/dom/media/eme/MediaKeys.cpp
+++ b/dom/media/eme/MediaKeys.cpp
@@ -54,61 +54,37 @@ MediaKeys::MediaKeys(nsPIDOMWindow* aPar
   , mKeySystem(aKeySystem)
   , mCDMVersion(aCDMVersion)
   , mCreatePromiseId(0)
 {
   EME_LOG("MediaKeys[%p] constructed keySystem=%s",
           this, NS_ConvertUTF16toUTF8(mKeySystem).get());
 }
 
-static PLDHashOperator
-RejectPromises(const uint32_t& aKey,
-               nsRefPtr<dom::DetailedPromise>& aPromise,
-               void* aClosure)
-{
-  aPromise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR,
-                        NS_LITERAL_CSTRING("Promise still outstanding at MediaKeys shutdown"));
-  ((MediaKeys*)aClosure)->Release();
-  return PL_DHASH_NEXT;
-}
-
 MediaKeys::~MediaKeys()
 {
   Shutdown();
   EME_LOG("MediaKeys[%p] destroyed", this);
 }
 
-static PLDHashOperator
-CopySessions(const nsAString& aKey,
-             nsRefPtr<MediaKeySession>& aSession,
-             void* aClosure)
-{
-  KeySessionHashMap* p = static_cast<KeySessionHashMap*>(aClosure);
-  p->Put(aSession->GetSessionId(), aSession);
-  return PL_DHASH_NEXT;
-}
-
-static PLDHashOperator
-CloseSessions(const nsAString& aKey,
-              nsRefPtr<MediaKeySession>& aSession,
-              void* aClosure)
-{
-  aSession->OnClosed();
-  return PL_DHASH_NEXT;
-}
-
 void
 MediaKeys::Terminated()
 {
   EME_LOG("MediaKeys[%p] CDM crashed unexpectedly", this);
 
   KeySessionHashMap keySessions;
   // Remove entries during iteration will screw it. Make a copy first.
-  mKeySessions.Enumerate(&CopySessions, &keySessions);
-  keySessions.Enumerate(&CloseSessions, nullptr);
+  for (auto iter = mKeySessions.Iter(); !iter.Done(); iter.Next()) {
+    nsRefPtr<MediaKeySession>& session = iter.Data();
+    keySessions.Put(session->GetSessionId(), session);
+  }
+  for (auto iter = keySessions.Iter(); !iter.Done(); iter.Next()) {
+    nsRefPtr<MediaKeySession>& session = iter.Data();
+    session->OnClosed();
+  }
   keySessions.Clear();
   MOZ_ASSERT(mKeySessions.Count() == 0);
 
   // Notify the element about that CDM has terminated.
   if (mElement) {
     mElement->DecodeError();
   }
 
@@ -120,17 +96,22 @@ MediaKeys::Shutdown()
 {
   if (mProxy) {
     mProxy->Shutdown();
     mProxy = nullptr;
   }
 
   nsRefPtr<MediaKeys> kungFuDeathGrip = this;
 
-  mPromises.Enumerate(&RejectPromises, this);
+  for (auto iter = mPromises.Iter(); !iter.Done(); iter.Next()) {
+    nsRefPtr<dom::DetailedPromise>& promise = iter.Data();
+    promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR,
+                         NS_LITERAL_CSTRING("Promise still outstanding at MediaKeys shutdown"));
+    Release();
+  }
   mPromises.Clear();
 }
 
 nsPIDOMWindow*
 MediaKeys::GetParentObject() const
 {
   return mParent;
 }
--- a/dom/media/encoder/TrackEncoder.cpp
+++ b/dom/media/encoder/TrackEncoder.cpp
@@ -192,17 +192,17 @@ VideoTrackEncoder::NotifyQueuedTrackChan
   if (!mInitialized) {
     mVideoInitCounter++;
     TRACK_LOG(LogLevel::Debug, ("Init the video encoder %d times", mVideoInitCounter));
     VideoSegment::ChunkIterator iter(const_cast<VideoSegment&>(video));
     while (!iter.IsEnded()) {
       VideoChunk chunk = *iter;
       if (!chunk.IsNull()) {
         gfx::IntSize imgsize = chunk.mFrame.GetImage()->GetSize();
-        gfxIntSize intrinsicSize = chunk.mFrame.GetIntrinsicSize();
+        gfx::IntSize intrinsicSize = chunk.mFrame.GetIntrinsicSize();
         nsresult rv = Init(imgsize.width, imgsize.height,
                            intrinsicSize.width, intrinsicSize.height,
                            aGraph->GraphRate());
         if (NS_FAILED(rv)) {
           LOG("[VideoTrackEncoder]: Fail to initialize the encoder!");
           NotifyCancel();
         }
         break;
--- a/dom/media/encoder/VP8TrackEncoder.cpp
+++ b/dom/media/encoder/VP8TrackEncoder.cpp
@@ -246,17 +246,17 @@ static bool isYUV444(const PlanarYCbCrIm
   return false;
 }
 
 nsresult VP8TrackEncoder::PrepareRawFrame(VideoChunk &aChunk)
 {
   nsRefPtr<Image> img;
   if (aChunk.mFrame.GetForceBlack() || aChunk.IsNull()) {
     if (!mMuteFrame) {
-      mMuteFrame = VideoFrame::CreateBlackImage(gfxIntSize(mFrameWidth, mFrameHeight));
+      mMuteFrame = VideoFrame::CreateBlackImage(gfx::IntSize(mFrameWidth, mFrameHeight));
       MOZ_ASSERT(mMuteFrame);
     }
     img = mMuteFrame;
   } else {
     img = aChunk.mFrame.GetImage();
   }
 
   ImageFormat format = img->GetFormat();
--- a/dom/media/gmp/GMPServiceChild.cpp
+++ b/dom/media/gmp/GMPServiceChild.cpp
@@ -306,30 +306,26 @@ GMPServiceChild::AllocPGMPContentParent(
 
 void
 GMPServiceChild::GetBridgedGMPContentParent(ProcessId aOtherPid,
                                             GMPContentParent** aGMPContentParent)
 {
   mContentParents.Get(aOtherPid, aGMPContentParent);
 }
 
-static PLDHashOperator
-FindAndRemoveGMPContentParent(const uint64_t& aKey,
-                              nsRefPtr<GMPContentParent>& aData,
-                              void* aUserArg)
-{
-  return aData == aUserArg ?
-         (PLDHashOperator)(PL_DHASH_STOP | PL_DHASH_REMOVE) :
-         PL_DHASH_NEXT;
-}
-
 void
 GMPServiceChild::RemoveGMPContentParent(GMPContentParent* aGMPContentParent)
 {
-  mContentParents.Enumerate(FindAndRemoveGMPContentParent, aGMPContentParent);
+  for (auto iter = mContentParents.Iter(); !iter.Done(); iter.Next()) {
+    nsRefPtr<GMPContentParent>& parent = iter.Data();
+    if (parent == aGMPContentParent) {
+      iter.Remove();
+      break;
+    }
+  }
 }
 
 static PLDHashOperator
 FillProcessIDArray(const uint64_t& aKey, GMPContentParent*, void* aUserArg)
 {
   static_cast<nsTArray<base::ProcessId>*>(aUserArg)->AppendElement(aKey);
   return PL_DHASH_NEXT;
 }
--- a/dom/media/ogg/OggReader.cpp
+++ b/dom/media/ogg/OggReader.cpp
@@ -235,17 +235,17 @@ void OggReader::SetupTargetTheora(Theora
   nsIntSize frameSize(aTheoraState->mInfo.frame_width,
                       aTheoraState->mInfo.frame_height);
   if (IsValidVideoRegion(frameSize, picture, displaySize)) {
     // Video track's frame sizes will not overflow. Activate the video track.
     mPicture = picture;
 
     VideoFrameContainer* container = mDecoder->GetVideoFrameContainer();
     if (container) {
-      container->ClearCurrentFrame(gfxIntSize(displaySize.width, displaySize.height));
+      container->ClearCurrentFrame(IntSize(displaySize.width, displaySize.height));
     }
 
     // Copy Theora info data for time computations on other threads.
     memcpy(&mTheoraInfo, &aTheoraState->mInfo, sizeof(mTheoraInfo));
 
     mTheoraState = aTheoraState;
     mTheoraSerial = aTheoraState->mSerial;
   }
--- a/dom/media/omx/MediaCodecReader.cpp
+++ b/dom/media/omx/MediaCodecReader.cpp
@@ -739,17 +739,17 @@ MediaCodecReader::HandleResourceAllocate
   if (duration >= INT64_C(0)) {
     mInfo.mMetadataDuration = Some(TimeUnit::FromMicroseconds(duration));
   }
 
   // Video track's frame sizes will not overflow. Activate the video track.
   VideoFrameContainer* container = mDecoder->GetVideoFrameContainer();
   if (container) {
     container->ClearCurrentFrame(
-      gfxIntSize(mInfo.mVideo.mDisplay.width, mInfo.mVideo.mDisplay.height));
+      gfx::IntSize(mInfo.mVideo.mDisplay.width, mInfo.mVideo.mDisplay.height));
   }
 
   nsRefPtr<MetadataHolder> metadata = new MetadataHolder();
   metadata->mInfo = mInfo;
   metadata->mTags = nullptr;
 
 #ifdef MOZ_AUDIO_OFFLOAD
   CheckAudioOffload();
@@ -842,54 +842,38 @@ MediaCodecReader::WaitFenceAndReleaseOut
 #endif
     }
     if (mVideoTrack.mCodec != nullptr) {
       mVideoTrack.mCodec->releaseOutputBuffer(releasingItems[i].mReleaseIndex);
     }
   }
 }
 
-PLDHashOperator
-MediaCodecReader::ReleaseTextureClient(TextureClient* aClient,
-                                       size_t& aIndex,
-                                       void* aUserArg)
-{
-  nsRefPtr<MediaCodecReader> reader = static_cast<MediaCodecReader*>(aUserArg);
-  MOZ_ASSERT(reader, "reader should not be nullptr in ReleaseTextureClient()");
-
-  return reader->ReleaseTextureClient(aClient, aIndex);
-}
-
-PLDHashOperator
-MediaCodecReader::ReleaseTextureClient(TextureClient* aClient,
-                                       size_t& aIndex)
-{
-  MOZ_ASSERT(aClient, "TextureClient should be a valid pointer");
-
-  aClient->ClearRecycleCallback();
-
-  if (mVideoTrack.mCodec != nullptr) {
-    mVideoTrack.mCodec->releaseOutputBuffer(aIndex);
-  }
-
-  return PL_DHASH_REMOVE;
-}
-
 void
 MediaCodecReader::ReleaseAllTextureClients()
 {
   MutexAutoLock al(mTextureClientIndexesLock);
   MOZ_ASSERT(mTextureClientIndexes.Count(), "All TextureClients should be released already");
 
   if (mTextureClientIndexes.Count() == 0) {
     return;
   }
   printf_stderr("All TextureClients should be released already");
 
-  mTextureClientIndexes.Enumerate(MediaCodecReader::ReleaseTextureClient, this);
+  for (auto iter = mTextureClientIndexes.Iter(); !iter.Done(); iter.Next()) {
+    TextureClient* client = iter.Key();
+    size_t& index = iter.Data();
+
+    client->ClearRecycleCallback();
+
+    if (mVideoTrack.mCodec != nullptr) {
+      mVideoTrack.mCodec->releaseOutputBuffer(index);
+    }
+    iter.Remove();
+  }
   mTextureClientIndexes.Clear();
 }
 
 void
 MediaCodecReader::DecodeVideoFrameSync(int64_t aTimeThreshold)
 {
   if (mVideoTrack.mCodec == nullptr || !mVideoTrack.mCodec->allocated() ||
       mVideoTrack.mOutputEndOfStream) {
--- a/dom/media/omx/MediaCodecReader.h
+++ b/dom/media/omx/MediaCodecReader.h
@@ -392,21 +392,16 @@ private:
                         int64_t aOffset);
 
   static void TextureClientRecycleCallback(TextureClient* aClient,
                                            void* aClosure);
   void TextureClientRecycleCallback(TextureClient* aClient);
   void WaitFenceAndReleaseOutputBuffer();
 
   void ReleaseRecycledTextureClients();
-  static PLDHashOperator ReleaseTextureClient(TextureClient* aClient,
-                                              size_t& aIndex,
-                                              void* aUserArg);
-  PLDHashOperator ReleaseTextureClient(TextureClient* aClient,
-                                       size_t& aIndex);
 
   void ReleaseAllTextureClients();
 
   android::sp<VideoResourceListener> mVideoListener;
 
   android::sp<android::ALooper> mLooper;
   android::sp<android::MetaData> mMetaData;
 
--- a/dom/media/omx/MediaOmxReader.cpp
+++ b/dom/media/omx/MediaOmxReader.cpp
@@ -302,17 +302,17 @@ void MediaOmxReader::HandleResourceAlloc
 
     // Video track's frame sizes will not overflow. Activate the video track.
     mHasVideo = true;
     mInfo.mVideo.mDisplay = displaySize;
     mPicture = pictureRect;
     mInitialFrame = frameSize;
     VideoFrameContainer* container = mDecoder->GetVideoFrameContainer();
     if (container) {
-      container->ClearCurrentFrame(gfxIntSize(displaySize.width, displaySize.height));
+      container->ClearCurrentFrame(IntSize(displaySize.width, displaySize.height));
     }
   }
 
   if (mOmxDecoder->HasAudio()) {
     int32_t numChannels, sampleRate;
     mOmxDecoder->GetAudioParameters(&numChannels, &sampleRate);
     mHasAudio = true;
     mInfo.mAudio.mChannels = numChannels;
--- a/dom/media/platforms/agnostic/eme/EMEDecoderModule.cpp
+++ b/dom/media/platforms/agnostic/eme/EMEDecoderModule.cpp
@@ -14,25 +14,16 @@
 #include "nsServiceManagerUtils.h"
 #include "MediaInfo.h"
 #include "nsClassHashtable.h"
 
 namespace mozilla {
 
 typedef MozPromiseRequestHolder<CDMProxy::DecryptPromise> DecryptPromiseRequestHolder;
 
-static PLDHashOperator
-DropDecryptPromises(MediaRawData* aKey,
-                    nsAutoPtr<DecryptPromiseRequestHolder>& aData,
-                    void* aUserArg)
-{
-  aData->DisconnectIfExists();
-  return PL_DHASH_REMOVE;
-}
-
 class EMEDecryptor : public MediaDataDecoder {
 
 public:
 
   EMEDecryptor(MediaDataDecoder* aDecoder,
                MediaDataDecoderCallback* aCallback,
                CDMProxy* aProxy,
                TaskQueue* aDecodeTaskQueue)
@@ -102,27 +93,35 @@ public:
       nsresult rv = mDecoder->Input(aDecrypted.mSample);
       unused << NS_WARN_IF(NS_FAILED(rv));
     }
   }
 
   nsresult Flush() override {
     MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
     MOZ_ASSERT(!mIsShutdown);
-    mDecrypts.Enumerate(&DropDecryptPromises, nullptr);
+    for (auto iter = mDecrypts.Iter(); !iter.Done(); iter.Next()) {
+      nsAutoPtr<DecryptPromiseRequestHolder>& holder = iter.Data();
+      holder->DisconnectIfExists();
+      iter.Remove();
+    }
     nsresult rv = mDecoder->Flush();
     unused << NS_WARN_IF(NS_FAILED(rv));
     mSamplesWaitingForKey->Flush();
     return rv;
   }
 
   nsresult Drain() override {
     MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
     MOZ_ASSERT(!mIsShutdown);
-    mDecrypts.Enumerate(&DropDecryptPromises, nullptr);
+    for (auto iter = mDecrypts.Iter(); !iter.Done(); iter.Next()) {
+      nsAutoPtr<DecryptPromiseRequestHolder>& holder = iter.Data();
+      holder->DisconnectIfExists();
+      iter.Remove();
+    }
     nsresult rv = mDecoder->Drain();
     unused << NS_WARN_IF(NS_FAILED(rv));
     return rv;
   }
 
   nsresult Shutdown() override {
     MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
     MOZ_ASSERT(!mIsShutdown);
--- a/dom/media/platforms/android/AndroidDecoderModule.cpp
+++ b/dom/media/platforms/android/AndroidDecoderModule.cpp
@@ -95,17 +95,17 @@ public:
       return nullptr;
     }
 
     EGLint attribs[] = {
       LOCAL_EGL_IMAGE_PRESERVED_KHR, LOCAL_EGL_TRUE,
       LOCAL_EGL_NONE, LOCAL_EGL_NONE
     };
 
-    EGLContext eglContext = static_cast<GLContextEGL*>(mGLContext.get())->GetEGLContext();
+    EGLContext eglContext = static_cast<GLContextEGL*>(mGLContext.get())->mContext;
     EGLImage eglImage = sEGLLibrary.fCreateImage(EGL_DISPLAY(), eglContext,
                                                  LOCAL_EGL_GL_TEXTURE_2D_KHR,
                                                  (EGLClientBuffer)tex, attribs);
     mGLContext->fDeleteTextures(1, &tex);
 
     return eglImage;
   }
 
--- a/dom/media/systemservices/MediaParent.cpp
+++ b/dom/media/systemservices/MediaParent.cpp
@@ -78,36 +78,31 @@ class OriginKeyStore : public nsISupport
       if (aPersist && !key->mSecondsStamp) {
         key->mSecondsStamp = PR_Now() / PR_USEC_PER_SEC;
         mPersistCount++;
       }
       aResult = key->mKey;
       return NS_OK;
     }
 
-    static PLDHashOperator
-    HashCleaner(const nsACString& aOrigin, nsAutoPtr<OriginKey>& aOriginKey,
-                void *aUserArg)
-    {
-      OriginKey* since = static_cast<OriginKey*>(aUserArg);
-
-      LOG((((aOriginKey->mSecondsStamp >= since->mSecondsStamp)?
-            "%s: REMOVE %lld >= %lld" :
-            "%s: KEEP   %lld < %lld"),
-            __FUNCTION__, aOriginKey->mSecondsStamp, since->mSecondsStamp));
-
-      return (aOriginKey->mSecondsStamp >= since->mSecondsStamp)?
-          PL_DHASH_REMOVE : PL_DHASH_NEXT;
-    }
-
     void Clear(int64_t aSinceWhen)
     {
       // Avoid int64_t* <-> void* casting offset
       OriginKey since(nsCString(), aSinceWhen  / PR_USEC_PER_SEC);
-      mKeys.Enumerate(HashCleaner, &since);
+      for (auto iter = mKeys.Iter(); !iter.Done(); iter.Next()) {
+        nsAutoPtr<OriginKey>& originKey = iter.Data();
+        LOG((((originKey->mSecondsStamp >= since.mSecondsStamp)?
+              "%s: REMOVE %lld >= %lld" :
+              "%s: KEEP   %lld < %lld"),
+              __FUNCTION__, originKey->mSecondsStamp, since.mSecondsStamp));
+
+        if (originKey->mSecondsStamp >= since.mSecondsStamp) {
+          iter.Remove();
+        }
+      }
       mPersistCount = 0;
     }
 
   protected:
     nsClassHashtable<nsCStringHashKey, OriginKey> mKeys;
     size_t mPersistCount;
   };
 
--- a/dom/media/systemservices/MediaSystemResourceService.cpp
+++ b/dom/media/systemservices/MediaSystemResourceService.cpp
@@ -136,46 +136,30 @@ MediaSystemResourceService::ReleaseResou
       resource->mResourceCount == 0) {
     // Resource does not exit
     return;
   }
   RemoveRequest(aParent, aId, aResourceType);
   UpdateRequests(aResourceType);
 }
 
-struct ReleaseResourceData
-{
-  MediaSystemResourceService* mSelf;
-  media::MediaSystemResourceManagerParent* mParent;
-};
-
-/*static*/PLDHashOperator
-MediaSystemResourceService::ReleaseResourceForKey(const uint32_t& aKey,
-                                                  nsAutoPtr<MediaSystemResource>& aData,
-                                                  void* aClosure)
-{
-  ReleaseResourceData* closure = static_cast<ReleaseResourceData*>(aClosure);
-
-  closure->mSelf->RemoveRequests(closure->mParent, static_cast<MediaSystemResourceType>(aKey));
-  closure->mSelf->UpdateRequests(static_cast<MediaSystemResourceType>(aKey));
-
-  return PLDHashOperator::PL_DHASH_NEXT;
-}
-
 void
 MediaSystemResourceService::ReleaseResource(media::MediaSystemResourceManagerParent* aParent)
 {
   MOZ_ASSERT(aParent);
 
   if (mDestroyed) {
     return;
   }
 
-  ReleaseResourceData data = { this, aParent };
-  mResources.Enumerate(ReleaseResourceForKey, &data);
+  for (auto iter = mResources.Iter(); !iter.Done(); iter.Next()) {
+    const uint32_t& key = iter.Key();
+    RemoveRequests(aParent, static_cast<MediaSystemResourceType>(key));
+    UpdateRequests(static_cast<MediaSystemResourceType>(key));
+  }
 }
 
 void
 MediaSystemResourceService::RemoveRequest(media::MediaSystemResourceManagerParent* aParent,
                                           uint32_t aId,
                                           MediaSystemResourceType aResourceType)
 {
   MOZ_ASSERT(aParent);
--- a/dom/media/systemservices/MediaSystemResourceService.h
+++ b/dom/media/systemservices/MediaSystemResourceService.h
@@ -72,20 +72,16 @@ private:
                      uint32_t aId,
                      MediaSystemResourceType aResourceType);
 
   void RemoveRequests(media::MediaSystemResourceManagerParent* aParent,
                       MediaSystemResourceType aResourceType);
 
   void UpdateRequests(MediaSystemResourceType aResourceType);
 
-  static PLDHashOperator ReleaseResourceForKey(const uint32_t& aKey,
-                                               nsAutoPtr<MediaSystemResource>& aData,
-                                               void* aClosure);
-
   bool mDestroyed;
 
   nsClassHashtable<nsUint32HashKey, MediaSystemResource> mResources;
 
   static StaticRefPtr<MediaSystemResourceService> sSingleton;
 };
 
 } // namespace mozilla
--- a/dom/media/webspeech/synth/pico/nsPicoService.cpp
+++ b/dom/media/webspeech/synth/pico/nsPicoService.cpp
@@ -496,50 +496,18 @@ nsPicoService::Speak(const nsAString& aT
 
 NS_IMETHODIMP
 nsPicoService::GetServiceType(SpeechServiceType* aServiceType)
 {
   *aServiceType = nsISpeechService::SERVICETYPE_DIRECT_AUDIO;
   return NS_OK;
 }
 
-struct VoiceTraverserData
-{
-  nsPicoService* mService;
-  nsSynthVoiceRegistry* mRegistry;
-};
-
 // private methods
 
-static PLDHashOperator
-PicoAddVoiceTraverser(const nsAString& aUri,
-                      nsRefPtr<PicoVoice>& aVoice,
-                      void* aUserArg)
-{
-  // If we are missing either a language or a voice resource, it is invalid.
-  if (aVoice->mTaFile.IsEmpty() || aVoice->mSgFile.IsEmpty()) {
-    return PL_DHASH_REMOVE;
-  }
-
-  VoiceTraverserData* data = static_cast<VoiceTraverserData*>(aUserArg);
-
-  nsAutoString name;
-  name.AssignLiteral("Pico ");
-  name.Append(aVoice->mLanguage);
-
-  // This service is multi-threaded and can handle more than one utterance at a
-  // time before previous utterances end. So, aQueuesUtterances == false
-  DebugOnly<nsresult> rv =
-    data->mRegistry->AddVoice(
-      data->mService, aUri, name, aVoice->mLanguage, true, false);
-  NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Failed to add voice");
-
-  return PL_DHASH_NEXT;
-}
-
 void
 nsPicoService::Init()
 {
   MOZ_ASSERT(!NS_IsMainThread());
   MOZ_ASSERT(!mInitialized);
 
   if (!sPicoApi.Init()) {
     NS_WARNING("Failed to initialize pico library");
@@ -612,18 +580,38 @@ nsPicoService::Init()
   }
 
   NS_DispatchToMainThread(NS_NewRunnableMethod(this, &nsPicoService::RegisterVoices));
 }
 
 void
 nsPicoService::RegisterVoices()
 {
-  VoiceTraverserData data = { this, nsSynthVoiceRegistry::GetInstance() };
-  mVoices.Enumerate(PicoAddVoiceTraverser, &data);
+  nsSynthVoiceRegistry* registry = nsSynthVoiceRegistry::GetInstance();
+
+  for (auto iter = mVoices.Iter(); !iter.Done(); iter.Next()) {
+    const nsAString& uri = iter.Key();
+    nsRefPtr<PicoVoice>& voice = iter.Data();
+
+    // If we are missing either a language or a voice resource, it is invalid.
+    if (voice->mTaFile.IsEmpty() || voice->mSgFile.IsEmpty()) {
+      iter.Remove();
+      continue;
+    }
+
+    nsAutoString name;
+    name.AssignLiteral("Pico ");
+    name.Append(voice->mLanguage);
+
+    // This service is multi-threaded and can handle more than one utterance at a
+    // time before previous utterances end. So, aQueuesUtterances == false
+    DebugOnly<nsresult> rv =
+      registry->AddVoice(this, uri, name, voice->mLanguage, true, false);
+    NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Failed to add voice");
+  }
 
   mInitialized = true;
 }
 
 bool
 nsPicoService::GetVoiceFileLanguage(const nsACString& aFileName, nsAString& aLang)
 {
   nsACString::const_iterator start, end;
--- a/dom/plugins/base/android/ANPOpenGL.cpp
+++ b/dom/plugins/base/android/ANPOpenGL.cpp
@@ -23,17 +23,17 @@ typedef nsNPAPIPluginInstance::TextureIn
 static ANPEGLContext anp_opengl_acquireContext(NPP instance) {
     nsNPAPIPluginInstance* pinst = static_cast<nsNPAPIPluginInstance*>(instance->ndata);
 
     GLContext* context = pinst->GLContext();
     if (!context)
         return nullptr;
 
     context->MakeCurrent();
-    return GLContextEGL::Cast(context)->GetEGLContext();
+    return GLContextEGL::Cast(context)->mContext;
 }
 
 static ANPTextureInfo anp_opengl_lockTexture(NPP instance) {
     nsNPAPIPluginInstance* pinst = static_cast<nsNPAPIPluginInstance*>(instance->ndata);
 
     TextureInfo pluginInfo = pinst->LockContentTexture();
 
     ANPTextureInfo info;
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -2582,17 +2582,17 @@ void nsPluginInstanceOwner::Paint(gfxCon
 
 #ifdef ANP_BITMAP_DRAWING_MODEL
   static nsRefPtr<gfxImageSurface> pluginSurface;
 
   if (pluginSurface == nullptr ||
       aFrameRect.width  != pluginSurface->Width() ||
       aFrameRect.height != pluginSurface->Height()) {
 
-    pluginSurface = new gfxImageSurface(gfxIntSize(aFrameRect.width, aFrameRect.height),
+    pluginSurface = new gfxImageSurface(gfx::IntSize(aFrameRect.width, aFrameRect.height),
                                         gfxImageFormat::ARGB32);
     if (!pluginSurface)
       return;
   }
 
   // Clears buffer.  I think this is needed.
   gfxUtils::ClearThebesSurface(pluginSurface);
 
--- a/dom/plugins/ipc/PPluginInstance.ipdl
+++ b/dom/plugins/ipc/PPluginInstance.ipdl
@@ -17,17 +17,17 @@ using NPError from "npapi.h";
 using struct mozilla::plugins::NPRemoteWindow from "mozilla/plugins/PluginMessageUtils.h";
 using struct mozilla::plugins::NPRemoteEvent from "mozilla/plugins/PluginMessageUtils.h";
 using NPRect from "npapi.h";
 using NPNURLVariable from "npapi.h";
 using NPCoordinateSpace from "npapi.h";
 using NPNVariable from "npapi.h";
 using mozilla::plugins::NativeWindowHandle from "mozilla/plugins/PluginMessageUtils.h";
 using gfxSurfaceType from "gfxTypes.h";
-using gfxIntSize from "nsSize.h";
+using mozilla::gfx::IntSize from "mozilla/gfx/2D.h";
 using struct mozilla::null_t from "ipc/IPCMessageUtils.h";
 using mozilla::plugins::WindowsSharedMemoryHandle from "mozilla/plugins/PluginMessageUtils.h";
 using mozilla::layers::SurfaceDescriptorX11 from "gfxipc/ShadowLayerUtils.h";
 using nsIntRect from "nsRect.h";
 
 namespace mozilla {
 namespace plugins {
 
@@ -184,17 +184,17 @@ parent:
   //               could be used for partial render of layer to topLevel context
   // @param newSurface - remotable surface
   // @param prevSurface - if the previous surface was shared-memory, returns
   //                      the shmem for reuse
   sync Show(NPRect updatedRect, SurfaceDescriptor newSurface)
     returns (SurfaceDescriptor prevSurface);
 
   async PPluginSurface(WindowsSharedMemoryHandle handle,
-                       gfxIntSize size,
+                       IntSize size,
                        bool transparent);
 
   intr NPN_PushPopupsEnabledState(bool aState);
 
   intr NPN_PopPopupsEnabledState();
 
   intr NPN_GetValueForURL(NPNURLVariable variable, nsCString url)
     returns (nsCString value, NPError result);
--- a/dom/plugins/ipc/PluginInstanceChild.cpp
+++ b/dom/plugins/ipc/PluginInstanceChild.cpp
@@ -2856,30 +2856,28 @@ PluginInstanceChild::CreateOptSurface(vo
         format = gfxImageFormat::RGB16_565;
     }
 
     if (mSurfaceType == gfxSurfaceType::Xlib) {
         if (!mIsTransparent  || mBackground) {
             Visual* defaultVisual = DefaultVisualOfScreen(screen);
             mCurrentSurface =
                 gfxXlibSurface::Create(screen, defaultVisual,
-                                       gfxIntSize(mWindow.width,
-                                                  mWindow.height));
+                                       IntSize(mWindow.width, mWindow.height));
             return mCurrentSurface != nullptr;
         }
 
         XRenderPictFormat* xfmt = XRenderFindStandardFormat(dpy, PictStandardARGB32);
         if (!xfmt) {
             NS_ERROR("Need X falback surface, but FindRenderFormat failed");
             return false;
         }
         mCurrentSurface =
             gfxXlibSurface::Create(screen, xfmt,
-                                   gfxIntSize(mWindow.width,
-                                              mWindow.height));
+                                   IntSize(mWindow.width, mWindow.height));
         return mCurrentSurface != nullptr;
     }
 #endif
 
 #ifdef XP_WIN
     if (mSurfaceType == gfxSurfaceType::Win32) {
         bool willHaveTransparentPixels = mIsTransparent && !mBackground;
 
@@ -2893,17 +2891,17 @@ PluginInstanceChild::CreateOptSurface(vo
         return true;
     }
 
     NS_RUNTIMEABORT("Shared-memory drawing not expected on Windows.");
 #endif
 
     // Make common shmem implementation working for any platform
     mCurrentSurface =
-        gfxSharedImageSurface::CreateUnsafe(this, gfxIntSize(mWindow.width, mWindow.height), format);
+        gfxSharedImageSurface::CreateUnsafe(this, IntSize(mWindow.width, mWindow.height), format);
     return !!mCurrentSurface;
 }
 
 bool
 PluginInstanceChild::MaybeCreatePlatformHelperSurface(void)
 {
     if (!mCurrentSurface) {
         NS_ERROR("Cannot create helper surface without mCurrentSurface");
@@ -2961,29 +2959,29 @@ PluginInstanceChild::MaybeCreatePlatform
     return true;
 }
 
 bool
 PluginInstanceChild::EnsureCurrentBuffer(void)
 {
 #ifndef XP_DARWIN
     nsIntRect toInvalidate(0, 0, 0, 0);
-    gfxIntSize winSize = gfxIntSize(mWindow.width, mWindow.height);
+    IntSize winSize = IntSize(mWindow.width, mWindow.height);
 
     if (mBackground && mBackground->GetSize() != winSize) {
         // It would be nice to keep the old background here, but doing
         // so can lead to cases in which we permanently keep the old
         // background size.
         mBackground = nullptr;
         toInvalidate.UnionRect(toInvalidate,
                                nsIntRect(0, 0, winSize.width, winSize.height));
     }
 
     if (mCurrentSurface) {
-        gfxIntSize surfSize = mCurrentSurface->GetSize();
+        IntSize surfSize = mCurrentSurface->GetSize();
         if (winSize != surfSize ||
             (mBackground && !CanPaintOnBackground()) ||
             (mBackground &&
              gfxContentType::COLOR != mCurrentSurface->GetContentType()) ||
             (!mBackground && mIsTransparent &&
              gfxContentType::COLOR == mCurrentSurface->GetContentType())) {
             // Don't try to use an old, invalid DC.
             mWindow.window = nullptr;
@@ -3304,17 +3302,17 @@ PluginInstanceChild::PaintRectWithAlphaE
                 gfxAlphaRecovery::AlignRectForSubimageRecovery(aRect,
                                                                surfaceAsImage);
         }
     }
 
     nsRefPtr<gfxImageSurface> whiteImage;
     nsRefPtr<gfxImageSurface> blackImage;
     gfxRect targetRect(rect.x, rect.y, rect.width, rect.height);
-    gfxIntSize targetSize(rect.width, rect.height);
+    IntSize targetSize(rect.width, rect.height);
     gfxPoint deviceOffset = -targetRect.TopLeft();
 
     // We always use a temporary "white image"
     whiteImage = new gfxImageSurface(targetSize, gfxImageFormat::RGB24);
     if (whiteImage->CairoStatus()) {
         return;
     }
 
@@ -3482,17 +3480,17 @@ PluginInstanceChild::ShowPluginFrame()
 
     // Clear accRect here to be able to pass
     // test_invalidate_during_plugin_paint  test
     nsIntRect rect = mAccumulatedInvalidRect;
     mAccumulatedInvalidRect.SetEmpty();
 
     // Fix up old invalidations that might have been made when our
     // surface was a different size
-    gfxIntSize surfaceSize = mCurrentSurface->GetSize();
+    IntSize surfaceSize = mCurrentSurface->GetSize();
     rect.IntersectRect(rect,
                        nsIntRect(0, 0, surfaceSize.width, surfaceSize.height));
 
     if (!ReadbackDifferenceRect(rect)) {
         // We couldn't read back the pixels that differ between the
         // current surface and last, so we have to invalidate the
         // entire window.
         rect.SetRect(0, 0, mWindow.width, mWindow.height);
@@ -3744,17 +3742,17 @@ PluginInstanceChild::RecvUpdateBackgroun
         default:
             NS_RUNTIMEABORT("Unexpected background surface descriptor");
         }
 
         if (!mBackground) {
             return false;
         }
 
-        gfxIntSize bgSize = mBackground->GetSize();
+        IntSize bgSize = mBackground->GetSize();
         mAccumulatedInvalidRect.UnionRect(mAccumulatedInvalidRect,
                                           nsIntRect(0, 0, bgSize.width, bgSize.height));
         AsyncShowPluginFrame();
         return true;
     }
 
     // XXX refactor me
     mAccumulatedInvalidRect.UnionRect(aRect, mAccumulatedInvalidRect);
@@ -3781,17 +3779,17 @@ PluginInstanceChild::RecvPPluginBackgrou
     // destroyed because we have a new background, then we expect to
     // be notified of that "soon", before processing the asynchronous
     // invalidation here.  If we're *not* getting a new background,
     // our current front surface is stale and we want to repaint
     // "soon" so that we can hand the browser back a surface with
     // alpha values.  (We should be notified of that invalidation soon
     // too, but we don't assume that here.)
     if (mBackground) {
-        gfxIntSize bgsize = mBackground->GetSize();
+        IntSize bgsize = mBackground->GetSize();
         mAccumulatedInvalidRect.UnionRect(
             nsIntRect(0, 0, bgsize.width, bgsize.height), mAccumulatedInvalidRect);
 
         // NB: we don't have to XSync here because only ShowPluginFrame()
         // uses mBackground, and it always XSyncs after finishing.
         mBackground = nullptr;
         AsyncShowPluginFrame();
     }
--- a/dom/plugins/ipc/PluginInstanceChild.h
+++ b/dom/plugins/ipc/PluginInstanceChild.h
@@ -108,17 +108,17 @@ protected:
 
     virtual void
     DoAsyncSetWindow(const gfxSurfaceType& aSurfaceType,
                      const NPRemoteWindow& aWindow,
                      bool aIsAsync);
 
     virtual PPluginSurfaceChild*
     AllocPPluginSurfaceChild(const WindowsSharedMemoryHandle&,
-                             const gfxIntSize&, const bool&) override {
+                             const gfx::IntSize&, const bool&) override {
         return new PPluginSurfaceChild();
     }
 
     virtual bool DeallocPPluginSurfaceChild(PPluginSurfaceChild* s) override {
         delete s;
         return true;
     }
 
--- a/dom/plugins/ipc/PluginInstanceParent.cpp
+++ b/dom/plugins/ipc/PluginInstanceParent.cpp
@@ -721,17 +721,17 @@ PluginInstanceParent::GetImageContainer(
     *aContainer = container;
     return NS_OK;
 }
 
 nsresult
 PluginInstanceParent::GetImageSize(nsIntSize* aSize)
 {
     if (mFrontSurface) {
-        gfxIntSize size = mFrontSurface->GetSize();
+        mozilla::gfx::IntSize size = mFrontSurface->GetSize();
         *aSize = nsIntSize(size.width, size.height);
         return NS_OK;
     }
 
 #ifdef XP_MACOSX
     if (mFrontIOSurface) {
         *aSize = nsIntSize(mFrontIOSurface->GetWidth(), mFrontIOSurface->GetHeight());
         return NS_OK;
@@ -790,17 +790,17 @@ PluginInstanceParent::BeginUpdateBackgro
         MOZ_ASSERT(aRect.TopLeft() == nsIntPoint(0, 0),
                    "Expecting rect for whole frame");
         if (!CreateBackground(aRect.Size())) {
             *aCtx = nullptr;
             return NS_OK;
         }
     }
 
-    gfxIntSize sz = mBackground->GetSize();
+    mozilla::gfx::IntSize sz = mBackground->GetSize();
 #ifdef DEBUG
     MOZ_ASSERT(nsIntRect(0, 0, sz.width, sz.height).Contains(aRect),
                "Update outside of background area");
 #endif
 
     RefPtr<gfx::DrawTarget> dt = gfxPlatform::GetPlatform()->
       CreateDrawTargetForSurface(mBackground, gfx::IntSize(sz.width, sz.height));
     nsRefPtr<gfxContext> ctx = new gfxContext(dt);
@@ -847,26 +847,26 @@ PluginInstanceParent::CreateBackground(c
     MOZ_ASSERT(!mBackground, "Already have a background");
 
     // XXX refactor me
 
 #if defined(MOZ_X11)
     Screen* screen = DefaultScreenOfDisplay(DefaultXDisplay());
     Visual* visual = DefaultVisualOfScreen(screen);
     mBackground = gfxXlibSurface::Create(screen, visual,
-                                         gfxIntSize(aSize.width, aSize.height));
+                                         mozilla::gfx::IntSize(aSize.width, aSize.height));
     return !!mBackground;
 
 #elif defined(XP_WIN)
     // We have chosen to create an unsafe surface in which the plugin
     // can read from the region while we're writing to it.
     mBackground =
         gfxSharedImageSurface::CreateUnsafe(
             this,
-            gfxIntSize(aSize.width, aSize.height),
+            mozilla::gfx::IntSize(aSize.width, aSize.height),
             gfxImageFormat::RGB24);
     return !!mBackground;
 #else
     return false;
 #endif
 }
 
 void
@@ -1595,17 +1595,17 @@ PluginInstanceParent::GetActorForNPObjec
     }
 
     actor->InitializeLocal(aObject);
     return actor;
 }
 
 PPluginSurfaceParent*
 PluginInstanceParent::AllocPPluginSurfaceParent(const WindowsSharedMemoryHandle& handle,
-                                                const gfxIntSize& size,
+                                                const mozilla::gfx::IntSize& size,
                                                 const bool& transparent)
 {
 #ifdef XP_WIN
     return new PluginSurfaceParent(handle, size, transparent);
 #else
     NS_ERROR("This shouldn't be called!");
     return nullptr;
 #endif
--- a/dom/plugins/ipc/PluginInstanceParent.h
+++ b/dom/plugins/ipc/PluginInstanceParent.h
@@ -164,17 +164,17 @@ public:
     // Async rendering
     virtual bool
     RecvShow(const NPRect& updatedRect,
              const SurfaceDescriptor& newSurface,
              SurfaceDescriptor* prevSurface) override;
 
     virtual PPluginSurfaceParent*
     AllocPPluginSurfaceParent(const WindowsSharedMemoryHandle& handle,
-                              const gfxIntSize& size,
+                              const mozilla::gfx::IntSize& size,
                               const bool& transparent) override;
 
     virtual bool
     DeallocPPluginSurfaceParent(PPluginSurfaceParent* s) override;
 
     virtual bool
     AnswerNPN_PushPopupsEnabledState(const bool& aState) override;
 
--- a/dom/plugins/ipc/PluginSurfaceParent.cpp
+++ b/dom/plugins/ipc/PluginSurfaceParent.cpp
@@ -7,17 +7,17 @@
 #include "mozilla/gfx/SharedDIBSurface.h"
 
 using mozilla::gfx::SharedDIBSurface;
 
 namespace mozilla {
 namespace plugins {
 
 PluginSurfaceParent::PluginSurfaceParent(const WindowsSharedMemoryHandle& handle,
-                                         const gfxIntSize& size,
+                                         const gfx::IntSize& size,
                                          bool transparent)
 {
   SharedDIBSurface* dibsurf = new SharedDIBSurface();
   if (dibsurf->Attach(handle, size.width, size.height, transparent))
     mSurface = dibsurf;
 }
 
 PluginSurfaceParent::~PluginSurfaceParent()
--- a/dom/plugins/ipc/PluginSurfaceParent.h
+++ b/dom/plugins/ipc/PluginSurfaceParent.h
@@ -18,17 +18,17 @@ class gfxASurface;
 
 namespace mozilla {
 namespace plugins {
 
 class PluginSurfaceParent : public PPluginSurfaceParent
 {
 public:
   PluginSurfaceParent(const WindowsSharedMemoryHandle& handle,
-                      const gfxIntSize& size,
+                      const gfx::IntSize& size,
                       const bool transparent);
   ~PluginSurfaceParent();
 
   virtual void ActorDestroy(ActorDestroyReason aWhy) override;
 
   gfxASurface* Surface() { return mSurface; }
 
 private:
--- a/dom/quota/QuotaManager.cpp
+++ b/dom/quota/QuotaManager.cpp
@@ -3570,17 +3570,17 @@ QuotaManager::GetInfoFromWindow(nsPIDOMW
 
 // static
 void
 QuotaManager::GetInfoForChrome(nsACString* aGroup,
                                nsACString* aOrigin,
                                bool* aIsApp)
 {
   MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(nsContentUtils::IsCallerChrome());
+  MOZ_ASSERT(nsContentUtils::LegacyIsCallerChromeOrNativeCode());
 
   if (aGroup) {
     ChromeOrigin(*aGroup);
   }
   if (aOrigin) {
     ChromeOrigin(*aOrigin);
   }
   if (aIsApp) {
--- a/dom/tests/mochitest/general/test_picture_pref.html
+++ b/dom/tests/mochitest/general/test_picture_pref.html
@@ -66,26 +66,27 @@ https://bugzilla.mozilla.org/show_bug.cg
       });
       document.body.appendChild(iframe);
       iframe.src = "data:text/html;base64," + btoa(container.innerHTML);
     });
   }
 
   function runTest(iframe) {
     var doc = iframe.contentDocument;
+    var win = iframe.contentWindow;
     var img = doc.querySelector("img");
     var source = doc.querySelector("source");
 
     is(img.sizes, undefined, "sizes should not be visible on <img>");
     is(source.sizes, undefined, "sizes should not be visible on <source>");
     is(source.srcset, undefined, "srcset should not be visible on <source>");
 
-    var imgSizesDesc = Object.getOwnPropertyDescriptor(HTMLImageElement.prototype, "sizes");
-    var sourceSizesDesc = Object.getOwnPropertyDescriptor(HTMLSourceElement.prototype, "sizes");
-    var sourceSrcsetDesc = Object.getOwnPropertyDescriptor(HTMLSourceElement.prototype, "srcset");
+    var imgSizesDesc = Object.getOwnPropertyDescriptor(win.HTMLImageElement.prototype, "sizes");
+    var sourceSizesDesc = Object.getOwnPropertyDescriptor(win.HTMLSourceElement.prototype, "sizes");
+    var sourceSrcsetDesc = Object.getOwnPropertyDescriptor(win.HTMLSourceElement.prototype, "srcset");
     is(imgSizesDesc, undefined, "HTMLImageElement should know nothing of sizes");
     is(sourceSizesDesc, undefined, "HTMLSourceElement should know nothing of sizes");
     is(sourceSrcsetDesc, undefined, "HTMLSourceElement should know nothing of srcset");
 
     // Make sure the test images loaded red.png, which is 1x1, not big.png
     for (var id of [ 'img1', 'img2' ]) {
       var testImg = doc.getElementById(id);
       is(testImg.naturalWidth, 1, "Image should have loaded small source");
--- a/dom/tests/mochitest/general/test_srcset_pref.html
+++ b/dom/tests/mochitest/general/test_srcset_pref.html
@@ -7,36 +7,35 @@ https://bugzilla.mozilla.org/show_bug.cg
   <title>Test for dom.image.srcset.enabled (Bug 870021)</title>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body onload="setupTest()">
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=870021">Mozilla Bug 870021</a>
 
 <div id="imgContainer">
-<img src="http://example.com/tests/image/test/mochitest/blue.png"
-     srcset="http://example.com/tests/image/test/mochitest/big.png">
 </div>
 
 <script type="application/javascript">
 
   const srcsetPref = 'dom.image.srcset.enabled';
 
   SimpleTest.waitForExplicitFinish();
 
   is(SpecialPowers.getBoolPref(srcsetPref), true, "srcset should be enabled by default");
 
   function setupTest() {
     // Ensure that disabling the pref works as expected
     SpecialPowers.pushPrefEnv({'set': [[ "dom.image.srcset.enabled", false ]] }, function() {
       var container = document.querySelector("#imgContainer");
-      // We want to re-create the element with the pref disabled to ensure
-      // webIDL attributes are not attached
-      container.innerHTML = container.innerHTML + " ";
-      var img = container.querySelector("img");
+
+      var img = document.createElement("img");
+      img.setAttribute("src", "http://example.com/tests/image/test/mochitest/blue.png");
+      img.setAttribute("srcset", "http://example.com/tests/image/test/mochitest/big.png");
+      container.insertBefore(img, container.firstChild);
       img.addEventListener("load", function imgLoad() {
         img.removeEventListener("load", imgLoad);
         runTest();
       });
     });
   }
 
   function runTest() {
--- a/dom/xslt/xpath/XPathExpression.cpp
+++ b/dom/xslt/xpath/XPathExpression.cpp
@@ -96,17 +96,19 @@ XPathExpression::EvaluateWithContext(nsI
                                      XPathResult* aInResult,
                                      ErrorResult& aRv)
 {
     if (aContextPosition > aContextSize) {
         aRv.Throw(NS_ERROR_FAILURE);
         return nullptr;
     }
 
-    if (!nsContentUtils::CanCallerAccess(&aContextNode)) {
+    if (!nsContentUtils::LegacyIsCallerNativeCode() &&
+        !nsContentUtils::CanCallerAccess(&aContextNode))
+    {
         aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
         return nullptr;
     }
 
     if (mCheckDocument) {
         nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocument);
         if (doc != aContextNode.OwnerDoc()) {
             aRv.Throw(NS_ERROR_DOM_WRONG_DOCUMENT_ERR);
--- a/dom/xslt/xslt/txMozillaXSLTProcessor.cpp
+++ b/dom/xslt/xslt/txMozillaXSLTProcessor.cpp
@@ -593,17 +593,18 @@ NS_IMETHODIMP
 txMozillaXSLTProcessor::ImportStylesheet(nsIDOMNode *aStyle)
 {
     NS_ENSURE_TRUE(aStyle, NS_ERROR_NULL_POINTER);
     
     // We don't support importing multiple stylesheets yet.
     NS_ENSURE_TRUE(!mStylesheetDocument && !mStylesheet,
                    NS_ERROR_NOT_IMPLEMENTED);
 
-    if (!nsContentUtils::CanCallerAccess(aStyle)) {
+    nsCOMPtr<nsINode> node = do_QueryInterface(aStyle);
+    if (!node || !nsContentUtils::SubjectPrincipalOrSystemIfNativeCaller()->Subsumes(node->NodePrincipal())) {
         return NS_ERROR_DOM_SECURITY_ERR;
     }
     
     nsCOMPtr<nsINode> styleNode = do_QueryInterface(aStyle);
     NS_ENSURE_TRUE(styleNode &&
                    (styleNode->IsElement() ||
                     styleNode->IsNodeOfType(nsINode::eDOCUMENT)),
                    NS_ERROR_INVALID_ARG);
@@ -708,18 +709,23 @@ txMozillaXSLTProcessor::TransformToFragm
                                             nsIDOMDocument *aOutput,
                                             nsIDOMDocumentFragment **aResult)
 {
     NS_ENSURE_ARG(aSource);
     NS_ENSURE_ARG(aOutput);
     NS_ENSURE_ARG_POINTER(aResult);
     NS_ENSURE_SUCCESS(mCompileResult, mCompileResult);
 
-    if (!nsContentUtils::CanCallerAccess(aSource) ||
-        !nsContentUtils::CanCallerAccess(aOutput)) {
+    nsCOMPtr<nsINode> node = do_QueryInterface(aSource);
+    nsCOMPtr<nsIDocument> doc = do_QueryInterface(aOutput);
+    NS_ENSURE_TRUE(node && doc, NS_ERROR_DOM_SECURITY_ERR);
+    nsIPrincipal* subject = nsContentUtils::SubjectPrincipalOrSystemIfNativeCaller();
+    if (!subject->Subsumes(node->NodePrincipal()) ||
+        !subject->Subsumes(doc->NodePrincipal()))
+    {
         return NS_ERROR_DOM_SECURITY_ERR;
     }
 
     nsresult rv = ensureStylesheet();
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsAutoPtr<txXPathNode> sourceNode(txXPathNativeNode::createXPathNode(aSource));
     if (!sourceNode) {
--- a/dom/xul/nsXULCommandDispatcher.cpp
+++ b/dom/xul/nsXULCommandDispatcher.cpp
@@ -130,17 +130,18 @@ nsXULCommandDispatcher::GetFocusedElemen
 
   nsCOMPtr<nsPIDOMWindow> focusedWindow;
   nsIContent* focusedContent =
     GetRootFocusedContentAndWindow(getter_AddRefs(focusedWindow));
   if (focusedContent) {
     CallQueryInterface(focusedContent, aElement);
 
     // Make sure the caller can access the focused element.
-    if (!nsContentUtils::CanCallerAccess(*aElement)) {
+    nsCOMPtr<nsINode> node = do_QueryInterface(*aElement);
+    if (!node || !nsContentUtils::SubjectPrincipalOrSystemIfNativeCaller()->Subsumes(node->NodePrincipal())) {
       // XXX This might want to return null, but we use that return value
       // to mean "there is no focused element," so to be clear, throw an
       // exception.
       NS_RELEASE(*aElement);
       return NS_ERROR_DOM_SECURITY_ERR;
     }
   }
 
--- a/embedding/components/commandhandler/nsCommandManager.cpp
+++ b/embedding/components/commandhandler/nsCommandManager.cpp
@@ -232,17 +232,17 @@ nsCommandManager::GetControllerForComman
                                           nsIDOMWindow* aTargetWindow,
                                           nsIController** aResult)
 {
   nsresult rv = NS_ERROR_FAILURE;
   *aResult = nullptr;
 
   // check if we're in content or chrome
   // if we're not chrome we must have a target window or we bail
-  if (!nsContentUtils::IsCallerChrome()) {
+  if (!nsContentUtils::LegacyIsCallerChromeOrNativeCode()) {
     if (!aTargetWindow) {
       return rv;
     }
 
     // if a target window is specified, it must be the window we expect
     if (aTargetWindow != mWindow) {
       return NS_ERROR_FAILURE;
     }
--- a/embedding/components/windowwatcher/nsWindowWatcher.cpp
+++ b/embedding/components/windowwatcher/nsWindowWatcher.cpp
@@ -588,17 +588,17 @@ nsWindowWatcher::OpenWindowInternal(nsID
 
   SizeSpec sizeSpec;
   CalcSizeSpec(features.get(), sizeSpec);
 
   nsCOMPtr<nsIScriptSecurityManager> sm(
     do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID));
 
   bool isCallerChrome =
-    nsContentUtils::IsCallerChrome() && !openedFromRemoteTab;
+    nsContentUtils::LegacyIsCallerChromeOrNativeCode() && !openedFromRemoteTab;
 
   dom::AutoJSAPI jsapiChromeGuard;
 
   bool windowTypeIsChrome =
     chromeFlags & nsIWebBrowserChrome::CHROME_OPENAS_CHROME;
   if (isCallerChrome && !hasChromeParent && !windowTypeIsChrome) {
     // open() is called from chrome on a non-chrome window, initialize an
     // AutoJSAPI with the callee to prevent the caller's privileges from leaking
@@ -1509,17 +1509,17 @@ nsWindowWatcher::CalculateChromeFlags(ns
       return chromeFlags;
     }
   } else {
     chromeFlags = nsIWebBrowserChrome::CHROME_WINDOW_BORDERS;
   }
 
   bool openedFromContentScript =
     aOpenedFromRemoteTab ? aCalledFromJS
-                         : !nsContentUtils::IsCallerChrome();
+                         : !nsContentUtils::LegacyIsCallerChromeOrNativeCode();
 
   /* This function has become complicated since browser windows and
      dialogs diverged. The difference is, browser windows assume all
      chrome not explicitly mentioned is off, if the features string
      is not null. Exceptions are some OS border chrome new with Mozilla.
      Dialogs interpret a (mostly) empty features string to mean
      "OS's choice," and also support an "all" flag explicitly disallowed
      in the standards-compliant window.(normal)open. */
--- a/gfx/gl/EGLUtils.cpp
+++ b/gfx/gl/EGLUtils.cpp
@@ -18,17 +18,17 @@ DoesEGLContextSupportSharingWithEGLImage
 }
 
 EGLImage
 CreateEGLImage(GLContext* gl, GLuint tex)
 {
     MOZ_ASSERT(DoesEGLContextSupportSharingWithEGLImage(gl));
 
     EGLClientBuffer clientBuffer = (EGLClientBuffer)((uint64_t)tex);
-    EGLContext eglContext = GLContextEGL::Cast(gl)->GetEGLContext();
+    EGLContext eglContext = GLContextEGL::Cast(gl)->mContext;
     EGLImage image = sEGLLibrary.fCreateImage(EGL_DISPLAY(),
                                               eglContext,
                                               LOCAL_EGL_GL_TEXTURE_2D,
                                               clientBuffer,
                                               nullptr);
     return image;
 }
 
@@ -37,17 +37,17 @@ CreateEGLImage(GLContext* gl, GLuint tex
 
 /*static*/ EGLImageWrapper*
 EGLImageWrapper::Create(GLContext* gl, GLuint tex)
 {
     MOZ_ASSERT(DoesEGLContextSupportSharingWithEGLImage(gl));
 
     GLLibraryEGL& library = sEGLLibrary;
     EGLDisplay display = EGL_DISPLAY();
-    EGLContext eglContext = GLContextEGL::Cast(gl)->GetEGLContext();
+    EGLContext eglContext = GLContextEGL::Cast(gl)->mContext;
     EGLClientBuffer clientBuffer = (EGLClientBuffer)((uint64_t)tex);
     EGLImage image = library.fCreateImage(display,
                                           eglContext,
                                           LOCAL_EGL_GL_TEXTURE_2D,
                                           clientBuffer,
                                           nullptr);
     if (!image) {
 #ifdef DEBUG
--- a/gfx/gl/GLContext.cpp
+++ b/gfx/gl/GLContext.cpp
@@ -301,17 +301,16 @@ GLContext::GLContext(const SurfaceCaps& 
     mIsOffscreen(isOffscreen),
     mContextLost(false),
     mVersion(0),
     mProfile(ContextProfile::Unknown),
     mVendor(GLVendor::Other),
     mRenderer(GLRenderer::Other),
     mHasRobustness(false),
     mTopError(LOCAL_GL_NO_ERROR),
-    mLocalErrorScope(nullptr),
     mSharedContext(sharedContext),
     mCaps(caps),
     mScreen(nullptr),
     mLockedSurface(nullptr),
     mMaxTextureSize(0),
     mMaxCubeMapTextureSize(0),
     mMaxTextureImageSize(0),
     mMaxRenderbufferSize(0),
--- a/gfx/gl/GLContext.h
+++ b/gfx/gl/GLContext.h
@@ -2,22 +2,23 @@
 /* vim: set ts=8 sts=4 et sw=4 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef GLCONTEXT_H_
 #define GLCONTEXT_H_
 
-#include <stdio.h>
-#include <stdint.h>
+#include <bitset>
 #include <ctype.h>
+#include <stdint.h>
+#include <stdio.h>
 #include <map>
-#include <bitset>
 #include <queue>
+#include <stack>
 
 #ifdef DEBUG
 #include <string.h>
 #endif
 
 #ifdef WIN32
 #include <windows.h>
 #endif
@@ -614,31 +615,30 @@ public:
         return err;
     }
 
     ////////////////////////////////////
     // Use this safer option.
     class LocalErrorScope;
 
 private:
-    LocalErrorScope* mLocalErrorScope;
+    std::stack<const LocalErrorScope*> mLocalErrorScopeStack;
 
 public:
     class LocalErrorScope {
         GLContext& mGL;
         GLenum mOldTop;
         bool mHasBeenChecked;
 
     public:
         explicit LocalErrorScope(GLContext& gl)
             : mGL(gl)
             , mHasBeenChecked(false)
         {
-            MOZ_ASSERT(!mGL.mLocalErrorScope);
-            mGL.mLocalErrorScope = this;
+            mGL.mLocalErrorScopeStack.push(this);
 
             mGL.FlushErrors();
 
             mOldTop = mGL.mTopError;
             mGL.mTopError = LOCAL_GL_NO_ERROR;
         }
 
         GLenum GetError() {
@@ -648,20 +648,20 @@ public:
             return mGL.fGetError();
         }
 
         ~LocalErrorScope() {
             MOZ_ASSERT(mHasBeenChecked);
 
             MOZ_ASSERT(mGL.fGetError() == LOCAL_GL_NO_ERROR);
 
+            MOZ_ASSERT(mGL.mLocalErrorScopeStack.top() == this);
+            mGL.mLocalErrorScopeStack.pop();
+
             mGL.mTopError = mOldTop;
-
-            MOZ_ASSERT(mGL.mLocalErrorScope == this);
-            mGL.mLocalErrorScope = nullptr;
         }
     };
 
     bool GetPotentialInteger(GLenum pname, GLint* param) {
         LocalErrorScope localError(*this);
 
         fGetIntegerv(pname, param);
 
@@ -733,17 +733,17 @@ private:
             GLenum err = FlushErrors();
 
             if (DebugMode() & DebugTrace) {
                 printf_stderr("[gl:%p] < %s [%s (0x%04x)]\n", this, funcName,
                               GLErrorToString(err), err);
             }
 
             if (err != LOCAL_GL_NO_ERROR &&
-                !mLocalErrorScope)
+                !mLocalErrorScopeStack.size())
             {
                 printf_stderr("[gl:%p] %s: Generated unexpected %s error."
                               " (0x%04x)\n", this, funcName,
                               GLErrorToString(err), err);
 
                 if (DebugMode() & DebugAbortOnError)
                     MOZ_CRASH("MOZ_GL_DEBUG_ABORT_ON_ERROR");
             }
--- a/gfx/gl/GLContextEGL.h
+++ b/gfx/gl/GLContextEGL.h
@@ -87,45 +87,46 @@ public:
     virtual bool SetupLookupFunction() override;
 
     virtual bool SwapBuffers() override;
 
     // hold a reference to the given surface
     // for the lifetime of this context.
     void HoldSurface(gfxASurface *aSurf);
 
-    EGLContext GetEGLContext() {
-        return mContext;
-    }
-
-    EGLSurface GetEGLSurface() {
+    EGLSurface GetEGLSurface() const {
         return mSurface;
     }
 
-    EGLDisplay GetEGLDisplay() {
-        return EGL_DISPLAY();
+    EGLDisplay GetEGLDisplay() const {
+        return sEGLLibrary.Display();
     }
 
     bool BindTex2DOffscreen(GLContext *aOffscreen);
     void UnbindTex2DOffscreen(GLContext *aOffscreen);
     void BindOffscreenFramebuffer();
 
     static already_AddRefed<GLContextEGL>
     CreateEGLPixmapOffscreenContext(const gfx::IntSize& size);
 
     static already_AddRefed<GLContextEGL>
-    CreateEGLPBufferOffscreenContext(const gfx::IntSize& size);
+    CreateEGLPBufferOffscreenContext(const gfx::IntSize& size,
+                                     const SurfaceCaps& minCaps);
 
 protected:
     friend class GLContextProviderEGL;
 
-    EGLConfig  mConfig;
+public:
+    const EGLConfig  mConfig;
+protected:
     EGLSurface mSurface;
+public:
+    const EGLContext mContext;
+protected:
     EGLSurface mSurfaceOverride;
-    EGLContext mContext;
     nsRefPtr<gfxASurface> mThebesSurface;
     bool mBound;
 
     bool mIsPBuffer;
     bool mIsDoubleBuffered;
     bool mCanBindToTexture;
     bool mShareWithEGLImage;
     bool mOwnsContext;
--- a/gfx/gl/GLContextProvider.h
+++ b/gfx/gl/GLContextProvider.h
@@ -4,84 +4,71 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef GLCONTEXTPROVIDER_H_
 #define GLCONTEXTPROVIDER_H_
 
 #include "GLContextTypes.h"
 #include "nsAutoPtr.h"
 #include "SurfaceTypes.h"
-#include "mozilla/TypedEnumBits.h"
 
 #include "nsSize.h" // for gfx::IntSize (needed by GLContextProviderImpl.h below)
 
 class nsIWidget;
 
 namespace mozilla {
 namespace gl {
 
-enum class CreateContextFlags : int8_t {
-    NONE = 0,
-    REQUIRE_COMPAT_PROFILE = 1 << 0,
-    // Force the use of hardware backed GL, don't allow software implementations.
-    FORCE_ENABLE_HARDWARE = 1 << 1,
-    /* Don't force discrete GPU to be used (if applicable) */
-    ALLOW_OFFLINE_RENDERER =  1 << 2,
-};
-MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(CreateContextFlags)
-
 #define IN_GL_CONTEXT_PROVIDER_H
 
 // Null is always there
 #define GL_CONTEXT_PROVIDER_NAME GLContextProviderNull
 #include "GLContextProviderImpl.h"
 #undef GL_CONTEXT_PROVIDER_NAME
 
 #ifdef XP_WIN
-#define GL_CONTEXT_PROVIDER_NAME GLContextProviderWGL
-#include "GLContextProviderImpl.h"
-#undef GL_CONTEXT_PROVIDER_NAME
-#define GL_CONTEXT_PROVIDER_DEFAULT GLContextProviderWGL
-#define DEFAULT_IMPL WGL
+  #define GL_CONTEXT_PROVIDER_NAME GLContextProviderWGL
+  #include "GLContextProviderImpl.h"
+  #undef GL_CONTEXT_PROVIDER_NAME
+  #define GL_CONTEXT_PROVIDER_DEFAULT GLContextProviderWGL
+  #define DEFAULT_IMPL WGL
 #endif
 
 #ifdef XP_MACOSX
-#define GL_CONTEXT_PROVIDER_NAME GLContextProviderCGL
-#include "GLContextProviderImpl.h"
-#undef GL_CONTEXT_PROVIDER_NAME
-#define GL_CONTEXT_PROVIDER_DEFAULT GLContextProviderCGL
+  #define GL_CONTEXT_PROVIDER_NAME GLContextProviderCGL
+  #include "GLContextProviderImpl.h"
+  #undef GL_CONTEXT_PROVIDER_NAME
+  #define GL_CONTEXT_PROVIDER_DEFAULT GLContextProviderCGL
 #endif
 
-#if defined(ANDROID) || defined(XP_WIN)
+#if defined(MOZ_X11)
+  #define GL_CONTEXT_PROVIDER_NAME GLContextProviderGLX
+  #include "GLContextProviderImpl.h"
+  #undef GL_CONTEXT_PROVIDER_NAME
+  #define GL_CONTEXT_PROVIDER_DEFAULT GLContextProviderGLX
+#endif
+
 #define GL_CONTEXT_PROVIDER_NAME GLContextProviderEGL
 #include "GLContextProviderImpl.h"
 #undef GL_CONTEXT_PROVIDER_NAME
 #ifndef GL_CONTEXT_PROVIDER_DEFAULT
-#define GL_CONTEXT_PROVIDER_DEFAULT GLContextProviderEGL
-#endif
+  #define GL_CONTEXT_PROVIDER_DEFAULT GLContextProviderEGL
 #endif
 
 #ifdef MOZ_GL_PROVIDER
-#define GL_CONTEXT_PROVIDER_NAME MOZ_GL_PROVIDER
-#include "GLContextProviderImpl.h"
-#undef GL_CONTEXT_PROVIDER_NAME
-#define GL_CONTEXT_PROVIDER_DEFAULT MOZ_GL_PROVIDER
-#endif
-
-#if defined(MOZ_X11) && !defined(GL_CONTEXT_PROVIDER_DEFAULT)
-#define GL_CONTEXT_PROVIDER_NAME GLContextProviderGLX
-#include "GLContextProviderImpl.h"
-#undef GL_CONTEXT_PROVIDER_NAME
-#define GL_CONTEXT_PROVIDER_DEFAULT GLContextProviderGLX
+  #define GL_CONTEXT_PROVIDER_NAME MOZ_GL_PROVIDER
+  #include "GLContextProviderImpl.h"
+  #undef GL_CONTEXT_PROVIDER_NAME
+  #define GL_CONTEXT_PROVIDER_DEFAULT MOZ_GL_PROVIDER
 #endif
 
 #ifdef GL_CONTEXT_PROVIDER_DEFAULT
-typedef GL_CONTEXT_PROVIDER_DEFAULT GLContextProvider;
+  typedef GL_CONTEXT_PROVIDER_DEFAULT GLContextProvider;
 #else
-typedef GLContextProviderNull GLContextProvider;
+  typedef GLContextProviderNull GLContextProvider;
 #endif
 
 #undef IN_GL_CONTEXT_PROVIDER_H
 
 } // namespace gl
 } // namespace mozilla
 
 #endif
--- a/gfx/gl/GLContextProviderCGL.mm
+++ b/gfx/gl/GLContextProviderCGL.mm
@@ -312,26 +312,27 @@ GLContextProviderCGL::CreateHeadless(Cre
         return nullptr;
     }
 
     return gl.forget();
 }
 
 already_AddRefed<GLContext>
 GLContextProviderCGL::CreateOffscreen(const IntSize& size,
-                                      const SurfaceCaps& caps,
+                                      const SurfaceCaps& minCaps,
                                       CreateContextFlags flags)
 {
-    nsRefPtr<GLContext> glContext = CreateHeadless(flags);
-    if (!glContext->InitOffscreen(size, caps)) {
-        NS_WARNING("Failed during InitOffscreen.");
+    RefPtr<GLContext> gl = CreateHeadless(flags);
+    if (!gl)
         return nullptr;
-    }
 
-    return glContext.forget();
+    if (!gl->InitOffscreen(size, minCaps))
+        return nullptr;
+
+    return gl.forget();
 }
 
 static nsRefPtr<GLContext> gGlobalContext;
 
 GLContext*
 GLContextProviderCGL::GetGlobalContext()
 {
     if (!sCGLLibrary.EnsureInitialized()) {
--- a/gfx/gl/GLContextProviderEGL.cpp
+++ b/gfx/gl/GLContextProviderEGL.cpp
@@ -1,123 +1,115 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "mozilla/ArrayUtils.h"
-
-#include "GLContextEGL.h"
-
-#if defined(XP_UNIX)
-
-#ifdef MOZ_WIDGET_GTK
-#include <gdk/gdkx.h>
-// we're using default display for now
-#define GET_NATIVE_WINDOW(aWidget) (EGLNativeWindowType)GDK_WINDOW_XID((GdkWindow *) aWidget->GetNativeData(NS_NATIVE_WINDOW))
+#if defined(MOZ_WIDGET_GTK)
+    #include <gdk/gdkx.h>
+    // we're using default display for now
+    #define GET_NATIVE_WINDOW(aWidget) ((EGLNativeWindowType)GDK_WINDOW_XID((GdkWindow*)aWidget->GetNativeData(NS_NATIVE_WINDOW)))
 #elif defined(MOZ_WIDGET_QT)
-#define GET_NATIVE_WINDOW(aWidget) (EGLNativeWindowType)(aWidget->GetNativeData(NS_NATIVE_SHAREABLE_WINDOW))
-#elif defined(MOZ_WIDGET_GONK)
-#define GET_NATIVE_WINDOW(aWidget) ((EGLNativeWindowType)aWidget->GetNativeData(NS_NATIVE_WINDOW))
-#include "libdisplay/GonkDisplay.h"
-#include "nsWindow.h"
-#include "nsScreenManagerGonk.h"
-#endif
-
-#if defined(ANDROID)
-/* from widget */
-#if defined(MOZ_WIDGET_ANDROID)
-#include "AndroidBridge.h"
-#endif
-
-#include <android/log.h>
-#define LOG(args...)  __android_log_print(ANDROID_LOG_INFO, "Gonk" , ## args)
-
-# if defined(MOZ_WIDGET_GONK)
-#  include "cutils/properties.h"
-#  include <ui/GraphicBuffer.h>
-
-using namespace android;
-# endif
-
-#endif
-
-#define GLES2_LIB "libGLESv2.so"
-#define GLES2_LIB2 "libGLESv2.so.2"
-
-#elif defined(XP_WIN)
-
-#include "nsIFile.h"
-
-#define GLES2_LIB "libGLESv2.dll"
-
-#ifndef WIN32_LEAN_AND_MEAN
-#define WIN32_LEAN_AND_MEAN 1
+    #define GET_NATIVE_WINDOW(aWidget) ((EGLNativeWindowType)aWidget->GetNativeData(NS_NATIVE_SHAREABLE_WINDOW))
+#else
+    #define GET_NATIVE_WINDOW(aWidget) ((EGLNativeWindowType)aWidget->GetNativeData(NS_NATIVE_WINDOW))
 #endif
 
-#include <windows.h>
+#if defined(XP_UNIX)
+    #ifdef MOZ_WIDGET_GONK
+        #include "libdisplay/GonkDisplay.h"
+        #include "nsWindow.h"
+        #include "nsScreenManagerGonk.h"
+    #endif
 
-// a little helper
-class AutoDestroyHWND {
-public:
-    AutoDestroyHWND(HWND aWnd = nullptr)
-        : mWnd(aWnd)
-    {
-    }
+    #ifdef ANDROID
+        /* from widget */
+        #ifdef MOZ_WIDGET_ANDROID
+            #include "AndroidBridge.h"
+        #endif
+
+        #include <android/log.h>
+        #define LOG(args...)  __android_log_print(ANDROID_LOG_INFO, "Gonk" , ## args)
 
-    ~AutoDestroyHWND() {
-        if (mWnd) {
-            ::DestroyWindow(mWnd);
-        }
-    }
+        #ifdef MOZ_WIDGET_GONK
+            #include "cutils/properties.h"
+            #include <ui/GraphicBuffer.h>
+
+            using namespace android;
+        #endif
+    #endif
 
-    operator HWND() {
-        return mWnd;
-    }
+    #define GLES2_LIB "libGLESv2.so"
+    #define GLES2_LIB2 "libGLESv2.so.2"
+
+#elif defined(XP_WIN)
+    #include "nsIFile.h"
+
+    #define GLES2_LIB "libGLESv2.dll"
+
+    #ifndef WIN32_LEAN_AND_MEAN
+        #define WIN32_LEAN_AND_MEAN 1
+    #endif
 
-    HWND forget() {
-        HWND w = mWnd;
-        mWnd = nullptr;
-        return w;
-    }
+    #include <windows.h>
 
-    HWND operator=(HWND aWnd) {
-        if (mWnd && mWnd != aWnd) {
-            ::DestroyWindow(mWnd);
+    // a little helper
+    class AutoDestroyHWND {
+    public:
+        AutoDestroyHWND(HWND aWnd = nullptr)
+            : mWnd(aWnd)
+        {
+        }
+
+        ~AutoDestroyHWND() {
+            if (mWnd) {
+                ::DestroyWindow(mWnd);
+            }
+        }
+
+        operator HWND() {
+            return mWnd;
         }
-        mWnd = aWnd;
-        return mWnd;
-    }
+
+        HWND forget() {
+            HWND w = mWnd;
+            mWnd = nullptr;
+            return w;
+        }
 
-    HWND mWnd;
-};
+        HWND operator=(HWND aWnd) {
+            if (mWnd && mWnd != aWnd) {
+                ::DestroyWindow(mWnd);
+            }
+            mWnd = aWnd;
+            return mWnd;
+        }
 
+        HWND mWnd;
+    };
 #else
-
-#error "Platform not recognized"
-
+    #error "Platform not recognized"
 #endif
 
-#include "mozilla/Preferences.h"
-#include "gfxUtils.h"
+#include "gfxASurface.h"
+#include "gfxCrashReporterUtils.h"
 #include "gfxFailure.h"
-#include "gfxASurface.h"
 #include "gfxPlatform.h"
+#include "gfxUtils.h"
+#include "GLBlitHelper.h"
+#include "GLContextEGL.h"
 #include "GLContextProvider.h"
 #include "GLLibraryEGL.h"
-#include "TextureImageEGL.h"
+#include "mozilla/ArrayUtils.h"
+#include "mozilla/Preferences.h"
 #include "nsDebug.h"
-#include "nsThreadUtils.h"
-
 #include "nsIWidget.h"
-
-#include "gfxCrashReporterUtils.h"
-
+#include "nsThreadUtils.h"
 #include "ScopedGLHelpers.h"
-#include "GLBlitHelper.h"
+#include "TextureImageEGL.h"
 
 using namespace mozilla::gfx;
 
 namespace mozilla {
 namespace gl {
 
 #define ADD_ATTR_2(_array, _k, _v) do {         \
     (_array).AppendElement(_k);                 \
@@ -185,43 +177,41 @@ DestroySurface(EGLSurface oldSurface) {
                                  EGL_NO_SURFACE, EGL_NO_SURFACE,
                                  EGL_NO_CONTEXT);
         sEGLLibrary.fDestroySurface(EGL_DISPLAY(), oldSurface);
     }
 }
 
 static EGLSurface
 CreateSurfaceForWindow(nsIWidget* widget, const EGLConfig& config) {
-    EGLSurface newSurface = EGL_NO_SURFACE;
+    EGLSurface newSurface = nullptr;
 
-    #ifdef MOZ_WIDGET_ANDROID
+#ifdef MOZ_WIDGET_ANDROID
         mozilla::AndroidBridge::Bridge()->RegisterCompositor();
         newSurface = mozilla::AndroidBridge::Bridge()->CreateEGLSurfaceForCompositor();
-        if (newSurface == EGL_NO_SURFACE) {
-            return EGL_NO_SURFACE;
-        }
-    #else
+#else
         MOZ_ASSERT(widget != nullptr);
-        newSurface = sEGLLibrary.fCreateWindowSurface(EGL_DISPLAY(), config, GET_NATIVE_WINDOW(widget), 0);
-    #endif
+        newSurface = sEGLLibrary.fCreateWindowSurface(EGL_DISPLAY(), config,
+                                                      GET_NATIVE_WINDOW(widget), 0);
+#endif
     return newSurface;
 }
 
 GLContextEGL::GLContextEGL(
                   const SurfaceCaps& caps,
                   GLContext* shareContext,
                   bool isOffscreen,
                   EGLConfig config,
                   EGLSurface surface,
                   EGLContext context)
     : GLContext(caps, shareContext, isOffscreen)
     , mConfig(config)
     , mSurface(surface)
+    , mContext(context)
     , mSurfaceOverride(EGL_NO_SURFACE)
-    , mContext(context)
     , mThebesSurface(nullptr)
     , mBound(false)
     , mIsPBuffer(false)
     , mIsDoubleBuffered(false)
     , mCanBindToTexture(false)
     , mShareWithEGLImage(false)
     , mOwnsContext(true)
 {
@@ -420,17 +410,17 @@ GLContextEGL::RenewSurface() {
     // pass again to CreateSurfaceForWindow below.
     // The reason why Android doesn't need this is that it delegates EGLSurface creation to
     // Java code which is the only thing that knows about our actual widget.
 #endif
     // unconditionally release the surface and create a new one. Don't try to optimize this away.
     // If we get here, then by definition we know that we want to get a new surface.
     ReleaseSurface();
     mSurface = mozilla::gl::CreateSurfaceForWindow(nullptr, mConfig); // the nullptr here is where we assume Android.
-    if (mSurface == EGL_NO_SURFACE) {
+    if (!mSurface) {
         return false;
     }
     return MakeCurrent(true);
 }
 
 void
 GLContextEGL::ReleaseSurface() {
     if (mOwnsContext) {
@@ -485,16 +475,20 @@ GLContextEGL::CreateSurfaceForWindow(nsI
 
     EGLConfig config;
     if (!CreateConfig(&config, aWidget)) {
         MOZ_CRASH("Failed to create EGLConfig!\n");
         return nullptr;
     }
 
     EGLSurface surface = mozilla::gl::CreateSurfaceForWindow(aWidget, config);
+    if (!surface) {
+        MOZ_CRASH("Failed to create EGLSurface for window!\n");
+        return nullptr;
+    }
     return surface;
 }
 
 /* static */ void
 GLContextEGL::DestroySurface(EGLSurface aSurface)
 {
     if (aSurface != EGL_NO_SURFACE) {
         sEGLLibrary.fDestroySurface(EGL_DISPLAY(), aSurface);
@@ -775,18 +769,17 @@ GLContextProviderEGL::CreateForWindow(ns
 
     EGLConfig config;
     if (!CreateConfig(&config, aWidget)) {
         MOZ_CRASH("Failed to create EGLConfig!\n");
         return nullptr;
     }
 
     EGLSurface surface = mozilla::gl::CreateSurfaceForWindow(aWidget, config);
-
-    if (surface == EGL_NO_SURFACE) {
+    if (!surface) {
         MOZ_CRASH("Failed to create EGLSurface!\n");
         return nullptr;
     }
 
     SurfaceCaps caps = SurfaceCaps::Any();
     nsRefPtr<GLContextEGL> glContext =
         GLContextEGL::CreateGLContext(caps,
                                       nullptr, false,
@@ -834,70 +827,154 @@ GLContextProviderEGL::DestroyEGLSurface(
     if (!sEGLLibrary.EnsureInitialized()) {
         MOZ_CRASH("Failed to load EGL library!\n");
     }
 
     sEGLLibrary.fDestroySurface(EGL_DISPLAY(), surface);
 }
 #endif // defined(ANDROID)
 
-already_AddRefed<GLContextEGL>
-GLContextEGL::CreateEGLPBufferOffscreenContext(const mozilla::gfx::IntSize& size)
+static void
+FillContextAttribs(bool alpha, bool depth, bool stencil, bool bpp16,
+                   nsTArray<EGLint>* out)
 {
-    EGLConfig config;
-    EGLSurface surface;
+    out->AppendElement(LOCAL_EGL_SURFACE_TYPE);
+    out->AppendElement(LOCAL_EGL_PBUFFER_BIT);
+
+    out->AppendElement(LOCAL_EGL_RENDERABLE_TYPE);
+    out->AppendElement(LOCAL_EGL_OPENGL_ES2_BIT);
+
+    out->AppendElement(LOCAL_EGL_RED_SIZE);
+    if (bpp16) {
+        out->AppendElement(alpha ? 4 : 5);
+    } else {
+        out->AppendElement(8);
+    }
+
+    out->AppendElement(LOCAL_EGL_GREEN_SIZE);
+    if (bpp16) {
+        out->AppendElement(alpha ? 4 : 6);
+    } else {
+        out->AppendElement(8);
+    }
+
+    out->AppendElement(LOCAL_EGL_BLUE_SIZE);
+    if (bpp16) {
+        out->AppendElement(alpha ? 4 : 5);
+    } else {
+        out->AppendElement(8);
+    }
+
+    out->AppendElement(LOCAL_EGL_ALPHA_SIZE);
+    if (alpha) {
+        out->AppendElement(bpp16 ? 4 : 8);
+    } else {
+        out->AppendElement(0);
+    }
 
-    const EGLint numConfigs = 1; // We only need one.
-    EGLConfig configs[numConfigs];
+    out->AppendElement(LOCAL_EGL_DEPTH_SIZE);
+    out->AppendElement(depth ? 16 : 0);
+
+    out->AppendElement(LOCAL_EGL_STENCIL_SIZE);
+    out->AppendElement(stencil ? 8 : 0);
+
+    // EGL_ATTRIBS_LIST_SAFE_TERMINATION_WORKING_AROUND_BUGS
+    out->AppendElement(LOCAL_EGL_NONE);
+    out->AppendElement(0);
+
+    out->AppendElement(0);
+    out->AppendElement(0);
+}
+
+static GLint
+GetAttrib(GLLibraryEGL* egl, EGLConfig config, EGLint attrib)
+{
+    EGLint bits = 0;
+    egl->fGetConfigAttrib(egl->Display(), config, attrib, &bits);
+    MOZ_ASSERT(egl->fGetError() == LOCAL_EGL_SUCCESS);
+
+    return bits;
+}
+
+static EGLConfig
+ChooseConfig(GLLibraryEGL* egl, const SurfaceCaps& minCaps,
+             SurfaceCaps* const out_configCaps)
+{
+    nsTArray<EGLint> configAttribList;
+    FillContextAttribs(minCaps.alpha, minCaps.depth, minCaps.stencil, minCaps.bpp16,
+                       &configAttribList);
+
+    const EGLint* configAttribs = configAttribList.Elements();
+
+    // We're guaranteed to get at least minCaps, and the sorting dictated by the spec for
+    // eglChooseConfig reasonably assures that a reasonable 'best' config is on top.
+    const EGLint kMaxConfigs = 1;
+    EGLConfig configs[kMaxConfigs];
     EGLint foundConfigs = 0;
-    if (!sEGLLibrary.fChooseConfig(EGL_DISPLAY(),
-                                   kEGLConfigAttribsOffscreenPBuffer,
-                                   configs, numConfigs,
-                                   &foundConfigs)
+    if (!egl->fChooseConfig(egl->Display(), configAttribs, configs, kMaxConfigs,
+                            &foundConfigs)
         || foundConfigs == 0)
     {
-        NS_WARNING("No EGL Config for minimal PBuffer!");
+        return EGL_NO_CONFIG;
+    }
+
+    EGLConfig config = configs[0];
+
+    *out_configCaps = minCaps; // Pick up any preserve, etc.
+    out_configCaps->color = true;
+    out_configCaps->alpha   = bool(GetAttrib(egl, config, LOCAL_EGL_ALPHA_SIZE));
+    out_configCaps->depth   = bool(GetAttrib(egl, config, LOCAL_EGL_DEPTH_SIZE));
+    out_configCaps->stencil = bool(GetAttrib(egl, config, LOCAL_EGL_STENCIL_SIZE));
+    out_configCaps->bpp16 = (GetAttrib(egl, config, LOCAL_EGL_RED_SIZE) < 8);
+
+    return config;
+}
+
+/*static*/ already_AddRefed<GLContextEGL>
+GLContextEGL::CreateEGLPBufferOffscreenContext(const mozilla::gfx::IntSize& size,
+                                               const SurfaceCaps& minCaps)
+{
+    SurfaceCaps configCaps;
+    EGLConfig config = ChooseConfig(&sEGLLibrary, minCaps, &configCaps);
+    if (config == EGL_NO_CONFIG) {
+        NS_WARNING("Failed to find a compatible config.");
         return nullptr;
     }
 
-    // We absolutely don't care, so just pick the first one.
-    config = configs[0];
     if (GLContext::ShouldSpew())
         sEGLLibrary.DumpEGLConfig(config);
 
     mozilla::gfx::IntSize pbSize(size);
-    surface = GLContextEGL::CreatePBufferSurfaceTryingPowerOfTwo(config,
-                                                                 LOCAL_EGL_NONE,
-                                                                 pbSize);
+    EGLSurface surface = GLContextEGL::CreatePBufferSurfaceTryingPowerOfTwo(config,
+                                                                            LOCAL_EGL_NONE,
+                                                                            pbSize);
     if (!surface) {
         NS_WARNING("Failed to create PBuffer for context!");
         return nullptr;
     }
 
-    SurfaceCaps dummyCaps = SurfaceCaps::Any();
-    nsRefPtr<GLContextEGL> glContext =
-        GLContextEGL::CreateGLContext(dummyCaps,
-                                      nullptr, true,
-                                      config, surface);
-    if (!glContext) {
+
+    RefPtr<GLContextEGL> gl = GLContextEGL::CreateGLContext(configCaps, nullptr, true,
+                                                            config, surface);
+    if (!gl) {
         NS_WARNING("Failed to create GLContext from PBuffer");
-        sEGLLibrary.fDestroySurface(EGL_DISPLAY(), surface);
+        sEGLLibrary.fDestroySurface(sEGLLibrary.Display(), surface);
         return nullptr;
     }
 
-    if (!glContext->Init()) {
+    if (!gl->Init()) {
         NS_WARNING("Failed to initialize GLContext!");
         // GLContextEGL::dtor will destroy |surface| for us.
         return nullptr;
     }
 
-    return glContext.forget();
+    return gl.forget();
 }
 
-already_AddRefed<GLContextEGL>
+/*static*/ already_AddRefed<GLContextEGL>
 GLContextEGL::CreateEGLPixmapOffscreenContext(const mozilla::gfx::IntSize& size)
 {
     gfxASurface *thebesSurface = nullptr;
     EGLNativePixmapType pixmap = 0;
 
     if (!pixmap) {
         return nullptr;
     }
@@ -927,59 +1004,87 @@ GLContextEGL::CreateEGLPixmapOffscreenCo
         return nullptr;
     }
 
     glContext->HoldSurface(thebesSurface);
 
     return glContext.forget();
 }
 
-already_AddRefed<GLContext>
+/*static*/ already_AddRefed<GLContext>
 GLContextProviderEGL::CreateHeadless(CreateContextFlags flags)
 {
-    if (!sEGLLibrary.EnsureInitialized(bool(flags & CreateContextFlags::FORCE_ENABLE_HARDWARE))) {
+    bool forceEnableHardware = bool(flags & CreateContextFlags::FORCE_ENABLE_HARDWARE);
+    if (!sEGLLibrary.EnsureInitialized(forceEnableHardware))
         return nullptr;
-    }
 
     mozilla::gfx::IntSize dummySize = mozilla::gfx::IntSize(16, 16);
-    nsRefPtr<GLContext> glContext;
-    glContext = GLContextEGL::CreateEGLPBufferOffscreenContext(dummySize);
-    if (!glContext)
-        return nullptr;
-
-    return glContext.forget();
+    SurfaceCaps dummyCaps = SurfaceCaps::Any();
+    return GLContextEGL::CreateEGLPBufferOffscreenContext(dummySize, dummyCaps);
 }
 
 // Under EGL, on Android, pbuffers are supported fine, though
 // often without the ability to texture from them directly.
-already_AddRefed<GLContext>
+/*static*/ already_AddRefed<GLContext>
 GLContextProviderEGL::CreateOffscreen(const mozilla::gfx::IntSize& size,
-                                      const SurfaceCaps& caps,
+                                      const SurfaceCaps& minCaps,
                                       CreateContextFlags flags)
 {
-    nsRefPtr<GLContext> glContext = CreateHeadless(flags);
-    if (!glContext)
+    bool forceEnableHardware = bool(flags & CreateContextFlags::FORCE_ENABLE_HARDWARE);
+    if (!sEGLLibrary.EnsureInitialized(forceEnableHardware))
         return nullptr;
 
-    if (!glContext->InitOffscreen(size, caps))
+    bool canOffscreenUseHeadless = true;
+    if (sEGLLibrary.IsANGLE()) {
+        // ANGLE needs to use PBuffers.
+        canOffscreenUseHeadless = false;
+    }
+
+    RefPtr<GLContext> gl;
+    SurfaceCaps offscreenCaps = minCaps;
+
+    if (canOffscreenUseHeadless) {
+        gl = CreateHeadless(flags);
+        if (!gl)
+            return nullptr;
+    } else {
+        SurfaceCaps minBackbufferCaps = minCaps;
+        if (minCaps.antialias) {
+            minBackbufferCaps.antialias = false;
+            minBackbufferCaps.depth = false;
+            minBackbufferCaps.stencil = false;
+        }
+
+        gl = GLContextEGL::CreateEGLPBufferOffscreenContext(size, minBackbufferCaps);
+        if (!gl)
+            return nullptr;
+
+        offscreenCaps = gl->Caps();
+        if (minCaps.antialias) {
+            offscreenCaps.depth = minCaps.depth;
+            offscreenCaps.stencil = minCaps.stencil;
+        }
+    }
+
+    if (!gl->InitOffscreen(size, offscreenCaps))
         return nullptr;
 
-    return glContext.forget();
+    return gl.forget();
 }
 
 // Don't want a global context on Android as 1) share groups across 2 threads fail on many Tegra drivers (bug 759225)
 // and 2) some mobile devices have a very strict limit on global number of GL contexts (bug 754257)
 // and 3) each EGL context eats 750k on B2G (bug 813783)
-GLContext*
+/*static*/ GLContext*
 GLContextProviderEGL::GetGlobalContext()
 {
     return nullptr;
 }
 
-void
+/*static*/ void
 GLContextProviderEGL::Shutdown()
 {
 }
 
 } /* namespace gl */
 } /* namespace mozilla */
 
 #undef EGL_ATTRIBS_LIST_SAFE_TERMINATION_WORKING_AROUND_BUGS
--- a/gfx/gl/GLContextProviderGLX.cpp
+++ b/gfx/gl/GLContextProviderGLX.cpp
@@ -1125,159 +1125,167 @@ GLContextProviderGLX::CreateForWindow(ns
                                                                      display,
                                                                      window,
                                                                      cfgs[matchIndex],
                                                                      false);
 
     return glContext.forget();
 }
 
-static already_AddRefed<GLContextGLX>
-CreateOffscreenPixmapContext(const IntSize& size)
+static bool
+ChooseConfig(GLXLibrary* glx, Display* display, int screen, const SurfaceCaps& minCaps,
+             ScopedXFree<GLXFBConfig>* const out_scopedConfigArr,
+             GLXFBConfig* const out_config, int* const out_visid)
 {
-    GLXLibrary& glx = sGLXLibrary;
-    if (!glx.EnsureInitialized()) {
-        return nullptr;
-    }
+    ScopedXFree<GLXFBConfig>& scopedConfigArr = *out_scopedConfigArr;
 
-    Display *display = DefaultXDisplay();
-    int xscreen = DefaultScreen(display);
+    if (minCaps.antialias)
+        return false;
 
     int attribs[] = {
         LOCAL_GLX_DRAWABLE_TYPE, LOCAL_GLX_PIXMAP_BIT,
         LOCAL_GLX_X_RENDERABLE, True,
+        LOCAL_GLX_RED_SIZE, 8,
+        LOCAL_GLX_GREEN_SIZE, 8,
+        LOCAL_GLX_BLUE_SIZE, 8,
+        LOCAL_GLX_ALPHA_SIZE, minCaps.alpha ? 8 : 0,
+        LOCAL_GLX_DEPTH_SIZE, minCaps.depth ? 16 : 0,
+        LOCAL_GLX_STENCIL_SIZE, minCaps.stencil ? 8 : 0,
         0
     };
+
     int numConfigs = 0;
+    scopedConfigArr = glx->xChooseFBConfig(display, screen, attribs, &numConfigs);
+    if (!scopedConfigArr || !numConfigs)
+        return false;
 
-    ScopedXFree<GLXFBConfig> cfgs;
-    cfgs = glx.xChooseFBConfig(display,
-                               xscreen,
-                               attribs,
-                               &numConfigs);
-    if (!cfgs) {
-        return nullptr;
-    }
+    // Issues with glxChooseFBConfig selection and sorting:
+    // * ALPHA_SIZE is sorted as 'largest total RGBA bits first'. If we don't request
+    //   alpha bits, we'll probably get RGBA anyways, since 32 is more than 24.
+    // * DEPTH_SIZE is sorted largest first, including for `0` inputs.
+    // * STENCIL_SIZE is smallest first, but it might return `8` even though we ask for
+    //   `0`.
 
-    MOZ_ASSERT(numConfigs > 0,
-               "glXChooseFBConfig() failed to match our requested format and "
-               "violated its spec!");
-
-    int visid = None;
-    int chosenIndex = 0;
+    // For now, we don't care about these. We *will* care when we do XPixmap sharing.
 
     for (int i = 0; i < numConfigs; ++i) {
-        int dtype;
+        GLXFBConfig curConfig = scopedConfigArr[i];
 
-        if (glx.xGetFBConfigAttrib(display, cfgs[i], LOCAL_GLX_DRAWABLE_TYPE, &dtype) != Success
-            || !(dtype & LOCAL_GLX_PIXMAP_BIT))
-        {
-            continue;
-        }
-        if (glx.xGetFBConfigAttrib(display, cfgs[i], LOCAL_GLX_VISUAL_ID, &visid) != Success
-            || visid == 0)
+        int visid;
+        if (glx->xGetFBConfigAttrib(display, curConfig, LOCAL_GLX_VISUAL_ID, &visid)
+            != Success)
         {
             continue;
         }
 
-        chosenIndex = i;
-        break;
+        if (!visid)
+            continue;
+
+        *out_config = curConfig;
+        *out_visid = visid;
+        return true;
     }
 
-    if (!visid) {
-        NS_WARNING("glXChooseFBConfig() didn't give us any configs with visuals!");
+    return false;
+}
+
+static already_AddRefed<GLContextGLX>
+CreateOffscreenPixmapContext(const IntSize& size, const SurfaceCaps& minCaps)
+{
+    GLXLibrary* glx = &sGLXLibrary;
+    if (!glx->EnsureInitialized())
+        return nullptr;
+
+    Display* display = DefaultXDisplay();
+    int screen = DefaultScreen(display);
+
+    ScopedXFree<GLXFBConfig> scopedConfigArr;
+    GLXFBConfig config;
+    int visid;
+    if (!ChooseConfig(glx, display, screen, minCaps, &scopedConfigArr, &config, &visid)) {
+        NS_WARNING("Failed to find a compatible config.");
         return nullptr;
     }
 
-    Visual *visual;
+    Visual* visual;
     int depth;
     FindVisualAndDepth(display, visid, &visual, &depth);
-    ScopedXErrorHandler xErrorHandler;
-    GLXPixmap glxpixmap = 0;
-    bool error = false;
 
-    IntSize dummySize(16, 16);
-    nsRefPtr<gfxXlibSurface> xsurface = gfxXlibSurface::Create(DefaultScreenOfDisplay(display),
-                                                               visual,
-                                                               dummySize);
-    if (xsurface->CairoStatus() != 0) {
+    ScopedXErrorHandler xErrorHandler;
+    bool error = false;
+    // Must be declared before goto:
+    Drawable drawable;
+    GLXPixmap pixmap;
+
+    gfx::IntSize dummySize(16, 16);
+    RefPtr<gfxXlibSurface> surface = gfxXlibSurface::Create(DefaultScreenOfDisplay(display),
+                                                            visual,
+                                                            dummySize);
+    if (surface->CairoStatus() != 0) {
         error = true;
         goto DONE_CREATING_PIXMAP;
     }
 
     // Handle slightly different signature between glXCreatePixmap and
     // its pre-GLX-1.3 extension equivalent (though given the ABI, we
     // might not need to).
-    if (glx.GLXVersionCheck(1, 3)) {
-        glxpixmap = glx.xCreatePixmap(display,
-                                          cfgs[chosenIndex],
-                                          xsurface->XDrawable(),
-                                          nullptr);
+    drawable = surface->XDrawable();
+    if (glx->GLXVersionCheck(1, 3)) {
+        pixmap = glx->xCreatePixmap(display, config, drawable, nullptr);
     } else {
-        glxpixmap = glx.xCreateGLXPixmapWithConfig(display,
-                                                       cfgs[chosenIndex],
-                                                       xsurface->
-                                                       XDrawable());
+        pixmap = glx->xCreateGLXPixmapWithConfig(display, config, drawable);
     }
-    if (glxpixmap == 0) {
+
+    if (pixmap == 0) {
         error = true;
     }
 
 DONE_CREATING_PIXMAP:
 
-    nsRefPtr<GLContextGLX> glContext;
     bool serverError = xErrorHandler.SyncAndGetError(display);
-
-    if (!error && // earlier recorded error
-        !serverError)
-    {
-        // We might have an alpha channel, but it doesn't matter.
-        SurfaceCaps dummyCaps = SurfaceCaps::Any();
-        GLContextGLX* shareContext = GetGlobalContextGLX();
+    if (error || serverError)
+        return nullptr;
 
-        glContext = GLContextGLX::CreateGLContext(dummyCaps,
-                                                  shareContext,
-                                                  true,
-                                                  display,
-                                                  glxpixmap,
-                                                  cfgs[chosenIndex],
-                                                  true,
-                                                  xsurface);
-    }
-
-    return glContext.forget();
+    GLContextGLX* shareContext = GetGlobalContextGLX();
+    return GLContextGLX::CreateGLContext(minCaps, shareContext, true, display, pixmap,
+                                         config, true, surface);
 }
 
-already_AddRefed<GLContext>
+/*static*/ already_AddRefed<GLContext>
 GLContextProviderGLX::CreateHeadless(CreateContextFlags)
 {
     IntSize dummySize = IntSize(16, 16);
-    nsRefPtr<GLContext> glContext = CreateOffscreenPixmapContext(dummySize);
-    if (!glContext)
-        return nullptr;
-
-    return glContext.forget();
+    SurfaceCaps dummyCaps = SurfaceCaps::Any();
+    return CreateOffscreenPixmapContext(dummySize, dummyCaps);
 }
 
-already_AddRefed<GLContext>
+/*static*/ already_AddRefed<GLContext>
 GLContextProviderGLX::CreateOffscreen(const IntSize& size,
-                                      const SurfaceCaps& caps,
+                                      const SurfaceCaps& minCaps,
                                       CreateContextFlags flags)
 {
-    nsRefPtr<GLContext> glContext = CreateHeadless(flags);
-    if (!glContext)
+    SurfaceCaps minBackbufferCaps = minCaps;
+    if (minCaps.antialias) {
+        minBackbufferCaps.antialias = false;
+        minBackbufferCaps.depth = false;
+        minBackbufferCaps.stencil = false;
+    }
+
+    RefPtr<GLContext> gl;
+    gl = CreateOffscreenPixmapContext(size, minBackbufferCaps);
+    if (!gl)
         return nullptr;
 
-    if (!glContext->InitOffscreen(size, caps))
+    if (!gl->InitOffscreen(size, minCaps))
         return nullptr;
 
-    return glContext.forget();
+    return gl.forget();
 }
 
-GLContext*
+/*static*/ GLContext*
 GLContextProviderGLX::GetGlobalContext()
 {
     static bool checkedContextSharing = false;
     static bool useContextSharing = false;
 
     if (!checkedContextSharing) {
         useContextSharing = getenv("MOZ_DISABLE_CONTEXT_SHARING_GLX") == 0;
         checkedContextSharing = true;
@@ -1288,27 +1296,29 @@ GLContextProviderGLX::GetGlobalContext()
         return nullptr;
     }
 
     static bool triedToCreateContext = false;
     if (!triedToCreateContext && !gGlobalContext) {
         triedToCreateContext = true;
 
         IntSize dummySize = IntSize(16, 16);
+        SurfaceCaps dummyCaps = SurfaceCaps::Any();
         // StaticPtr doesn't support assignments from already_AddRefed,
         // so use a temporary nsRefPtr to make the reference counting
         // fall out correctly.
-        nsRefPtr<GLContext> holder = CreateOffscreenPixmapContext(dummySize);
+        RefPtr<GLContext> holder;
+        holder = CreateOffscreenPixmapContext(dummySize, dummyCaps);
         gGlobalContext = holder;
     }
 
     return gGlobalContext;
 }
 
-void
+/*static*/ void
 GLContextProviderGLX::Shutdown()
 {
     gGlobalContext = nullptr;
 }
 
 } /* namespace gl */
 } /* namespace mozilla */
 
--- a/gfx/gl/GLContextProviderImpl.h
+++ b/gfx/gl/GLContextProviderImpl.h
@@ -49,26 +49,28 @@ public:
      *
      * The offscreen context returned by this method will always have
      * the ability to be rendered into a context created by a window.
      * It might or might not share resources with the global context;
      * query GetSharedContext() for a non-null result to check.  If
      * resource sharing can be avoided on the target platform, it will
      * be, in order to isolate the offscreen context.
      *
-     * @param size The initial size of this offscreen context.
-     * @param caps The SurfaceCaps for this offscreen context.
-     * @param flags The set of CreateContextFlags to be used for this
-     *              offscreen context.
+     * @param size    The initial size of this offscreen context.
+     * @param minCaps The required SurfaceCaps for this offscreen context. The resulting
+     *                context *may* have more/better caps than requested, but it cannot
+     *                have fewer/worse caps than requested.
+     * @param flags   The set of CreateContextFlags to be used for this
+     *                offscreen context.
      *
      * @return Context to use for offscreen rendering
      */
     static already_AddRefed<GLContext>
     CreateOffscreen(const mozilla::gfx::IntSize& size,
-                    const SurfaceCaps& caps,
+                    const SurfaceCaps& minCaps,
                     CreateContextFlags flags);
 
     // Just create a context. We'll add offscreen stuff ourselves.
     static already_AddRefed<GLContext>
     CreateHeadless(CreateContextFlags flags);
 
     /**
      * Create wrapping Gecko GLContext for external gl context.
--- a/gfx/gl/GLContextProviderWGL.cpp
+++ b/gfx/gl/GLContextProviderWGL.cpp
@@ -601,17 +601,17 @@ CreateWindowOffscreenContext()
     SurfaceCaps caps = SurfaceCaps::ForRGBA();
     nsRefPtr<GLContextWGL> glContext = new GLContextWGL(caps,
                                                         shareContext, true,
                                                         dc, context, win);
 
     return glContext.forget();
 }
 
-already_AddRefed<GLContext>
+/*static*/ already_AddRefed<GLContext>
 GLContextProviderWGL::CreateHeadless(CreateContextFlags)
 {
     if (!sWGLLib.EnsureInitialized()) {
         return nullptr;
     }
 
     nsRefPtr<GLContextWGL> glContext;
 
@@ -634,34 +634,34 @@ GLContextProviderWGL::CreateHeadless(Cre
     {
         return nullptr;
     }
 
     nsRefPtr<GLContext> retGL = glContext.get();
     return retGL.forget();
 }
 
-already_AddRefed<GLContext>
+/*static*/ already_AddRefed<GLContext>
 GLContextProviderWGL::CreateOffscreen(const IntSize& size,
-                                      const SurfaceCaps& caps,
+                                      const SurfaceCaps& minCaps,
                                       CreateContextFlags flags)
 {
-    nsRefPtr<GLContext> glContext = CreateHeadless(flags);
-    if (!glContext)
+    RefPtr<GLContext> gl = CreateHeadless(flags);
+    if (!gl)
         return nullptr;
 
-    if (!glContext->InitOffscreen(size, caps))
+    if (!gl->InitOffscreen(size, minCaps))
         return nullptr;
 
-    return glContext.forget();
+    return gl.forget();
 }
 
 static nsRefPtr<GLContextWGL> gGlobalContext;
 
-GLContext *
+/*static*/ GLContext*
 GLContextProviderWGL::GetGlobalContext()
 {
     if (!sWGLLib.EnsureInitialized()) {
         return nullptr;
     }
 
     static bool triedToCreateContext = false;
 
@@ -679,16 +679,16 @@ GLContextProviderWGL::GetGlobalContext()
             gGlobalContext = nullptr;
             return nullptr;
         }
     }
 
     return static_cast<GLContext*>(gGlobalContext);
 }
 
-void
+/*static*/ void
 GLContextProviderWGL::Shutdown()
 {
     gGlobalContext = nullptr;
 }
 
 } /* namespace gl */
 } /* namespace mozilla */
--- a/gfx/gl/GLContextTypes.h
+++ b/gfx/gl/GLContextTypes.h
@@ -2,16 +2,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef GLCONTEXT_TYPES_H_
 #define GLCONTEXT_TYPES_H_
 
 #include "GLTypes.h"
+#include "mozilla/TypedEnumBits.h"
 
 namespace mozilla {
 namespace gl {
 
 class GLContext;
 
 enum class GLContextType {
     Unknown,
@@ -38,12 +39,22 @@ struct GLFormats
 
     GLenum depthStencil;
     GLenum depth;
     GLenum stencil;
 
     GLsizei samples;
 };
 
+enum class CreateContextFlags : int8_t {
+    NONE = 0,
+    REQUIRE_COMPAT_PROFILE = 1 << 0,
+    // Force the use of hardware backed GL, don't allow software implementations.
+    FORCE_ENABLE_HARDWARE = 1 << 1,
+    /* Don't force discrete GPU to be used (if applicable) */
+    ALLOW_OFFLINE_RENDERER =  1 << 2,
+};
+MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(CreateContextFlags)
+
 } /* namespace gl */
 } /* namespace mozilla */
 
 #endif /* GLCONTEXT_TYPES_H_ */
--- a/gfx/gl/GLLibraryEGL.h
+++ b/gfx/gl/GLLibraryEGL.h
@@ -12,50 +12,42 @@
 #include "GLLibraryLoader.h"
 #include "mozilla/ThreadLocal.h"
 #include "nsIFile.h"
 #include "GeckoProfiler.h"
 
 #include <bitset>
 #include <vector>
 
-#if defined(XP_WIN)
-
-#ifndef WIN32_LEAN_AND_MEAN
-#define WIN32_LEAN_AND_MEAN 1
-#endif
+#ifdef XP_WIN
+    #ifndef WIN32_LEAN_AND_MEAN
+        #define WIN32_LEAN_AND_MEAN 1
+    #endif
 
-#include <windows.h>
+    #include <windows.h>
 
-typedef HDC EGLNativeDisplayType;
-typedef HBITMAP EGLNativePixmapType;
-typedef HWND EGLNativeWindowType;
-
-#define GET_NATIVE_WINDOW(aWidget) ((EGLNativeWindowType)aWidget->GetNativeData(NS_NATIVE_WINDOW))
-
+    typedef HDC EGLNativeDisplayType;
+    typedef HBITMAP EGLNativePixmapType;
+    typedef HWND EGLNativeWindowType;
 #else
-typedef void *EGLNativeDisplayType;
-typedef void *EGLNativePixmapType;
-typedef void *EGLNativeWindowType;
+    typedef void* EGLNativeDisplayType;
+    typedef void* EGLNativePixmapType;
+    typedef void* EGLNativeWindowType;
 
-#ifdef ANDROID
-// We only need to explicitly dlopen egltrace
-// on android as we can use LD_PRELOAD or other tricks
-// on other platforms. We look for it in /data/local
-// as that's writeable by all users
-//
-// This should really go in GLLibraryEGL.cpp but we currently reference
-// APITRACE_LIB in GLContextProviderEGL.cpp. Further refactoring
-// will come in subsequent patches on Bug 732865
-#define APITRACE_LIB "/data/local/tmp/egltrace.so"
-
-#ifdef MOZ_WIDGET_ANDROID
-
-#endif // MOZ_WIDGET_ANDROID
-#endif // ANDROID
+    #ifdef ANDROID
+        // We only need to explicitly dlopen egltrace
+        // on android as we can use LD_PRELOAD or other tricks
+        // on other platforms. We look for it in /data/local
+        // as that's writeable by all users
+        //
+        // This should really go in GLLibraryEGL.cpp but we currently reference
+        // APITRACE_LIB in GLContextProviderEGL.cpp. Further refactoring
+        // will come in subsequent patches on Bug 732865
+        #define APITRACE_LIB "/data/local/tmp/egltrace.so"
+    #endif
 #endif
 
 #if defined(MOZ_X11)
 #define EGL_DEFAULT_DISPLAY  ((EGLNativeDisplayType)mozilla::DefaultXDisplay())
 #else
 #define EGL_DEFAULT_DISPLAY  ((EGLNativeDisplayType)0)
 #endif
 
--- a/gfx/gl/GLScreenBuffer.cpp
+++ b/gfx/gl/GLScreenBuffer.cpp
@@ -481,19 +481,26 @@ GLScreenBuffer::Swap(const gfx::IntSize&
         !mDraw)
     {
         auto src  = mFront->Surf();
         auto dest = mBack->Surf();
 
         //uint32_t srcPixel = ReadPixel(src);
         //uint32_t destPixel = ReadPixel(dest);
         //printf_stderr("Before: src: 0x%08x, dest: 0x%08x\n", srcPixel, destPixel);
+#ifdef DEBUG
+        GLContext::LocalErrorScope errorScope(*mGL);
+#endif
 
         SharedSurface::ProdCopy(src, dest, mFactory.get());
 
+#ifdef DEBUG
+        MOZ_ASSERT(!errorScope.GetError());
+#endif
+
         //srcPixel = ReadPixel(src);
         //destPixel = ReadPixel(dest);
         //printf_stderr("After: src: 0x%08x, dest: 0x%08x\n", srcPixel, destPixel);
     }
 
     // XXX: We would prefer to fence earlier on platforms that don't need
     // the full ProducerAcquire/ProducerRelease semantics, so that the fence
     // doesn't include the copy operation. Unfortunately, the current API
--- a/gfx/gl/GLXLibrary.h
+++ b/gfx/gl/GLXLibrary.h
@@ -16,16 +16,17 @@ typedef XID GLXPixmap;
 typedef XID GLXDrawable;
 /* GLX 1.3 and later */
 typedef struct __GLXFBConfigRec *GLXFBConfig;
 typedef XID GLXFBConfigID;
 typedef XID GLXContextID;
 typedef XID GLXWindow;
 typedef XID GLXPbuffer;
 // end of stuff from glx.h
+#include "prenv.h"
 
 struct PRLibrary;
 class gfxASurface;
 
 namespace mozilla {
 namespace gl {
 
 class GLXLibrary
@@ -103,16 +104,22 @@ public:
     void ReleaseTexImage(Display* aDisplay, GLXPixmap aPixmap);
     void UpdateTexImage(Display* aDisplay, GLXPixmap aPixmap);
 
     bool UseTextureFromPixmap() { return mUseTextureFromPixmap; }
     bool HasRobustness() { return mHasRobustness; }
     bool SupportsTextureFromPixmap(gfxASurface* aSurface);
     bool IsATI() { return mIsATI; }
     bool GLXVersionCheck(int aMajor, int aMinor);
+    bool UseSurfaceSharing() {
+      // Disable surface sharing due to issues with compatible FBConfigs on
+      // NVIDIA drivers as described in bug 1193015.
+      static bool useSharing = PR_GetEnv("MOZ_GLX_USE_SURFACE_SHARING");
+      return mUseTextureFromPixmap && useSharing;
+    }
 
 private:
     
     typedef void (GLAPIENTRY * PFNGLXDESTROYCONTEXTPROC) (Display*,
                                                           GLXContext);
     PFNGLXDESTROYCONTEXTPROC xDestroyContextInternal;
     typedef Bool (GLAPIENTRY * PFNGLXMAKECURRENTPROC) (Display*,
                                                        GLXDrawable,
--- a/gfx/gl/SharedSurfaceANGLE.cpp
+++ b/gfx/gl/SharedSurfaceANGLE.cpp
@@ -36,27 +36,24 @@ CreatePBufferSurface(GLLibraryEGL* egl,
     EGLint err = egl->fGetError();
     if (err != LOCAL_EGL_SUCCESS)
         return 0;
 
     return surface;
 }
 
 /*static*/ UniquePtr<SharedSurface_ANGLEShareHandle>
-SharedSurface_ANGLEShareHandle::Create(GLContext* gl,
-                                       EGLContext context, EGLConfig config,
+SharedSurface_ANGLEShareHandle::Create(GLContext* gl, EGLConfig config,
                                        const gfx::IntSize& size, bool hasAlpha)
 {
     GLLibraryEGL* egl = &sEGLLibrary;
     MOZ_ASSERT(egl);
     MOZ_ASSERT(egl->IsExtensionSupported(
                GLLibraryEGL::ANGLE_surface_d3d_texture_2d_share_handle));
-
-    if (!context || !config)
-        return nullptr;
+    MOZ_ASSERT(config);
 
     EGLDisplay display = egl->Display();
     EGLSurface pbuffer = CreatePBufferSurface(egl, display, config, size);
     if (!pbuffer)
         return nullptr;
 
     // Declare everything before 'goto's.
     HANDLE shareHandle = nullptr;
@@ -77,44 +74,42 @@ SharedSurface_ANGLEShareHandle::Create(G
 
     GLuint fence = 0;
     if (gl->IsExtensionSupported(GLContext::NV_fence)) {
         gl->MakeCurrent();
         gl->fGenFences(1, &fence);
     }
 
     typedef SharedSurface_ANGLEShareHandle ptrT;
-    UniquePtr<ptrT> ret( new ptrT(gl, egl, size, hasAlpha, context,
-                                  pbuffer, shareHandle, keyedMutex, fence) );
+    UniquePtr<ptrT> ret( new ptrT(gl, egl, size, hasAlpha, pbuffer, shareHandle,
+                                  keyedMutex, fence) );
     return Move(ret);
 }
 
 EGLDisplay
 SharedSurface_ANGLEShareHandle::Display()
 {
     return mEGL->Display();
 }
 
 SharedSurface_ANGLEShareHandle::SharedSurface_ANGLEShareHandle(GLContext* gl,
                                                                GLLibraryEGL* egl,
                                                                const gfx::IntSize& size,
                                                                bool hasAlpha,
-                                                               EGLContext context,
                                                                EGLSurface pbuffer,
                                                                HANDLE shareHandle,
                                                                const RefPtr<IDXGIKeyedMutex>& keyedMutex,
                                                                GLuint fence)
     : SharedSurface(SharedSurfaceType::EGLSurfaceANGLE,
                     AttachmentType::Screen,
                     gl,
                     size,
                     hasAlpha,
                     true)
     , mEGL(egl)
-    , mContext(context)
     , mPBuffer(pbuffer)
     , mShareHandle(shareHandle)
     , mKeyedMutex(keyedMutex)
     , mFence(fence)
 {
 }
 
 
@@ -276,186 +271,42 @@ SharedSurface_ANGLEShareHandle::ToSurfac
     *out_descriptor = layers::SurfaceDescriptorD3D10((WindowsHandle)mShareHandle, format,
                                                      mSize);
     return true;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // Factory
 
-static void
-FillPBufferAttribs_ByBits(nsTArray<EGLint>& aAttrs,
-                          int redBits, int greenBits,
-                          int blueBits, int alphaBits,
-                          int depthBits, int stencilBits)
-{
-    aAttrs.Clear();
-
-#if defined(A1) || defined(A2)
-#error The temp-macro names we want are already defined.
-#endif
-
-#define A1(_x)      do { aAttrs.AppendElement(_x); } while (0)
-#define A2(_x,_y)   do { A1(_x); A1(_y); } while (0)
-
-    A2(LOCAL_EGL_RENDERABLE_TYPE, LOCAL_EGL_OPENGL_ES2_BIT);
-    A2(LOCAL_EGL_SURFACE_TYPE, LOCAL_EGL_PBUFFER_BIT);
-
-    A2(LOCAL_EGL_RED_SIZE, redBits);
-    A2(LOCAL_EGL_GREEN_SIZE, greenBits);
-    A2(LOCAL_EGL_BLUE_SIZE, blueBits);
-    A2(LOCAL_EGL_ALPHA_SIZE, alphaBits);
-
-    A2(LOCAL_EGL_DEPTH_SIZE, depthBits);
-    A2(LOCAL_EGL_STENCIL_SIZE, stencilBits);
-
-    A1(LOCAL_EGL_NONE);
-#undef A1
-#undef A2
-}
-
-static void
-FillPBufferAttribs_BySizes(nsTArray<EGLint>& attribs,
-                           bool bpp16, bool hasAlpha,
-                           int depthBits, int stencilBits)
-{
-    int red = 0;
-    int green = 0;
-    int blue = 0;
-    int alpha = 0;
-
-    if (bpp16) {
-        if (hasAlpha) {
-            red = green = blue = alpha = 4;
-        } else {
-            red = 5;
-            green = 6;
-            blue = 5;
-        }
-    } else {
-        red = green = blue = 8;
-        if (hasAlpha)
-            alpha = 8;
-    }
-
-    FillPBufferAttribs_ByBits(attribs, red, green, blue, alpha, depthBits,
-                              stencilBits);
-}
-
-static bool
-DoesAttribBitsMatchCapBool(GLLibraryEGL* egl, EGLConfig config, EGLint attrib,
-                           bool capBool)
-{
-    EGLint bits = 0;
-    egl->fGetConfigAttrib(egl->Display(), config, attrib, &bits);
-    MOZ_ASSERT(egl->fGetError() == LOCAL_EGL_SUCCESS);
-
-    bool hasBits = !!bits;
-
-    return hasBits == capBool;
-}
-
-static EGLConfig
-ChooseConfig(GLContext* gl, GLLibraryEGL* egl, const SurfaceCaps& caps)
-{
-    MOZ_ASSERT(egl);
-    MOZ_ASSERT(caps.color);
-
-    // We might want 24-bit depth, but we're only (fairly) sure to get 16-bit.
-    int depthBits = caps.depth ? 16 : 0;
-    int stencilBits = caps.stencil ? 8 : 0;
-
-    // Ok, now we have everything.
-    nsTArray<EGLint> attribs(32);
-    FillPBufferAttribs_BySizes(attribs, caps.bpp16, caps.alpha, depthBits,
-                               stencilBits);
-
-    // Time to try to get this config:
-    EGLConfig configs[64];
-    int numConfigs = sizeof(configs)/sizeof(EGLConfig);
-    int foundConfigs = 0;
-
-    if (!egl->fChooseConfig(egl->Display(), attribs.Elements(), configs,
-                            numConfigs, &foundConfigs) ||
-        !foundConfigs)
-    {
-        NS_WARNING("No configs found for the requested formats.");
-        return EGL_NO_CONFIG;
-    }
-
-    // The requests passed to ChooseConfig are treated as minimums. If you ask
-    // for 0 bits of alpha, we might still get 8 bits.
-    EGLConfig config = EGL_NO_CONFIG;
-    for (int i = 0; i < foundConfigs; i++) {
-        EGLConfig cur = configs[i];
-        if (!DoesAttribBitsMatchCapBool(egl, cur, LOCAL_EGL_ALPHA_SIZE,
-                                        caps.alpha) ||
-            !DoesAttribBitsMatchCapBool(egl, cur, LOCAL_EGL_DEPTH_SIZE,
-                                        caps.depth) ||
-            !DoesAttribBitsMatchCapBool(egl, cur, LOCAL_EGL_STENCIL_SIZE,
-                                        caps.stencil))
-        {
-            continue;
-        }
-
-        config = cur;
-        break;
-    }
-
-    if (config == EGL_NO_CONFIG) {
-        NS_WARNING("No acceptable EGLConfig found.");
-        return EGL_NO_CONFIG;
-    }
-
-    if (gl->DebugMode()) {
-        egl->DumpEGLConfig(config);
-    }
-
-    return config;
-}
-
 /*static*/ UniquePtr<SurfaceFactory_ANGLEShareHandle>
 SurfaceFactory_ANGLEShareHandle::Create(GLContext* gl, const SurfaceCaps& caps,
                                         const RefPtr<layers::ISurfaceAllocator>& allocator,
                                         const layers::TextureFlags& flags)
 {
     GLLibraryEGL* egl = &sEGLLibrary;
     if (!egl)
         return nullptr;
 
     auto ext = GLLibraryEGL::ANGLE_surface_d3d_texture_2d_share_handle;
     if (!egl->IsExtensionSupported(ext))
         return nullptr;
 
-    bool success;
-    typedef SurfaceFactory_ANGLEShareHandle ptrT;
-    UniquePtr<ptrT> ret( new ptrT(gl, caps, allocator, flags, egl, &success) );
+    EGLConfig config = GLContextEGL::Cast(gl)->mConfig;
 
-    if (!success)
-        return nullptr;
-
+    typedef SurfaceFactory_ANGLEShareHandle ptrT;
+    UniquePtr<ptrT> ret( new ptrT(gl, caps, allocator, flags, egl, config) );
     return Move(ret);
 }
 
 SurfaceFactory_ANGLEShareHandle::SurfaceFactory_ANGLEShareHandle(GLContext* gl,
                                                                  const SurfaceCaps& caps,
                                                                  const RefPtr<layers::ISurfaceAllocator>& allocator,
                                                                  const layers::TextureFlags& flags,
                                                                  GLLibraryEGL* egl,
-                                                                 bool* const out_success)
+                                                                 EGLConfig config)
     : SurfaceFactory(SharedSurfaceType::EGLSurfaceANGLE, gl, caps, allocator, flags)
     , mProdGL(gl)
     , mEGL(egl)
-{
-    MOZ_ASSERT(out_success);
-    *out_success = false;
-
-    mContext = GLContextEGL::Cast(mProdGL)->GetEGLContext();
-    mConfig = ChooseConfig(mProdGL, mEGL, mReadCaps);
-    if (mConfig == EGL_NO_CONFIG)
-        return;
-
-    MOZ_ASSERT(mConfig && mContext);
-    *out_success = true;
-}
+    , mConfig(config)
+{ }
 
 } /* namespace gl */
 } /* namespace mozilla */
--- a/gfx/gl/SharedSurfaceANGLE.h
+++ b/gfx/gl/SharedSurfaceANGLE.h
@@ -18,45 +18,42 @@ namespace gl {
 class GLContext;
 class GLLibraryEGL;
 
 class SharedSurface_ANGLEShareHandle
     : public SharedSurface
 {
 public:
     static UniquePtr<SharedSurface_ANGLEShareHandle> Create(GLContext* gl,
-                                                            EGLContext context,
                                                             EGLConfig config,
                                                             const gfx::IntSize& size,
                                                             bool hasAlpha);
 
     static SharedSurface_ANGLEShareHandle* Cast(SharedSurface* surf) {
         MOZ_ASSERT(surf->mType == SharedSurfaceType::EGLSurfaceANGLE);
 
         return (SharedSurface_ANGLEShareHandle*)surf;
     }
 
 protected:
     GLLibraryEGL* const mEGL;
-    const EGLContext mContext;
     const EGLSurface mPBuffer;
 public:
     const HANDLE mShareHandle;
 protected:
     RefPtr<IDXGIKeyedMutex> mKeyedMutex;
     RefPtr<IDXGIKeyedMutex> mConsumerKeyedMutex;
     RefPtr<ID3D11Texture2D> mConsumerTexture;
 
     const GLuint mFence;
 
     SharedSurface_ANGLEShareHandle(GLContext* gl,
                                    GLLibraryEGL* egl,
                                    const gfx::IntSize& size,
                                    bool hasAlpha,
-                                   EGLContext context,
                                    EGLSurface pbuffer,
                                    HANDLE shareHandle,
                                    const RefPtr<IDXGIKeyedMutex>& keyedMutex,
                                    GLuint fence);
 
     EGLDisplay Display();
 
 public:
@@ -89,35 +86,32 @@ public:
 
 
 class SurfaceFactory_ANGLEShareHandle
     : public SurfaceFactory
 {
 protected:
     GLContext* const mProdGL;
     GLLibraryEGL* const mEGL;
-    EGLContext mContext;
-    EGLConfig mConfig;
+    const EGLConfig mConfig;
 
 public:
     static UniquePtr<SurfaceFactory_ANGLEShareHandle> Create(GLContext* gl,
                                                              const SurfaceCaps& caps,
                                                              const RefPtr<layers::ISurfaceAllocator>& allocator,
                                                              const layers::TextureFlags& flags);
 
 protected:
     SurfaceFactory_ANGLEShareHandle(GLContext* gl, const SurfaceCaps& caps,
                                     const RefPtr<layers::ISurfaceAllocator>& allocator,
                                     const layers::TextureFlags& flags, GLLibraryEGL* egl,
-                                    bool* const out_success);
+                                    EGLConfig config);
 
     virtual UniquePtr<SharedSurface> CreateShared(const gfx::IntSize& size) override {
         bool hasAlpha = mReadCaps.alpha;
-        return SharedSurface_ANGLEShareHandle::Create(mProdGL,
-                                                      mContext, mConfig,
-                                                      size, hasAlpha);
+        return SharedSurface_ANGLEShareHandle::Create(mProdGL, mConfig, size, hasAlpha);
     }
 };
 
 } /* namespace gfx */
 } /* namespace mozilla */
 
 #endif /* SHARED_SURFACE_ANGLE_H_ */
--- a/gfx/gl/SharedSurfaceEGL.cpp
+++ b/gfx/gl/SharedSurfaceEGL.cpp
@@ -215,17 +215,17 @@ SharedSurface_EGLImage::ToSurfaceDescrip
 
 ////////////////////////////////////////////////////////////////////////
 
 /*static*/ UniquePtr<SurfaceFactory_EGLImage>
 SurfaceFactory_EGLImage::Create(GLContext* prodGL, const SurfaceCaps& caps,
                                 const RefPtr<layers::ISurfaceAllocator>& allocator,
                                 const layers::TextureFlags& flags)
 {
-    EGLContext context = GLContextEGL::Cast(prodGL)->GetEGLContext();
+    EGLContext context = GLContextEGL::Cast(prodGL)->mContext;
 
     typedef SurfaceFactory_EGLImage ptrT;
     UniquePtr<ptrT> ret;
 
     GLLibraryEGL* egl = &sEGLLibrary;
     if (SharedSurface_EGLImage::HasExtensions(egl, prodGL)) {
         ret.reset( new ptrT(prodGL, caps, allocator, flags, context) );
     }
--- a/gfx/gl/moz.build
+++ b/gfx/gl/moz.build
@@ -66,17 +66,17 @@ if CONFIG['MOZ_X11']:
 # Win32 is a special snowflake, for ANGLE
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
     EXPORTS += [
         'GLContextWGL.h',
         'SharedSurfaceANGLE.h', # Needs <windows.h> for `HANDLE`.
         'WGLLibrary.h',
     ]
     UNIFIED_SOURCES += [
-        'GLContextProviderEGL.cpp',
+        'GLContextProviderWGL.cpp',
         'SharedSurfaceANGLE.cpp',
     ]
 if CONFIG['MOZ_ENABLE_SKIA_GPU']:
     EXPORTS += ['SkiaGLGlue.h']
     UNIFIED_SOURCES += [
         'SkiaGLGlue.cpp',
     ]
 
@@ -108,30 +108,27 @@ elif gl_provider == 'GLX':
     # as it includes X11 headers which cause conflicts.
     SOURCES += [
         'GLContextProviderGLX.cpp',
         'SharedSurfaceGLX.cpp'
     ]
     EXPORTS += [
         'SharedSurfaceGLX.h'
     ]
-else:
-    UNIFIED_SOURCES += [
-        'GLContextProvider%s.cpp' % gl_provider,
-    ]
 
 UNIFIED_SOURCES += [
     'AndroidNativeWindow.cpp',
     'AndroidSurfaceTexture.cpp',
     'DecomposeIntoNoRepeatTriangles.cpp',
     'EGLUtils.cpp',
     'GfxTexturesReporter.cpp',
     'GLBlitHelper.cpp',
     'GLContext.cpp',
     'GLContextFeatures.cpp',
+    'GLContextProviderEGL.cpp',
     'GLContextTypes.cpp',
     'GLDebugUtils.cpp',
     'GLLibraryEGL.cpp',
     'GLLibraryLoader.cpp',
     'GLReadTexImageHelper.cpp',
     'GLScreenBuffer.cpp',
     'GLTextureImage.cpp',
     'GLUploadHelpers.cpp',
--- a/gfx/layers/basic/BasicLayerManager.cpp
+++ b/gfx/layers/basic/BasicLayerManager.cpp
@@ -579,17 +579,17 @@ BasicLayerManager::EndTransactionInterna
 
 void
 BasicLayerManager::FlashWidgetUpdateArea(gfxContext *aContext)
 {
   if (gfxPrefs::WidgetUpdateFlashing()) {
     float r = float(rand()) / RAND_MAX;
     float g = float(rand()) / RAND_MAX;
     float b = float(rand()) / RAND_MAX;
-    aContext->SetColor(gfxRGBA(r, g, b, 0.2));
+    aContext->SetColor(Color(r, g, b, 0.2f));
     aContext->Paint();
   }
 }
 
 bool
 BasicLayerManager::EndEmptyTransaction(EndTransactionFlags aFlags)
 {
   mInTransaction = false;
@@ -999,20 +999,19 @@ BasicLayerManager::PaintLayer(gfxContext
 
     // Temporary fast fix for bug 725886
     // Revert these changes when 725886 is ready
     MOZ_ASSERT(untransformedDT,
                "We should always allocate an untransformed surface with 3d transforms!");
     gfxRect destRect;
 #ifdef DEBUG
     if (aLayer->GetDebugColorIndex() != 0) {
-      gfxRGBA  color((aLayer->GetDebugColorIndex() & 1) ? 1.0 : 0.0,
-                     (aLayer->GetDebugColorIndex() & 2) ? 1.0 : 0.0,
-                     (aLayer->GetDebugColorIndex() & 4) ? 1.0 : 0.0,
-                     1.0);
+      Color color((aLayer->GetDebugColorIndex() & 1) ? 1.f : 0.f,
+                  (aLayer->GetDebugColorIndex() & 2) ? 1.f : 0.f,
+                  (aLayer->GetDebugColorIndex() & 4) ? 1.f : 0.f);
 
       nsRefPtr<gfxContext> temp = new gfxContext(untransformedDT, Point(bounds.x, bounds.y));
       temp->SetColor(color);
       temp->Paint();
     }
 #endif
     Matrix4x4 effectiveTransform = aLayer->GetEffectiveTransform();
     nsRefPtr<gfxASurface> result =
--- a/gfx/layers/client/ClientCanvasLayer.cpp
+++ b/gfx/layers/client/ClientCanvasLayer.cpp
@@ -87,17 +87,17 @@ ClientCanvasLayer::Initialize(const Data
   if (!gfxPrefs::WebGLForceLayersReadback()) {
     switch (forwarder->GetCompositorBackendType()) {
       case mozilla::layers::LayersBackend::LAYERS_OPENGL: {
 #if defined(XP_MACOSX)
         factory = SurfaceFactory_IOSurface::Create(mGLContext, caps, forwarder, mFlags);
 #elif defined(MOZ_WIDGET_GONK)
         factory = MakeUnique<SurfaceFactory_Gralloc>(mGLContext, caps, forwarder, mFlags);
 #elif defined(GL_PROVIDER_GLX)
-        if (sGLXLibrary.UseTextureFromPixmap())
+        if (sGLXLibrary.UseSurfaceSharing())
           factory = SurfaceFactory_GLXDrawable::Create(mGLContext, caps, forwarder, mFlags);
 #else
         if (mGLContext->GetContextType() == GLContextType::EGL) {
           if (XRE_IsParentProcess()) {
             factory = SurfaceFactory_EGLImage::Create(mGLContext, caps, forwarder,
                                                       mFlags);
           }
         }
--- a/gfx/layers/client/TiledContentClient.cpp
+++ b/gfx/layers/client/TiledContentClient.cpp
@@ -41,39 +41,39 @@
 #include <sstream>
 using mozilla::layers::Layer;
 static void DrawDebugOverlay(mozilla::gfx::DrawTarget* dt, int x, int y, int width, int height)
 {
   gfxContext c(dt);
 
   // Draw border
   c.NewPath();
-  c.SetDeviceColor(gfxRGBA(0.0, 0.0, 0.0, 1.0));
+  c.SetDeviceColor(Color(0.f, 0.f, 0.f));
   c.Rectangle(gfxRect(0, 0, width, height));
   c.Stroke();
 
   // Build tile description
   std::stringstream ss;
   ss << x << ", " << y;
 
   // Draw text using cairo toy text API
   cairo_t* cr = c.GetCairo();
   cairo_set_font_size(cr, 25);
   cairo_text_extents_t extents;
   cairo_text_extents(cr, ss.str().c_str(), &extents);
 
   int textWidth = extents.width + 6;
 
   c.NewPath();
-  c.SetDeviceColor(gfxRGBA(0.0, 0.0, 0.0, 1.0));
+  c.SetDeviceColor(Color(0.f, 0.f, 0.f));
   c.Rectangle(gfxRect(gfxPoint(2,2),gfxSize(textWidth, 30)));
   c.Fill();
 
   c.NewPath();
-  c.SetDeviceColor(gfxRGBA(1.0, 0.0, 0.0, 1.0));
+  c.SetDeviceColor(Color(1.0, 0.0, 0.0));
   c.Rectangle(gfxRect(gfxPoint(2,2),gfxSize(textWidth, 30)));
   c.Stroke();
 
   c.NewPath();
   cairo_move_to(cr, 4, 28);
   cairo_show_text(cr, ss.str().c_str());
 
 }
--- a/gfx/src/nsSize.h
+++ b/gfx/src/nsSize.h
@@ -9,17 +9,16 @@
 #include "nsCoord.h"
 #include "mozilla/gfx/BaseSize.h"
 #include "mozilla/gfx/Point.h"
 
 // Maximum allowable size
 #define NS_MAXSIZE nscoord_MAX
 
 typedef mozilla::gfx::IntSize nsIntSize;
-typedef nsIntSize gfxIntSize;
 
 struct nsSize : public mozilla::gfx::BaseSize<nscoord, nsSize> {
   typedef mozilla::gfx::BaseSize<nscoord, nsSize> Super;
 
   nsSize() : Super() {}
   nsSize(nscoord aWidth, nscoord aHeight) : Super(aWidth, aHeight) {}
 
   inline mozilla::gfx::IntSize ScaleToNearestPixels(float aXScale, float aYScale,
--- a/gfx/thebes/gfx2DGlue.h
+++ b/gfx/thebes/gfx2DGlue.h
@@ -35,17 +35,17 @@ inline Rect ToRect(const IntRect &aRect)
 }
 
 inline Color ToColor(const gfxRGBA &aRGBA)
 {
   return Color(Float(aRGBA.r), Float(aRGBA.g),
                Float(aRGBA.b), Float(aRGBA.a));
 }
 
-inline gfxRGBA ThebesColor(Color &aColor)
+inline gfxRGBA ThebesColor(const Color &aColor)
 {
   return gfxRGBA(aColor.r, aColor.g, aColor.b, aColor.a);
 }
 
 inline Matrix ToMatrix(const gfxMatrix &aMatrix)
 {
   return Matrix(Float(aMatrix._11), Float(aMatrix._12), Float(aMatrix._21),
                 Float(aMatrix._22), Float(aMatrix._31), Float(aMatrix._32));
--- a/gfx/thebes/gfxBlur.cpp
+++ b/gfx/thebes/gfxBlur.cpp
@@ -165,68 +165,109 @@ struct BlurCacheKey : public PLDHashEntr
   typedef const BlurCacheKey* KeyTypePointer;
   enum { ALLOW_MEMMOVE = true };
 
   IntSize mMinSize;
   IntSize mBlurRadius;
   gfxRGBA mShadowColor;
   BackendType mBackend;
   RectCornerRadii mCornerRadii;
+  bool mIsInset;
 
-  BlurCacheKey(IntSize aMinimumSize, gfxIntSize aBlurRadius,
+  // Only used for inset blurs
+  bool mHasBorderRadius;
+  IntSize mSpreadRadius;
+  IntSize mInnerMinSize;
+
+  BlurCacheKey(IntSize aMinSize, IntSize aBlurRadius,
                RectCornerRadii* aCornerRadii, gfxRGBA aShadowColor,
-               BackendType aBackend)
-    : mMinSize(aMinimumSize)
-    , mBlurRadius(aBlurRadius)
-    , mShadowColor(aShadowColor)
-    , mBackend(aBackend)
-    , mCornerRadii(aCornerRadii ? *aCornerRadii : RectCornerRadii())
-  { }
+               BackendType aBackendType)
+    : BlurCacheKey(aMinSize, IntSize(0, 0),
+                   aBlurRadius, IntSize(0, 0),
+                   aCornerRadii, aShadowColor,
+                   false, false, aBackendType)
+  {}
 
   explicit BlurCacheKey(const BlurCacheKey* aOther)
     : mMinSize(aOther->mMinSize)
     , mBlurRadius(aOther->mBlurRadius)
     , mShadowColor(aOther->mShadowColor)
     , mBackend(aOther->mBackend)
     , mCornerRadii(aOther->mCornerRadii)
+    , mIsInset(aOther->mIsInset)
+    , mHasBorderRadius(aOther->mHasBorderRadius)
+    , mSpreadRadius(aOther->mSpreadRadius)
+    , mInnerMinSize(aOther->mInnerMinSize)
+  { }
+
+  explicit BlurCacheKey(IntSize aOuterMinSize, IntSize aInnerMinSize,
+                        IntSize aBlurRadius, IntSize aSpreadRadius,
+                        const RectCornerRadii* aCornerRadii, gfxRGBA aShadowColor,
+                        bool aIsInset,
+                        bool aHasBorderRadius, BackendType aBackendType)
+    : mMinSize(aOuterMinSize)
+    , mBlurRadius(aBlurRadius)
+    , mShadowColor(aShadowColor)
+    , mBackend(aBackendType)
+    , mCornerRadii(aCornerRadii ? *aCornerRadii : RectCornerRadii())
+    , mIsInset(aIsInset)
+    , mHasBorderRadius(aHasBorderRadius)
+    , mSpreadRadius(aSpreadRadius)
+    , mInnerMinSize(aInnerMinSize)
   { }
 
   static PLDHashNumber
   HashKey(const KeyTypePointer aKey)
   {
     PLDHashNumber hash = 0;
     hash = AddToHash(hash, aKey->mMinSize.width, aKey->mMinSize.height);
     hash = AddToHash(hash, aKey->mBlurRadius.width, aKey->mBlurRadius.height);
 
     hash = AddToHash(hash, HashBytes(&aKey->mShadowColor.r, sizeof(gfxFloat)));
     hash = AddToHash(hash, HashBytes(&aKey->mShadowColor.g, sizeof(gfxFloat)));
     hash = AddToHash(hash, HashBytes(&aKey->mShadowColor.b, sizeof(gfxFloat)));
     hash = AddToHash(hash, HashBytes(&aKey->mShadowColor.a, sizeof(gfxFloat)));
 
     for (int i = 0; i < 4; i++) {
-    hash = AddToHash(hash, aKey->mCornerRadii[i].width, aKey->mCornerRadii[i].height);
+      hash = AddToHash(hash, aKey->mCornerRadii[i].width, aKey->mCornerRadii[i].height);
     }
 
     hash = AddToHash(hash, (uint32_t)aKey->mBackend);
+
+    if (aKey->mIsInset) {
+      hash = AddToHash(hash, aKey->mSpreadRadius.width, aKey->mSpreadRadius.height);
+      hash = AddToHash(hash, aKey->mInnerMinSize.width, aKey->mInnerMinSize.height);
+      hash = AddToHash(hash, HashBytes(&aKey->mHasBorderRadius, sizeof(bool)));
+    }
     return hash;
   }
 
-  bool KeyEquals(KeyTypePointer aKey) const
+  bool
+  KeyEquals(KeyTypePointer aKey) const
   {
     if (aKey->mMinSize == mMinSize &&
         aKey->mBlurRadius == mBlurRadius &&
         aKey->mCornerRadii == mCornerRadii &&
         aKey->mShadowColor == mShadowColor &&
         aKey->mBackend == mBackend) {
+
+      if (mIsInset) {
+        return (mHasBorderRadius == aKey->mHasBorderRadius) &&
+                (mInnerMinSize == aKey->mInnerMinSize) &&
+                (mSpreadRadius == aKey->mSpreadRadius);
+      }
+
       return true;
      }
 
      return false;
   }
-  static KeyTypePointer KeyToPointer(KeyType aKey)
+
+  static KeyTypePointer
+  KeyToPointer(KeyType aKey)
   {
     return &aKey;
   }
 };
 
 /**
  * This class is what is cached. It need to be allocated in an object separated
  * to the cache entry to be able to be tracked by the nsExpirationTracker.
@@ -270,32 +311,53 @@ class BlurCache final : public nsExpirat
 
     virtual void NotifyExpired(BlurCacheData* aObject)
     {
       RemoveObject(aObject);
       mHashEntries.Remove(aObject->mKey);
     }
 
     BlurCacheData* Lookup(const IntSize aMinSize,
-                          const gfxIntSize& aBlurRadius,
+                          const IntSize& aBlurRadius,
                           RectCornerRadii* aCornerRadii,
                           const gfxRGBA& aShadowColor,
                           BackendType aBackendType)
     {
       BlurCacheData* blur =
         mHashEntries.Get(BlurCacheKey(aMinSize, aBlurRadius,
                                       aCornerRadii, aShadowColor,
                                       aBackendType));
       if (blur) {
         MarkUsed(blur);
       }
 
       return blur;
     }
 
+    BlurCacheData* LookupInsetBoxShadow(const IntSize aOuterMinSize,
+                                        const IntSize aInnerMinSize,
+                                        const IntSize& aBlurRadius,
+                                        const IntSize& aSpreadRadius,
+                                        const RectCornerRadii* aCornerRadii,
+                                        const gfxRGBA& aShadowColor,
+                                        const bool& aHasBorderRadius,
+                                        BackendType aBackendType)
+    {
+      BlurCacheKey key(aOuterMinSize, aInnerMinSize,
+                       aBlurRadius, aSpreadRadius,
+                       aCornerRadii, aShadowColor,
+                       true, aHasBorderRadius, aBackendType);
+      BlurCacheData* blur = mHashEntries.Get(key);
+      if (blur) {
+        MarkUsed(blur);
+      }
+
+      return blur;
+    }
+
     // Returns true if we successfully register the blur in the cache, false
     // otherwise.
     bool RegisterEntry(BlurCacheData* aValue)
     {
       nsresult rv = AddObject(aValue);
       if (NS_FAILED(rv)) {
         // We are OOM, and we cannot track this object. We don't want stall
         // entries in the hash table (since the expiration tracker is responsible
@@ -316,17 +378,17 @@ class BlurCache final : public nsExpirat
      */
     nsClassHashtable<BlurCacheKey, BlurCacheData> mHashEntries;
 };
 
 static BlurCache* gBlurCache = nullptr;
 
 static IntSize
 ComputeMinSizeForShadowShape(RectCornerRadii* aCornerRadii,
-                             gfxIntSize aBlurRadius,
+                             IntSize aBlurRadius,
                              IntMargin& aSlice,
                              const IntSize& aRectSize)
 {
   float cornerWidth = 0;
   float cornerHeight = 0;
   if (aCornerRadii) {
     RectCornerRadii corners = *aCornerRadii;
     for (size_t i = 0; i < 4; i++) {
@@ -363,45 +425,45 @@ ComputeMinSizeForShadowShape(RectCornerR
   MOZ_ASSERT(aSlice.LeftRight() <= minSize.width);
   MOZ_ASSERT(aSlice.TopBottom() <= minSize.height);
   return minSize;
 }
 
 void
 CacheBlur(DrawTarget& aDT,
           const IntSize& aMinSize,
-          const gfxIntSize& aBlurRadius,
+          const IntSize& aBlurRadius,
           RectCornerRadii* aCornerRadii,
           const gfxRGBA& aShadowColor,
           IntMargin aExtendDest,
           SourceSurface* aBoxShadow)
 {
   BlurCacheKey key(aMinSize, aBlurRadius, aCornerRadii, aShadowColor, aDT.GetBackendType());
   BlurCacheData* data = new BlurCacheData(aBoxShadow, aExtendDest, key);
   if (!gBlurCache->RegisterEntry(data)) {
     delete data;
   }
 }
 
 // Blurs a small surface and creates the mask.
 static already_AddRefed<SourceSurface>
 CreateBlurMask(const IntSize& aRectSize,
                RectCornerRadii* aCornerRadii,
-               gfxIntSize aBlurRadius,
+               IntSize aBlurRadius,
                IntMargin& aExtendDestBy,
                IntMargin& aSliceBorder,
                DrawTarget& aDestDrawTarget)
 {
   IntMargin slice;
   gfxAlphaBoxBlur blur;
   IntSize minSize =
     ComputeMinSizeForShadowShape(aCornerRadii, aBlurRadius, slice, aRectSize);
   IntRect minRect(IntPoint(), minSize);
 
-  gfxContext* blurCtx = blur.Init(ThebesRect(Rect(minRect)), gfxIntSize(),
+  gfxContext* blurCtx = blur.Init(ThebesRect(Rect(minRect)), IntSize(),
                                   aBlurRadius, nullptr, nullptr);
 
   if (!blurCtx) {
     return nullptr;
   }
 
   DrawTarget* blurDT = blurCtx->GetDrawTarget();
   ColorPattern black(Color(0.f, 0.f, 0.f, 1.f));
@@ -426,36 +488,36 @@ CreateBlurMask(const IntSize& aRectSize,
 
   MOZ_ASSERT(aSliceBorder.LeftRight() <= expandedMinRect.width);
   MOZ_ASSERT(aSliceBorder.TopBottom() <= expandedMinRect.height);
 
   return result.forget();
 }
 
 static already_AddRefed<SourceSurface>
-CreateBoxShadow(DrawTarget& aDT, SourceSurface* aBlurMask, const gfxRGBA& aShadowColor)
+CreateBoxShadow(SourceSurface* aBlurMask, const gfxRGBA& aShadowColor)
 {
   IntSize blurredSize = aBlurMask->GetSize();
   gfxPlatform* platform = gfxPlatform::GetPlatform();
   RefPtr<DrawTarget> boxShadowDT =
     platform->CreateOffscreenContentDrawTarget(blurredSize, SurfaceFormat::B8G8R8A8);
 
   if (!boxShadowDT) {
     return nullptr;
   }
 
   ColorPattern shadowColor(ToDeviceColor(aShadowColor));
   boxShadowDT->MaskSurface(shadowColor, aBlurMask, Point(0, 0));
   return boxShadowDT->Snapshot();
 }
 
-SourceSurface*
+static SourceSurface*
 GetBlur(DrawTarget& aDT,
         const IntSize& aRectSize,
-        const gfxIntSize& aBlurRadius,
+        const IntSize& aBlurRadius,
         RectCornerRadii* aCornerRadii,
         const gfxRGBA& aShadowColor,
         IntMargin& aExtendDestBy,
         IntMargin& aSlice)
 {
   if (!gBlurCache) {
     gBlurCache = new BlurCache();
   }
@@ -475,17 +537,17 @@ GetBlur(DrawTarget& aDT,
 
   RefPtr<SourceSurface> blurMask =
     CreateBlurMask(aRectSize, aCornerRadii, aBlurRadius, aExtendDestBy, aSlice, aDT);
 
   if (!blurMask) {
     return nullptr;
   }
 
-  RefPtr<SourceSurface> boxShadow = CreateBoxShadow(aDT, blurMask, aShadowColor);
+  RefPtr<SourceSurface> boxShadow = CreateBoxShadow(blurMask, aShadowColor);
   if (!boxShadow) {
     return nullptr;
   }
 
   CacheBlur(aDT, minSize, aBlurRadius, aCornerRadii, aShadowColor, aExtendDestBy, boxShadow);
   return boxShadow;
 }
 
@@ -536,16 +598,78 @@ DrawCorner(DrawTarget& aDT, SourceSurfac
 {
   if (aSkipRect.Contains(aDest)) {
     return;
   }
 
   aDT.DrawSurface(aSurface, aDest, aSrc);
 }
 
+static void
+DrawBoxShadows(DrawTarget& aDestDrawTarget, SourceSurface* aSourceBlur,
+               Rect aDstOuter, Rect aDstInner, Rect aSrcOuter, Rect aSrcInner,
+               Rect aSkipRect)
+{
+  // Corners: top left, top right, bottom left, bottom right
+  DrawCorner(aDestDrawTarget, aSourceBlur,
+             RectWithEdgesTRBL(aDstOuter.Y(), aDstInner.X(),
+                               aDstInner.Y(), aDstOuter.X()),
+             RectWithEdgesTRBL(aSrcOuter.Y(), aSrcInner.X(),
+                               aSrcInner.Y(), aSrcOuter.X()),
+             aSkipRect);
+
+  DrawCorner(aDestDrawTarget, aSourceBlur,
+             RectWithEdgesTRBL(aDstOuter.Y(), aDstOuter.XMost(),
+                               aDstInner.Y(), aDstInner.XMost()),
+             RectWithEdgesTRBL(aSrcOuter.Y(), aSrcOuter.XMost(),
+                               aSrcInner.Y(), aSrcInner.XMost()),
+             aSkipRect);
+
+  DrawCorner(aDestDrawTarget, aSourceBlur,
+             RectWithEdgesTRBL(aDstInner.YMost(), aDstInner.X(),
+                               aDstOuter.YMost(), aDstOuter.X()),
+             RectWithEdgesTRBL(aSrcInner.YMost(), aSrcInner.X(),
+                               aSrcOuter.YMost(), aSrcOuter.X()),
+             aSkipRect);
+
+  DrawCorner(aDestDrawTarget, aSourceBlur,
+             RectWithEdgesTRBL(aDstInner.YMost(), aDstOuter.XMost(),
+                               aDstOuter.YMost(), aDstInner.XMost()),
+             RectWithEdgesTRBL(aSrcInner.YMost(), aSrcOuter.XMost(),
+                               aSrcOuter.YMost(), aSrcInner.XMost()),
+             aSkipRect);
+
+  // Edges: top, left, right, bottom
+  RepeatOrStretchSurface(aDestDrawTarget, aSourceBlur,
+                         RectWithEdgesTRBL(aDstOuter.Y(), aDstInner.XMost(),
+                                           aDstInner.Y(), aDstInner.X()),
+                         RectWithEdgesTRBL(aSrcOuter.Y(), aSrcInner.XMost(),
+                                           aSrcInner.Y(), aSrcInner.X()),
+                         aSkipRect);
+  RepeatOrStretchSurface(aDestDrawTarget, aSourceBlur,
+                         RectWithEdgesTRBL(aDstInner.Y(), aDstInner.X(),
+                                           aDstInner.YMost(), aDstOuter.X()),
+                         RectWithEdgesTRBL(aSrcInner.Y(), aSrcInner.X(),
+                                           aSrcInner.YMost(), aSrcOuter.X()),
+                         aSkipRect);
+  RepeatOrStretchSurface(aDestDrawTarget, aSourceBlur,
+                         RectWithEdgesTRBL(aDstInner.Y(), aDstOuter.XMost(),
+                                           aDstInner.YMost(), aDstInner.XMost()),
+                         RectWithEdgesTRBL(aSrcInner.Y(), aSrcOuter.XMost(),
+                                           aSrcInner.YMost(), aSrcInner.XMost()),
+                         aSkipRect);
+  RepeatOrStretchSurface(aDestDrawTarget, aSourceBlur,
+                         RectWithEdgesTRBL(aDstInner.YMost(), aDstInner.XMost(),
+                                           aDstOuter.YMost(), aDstInner.X()),
+                         RectWithEdgesTRBL(aSrcInner.YMost(), aSrcInner.XMost(),
+                                           aSrcOuter.YMost(), aSrcInner.X()),
+                         aSkipRect);
+}
+
+
 /***
  * We draw a blurred a rectangle by only blurring a smaller rectangle and
  * splitting the rectangle into 9 parts.
  * First, a small minimum source rect is calculated and used to create a blur
  * mask since the actual blurring itself is expensive. Next, we use the mask
  * with the given shadow color to create a minimally-sized box shadow of the
  * right color. Finally, we cut out the 9 parts from the box-shadow source and
  * paint each part in the right place, stretching the non-corner parts to fill
@@ -593,70 +717,18 @@ gfxAlphaBoxBlur::BlurRectangle(gfxContex
 
   Rect skipRect = ToRect(aSkipRect);
 
   if (srcInner.IsEqualInterior(srcOuter)) {
     MOZ_ASSERT(dstInner.IsEqualInterior(dstOuter));
     // The target rect is smaller than the minimal size so just draw the surface
     destDrawTarget.DrawSurface(boxShadow, dstInner, srcInner);
   } else {
-    // Corners: top left, top right, bottom left, bottom right
-    DrawCorner(destDrawTarget, boxShadow,
-               RectWithEdgesTRBL(dstOuter.Y(), dstInner.X(),
-                                 dstInner.Y(), dstOuter.X()),
-               RectWithEdgesTRBL(srcOuter.Y(), srcInner.X(),
-                                 srcInner.Y(), srcOuter.X()),
-               skipRect);
-
-    DrawCorner(destDrawTarget, boxShadow,
-               RectWithEdgesTRBL(dstOuter.Y(), dstOuter.XMost(),
-                                 dstInner.Y(), dstInner.XMost()),
-               RectWithEdgesTRBL(srcOuter.Y(), srcOuter.XMost(),
-                                 srcInner.Y(), srcInner.XMost()),
-               skipRect);
-
-    DrawCorner(destDrawTarget, boxShadow,
-               RectWithEdgesTRBL(dstInner.YMost(), dstInner.X(),
-                                 dstOuter.YMost(), dstOuter.X()),
-               RectWithEdgesTRBL(srcInner.YMost(), srcInner.X(),
-                                 srcOuter.YMost(), srcOuter.X()),
-               skipRect);
-
-    DrawCorner(destDrawTarget, boxShadow,
-               RectWithEdgesTRBL(dstInner.YMost(), dstOuter.XMost(),
-                                 dstOuter.YMost(), dstInner.XMost()),
-               RectWithEdgesTRBL(srcInner.YMost(), srcOuter.XMost(),
-                                 srcOuter.YMost(), srcInner.XMost()),
-               skipRect);
-
-    // Edges: top, left, right, bottom
-    RepeatOrStretchSurface(destDrawTarget, boxShadow,
-                           RectWithEdgesTRBL(dstOuter.Y(), dstInner.XMost(),
-                                             dstInner.Y(), dstInner.X()),
-                           RectWithEdgesTRBL(srcOuter.Y(), srcInner.XMost(),
-                                             srcInner.Y(), srcInner.X()),
-                           skipRect);
-    RepeatOrStretchSurface(destDrawTarget, boxShadow,
-                           RectWithEdgesTRBL(dstInner.Y(), dstInner.X(),
-                                             dstInner.YMost(), dstOuter.X()),
-                           RectWithEdgesTRBL(srcInner.Y(), srcInner.X(),
-                                             srcInner.YMost(), srcOuter.X()),
-                           skipRect);
-    RepeatOrStretchSurface(destDrawTarget, boxShadow,
-                           RectWithEdgesTRBL(dstInner.Y(), dstOuter.XMost(),
-                                             dstInner.YMost(), dstInner.XMost()),
-                           RectWithEdgesTRBL(srcInner.Y(), srcOuter.XMost(),
-                                             srcInner.YMost(), srcInner.XMost()),
-                           skipRect);
-    RepeatOrStretchSurface(destDrawTarget, boxShadow,
-                           RectWithEdgesTRBL(dstInner.YMost(), dstInner.XMost(),
-                                             dstOuter.YMost(), dstInner.X()),
-                           RectWithEdgesTRBL(srcInner.YMost(), srcInner.XMost(),
-                                             srcOuter.YMost(), srcInner.X()),
-                           skipRect);
+    DrawBoxShadows(destDrawTarget, boxShadow, dstOuter, dstInner,
+                   srcOuter, srcInner, skipRect);
 
     // Middle part
     RepeatOrStretchSurface(destDrawTarget, boxShadow,
                            RectWithEdgesTRBL(dstInner.Y(), dstInner.XMost(),
                                              dstInner.YMost(), dstInner.X()),
                            RectWithEdgesTRBL(srcInner.Y(), srcInner.XMost(),
                                              srcInner.YMost(), srcInner.X()),
                            skipRect);
@@ -677,8 +749,257 @@ gfxAlphaBoxBlur::BlurRectangle(gfxContex
   // will not just fill the pixels that have their pixel center inside the
   // filled shape. Instead, it will fill all the pixels which are partially
   // covered by the shape. So for pixels on the edge between two adjacent parts,
   // all those pixels will be painted to by both parts, which looks very bad.
 
   destDrawTarget.PopClip();
 }
 
+static already_AddRefed<Path>
+GetBoxShadowInsetPath(DrawTarget* aDrawTarget,
+                      const Rect aOuterRect, const Rect aInnerRect,
+                      const bool aHasBorderRadius, const RectCornerRadii& aInnerClipRadii)
+{
+  /***
+   * We create an inset path by having two rects.
+   *
+   *  -----------------------
+   *  |  ________________   |
+   *  | |                |  |
+   *  | |                |  |
+   *  | ------------------  |
+   *  |_____________________|
+   *
+   * The outer rect and the inside rect. The path
+   * creates a frame around the content where we draw the inset shadow.
+   */
+  RefPtr<PathBuilder> builder =
+    aDrawTarget->CreatePathBuilder(FillRule::FILL_EVEN_ODD);
+  AppendRectToPath(builder, aOuterRect, true);
+
+  if (aHasBorderRadius) {
+    AppendRoundedRectToPath(builder, aInnerRect, aInnerClipRadii, false);
+  } else {
+    AppendRectToPath(builder, aInnerRect, false);
+  }
+  return builder->Finish();
+}
+
+static void
+ComputeRectsForInsetBoxShadow(IntSize aBlurRadius,
+                              IntSize aSpreadRadius,
+                              Rect& aOutOuterRect,
+                              Rect& aOutInnerRect,
+                              Margin& aOutPathMargins,
+                              const Rect& aDestRect,
+                              const Rect& aShadowClipRect)
+{
+  IntSize marginSize = aBlurRadius + aSpreadRadius;
+  aOutPathMargins.SizeTo(marginSize.height, marginSize.width, marginSize.height, marginSize.width);
+  aOutPathMargins += aOutPathMargins;
+
+  aOutOuterRect.x = 0;
+  aOutInnerRect.x = marginSize.width;
+
+  aOutOuterRect.y = 0;
+  aOutInnerRect.y = marginSize.height;
+
+  // + 1 for the middle edges so we can sample them
+  aOutInnerRect.width = aOutPathMargins.LeftRight() + 1;
+  aOutInnerRect.height = aOutPathMargins.TopBottom() + 1;
+
+  // The outer path rect needs to be 1 blur radius past the inner edges
+  aOutOuterRect.width = aOutInnerRect.XMost() + marginSize.width;
+  aOutOuterRect.height = aOutInnerRect.YMost() + marginSize.height;
+
+  if ((aOutOuterRect.width >= aDestRect.width) ||
+      (aOutOuterRect.height >= aDestRect.height) ||
+      (aOutInnerRect.width >= aShadowClipRect.width) ||
+      (aOutInnerRect.height >= aShadowClipRect.height))
+  {
+    aOutOuterRect.width = aDestRect.width;
+    aOutOuterRect.height = aDestRect.height;
+    aOutInnerRect.width = aShadowClipRect.width;
+    aOutInnerRect.height = aShadowClipRect.height;
+    aOutPathMargins.SizeTo(0, 0, 0, 0);
+  }
+}
+
+static void
+FillDestinationPath(gfxContext* aDestinationCtx,
+                    const Rect aDestinationRect,
+                    const Rect aShadowClipRect,
+                    const Color& aShadowColor,
+                    const bool aHasBorderRadius,
+                    const RectCornerRadii& aInnerClipRadii)
+{
+  // When there is no blur radius, fill the path onto the destination
+  // surface.
+  aDestinationCtx->SetColor(ThebesColor(aShadowColor));
+  DrawTarget* destDrawTarget = aDestinationCtx->GetDrawTarget();
+  RefPtr<Path> shadowPath = GetBoxShadowInsetPath(destDrawTarget, aDestinationRect,
+                                                  aShadowClipRect, aHasBorderRadius,
+                                                  aInnerClipRadii);
+
+  aDestinationCtx->SetPath(shadowPath);
+  aDestinationCtx->Fill();
+}
+
+void
+CacheInsetBlur(const IntSize aMinOuterSize,
+               const IntSize aMinInnerSize,
+               const IntSize& aBlurRadius,
+               const IntSize& aSpreadRadius,
+               const RectCornerRadii* aCornerRadii,
+               const gfxRGBA& aShadowColor,
+               const bool& aHasBorderRadius,
+               BackendType aBackendType,
+               IntMargin aExtendBy,
+               SourceSurface* aBoxShadow)
+{
+  BlurCacheKey key(aMinOuterSize, aMinInnerSize,
+                   aBlurRadius, aSpreadRadius,
+                   aCornerRadii, aShadowColor,
+                   true, aHasBorderRadius, aBackendType);
+  BlurCacheData* data = new BlurCacheData(aBoxShadow, aExtendBy, key);
+  if (!gBlurCache->RegisterEntry(data)) {
+    delete data;
+  }
+}
+
+already_AddRefed<mozilla::gfx::SourceSurface>
+gfxAlphaBoxBlur::GetInsetBlur(Rect& aOuterRect,
+                              Rect& aInnerRect,
+                              const IntSize& aBlurRadius,
+                              const IntSize& aSpreadRadius,
+                              const RectCornerRadii& aInnerClipRadii,
+                              const Color& aShadowColor,
+                              const bool& aHasBorderRadius,
+                              IntPoint& aOutTopLeft,
+                              gfxContext* aDestinationCtx)
+
+{
+  if (!gBlurCache) {
+    gBlurCache = new BlurCache();
+  }
+
+  IntSize outerRectSize = RoundedToInt(aOuterRect).Size();
+  IntSize innerRectSize = RoundedToInt(aInnerRect).Size();
+  DrawTarget* destDrawTarget = aDestinationCtx->GetDrawTarget();
+
+  BlurCacheData* cached =
+      gBlurCache->LookupInsetBoxShadow(outerRectSize, innerRectSize, aBlurRadius, aSpreadRadius,
+                                       &aInnerClipRadii, ThebesColor(aShadowColor),
+                                       aHasBorderRadius, destDrawTarget->GetBackendType());
+
+  if (cached) {
+    IntMargin extends = cached->mExtendDest;
+    aOutTopLeft.x = extends.left;
+    aOutTopLeft.y = extends.top;
+    // So we don't forget the actual cached blur
+    RefPtr<SourceSurface> cachedBlur = cached->mBlur;
+    return cachedBlur.forget();
+  }
+
+  // Dirty rect and skip rect are null for the min inset shadow.
+  // When rendering inset box shadows, we respect the spread radius by changing
+  //  the shape of the unblurred shadow, and can pass a spread radius of zero here.
+  IntSize zeroSpread(0, 0);
+  gfxContext* minGfxContext = Init(ThebesRect(aOuterRect), zeroSpread, aBlurRadius, nullptr, nullptr);
+  if (!minGfxContext) {
+    return nullptr;
+  }
+
+  DrawTarget* minDrawTarget = minGfxContext->GetDrawTarget();
+  RefPtr<Path> maskPath = GetBoxShadowInsetPath(minDrawTarget, aOuterRect,
+                                                aInnerRect, aHasBorderRadius,
+                                                aInnerClipRadii);
+
+  minGfxContext->SetColor(ThebesColor(aShadowColor));
+  minGfxContext->SetPath(maskPath);
+  minGfxContext->Fill();
+
+  RefPtr<SourceSurface> minMask = DoBlur(minDrawTarget, &aOutTopLeft);
+  if (!minMask) {
+    return nullptr;
+  }
+
+  RefPtr<SourceSurface> minInsetBlur = CreateBoxShadow(minMask, ThebesColor(aShadowColor));
+  if (!minInsetBlur) {
+    return nullptr;
+  }
+
+  IntMargin extendBy(aOutTopLeft.y, 0, 0, aOutTopLeft.x);
+  CacheInsetBlur(outerRectSize, innerRectSize,
+                 aBlurRadius, aSpreadRadius,
+                 &aInnerClipRadii, ThebesColor(aShadowColor),
+                 aHasBorderRadius, destDrawTarget->GetBackendType(),
+                 extendBy, minInsetBlur);
+  return minInsetBlur.forget();
+}
+
+/***
+ * Blur an inset box shadow by doing:
+ * 1) Create a minimal box shadow path that creates a frame.
+ * 2) Draw the box shadow portion over the destination surface.
+ * 3) The "inset" part is created by a clip rect that properly clips
+ *    the alpha mask so that it has clean edges. We still create the full
+ *    proper alpha mask, but let the clip deal with the clean edges.
+ *
+ * All parameters should already be in device pixels.
+ */
+void
+gfxAlphaBoxBlur::BlurInsetBox(gfxContext* aDestinationCtx,
+                              const Rect aDestinationRect,
+                              const Rect aShadowClipRect,
+                              const IntSize aBlurRadius,
+                              const IntSize aSpreadRadius,
+                              const Color& aShadowColor,
+                              bool aHasBorderRadius,
+                              const RectCornerRadii& aInnerClipRadii,
+                              const Rect aSkipRect)
+{
+  // Blur inset shadows ALWAYS have a 0 spread radius.
+  if ((aBlurRadius.width <= 0 && aBlurRadius.height <= 0)) {
+    FillDestinationPath(aDestinationCtx, aDestinationRect, aShadowClipRect,
+        aShadowColor, aHasBorderRadius, aInnerClipRadii);
+    return;
+  }
+
+  DrawTarget* destDrawTarget = aDestinationCtx->GetDrawTarget();
+  Rect outerRect;
+  Rect innerRect;
+  Margin pathMargins;
+  ComputeRectsForInsetBoxShadow(aBlurRadius, aSpreadRadius,
+                                outerRect, innerRect,
+                                pathMargins,
+                                aDestinationRect,
+                                aShadowClipRect);
+
+  IntPoint topLeft;
+  RefPtr<SourceSurface> minInsetBlur = GetInsetBlur(outerRect, innerRect,
+                                                    aBlurRadius, aSpreadRadius,
+                                                    aInnerClipRadii, aShadowColor,
+                                                    aHasBorderRadius,
+                                                    topLeft, aDestinationCtx);
+  if (!minInsetBlur) {
+    return;
+  }
+
+  Rect destRectOuter(aDestinationRect);
+  Rect destRectInner(destRectOuter);
+  destRectInner.Deflate(pathMargins);
+
+  Rect srcRectOuter(outerRect);
+  srcRectOuter.MoveBy(abs(topLeft.x), abs(topLeft.y));
+  Rect srcRectInner(srcRectOuter);
+  srcRectInner.Deflate(pathMargins);
+
+  if (srcRectOuter.IsEqualInterior(srcRectInner)) {
+    destDrawTarget->DrawSurface(minInsetBlur, destRectOuter, srcRectOuter);
+  } else {
+    DrawBoxShadows(*destDrawTarget, minInsetBlur,
+                   destRectOuter, destRectInner,
+                   srcRectOuter, srcRectInner,
+                   aSkipRect);
+ }
+}
--- a/gfx/thebes/gfxBlur.h
+++ b/gfx/thebes/gfxBlur.h
@@ -15,16 +15,17 @@
 
 class gfxContext;
 struct gfxRect;
 struct gfxRGBA;
 
 namespace mozilla {
   namespace gfx {
     class AlphaBoxBlur;
+    struct Color;
     struct RectCornerRadii;
     class SourceSurface;
     class DrawTarget;
   } // namespace gfx
 } // namespace mozilla
 
 /**
  * Implementation of a triple box blur approximation of a Gaussian blur.
@@ -130,19 +131,54 @@ public:
                               RectCornerRadii* aCornerRadii,
                               const gfxPoint& aBlurStdDev,
                               const gfxRGBA& aShadowColor,
                               const gfxRect& aDirtyRect,
                               const gfxRect& aSkipRect);
 
     static void ShutdownBlurCache();
 
-
+    /***
+     * Blurs an inset box shadow according to a given path.
+     * This is equivalent to calling Init(), drawing the inset path,
+     * and calling paint. Do not call Init() if using this method.
+     *
+     * @param aDestinationCtx     The destination to blur to.
+     * @param aDestinationRect    The destination rect in device pixels
+     * @param aShadowClipRect     The destiniation inner rect of the
+     *                            inset path in device pixels.
+     * @param aBlurRadius         The standard deviation of the blur.
+     * @param aSpreadRadius       The spread radius in device pixels.
+     * @param aShadowColor        The color of the blur.
+     * @param aHasBorderRadius    If this element also has a border radius
+     * @param aInnerClipRadii     Corner radii for the inside rect if it is a rounded rect.
+     * @param aSKipRect           An area in device pixels we don't have to paint in.
+     */
+    void BlurInsetBox(gfxContext* aDestinationCtx,
+                      const mozilla::gfx::Rect aDestinationRect,
+                      const mozilla::gfx::Rect aShadowClipRect,
+                      const mozilla::gfx::IntSize aBlurRadius,
+                      const mozilla::gfx::IntSize aSpreadRadius,
+                      const mozilla::gfx::Color& aShadowColor,
+                      const bool aHasBorderRadius,
+                      const RectCornerRadii& aInnerClipRadii,
+                      const mozilla::gfx::Rect aSkipRect);
 
 protected:
+    already_AddRefed<mozilla::gfx::SourceSurface>
+                   GetInsetBlur(mozilla::gfx::Rect& aOuterRect,
+                                mozilla::gfx::Rect& aInnerRect,
+                                const mozilla::gfx::IntSize& aBlurRadius,
+                                const mozilla::gfx::IntSize& aSpreadRadius,
+                                const RectCornerRadii& aInnerClipRadii,
+                                const mozilla::gfx::Color& aShadowColor,
+                                const bool& aHasBorderRadius,
+                                mozilla::gfx::IntPoint& aOutTopLeft,
+                                gfxContext* aDestinationCtx);
+
     /**
      * The context of the temporary alpha surface.
      */
     nsRefPtr<gfxContext> mContext;
 
     /**
      * The temporary alpha surface.
      */
--- a/gfx/thebes/gfxContext.cpp
+++ b/gfx/thebes/gfxContext.cpp
@@ -702,45 +702,53 @@ gfxContext::ClipContainsRect(const gfxRe
   }
 
   return clipBounds.Contains(ToRect(aRect));
 }
 
 // rendering sources
 
 void
-gfxContext::SetColor(const gfxRGBA& c)
+gfxContext::SetColor(const gfxRGBA& aColor)
+{
+  CurrentState().pattern = nullptr;
+  CurrentState().sourceSurfCairo = nullptr;
+  CurrentState().sourceSurface = nullptr;
+  CurrentState().color = ToDeviceColor(aColor);
+}
+
+void
+gfxContext::SetColor(const Color& aColor)
 {
   CurrentState().pattern = nullptr;
   CurrentState().sourceSurfCairo = nullptr;
   CurrentState().sourceSurface = nullptr;
-  CurrentState().color = ToDeviceColor(c);
+  CurrentState().color = ToDeviceColor(aColor);
 }
 
 void
-gfxContext::SetDeviceColor(const gfxRGBA& c)
+gfxContext::SetDeviceColor(const Color& aColor)
 {
   CurrentState().pattern = nullptr;
   CurrentState().sourceSurfCairo = nullptr;
   CurrentState().sourceSurface = nullptr;
-  CurrentState().color = ToColor(c);
+  CurrentState().color = aColor;
 }
 
 bool
-gfxContext::GetDeviceColor(gfxRGBA& c)
+gfxContext::GetDeviceColor(Color& aColorOut)
 {
   if (CurrentState().sourceSurface) {
     return false;
   }
   if (CurrentState().pattern) {
-    gfxRGBA color;
-    return CurrentState().pattern->GetSolidColor(c);
+    return CurrentState().pattern->GetSolidColor(aColorOut);
   }
 
-  c = ThebesRGBA(CurrentState().color);
+  aColorOut = CurrentState().color;
   return true;
 }
 
 void
 gfxContext::SetSource(gfxASurface *surface, const gfxPoint& offset)
 {
   CurrentState().surfTransform = Matrix(1.0f, 0, 0, 1.0f, Float(offset.x), Float(offset.y));
   CurrentState().pattern = nullptr;
--- a/gfx/thebes/gfxContext.h
+++ b/gfx/thebes/gfxContext.h
@@ -250,31 +250,32 @@ public:
     /**
      ** Painting sources
      **/
 
     /**
      * Set a solid color to use for drawing.  This color is in the device color space
      * and is not transformed.
      */
-    void SetDeviceColor(const gfxRGBA& c);
+    void SetDeviceColor(const mozilla::gfx::Color& aColor);
 
     /**
      * Gets the current color.  It's returned in the device color space.
      * returns false if there is something other than a color
      *         set as the current source (pattern, surface, etc)
      */
-    bool GetDeviceColor(gfxRGBA& c);
+    bool GetDeviceColor(mozilla::gfx::Color& aColorOut);
 
     /**
      * Set a solid color in the sRGB color space to use for drawing.
      * If CMS is not enabled, the color is treated as a device-space color
      * and this call is identical to SetDeviceColor().
      */
-    void SetColor(const gfxRGBA& c);
+    void SetColor(const gfxRGBA& aColor);
+    void SetColor(const mozilla::gfx::Color& aColor);
 
     /**
      * Uses a surface for drawing. This is a shorthand for creating a
      * pattern and setting it.
      *
      * @param offset from the source surface, to use only part of it.
      *        May need to make it negative.
      */
--- a/gfx/thebes/gfxPattern.cpp
+++ b/gfx/thebes/gfxPattern.cpp
@@ -204,20 +204,20 @@ gfxPattern::Filter() const
 {
   if (mGfxPattern.GetPattern()->GetType() != PatternType::SURFACE) {
     return GraphicsFilter::FILTER_GOOD;
   }
   return ThebesFilter(static_cast<const SurfacePattern*>(mGfxPattern.GetPattern())->mFilter);
 }
 
 bool
-gfxPattern::GetSolidColor(gfxRGBA& aColor)
+gfxPattern::GetSolidColor(Color& aColorOut)
 {
   if (mGfxPattern.GetPattern()->GetType() == PatternType::COLOR) {
-    aColor = ThebesColor(static_cast<ColorPattern*>(mGfxPattern.GetPattern())->mColor);
+    aColorOut = static_cast<ColorPattern*>(mGfxPattern.GetPattern())->mColor;
     return true;
   }
 
  return false;
 }
 
 gfxPattern::GraphicsPatternType
 gfxPattern::GetType() const
--- a/gfx/thebes/gfxPattern.h
+++ b/gfx/thebes/gfxPattern.h
@@ -85,17 +85,17 @@ public:
     GraphicsPatternType GetType() const;
 
     int CairoStatus();
 
     void SetFilter(GraphicsFilter filter);
     GraphicsFilter Filter() const;
 
     /* returns TRUE if it succeeded */
-    bool GetSolidColor(gfxRGBA& aColor);
+    bool GetSolidColor(mozilla::gfx::Color& aColorOut);
 
 private:
     // Private destructor, to discourage deletion outside of Release():
     ~gfxPattern() {}
 
     mozilla::gfx::GeneralPattern mGfxPattern;
     mozilla::RefPtr<mozilla::gfx::SourceSurface> mSourceSurface;
     mozilla::gfx::Matrix mPatternToUserSpace;
--- a/gfx/thebes/gfxTextRun.cpp
+++ b/gfx/thebes/gfxTextRun.cpp
@@ -512,48 +512,47 @@ HasSyntheticBold(gfxTextRun *aRun, uint3
     }
 
     return false;
 }
 
 // returns true if color is non-opaque (i.e. alpha != 1.0) or completely transparent, false otherwise
 // if true, color is set on output
 static bool
-HasNonOpaqueColor(gfxContext *aContext, gfxRGBA& aCurrentColor)
+HasNonOpaqueColor(gfxContext *aContext, Color& aCurrentColorOut)
 {
-    if (aContext->GetDeviceColor(aCurrentColor)) {
-        if (aCurrentColor.a < 1.0 && aCurrentColor.a > 0.0) {
+    if (aContext->GetDeviceColor(aCurrentColorOut)) {
+        if (0.0 < aCurrentColorOut.a && aCurrentColorOut.a < 1.0) {
             return true;
         }
     }
-        
     return false;
 }
 
 // helper class for double-buffering drawing with non-opaque color
 struct BufferAlphaColor {
     explicit BufferAlphaColor(gfxContext *aContext)
         : mContext(aContext)
         , mAlpha(0.0)
     {
 
     }
 
     ~BufferAlphaColor() {}
 
-    void PushSolidColor(const gfxRect& aBounds, const gfxRGBA& aAlphaColor, uint32_t appsPerDevUnit)
+    void PushSolidColor(const gfxRect& aBounds, const Color& aAlphaColor, uint32_t appsPerDevUnit)
     {
         mContext->Save();
         mContext->NewPath();
         mContext->Rectangle(gfxRect(aBounds.X() / appsPerDevUnit,
                     aBounds.Y() / appsPerDevUnit,
                     aBounds.Width() / appsPerDevUnit,
                     aBounds.Height() / appsPerDevUnit), true);
         mContext->Clip();
-        mContext->SetColor(gfxRGBA(aAlphaColor.r, aAlphaColor.g, aAlphaColor.b));
+        mContext->SetColor(Color(aAlphaColor.r, aAlphaColor.g, aAlphaColor.b));
         mContext->PushGroup(gfxContentType::COLOR_ALPHA);
         mAlpha = aAlphaColor.a;
     }
 
     void PopAlpha()
     {
         // pop the text, using the color alpha as the opacity
         mContext->PopGroupToSource();
@@ -577,17 +576,17 @@ gfxTextRun::Draw(gfxContext *aContext, g
     NS_ASSERTION(aDrawMode == DrawMode::GLYPH_PATH ||
                  !(int(aDrawMode) & int(DrawMode::GLYPH_PATH)),
                  "GLYPH_PATH cannot be used with GLYPH_FILL, GLYPH_STROKE or GLYPH_STROKE_UNDERNEATH");
     NS_ASSERTION(aDrawMode == DrawMode::GLYPH_PATH || !aCallbacks,
                  "callback must not be specified unless using GLYPH_PATH");
 
     bool skipDrawing = mSkipDrawing;
     if (aDrawMode == DrawMode::GLYPH_FILL) {
-        gfxRGBA currentColor;
+        Color currentColor;
         if (aContext->GetDeviceColor(currentColor) && currentColor.a == 0) {
             skipDrawing = true;
         }
     }
 
     gfxFloat direction = GetDirection();
 
     if (skipDrawing) {
@@ -602,17 +601,17 @@ gfxTextRun::Draw(gfxContext *aContext, g
 
         // return without drawing
         return;
     }
 
     // synthetic bolding draws glyphs twice ==> colors with opacity won't draw
     // correctly unless first drawn without alpha
     BufferAlphaColor syntheticBoldBuffer(aContext);
-    gfxRGBA currentColor;
+    Color currentColor;
     bool needToRestore = false;
 
     if (aDrawMode == DrawMode::GLYPH_FILL &&
         HasNonOpaqueColor(aContext, currentColor) &&
         HasSyntheticBold(this, aStart, aLength)) {
         needToRestore = true;
         // measure text, use the bounding box
         gfxTextRun::Metrics metrics = MeasureText(aStart, aLength,
--- a/gfx/thebes/gfxUtils.cpp
+++ b/gfx/thebes/gfxUtils.cpp
@@ -658,18 +658,18 @@ PrescaleAndTileDrawable(gfxDrawable* aDr
     return false;
   }
 
   Rect scaledImageRect = ToMatrix(scaleMatrix).TransformBounds(aImageRect);
   if (!ShouldUseTempSurface(scaledImageRect, scaledNeededRect)) {
     return false;
   }
 
-  gfxIntSize scaledImageSize((int32_t)scaledImageRect.width,
-                             (int32_t)scaledImageRect.height);
+  IntSize scaledImageSize((int32_t)scaledImageRect.width,
+                          (int32_t)scaledImageRect.height);
   if (scaledImageSize.width != scaledImageRect.width ||
       scaledImageSize.height != scaledImageRect.height) {
     // If the scaled image isn't pixel aligned, we'll get artifacts
     // so we have to take the slow path.
     return false;
   }
 
   RefPtr<DrawTarget> scaledDT =
--- a/gfx/thebes/gfxWindowsPlatform.cpp
+++ b/gfx/thebes/gfxWindowsPlatform.cpp
@@ -1989,35 +1989,45 @@ gfxWindowsPlatform::CheckD3D11Support(bo
   return FeatureStatus::Available;
 }
 
 // We don't have access to the D3D11CreateDevice type in gfxWindowsPlatform.h,
 // since it doesn't include d3d11.h, so we use a static here. It should only
 // be used within InitializeD3D11.
 decltype(D3D11CreateDevice)* sD3D11CreateDeviceFn = nullptr;
 
+bool
+gfxWindowsPlatform::AttemptD3D11DeviceCreationHelper(
+  IDXGIAdapter1* aAdapter, HRESULT& aResOut)
+{
+  MOZ_SEH_TRY {
+    aResOut =
+      sD3D11CreateDeviceFn(
+        aAdapter, D3D_DRIVER_TYPE_UNKNOWN, nullptr,
+        // Use D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS
+        // to prevent bug 1092260. IE 11 also uses this flag.
+        D3D11_CREATE_DEVICE_BGRA_SUPPORT | D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS,
+        mFeatureLevels.Elements(), mFeatureLevels.Length(),
+        D3D11_SDK_VERSION, byRef(mD3D11Device), nullptr, nullptr);
+  } MOZ_SEH_EXCEPT (EXCEPTION_EXECUTE_HANDLER) {
+    return false;
+  }
+  return true;
+}
+
 FeatureStatus
 gfxWindowsPlatform::AttemptD3D11DeviceCreation()
 {
   RefPtr<IDXGIAdapter1> adapter = GetDXGIAdapter();
   if (!adapter) {
     return FeatureStatus::Unavailable;
   }
 
-  HRESULT hr = E_INVALIDARG;
-  MOZ_SEH_TRY {
-    hr =
-      sD3D11CreateDeviceFn(adapter, D3D_DRIVER_TYPE_UNKNOWN, nullptr,
-                           // Use
-                           // D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS
-                           // to prevent bug 1092260. IE 11 also uses this flag.
-                           D3D11_CREATE_DEVICE_BGRA_SUPPORT | D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS,
-                           mFeatureLevels.Elements(), mFeatureLevels.Length(),
-                           D3D11_SDK_VERSION, byRef(mD3D11Device), nullptr, nullptr);
-  } MOZ_SEH_EXCEPT (EXCEPTION_EXECUTE_HANDLER) {
+  HRESULT hr;
+  if (!AttemptD3D11DeviceCreationHelper(adapter, hr)) {
     gfxCriticalError() << "Crash during D3D11 device creation";
     return FeatureStatus::Crashed;
   }
 
   if (FAILED(hr) || !mD3D11Device) {
     mD3D11Device = nullptr;
     gfxCriticalError() << "D3D11 device creation failed: " << hexa(hr);
     return FeatureStatus::Failed;
@@ -2038,43 +2048,54 @@ gfxWindowsPlatform::AttemptD3D11DeviceCr
       gANGLESupportsD3D11 = false;
   }
 
   mD3D11Device->SetExceptionMode(0);
   mIsWARP = false;
   return FeatureStatus::Available;
 }
 
+bool
+gfxWindowsPlatform::AttemptWARPDeviceCreationHelper(
+  ScopedGfxFeatureReporter& aReporterWARP, HRESULT& aResOut)
+{
+  MOZ_SEH_TRY {
+    aResOut =
+      sD3D11CreateDeviceFn(
+        nullptr, D3D_DRIVER_TYPE_WARP, nullptr,
+        // Use D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS
+        // to prevent bug 1092260. IE 11 also uses this flag.
+        D3D11_CREATE_DEVICE_BGRA_SUPPORT,
+        mFeatureLevels.Elements(), mFeatureLevels.Length(),
+        D3D11_SDK_VERSION, byRef(mD3D11Device), nullptr, nullptr);
+
+    aReporterWARP.SetSuccessful();
+  } MOZ_SEH_EXCEPT (EXCEPTION_EXECUTE_HANDLER) {
+    return false;
+  }
+  return true;
+}
+
 FeatureStatus
 gfxWindowsPlatform::AttemptWARPDeviceCreation()
 {
   ScopedGfxFeatureReporter reporterWARP("D3D11-WARP", gfxPrefs::LayersD3D11ForceWARP());
 
-  MOZ_SEH_TRY {
-    HRESULT hr =
-      sD3D11CreateDeviceFn(nullptr, D3D_DRIVER_TYPE_WARP, nullptr,
-                           // Use
-                           // D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS
-                           // to prevent bug 1092260. IE 11 also uses this flag.
-                           D3D11_CREATE_DEVICE_BGRA_SUPPORT,
-                           mFeatureLevels.Elements(), mFeatureLevels.Length(),
-                           D3D11_SDK_VERSION, byRef(mD3D11Device), nullptr, nullptr);
-
-    if (FAILED(hr)) {
-      // This should always succeed... in theory.
-      gfxCriticalError() << "Failed to initialize WARP D3D11 device! " << hexa(hr);
-      return FeatureStatus::Failed;
-    }
-
-    reporterWARP.SetSuccessful();
-  } MOZ_SEH_EXCEPT (EXCEPTION_EXECUTE_HANDLER) {
+  HRESULT hr;
+  if (!AttemptWARPDeviceCreationHelper(reporterWARP, hr)) {
     gfxCriticalError() << "Exception occurred initializing WARP D3D11 device!";
     return FeatureStatus::Crashed;
   }
 
+  if (FAILED(hr)) {
+    // This should always succeed... in theory.
+    gfxCriticalError() << "Failed to initialize WARP D3D11 device! " << hexa(hr);
+    return FeatureStatus::Failed;
+  }
+
   // Only test for texture sharing on Windows 8 since it puts the device into
   // an unusable state if used on Windows 7
   if (IsWin8OrLater()) {
     mCompositorD3D11TextureSharingWorks = ::DoesD3D11TextureSharingWork(mD3D11Device);
   }
   mD3D11Device->SetExceptionMode(0);
   mIsWARP = true;
   return FeatureStatus::Available;
@@ -2098,37 +2119,47 @@ gfxWindowsPlatform::ContentAdapterIsPare
   {
     gfxCriticalNote << "VendorIDMismatch " << hexa(parent.vendorID()) << " " << hexa(desc.VendorId);
     return false;
   }
 
   return true;
 }
 
+bool
+gfxWindowsPlatform::AttemptD3D11ContentDeviceCreationHelper(
+  IDXGIAdapter1* aAdapter, HRESULT& aResOut)
+{
+  MOZ_SEH_TRY {
+    aResOut =
+      sD3D11CreateDeviceFn(
+        aAdapter, mIsWARP ? D3D_DRIVER_TYPE_WARP : D3D_DRIVER_TYPE_UNKNOWN,
+        nullptr, D3D11_CREATE_DEVICE_BGRA_SUPPORT,
+        mFeatureLevels.Elements(), mFeatureLevels.Length(),
+        D3D11_SDK_VERSION, byRef(mD3D11ContentDevice), nullptr, nullptr);
+
+  } MOZ_SEH_EXCEPT (EXCEPTION_EXECUTE_HANDLER) {
+    return false;
+  }
+  return true;
+}
+
 FeatureStatus
 gfxWindowsPlatform::AttemptD3D11ContentDeviceCreation()
 {
   RefPtr<IDXGIAdapter1> adapter;
   if (!mIsWARP) {
     adapter = GetDXGIAdapter();
     if (!adapter) {
       return FeatureStatus::Unavailable;
     }
   }
 
-  HRESULT hr = E_INVALIDARG;
-  MOZ_SEH_TRY {
-    hr =
-      sD3D11CreateDeviceFn(adapter,
-                           mIsWARP ? D3D_DRIVER_TYPE_WARP : D3D_DRIVER_TYPE_UNKNOWN,
-                           nullptr,
-                           D3D11_CREATE_DEVICE_BGRA_SUPPORT,
-                           mFeatureLevels.Elements(), mFeatureLevels.Length(),
-                           D3D11_SDK_VERSION, byRef(mD3D11ContentDevice), nullptr, nullptr);
-  } MOZ_SEH_EXCEPT (EXCEPTION_EXECUTE_HANDLER) {
+  HRESULT hr;
+  if (!AttemptD3D11ContentDeviceCreationHelper(adapter, hr)) {
     return FeatureStatus::Crashed;
   }
 
   if (FAILED(hr)) {
     return FeatureStatus::Failed;
   }
 
   // InitializeD2D() will abort early if the compositor device did not support
@@ -2477,53 +2508,52 @@ gfxWindowsPlatform::InitializeD2D1()
     }
     return;
   }
 
   MOZ_ASSERT(mD2D1Status == FeatureStatus::Available);
   d2d1_1.SetSuccessful();
 }
 
+bool
+gfxWindowsPlatform::CreateD3D11DecoderDeviceHelper(
+  IDXGIAdapter1* aAdapter, RefPtr<ID3D11Device>& aDevice, HRESULT& aResOut)
+{
+  MOZ_SEH_TRY{
+    aResOut =
+      sD3D11CreateDeviceFn(
+        aAdapter, D3D_DRIVER_TYPE_UNKNOWN, nullptr,
+        D3D11_CREATE_DEVICE_VIDEO_SUPPORT,
+        mFeatureLevels.Elements(), mFeatureLevels.Length(),
+        D3D11_SDK_VERSION, byRef(aDevice), nullptr, nullptr);
+
+  } MOZ_SEH_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
+    return false;
+  }
+  return true;
+}
+
 already_AddRefed<ID3D11Device>
 gfxWindowsPlatform::CreateD3D11DecoderDevice()
 {
-  nsModuleHandle d3d11Module(LoadLibrarySystem32(L"d3d11.dll"));
-  decltype(D3D11CreateDevice)* d3d11CreateDevice = (decltype(D3D11CreateDevice)*)
-    GetProcAddress(d3d11Module, "D3D11CreateDevice");
-
-   if (!d3d11CreateDevice) {
+   if (!sD3D11CreateDeviceFn) {
     // We should just be on Windows Vista or XP in this case.
     return nullptr;
   }
 
-  nsTArray<D3D_FEATURE_LEVEL> featureLevels;
-  if (IsWin8OrLater()) {
-    featureLevels.AppendElement(D3D_FEATURE_LEVEL_11_1);
-  }
-  featureLevels.AppendElement(D3D_FEATURE_LEVEL_11_0);
-  featureLevels.AppendElement(D3D_FEATURE_LEVEL_10_1);
-  featureLevels.AppendElement(D3D_FEATURE_LEVEL_10_0);
-  featureLevels.AppendElement(D3D_FEATURE_LEVEL_9_3);
-
   RefPtr<IDXGIAdapter1> adapter = GetDXGIAdapter();
 
   if (!adapter) {
     return nullptr;
   }
 
-  HRESULT hr = E_INVALIDARG;
-
   RefPtr<ID3D11Device> device;
 
-  MOZ_SEH_TRY{
-    hr = d3d11CreateDevice(adapter, D3D_DRIVER_TYPE_UNKNOWN, nullptr,
-                           D3D11_CREATE_DEVICE_VIDEO_SUPPORT,
-                           featureLevels.Elements(), featureLevels.Length(),
-                           D3D11_SDK_VERSION, byRef(device), nullptr, nullptr);
-  } MOZ_SEH_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
+  HRESULT hr;
+  if (!CreateD3D11DecoderDeviceHelper(adapter, device, hr)) {
     return nullptr;
   }
 
   if (FAILED(hr) || !DoesD3D11DeviceWork()) {
     return nullptr;
   }
 
   nsRefPtr<ID3D10Multithread> multi;
--- a/gfx/thebes/gfxWindowsPlatform.h
+++ b/gfx/thebes/gfxWindowsPlatform.h
@@ -8,16 +8,17 @@
 
 
 /**
  * XXX to get CAIRO_HAS_D2D_SURFACE, CAIRO_HAS_DWRITE_FONT
  * and cairo_win32_scaled_font_select_font
  */
 #include "cairo-win32.h"
 
+#include "gfxCrashReporterUtils.h"
 #include "gfxFontUtils.h"
 #include "gfxWindowsSurface.h"
 #include "gfxFont.h"
 #ifdef CAIRO_HAS_DWRITE_FONT
 #include "gfxDWriteFonts.h"
 #endif
 #include "gfxPlatform.h"
 #include "gfxTelemetry.h"
@@ -246,16 +247,19 @@ public:
     ID3D11Device *GetD3D11Device();
     ID3D11Device *GetD3D11ContentDevice();
     ID3D11Device* GetD3D11DeviceForCurrentThread();
     // Device to be used on the ImageBridge thread
     ID3D11Device *GetD3D11ImageBridgeDevice();
 
     // Create a D3D11 device to be used for DXVA decoding.
     already_AddRefed<ID3D11Device> CreateD3D11DecoderDevice();
+    bool CreateD3D11DecoderDeviceHelper(
+      IDXGIAdapter1* aAdapter, mozilla::RefPtr<ID3D11Device>& aDevice,
+      HRESULT& aResOut);
 
     mozilla::layers::ReadbackManagerD3D11* GetReadbackManager();
 
     static bool IsOptimus();
 
     bool IsWARP() { return mIsWARP; }
 
     // Returns whether the compositor's D3D11 device supports texture sharing.
@@ -314,20 +318,31 @@ private:
     bool InitDWriteSupport();
 
     void DisableD2D();
 
     mozilla::gfx::FeatureStatus CheckAccelerationSupport();
     mozilla::gfx::FeatureStatus CheckD3D11Support(bool* aCanUseHardware);
     mozilla::gfx::FeatureStatus CheckD2DSupport();
     mozilla::gfx::FeatureStatus CheckD2D1Support();
+
     mozilla::gfx::FeatureStatus AttemptD3D11DeviceCreation();
+    bool AttemptD3D11DeviceCreationHelper(
+        IDXGIAdapter1* aAdapter, HRESULT& aResOut);
+
     mozilla::gfx::FeatureStatus AttemptWARPDeviceCreation();
+    bool AttemptWARPDeviceCreationHelper(
+        mozilla::ScopedGfxFeatureReporter& aReporterWARP, HRESULT& aResOut);
+
     mozilla::gfx::FeatureStatus AttemptD3D11ImageBridgeDeviceCreation();
+
     mozilla::gfx::FeatureStatus AttemptD3D11ContentDeviceCreation();
+    bool gfxWindowsPlatform::AttemptD3D11ContentDeviceCreationHelper(
+        IDXGIAdapter1* aAdapter, HRESULT& aResOut);
+
     bool CanUseD3D11ImageBridge();
     bool ContentAdapterIsParentAdapter(ID3D11Device* device);
 
     void DisableD3D11AfterCrash();
     void ResetD3D11Devices();
 
     IDXGIAdapter1 *GetDXGIAdapter();
     bool IsDeviceReset(HRESULT hr, DeviceResetReason* aReason);
--- a/gfx/thebes/moz.build
+++ b/gfx/thebes/moz.build
@@ -258,19 +258,16 @@ if CONFIG['ENABLE_INTL_API']:
     CFLAGS += CONFIG['MOZ_ICU_CFLAGS']
     USE_LIBS += [
         'icu',
     ]
 
 if CONFIG['GNU_CXX']:
     CXXFLAGS += ['-Wshadow']
 
-if CONFIG['_MSC_VER']:
-    ALLOW_COMPILER_WARNINGS = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 GENERATED_FILES = [
     'DeprecatedPremultiplyTables.h',
 ]
 
--- a/image/DynamicImage.cpp
+++ b/image/DynamicImage.cpp
@@ -125,25 +125,25 @@ DynamicImage::GetHeight(int32_t* aHeight
 {
   *aHeight = mDrawable->Size().height;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 DynamicImage::GetIntrinsicSize(nsSize* aSize)
 {
-  gfxIntSize intSize(mDrawable->Size());
+  IntSize intSize(mDrawable->Size());
   *aSize = nsSize(intSize.width, intSize.height);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 DynamicImage::GetIntrinsicRatio(nsSize* aSize)
 {
-  gfxIntSize intSize(mDrawable->Size());
+  IntSize intSize(mDrawable->Size());
   *aSize = nsSize(intSize.width, intSize.height);
   return NS_OK;
 }
 
 NS_IMETHODIMP_(Orientation)
 DynamicImage::GetOrientation()
 {
   return Orientation();
@@ -162,17 +162,17 @@ DynamicImage::GetAnimated(bool* aAnimate
   *aAnimated = false;
   return NS_OK;
 }
 
 NS_IMETHODIMP_(already_AddRefed<SourceSurface>)
 DynamicImage::GetFrame(uint32_t aWhichFrame,
                        uint32_t aFlags)
 {
-  gfxIntSize size(mDrawable->Size());
+  IntSize size(mDrawable->Size());
   return GetFrameAtSize(IntSize(size.width, size.height),
                         aWhichFrame,
                         aFlags);
 }
 
 NS_IMETHODIMP_(already_AddRefed<SourceSurface>)
 DynamicImage::GetFrameAtSize(const IntSize& aSize,
                              uint32_t aWhichFrame,
@@ -220,17 +220,17 @@ DynamicImage::Draw(gfxContext* aContext,
                    const ImageRegion& aRegion,
                    uint32_t aWhichFrame,
                    GraphicsFilter aFilter,
                    const Maybe<SVGImageContext>& aSVGContext,
                    uint32_t aFlags)
 {
   MOZ_ASSERT(!aSize.IsEmpty(), "Unexpected empty size");
 
-  gfxIntSize drawableSize(mDrawable->Size());
+  IntSize drawableSize(mDrawable->Size());
 
   if (aSize == drawableSize) {
     gfxUtils::DrawPixelSnapped(aContext, mDrawable, drawableSize, aRegion,
                                SurfaceFormat::B8G8R8A8, aFilter);
     return DrawResult::SUCCESS;
   }
 
   gfxSize scale(double(aSize.width) / drawableSize.width,
@@ -322,17 +322,17 @@ NS_IMETHODIMP_(void)
 DynamicImage::SetAnimationStartTime(const mozilla::TimeStamp& aTime)
 { }
 
 nsIntSize
 DynamicImage::OptimalImageSizeForDest(const gfxSize& aDest,
                                       uint32_t aWhichFrame,
                                       GraphicsFilter aFilter, uint32_t aFlags)
 {
-  gfxIntSize size(mDrawable->Size());
+  IntSize size(mDrawable->Size());
   return nsIntSize(size.width, size.height);
 }
 
 NS_IMETHODIMP_(nsIntRect)
 DynamicImage::GetImageSpaceInvalidationRect(const nsIntRect& aRect)
 {
   return aRect;
 }
--- a/image/OrientedImage.cpp
+++ b/image/OrientedImage.cpp
@@ -76,17 +76,17 @@ OrientedImage::GetFrame(uint32_t aWhichF
 {
   nsresult rv;
 
   if (mOrientation.IsIdentity()) {
     return InnerImage()->GetFrame(aWhichFrame, aFlags);
   }
 
   // Get the underlying dimensions.
-  gfxIntSize size;
+  IntSize size;
   rv = InnerImage()->GetWidth(&size.width);
   NS_ENSURE_SUCCESS(rv, nullptr);
   rv = InnerImage()->GetHeight(&size.height);
   NS_ENSURE_SUCCESS(rv, nullptr);
 
   // Determine an appropriate format for the surface.
   gfx::SurfaceFormat surfaceFormat;
   if (InnerImage()->IsOpaque()) {
--- a/image/imgFrame.cpp
+++ b/image/imgFrame.cpp
@@ -534,17 +534,17 @@ imgFrame::SurfaceForDrawing(bool        
 
   // Not tiling, and we have a surface, so we can account for
   // padding and/or a partial decode just by twiddling parameters.
   gfxPoint paddingTopLeft(aPadding.left, aPadding.top);
   aRegion = aRegion.Intersect(available) - paddingTopLeft;
   aContext->Multiply(gfxMatrix::Translation(paddingTopLeft));
   aImageRect = gfxRect(0, 0, mSize.width, mSize.height);
 
-  gfxIntSize availableSize(mDecoded.width, mDecoded.height);
+  IntSize availableSize(mDecoded.width, mDecoded.height);
   return SurfaceWithFormat(new gfxSurfaceDrawable(aSurface, availableSize),
                            mFormat);
 }
 
 bool imgFrame::Draw(gfxContext* aContext, const ImageRegion& aRegion,
                     GraphicsFilter aFilter, uint32_t aImageFlags)
 {
   PROFILER_LABEL("imgFrame", "Draw",
--- a/js/public/UbiNode.h
+++ b/js/public/UbiNode.h
@@ -851,17 +851,18 @@ class EdgeRange {
     virtual ~EdgeRange() { }
 
     // True if there are no more edges in this range.
     bool empty() const { return !front_; }
 
     // The front edge of this range. This is owned by the EdgeRange, and is
     // only guaranteed to live until the next call to popFront, or until
     // the EdgeRange is destructed.
-    const Edge& front() { return *front_; }
+    const Edge& front() const { return *front_; }
+    Edge& front() { return *front_; }
 
     // Remove the front edge from this range. This should only be called if
     // !empty().
     virtual void popFront() = 0;
 
   private:
     EdgeRange(const EdgeRange&) = delete;
     EdgeRange& operator=(const EdgeRange&) = delete;
rename from js/public/UbiNodeTraverse.h
rename to js/public/UbiNodeBreadthFirst.h
--- a/js/public/UbiNodeTraverse.h
+++ b/js/public/UbiNodeBreadthFirst.h
@@ -1,16 +1,16 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * vim: set ts=8 sts=4 et sw=4 tw=99:
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#ifndef js_UbiNodeTraverse_h
-#define js_UbiNodeTraverse_h
+#ifndef js_UbiNodeBreadthFirst_h
+#define js_UbiNodeBreadthFirst_h
 
 #include "js/UbiNode.h"
 #include "js/Utility.h"
 #include "js/Vector.h"
 
 namespace JS {
 namespace ubi {
 
@@ -236,9 +236,9 @@ struct BreadthFirst {
 
     // True if we've been asked to abandon the current edge's referent.
     bool abandonRequested;
 };
 
 } // namespace ubi
 } // namespace JS
 
-#endif // js_UbiNodeTraverse.h
+#endif // js_UbiNodeBreadthFirst_h
--- a/js/public/UbiNodeCensus.h
+++ b/js/public/UbiNodeCensus.h
@@ -7,17 +7,17 @@
 #ifndef js_UbiNodeCensus_h
 #define js_UbiNodeCensus_h
 
 #include "mozilla/Move.h"
 
 #include "jsapi.h"
 
 #include "js/UbiNode.h"
-#include "js/UbiNodeTraverse.h"
+#include "js/UbiNodeBreadthFirst.h"
 
 // A census is a ubi::Node traversal that assigns each node to one or more
 // buckets, and returns a report with the size of each bucket.
 //
 // We summarize the results of a census with counts broken down according to
 // criteria selected by the API consumer code that is requesting the census. For
 // example, the following breakdown might give an interesting overview of the
 // heap:
new file mode 100644
--- /dev/null
+++ b/js/public/UbiNodePostOrder.h
@@ -0,0 +1,165 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sts=4 et sw=4 tw=99:
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef js_UbiNodePostOrder_h
+#define js_UbiNodePostOrder_h
+
+#include "mozilla/DebugOnly.h"
+#include "mozilla/Move.h"
+
+#include "jsalloc.h"
+
+#include "js/UbiNode.h"
+#include "js/Utility.h"
+#include "js/Vector.h"
+
+namespace JS {
+namespace ubi {
+
+// A post-order depth-first traversal of `ubi::Node` graphs.
+//
+// NB: This traversal visits each node reachable from the start set exactly
+// once, and does not visit edges at all. Therefore, this traversal would be a
+// very poor choice for recording multiple paths to the same node, for example.
+// If your analysis needs to consider edges, use `JS::ubi::BreadthFirst`
+// instead.
+//
+// No GC may occur while an instance of `PostOrder` is live.
+//
+// The `Visitor` type provided to `PostOrder::traverse` must have the following
+// member:
+//
+//   bool operator()(Node& node)
+//
+//     The visitor method. This method is called once for each `node` reachable
+//     from the start set in post-order.
+//
+//     The visitor function should return true on success, or false if an error
+//     occurs. A false return value terminates the traversal immediately, and
+//     causes `PostOrder::traverse` to return false.
+struct PostOrder {
+  private:
+    struct OriginAndEdges {
+        Node       origin;
+        EdgeVector edges;
+
+        OriginAndEdges(const Node& node, EdgeVector&& edges)
+          : origin(node)
+          , edges(mozilla::Move(edges))
+        { }
+
+        OriginAndEdges(const OriginAndEdges& rhs) = delete;
+        OriginAndEdges& operator=(const OriginAndEdges& rhs) = delete;
+
+        OriginAndEdges(OriginAndEdges&& rhs)
+          : origin(rhs.origin)
+          , edges(mozilla::Move(rhs.edges))
+        {
+            MOZ_ASSERT(&rhs != this, "self-move disallowed");
+        }
+
+        OriginAndEdges& operator=(OriginAndEdges&& rhs) {
+            this->~OriginAndEdges();
+            new (this) OriginAndEdges(mozilla::Move(rhs));
+            return *this;
+        }
+    };
+
+    using Stack = js::Vector<OriginAndEdges, 256, js::SystemAllocPolicy>;
+    using Set = js::HashSet<Node, js::DefaultHasher<Node>, js::SystemAllocPolicy>;
+
+    JSRuntime*               rt;
+    Set                      seen;
+    Stack                    stack;
+    mozilla::DebugOnly<bool> traversed;
+
+  private:
+    bool fillEdgesFromRange(EdgeVector& edges, UniquePtr<EdgeRange>& range) {
+        MOZ_ASSERT(range);
+        for ( ; !range->empty(); range->popFront()) {
+            if (!edges.append(mozilla::Move(range->front())))
+                return false;
+        }
+        return true;
+    }
+
+    bool pushForTraversing(const Node& node) {
+        EdgeVector edges;
+        auto range = node.edges(rt, /* wantNames */ false);
+        return range &&
+            fillEdgesFromRange(edges, range) &&
+            stack.append(OriginAndEdges(node, mozilla::Move(edges)));
+    }
+
+
+  public:
+    // Construct a post-order traversal object.
+    //
+    // The traversal asserts that no GC happens in its runtime during its
+    // lifetime via the `AutoCheckCannotGC&` parameter. We do nothing with it,
+    // other than require it to exist with a lifetime that encloses our own.
+    PostOrder(JSRuntime* rt, AutoCheckCannotGC&)
+      : rt(rt)
+      , seen()
+      , stack()
+      , traversed(false)
+    { }
+
+    // Initialize this traversal object. Return false on OOM.
+    bool init() { return seen.init(); }
+
+    // Add `node` as a starting point for the traversal. You may add
+    // as many starting points as you like. Returns false on OOM.
+    bool addStart(const Node& node) {
+        if (!seen.put(node))
+            return false;
+        return pushForTraversing(node);
+    }
+
+    // Traverse the graph in post-order, starting with the set of nodes passed
+    // to `addStart` and applying `visitor::operator()` for each node in
+    // the graph, as described above.
+    //
+    // This should be called only once per instance of this class.
+    //
+    // Return false on OOM or error return from `visitor::operator()`.
+    template<typename Visitor>
+    bool traverse(Visitor visitor) {
+        MOZ_ASSERT(!traversed, "Can only traverse() once!");
+        traversed = true;
+
+        while (!stack.empty()) {
+            auto& origin = stack.back().origin;
+            auto& edges = stack.back().edges;
+
+            if (edges.empty()) {
+                if (!visitor(origin))
+                    return false;
+                stack.popBack();
+                continue;
+            }
+
+            Edge edge = mozilla::Move(edges.back());
+            edges.popBack();
+
+            auto ptr = seen.lookupForAdd(edge.referent);
+            // We've already seen this node, don't follow its edges.
+            if (ptr)
+                continue;
+
+            // Mark the referent as seen and follow its edges.
+            if (!seen.add(ptr, edge.referent) || !pushForTraversing(edge.referent))
+                return false;
+        }
+
+        return true;
+    }
+};
+
+} // namespace ubi
+} // namespace JS
+
+#endif // js_UbiNodePostOrder_h
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -20,17 +20,17 @@
 #include "asmjs/AsmJSLink.h"
 #include "asmjs/AsmJSValidate.h"
 #include "jit/InlinableNatives.h"
 #include "jit/JitFrameIterator.h"
 #include "js/Debug.h"
 #include "js/HashTable.h"
 #include "js/StructuredClone.h"
 #include "js/UbiNode.h"
-#include "js/UbiNodeTraverse.h"
+#include "js/UbiNodeBreadthFirst.h"
 #include "js/Vector.h"
 #include "vm/GlobalObject.h"
 #include "vm/Interpreter.h"
 #include "vm/ProxyObject.h"
 #include "vm/SavedStacks.h"
 #include "vm/Stack.h"
 #include "vm/TraceLogging.h"
 
--- a/js/src/builtin/Utilities.js
+++ b/js/src/builtin/Utilities.js
@@ -44,17 +44,16 @@ var std_String_substring = String_substr
 var std_WeakMap = WeakMap;
 // StopIteration is a bare constructor without properties or methods.
 var std_StopIteration = StopIteration;
 var std_Map_iterator_next = MapIteratorNext;
 
 
 /********** List specification type **********/
 
-
 /* Spec: ECMAScript Language Specification, 5.1 edition, 8.8 */
 function List() {
     this.length = 0;
 }
 
 {
   let ListProto = std_Object_create(null);
   ListProto.indexOf = std_Array_indexOf;
@@ -188,8 +187,15 @@ function SpeciesConstructor(obj, default
 
     // Step 9.
     if (IsConstructor(s))
         return s;
 
     // Step 10.
     ThrowTypeError(JSMSG_NOT_CONSTRUCTOR, "@@species property of object's constructor");
 }
+
+/*************************************** Testing functions ***************************************/
+function outer() {
+    return function inner() {
+        return "foo";
+    }
+}
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -5775,26 +5775,26 @@ BytecodeEmitter::emitFunction(ParseNode*
      * case, if the lambda runs multiple times then CloneFunctionObject will
      * make a deep clone of its contents.
      */
     if (fun->isInterpreted()) {
         bool singleton = checkRunOnceContext();
         if (!JSFunction::setTypeForScriptedFunction(cx, fun, singleton))
             return false;
 
+        SharedContext* outersc = sc;
         if (fun->isInterpretedLazy()) {
             if (!fun->lazyScript()->sourceObject()) {
                 JSObject* scope = innermostStaticScope();
                 JSObject* source = script->sourceObject();
                 fun->lazyScript()->setParent(scope, &source->as<ScriptSourceObject>());
             }
             if (emittingRunOnceLambda)
                 fun->lazyScript()->setTreatAsRunOnce();
         } else {
-            SharedContext* outersc = sc;
 
             if (outersc->isFunctionBox() && outersc->asFunctionBox()->mightAliasLocals())
                 funbox->setMightAliasLocals();      // inherit mightAliasLocals from parent
             MOZ_ASSERT_IF(outersc->strict(), funbox->strictScript);
 
             // Inherit most things (principals, version, etc) from the
             // parent.  Use default values for the rest.
             Rooted<JSScript*> parent(cx, script);
@@ -5822,16 +5822,18 @@ BytecodeEmitter::emitFunction(ParseNode*
 
             /* We measured the max scope depth when we parsed the function. */
             if (!bce2.emitFunctionScript(pn->pn_body))
                 return false;
 
             if (funbox->usesArguments && funbox->usesApply && funbox->usesThis)
                 script->setUsesArgumentsApplyAndThis();
         }
+        if (outersc->isFunctionBox())
+            outersc->asFunctionBox()->function()->nonLazyScript()->setHasInnerFunctions(true);
     } else {
         MOZ_ASSERT(IsAsmJSModuleNative(fun->native()));
     }
 
     /* Make the function object a literal in the outer script's pool. */
     unsigned index = objectList.add(pn->pn_funbox);
 
     /* Non-hoisted functions simply emit their respective op. */
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -6700,20 +6700,25 @@ Parser<ParseHandler>::statement(YieldHan
             if (!abortIfSyntaxParser())
                 return null();
             if (!report(ParseWarning, false, null(), JSMSG_USE_ASM_DIRECTIVE_FAIL))
                 return null();
         }
         return expressionStatement(yieldHandling);
 
       case TOK_YIELD: {
+        // Don't use a ternary operator here due to obscure linker issues
+        // around using static consts in the arms of a ternary.
+        TokenStream::Modifier modifier;
+        if (yieldExpressionsSupported())
+            modifier = TokenStream::Operand;
+        else
+            modifier = TokenStream::None;
+
         TokenKind next;
-        TokenStream::Modifier modifier = yieldExpressionsSupported()
-                                         ? TokenStream::Operand
-                                         : TokenStream::None;
         if (!tokenStream.peekToken(&next, modifier))
             return null();
         if (next == TOK_COLON) {
             if (!checkYieldNameValidity())
                 return null();
             return labeledStatement(yieldHandling);
         }
         return expressionStatement(yieldHandling);
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/relazify-selfhosted.js
@@ -0,0 +1,4 @@
+var g = newGlobal();
+g.eval("this.inner = getSelfHostedValue('outer')()");
+gc();
+g.inner();
--- a/js/src/jsapi-tests/testUbiNode.cpp
+++ b/js/src/jsapi-tests/testUbiNode.cpp
@@ -1,21 +1,62 @@
 /* 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 "builtin/TestingFunctions.h"
 #include "js/UbiNode.h"
+#include "js/UbiNodePostOrder.h"
 #include "jsapi-tests/tests.h"
 #include "vm/SavedFrame.h"
 
 using JS::RootedObject;
 using JS::RootedScript;
 using JS::RootedString;
 
+// A helper JS::ubi::Node concrete implementation that can be used to make mock
+// graphs for testing traversals with.
+struct FakeNode
+{
+    char                name;
+    JS::ubi::EdgeVector edges;
+
+    explicit FakeNode(char name) : name(name), edges() { }
+
+    bool addEdgeTo(FakeNode& referent) {
+        JS::ubi::Node node(&referent);
+        return edges.emplaceBack(nullptr, node);
+    }
+};
+
+namespace JS {
+namespace ubi {
+
+template<>
+struct Concrete<FakeNode> : public Base
+{
+    static const char16_t concreteTypeName[];
+    const char16_t* typeName() const { return concreteTypeName; }
+
+    UniquePtr<EdgeRange> edges(JSRuntime* rt, bool wantNames) const {
+        return UniquePtr<EdgeRange>(js_new<PreComputedEdgeRange>(get().edges));
+    }
+
+    static void construct(void* storage, FakeNode* ptr) { new (storage) Concrete(ptr); }
+
+  protected:
+    explicit Concrete(FakeNode* ptr) : Base(ptr) { }
+    FakeNode& get() const { return *static_cast<FakeNode*>(ptr); }
+};
+
+const char16_t Concrete<FakeNode>::concreteTypeName[] = MOZ_UTF16("FakeNode");
+
+} // namespace ubi
+} // namespace JS
+
 // ubi::Node::zone works
 BEGIN_TEST(test_ubiNodeZone)
 {
     RootedObject global1(cx, JS::CurrentGlobalOrNull(cx));
     CHECK(global1);
     CHECK(JS::ubi::Node(global1).zone() == cx->zone());
 
     RootedObject global2(cx, JS_NewGlobalObject(cx, getGlobalClass(), nullptr,
@@ -218,8 +259,89 @@ BEGIN_TEST(test_ubiCoarseType)
     // Test that the default when coarseType() is not overridden is Other.
 
     JS::Symbol* sym = nullptr;
     CHECK(JS::ubi::Node(sym).coarseType() == JS::ubi::CoarseType::Other);
 
     return true;
 }
 END_TEST(test_ubiCoarseType)
+
+BEGIN_TEST(test_ubiPostOrder)
+{
+    // Construct the following graph:
+    //
+    //                          .-----.
+    //                          |     |
+    //                  .-------|  r  |---------------.
+    //                  |       |     |               |
+    //                  |       '-----'               |
+    //                  |                             |
+    //               .--V--.                       .--V--.
+    //               |     |                       |     |
+    //        .------|  a  |------.           .----|  e  |----.
+    //        |      |     |      |           |    |     |    |
+    //        |      '--^--'      |           |    '-----'    |
+    //        |         |         |           |               |
+    //     .--V--.      |      .--V--.     .--V--.         .--V--.
+    //     |     |      |      |     |     |     |         |     |
+    //     |  b  |      '------|  c  |----->  f  |--------->  g  |
+    //     |     |             |     |     |     |         |     |
+    //     '-----'             '-----'     '-----'         '-----'
+    //        |                   |
+    //        |      .-----.      |
+    //        |      |     |      |
+    //        '------>  d  <------'
+    //               |     |
+    //               '-----'
+    //
+
+    FakeNode r('r');
+    FakeNode a('a');
+    FakeNode b('b');
+    FakeNode c('c');
+    FakeNode d('d');
+    FakeNode e('e');
+    FakeNode f('f');
+    FakeNode g('g');
+
+    r.addEdgeTo(a);
+    r.addEdgeTo(e);
+    a.addEdgeTo(b);
+    a.addEdgeTo(c);
+    b.addEdgeTo(d);
+    c.addEdgeTo(a);
+    c.addEdgeTo(d);
+    c.addEdgeTo(f);
+    e.addEdgeTo(f);
+    e.addEdgeTo(g);
+    f.addEdgeTo(g);
+
+    js::Vector<char, 8, js::SystemAllocPolicy> visited;
+    {
+        // Do a PostOrder traversal, starting from r. Accumulate the names of
+        // the nodes we visit in `visited`.
+        JS::AutoCheckCannotGC nogc(rt);
+        JS::ubi::PostOrder traversal(rt, nogc);
+        CHECK(traversal.init());
+        CHECK(traversal.addStart(&r));
+        CHECK(traversal.traverse([&](const JS::ubi::Node& node) {
+            return visited.append(node.as<FakeNode>()->name);
+        }));
+    }
+
+    fprintf(stderr, "visited.length() = %lu\n", (unsigned long) visited.length());
+    for (size_t i = 0; i < visited.length(); i++)
+        fprintf(stderr, "visited[%lu] = '%c'\n", (unsigned long) i, visited[i]);
+
+    CHECK(visited.length() == 8);
+    CHECK(visited[0] == 'g');
+    CHECK(visited[1] == 'f');
+    CHECK(visited[2] == 'e');
+    CHECK(visited[3] == 'd');
+    CHECK(visited[4] == 'c');
+    CHECK(visited[5] == 'b');
+    CHECK(visited[6] == 'a');
+    CHECK(visited[7] == 'r');
+
+    return true;
+}
+END_TEST(test_ubiPostOrder)
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -595,16 +595,17 @@ js::XDRScript(XDRState<mode>* xdr, Handl
         IsStarGenerator,
         OwnSource,
         ExplicitUseStrict,
         SelfHosted,
         HasSingleton,
         TreatAsRunOnce,
         HasLazyScript,
         HasNonSyntacticScope,
+        HasInnerFunctions,
     };
 
     uint32_t length, lineno, column, nslots;
     uint32_t natoms, nsrcnotes, i;
     uint32_t nconsts, nobjects, nregexps, ntrynotes, nblockscopes, nyieldoffsets;
     uint32_t prologueLength, version;
     uint32_t funLength = 0;
     uint32_t nTypeSets = 0;
@@ -730,16 +731,18 @@ js::XDRScript(XDRState<mode>* xdr, Handl
         if (script->hasSingletons())
             scriptBits |= (1 << HasSingleton);
         if (script->treatAsRunOnce())
             scriptBits |= (1 << TreatAsRunOnce);
         if (script->isRelazifiable())
             scriptBits |= (1 << HasLazyScript);
         if (script->hasNonSyntacticScope())
             scriptBits |= (1 << HasNonSyntacticScope);
+        if (script->hasInnerFunctions())
+            scriptBits |= (1 << HasInnerFunctions);
     }
 
     if (!xdr->codeUint32(&prologueLength))
         return false;
     if (!xdr->codeUint32(&version))
         return false;
 
     // To fuse allocations, we need lengths of all embedded arrays early.
@@ -864,16 +867,18 @@ js::XDRScript(XDRState<mode>* xdr, Handl
         if (scriptBits & (1 << IsGeneratorExp))
             script->isGeneratorExp_ = true;
         if (scriptBits & (1 << HasSingleton))
             script->hasSingletons_ = true;
         if (scriptBits & (1 << TreatAsRunOnce))
             script->treatAsRunOnce_ = true;
         if (scriptBits & (1 << HasNonSyntacticScope))
             script->hasNonSyntacticScope_ = true;
+        if (scriptBits & (1 << HasInnerFunctions))
+            script->hasInnerFunctions_ = true;
 
         if (scriptBits & (1 << IsLegacyGenerator)) {
             MOZ_ASSERT(!(scriptBits & (1 << IsStarGenerator)));
             script->setGeneratorKind(LegacyGenerator);
         } else if (scriptBits & (1 << IsStarGenerator))
             script->setGeneratorKind(StarGenerator);
     }
 
@@ -3367,16 +3372,17 @@ js::detail::CopyScript(JSContext* cx, Ha
     dst->strict_ = src->strict();
     dst->explicitUseStrict_ = src->explicitUseStrict();
     dst->bindingsAccessedDynamically_ = src->bindingsAccessedDynamically();
     dst->funHasExtensibleScope_ = src->funHasExtensibleScope();
     dst->funNeedsDeclEnvObject_ = src->funNeedsDeclEnvObject();
     dst->funHasAnyAliasedFormal_ = src->funHasAnyAliasedFormal();
     dst->hasSingletons_ = src->hasSingletons();
     dst->treatAsRunOnce_ = src->treatAsRunOnce();
+    dst->hasInnerFunctions_ = src->hasInnerFunctions();
     dst->isGeneratorExp_ = src->isGeneratorExp();
     dst->setGeneratorKind(src->generatorKind());
 
     if (nconsts != 0) {
         HeapValue* vector = Rebase<HeapValue>(dst, src, src->consts()->vector);
         dst->consts()->vector = vector;
         for (unsigned i = 0; i < nconsts; ++i)
             MOZ_ASSERT_IF(vector[i].isMarkable(), vector[i].toString()->isAtom());
--- a/js/src/jsscript.h
+++ b/js/src/jsscript.h
@@ -1149,16 +1149,20 @@ class JSScript : public js::gc::TenuredC
     // Do not relazify this script. This is used by the relazify() testing
     // function for scripts that are on the stack and also by the AutoDelazify
     // RAII class. Usually we don't relazify functions in compartments with
     // scripts on the stack, but the relazify() testing function overrides that,
     // and sometimes we're working with a cross-compartment function and need to
     // keep it from relazifying.
     bool doNotRelazify_:1;
 
+    // Script contains inner functions. Used to check if we can relazify the
+    // script.
+    bool hasInnerFunctions_:1;
+
     bool needsHomeObject_:1;
 
     bool isDerivedClassConstructor_:1;
 
     // Add padding so JSScript is gc::Cell aligned. Make padding protected
     // instead of private to suppress -Wunused-private-field compiler warnings.
   protected:
 #if JS_BITS_PER_WORD == 32
@@ -1478,16 +1482,24 @@ class JSScript : public js::gc::TenuredC
         MOZ_ASSERT(generation <= 1);
         typesGeneration_ = (bool) generation;
     }
 
     void setDoNotRelazify(bool b) {
         doNotRelazify_ = b;
     }
 
+    void setHasInnerFunctions(bool b) {
+        hasInnerFunctions_ = b;
+    }
+
+    bool hasInnerFunctions() const {
+        return hasInnerFunctions_;
+    }
+
     bool hasAnyIonScript() const {
         return hasIonScript();
     }
 
     bool hasIonScript() const {
         bool res = ion && ion != ION_DISABLED_SCRIPT && ion != ION_COMPILING_SCRIPT &&
                           ion != ION_PENDING_SCRIPT;
         MOZ_ASSERT_IF(res, baseline);
@@ -1540,17 +1552,17 @@ class JSScript : public js::gc::TenuredC
     uint8_t* baselineOrIonRawPointer() const {
         return baselineOrIonRaw;
     }
     static size_t offsetOfBaselineOrIonSkipArgCheck() {
         return offsetof(JSScript, baselineOrIonSkipArgCheck);
     }
 
     bool isRelazifiable() const {
-        return (selfHosted() || lazyScript) && !types_ &&
+        return (selfHosted() || lazyScript) && !hasInnerFunctions_ && !types_ &&
                !isGenerator() && !hasBaselineScript() && !hasAnyIonScript() &&
                !hasScriptCounts() && !doNotRelazify_;
     }
     void setLazyScript(js::LazyScript* lazy) {
         lazyScript = lazy;
     }
     js::LazyScript* maybeLazyScript() {
         return lazyScript;
--- a/js/src/moz.build
+++ b/js/src/moz.build
@@ -124,18 +124,19 @@ EXPORTS.js += [
     '../public/StructuredClone.h',
     '../public/TraceableHashTable.h',
     '../public/TraceableVector.h',
     '../public/TraceKind.h',
     '../public/TracingAPI.h',
     '../public/TrackedOptimizationInfo.h',
     '../public/TypeDecls.h',
     '../public/UbiNode.h',
+    '../public/UbiNodeBreadthFirst.h',
     '../public/UbiNodeCensus.h',
-    '../public/UbiNodeTraverse.h',
+    '../public/UbiNodePostOrder.h',
     '../public/Utility.h',
     '../public/Value.h',
     '../public/Vector.h',
     '../public/WeakMapPtr.h',
 ]
 
 UNIFIED_SOURCES += [
     'asmjs/AsmJSCompile.cpp',
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -19,17 +19,17 @@
 
 #include "frontend/BytecodeCompiler.h"
 #include "gc/Marking.h"
 #include "jit/BaselineDebugModeOSR.h"
 #include "jit/BaselineJIT.h"
 #include "jit/JSONSpewer.h"
 #include "jit/MIRGraph.h"
 #include "js/GCAPI.h"
-#include "js/UbiNodeTraverse.h"
+#include "js/UbiNodeBreadthFirst.h"
 #include "js/Vector.h"
 #include "vm/ArgumentsObject.h"
 #include "vm/DebuggerMemory.h"
 #include "vm/SPSProfiler.h"
 #include "vm/TraceLogging.h"
 #include "vm/WrapperObject.h"
 
 #include "jsgcinlines.h"
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -1571,17 +1571,17 @@ FrameLayerBuilder::Init(nsDisplayListBui
 }
 
 void
 FrameLayerBuilder::FlashPaint(gfxContext *aContext)
 {
   float r = float(rand()) / RAND_MAX;
   float g = float(rand()) / RAND_MAX;
   float b = float(rand()) / RAND_MAX;
-  aContext->SetColor(gfxRGBA(r, g, b, 0.4));
+  aContext->SetColor(Color(r, g, b, 0.4f));
   aContext->Paint();
 }
 
 static FrameLayerBuilder::DisplayItemData*
 AssertDisplayItemData(FrameLayerBuilder::DisplayItemData* aData)
 {
   MOZ_RELEASE_ASSERT(aData);
   MOZ_RELEASE_ASSERT(sAliveDisplayItemDatas && sAliveDisplayItemDatas->Contains(aData));
--- a/layout/base/gtest/moz.build
+++ b/layout/base/gtest/moz.build
@@ -7,17 +7,17 @@
 UNIFIED_SOURCES += [
     'TestAccessibleCaretEventHub.cpp',
     'TestAccessibleCaretManager.cpp',
 ]
 
 # THE MOCK_METHOD2 macro from gtest triggers this clang warning and it's hard
 # to work around, so we just ignore it.
 if CONFIG['CLANG_CXX']:
-  CXXFLAGS += ['-Wno-error=inconsistent-missing-override']
+  CXXFLAGS += ['-Wno-inconsistent-missing-override']
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 LOCAL_INCLUDES += [
     '/docshell/base',
     '/layout/base',
     '/layout/style',
 ]
--- a/layout/base/nsCSSRendering.cpp
+++ b/layout/base/nsCSSRendering.cpp
@@ -1576,63 +1576,47 @@ nsCSSRendering::PaintBoxShadowInner(nsPr
 
     // When there's a blur radius, gfxAlphaBoxBlur leaves the skiprect area
     // unchanged. And by construction the gfxSkipRect is not touched by the
     // rendered shadow (even after blurring), so those pixels must be completely
     // transparent in the shadow, so drawing them changes nothing.
     gfxContext* renderContext = aRenderingContext.ThebesContext();
     DrawTarget* drawTarget = renderContext->GetDrawTarget();
     nsContextBoxBlur blurringArea;
-    gfxContext* shadowContext =
-      blurringArea.Init(shadowPaintRect, 0, blurRadius, twipsPerPixel,
-                        renderContext, aDirtyRect, &skipGfxRect);
-    if (!shadowContext)
-      continue;
-    DrawTarget* shadowDT = shadowContext->GetDrawTarget();
-
-    // shadowContext is owned by either blurringArea or aRenderingContext.
-    MOZ_ASSERT(shadowContext == renderContext ||
-               shadowContext == blurringArea.GetContext());
-
-    // Set the shadow color; if not specified, use the foreground color
-    Color shadowColor = Color::FromABGR(shadowItem->mHasColor ?
-                                          shadowItem->mColor :
-                                          aForFrame->StyleColor()->mColor);
-    renderContext->Save();
-    renderContext->SetColor(ThebesColor(shadowColor));
 
     // Clip the context to the area of the frame's padding rect, so no part of the
     // shadow is painted outside. Also cut out anything beyond where the inset shadow
     // will be.
     Rect shadowGfxRect = NSRectToRect(paddingRect, twipsPerPixel);
     shadowGfxRect.Round();
+
+    // Set the shadow color; if not specified, use the foreground color
+    Color shadowColor = Color::FromABGR(shadowItem->mHasColor ?
+                                          shadowItem->mColor :
+                                          aForFrame->StyleColor()->mColor);
+
+    renderContext->Save();
+
+    // This clips the outside border radius.
+    // clipRectRadii is the border radius inside the inset shadow.
     if (hasBorderRadius) {
       RefPtr<Path> roundedRect =
         MakePathForRoundedRect(*drawTarget, shadowGfxRect, innerRadii);
       renderContext->Clip(roundedRect);
     } else {
       renderContext->Clip(shadowGfxRect);
     }
 
-    // Fill the surface minus the area within the frame that we should
-    // not paint in, and blur and apply it.
-    RefPtr<PathBuilder> builder =
-      shadowDT->CreatePathBuilder(FillRule::FILL_EVEN_ODD);
-    AppendRectToPath(builder, shadowPaintGfxRect, true);
-    if (hasBorderRadius) {
-      AppendRoundedRectToPath(builder, shadowClipGfxRect, clipRectRadii, false);
-    } else {
-      AppendRectToPath(builder, shadowClipGfxRect, false);
-    }
-    RefPtr<Path> path = builder->Finish();
-    shadowContext->SetPath(path);
-    shadowContext->Fill();
-    shadowContext->NewPath();
-
-    blurringArea.DoPaint();
+    nsContextBoxBlur insetBoxBlur;
+    gfxRect destRect = nsLayoutUtils::RectToGfxRect(shadowPaintRect, twipsPerPixel);
+    insetBoxBlur.InsetBoxBlur(renderContext, ToRect(destRect),
+                              shadowClipGfxRect, shadowColor,
+                              blurRadius, spreadDistanceAppUnits,
+                              twipsPerPixel, hasBorderRadius,
+                              clipRectRadii, ToRect(skipGfxRect));
     renderContext->Restore();
   }
 }
 
 DrawResult
 nsCSSRendering::PaintBackground(nsPresContext* aPresContext,
                                 nsRenderingContext& aRenderingContext,
                                 nsIFrame* aForFrame,
@@ -2930,17 +2914,17 @@ nsCSSRendering::PaintBackgroundWithSC(ns
     GetBackgroundClip(bg->BottomLayer(),
                       aForFrame, aBorder, aBorderArea,
                       aDirtyRect, (aFlags & PAINTBG_WILL_PAINT_BORDER), appUnitsPerPixel,
                       &clipState);
   }
 
   // If we might be using a background color, go ahead and set it now.
   if (drawBackgroundColor && !isCanvasFrame)
-    ctx->SetColor(gfxRGBA(bgColor));
+    ctx->SetColor(Color::FromABGR(bgColor));
 
   // NOTE: no Save() yet, we do that later by calling autoSR.EnsureSaved(ctx)
   // in the cases we need it.
   gfxContextAutoSaveRestore autoSR;
 
   // If there is no background image, draw a color.  (If there is
   // neither a background image nor a color, we wouldn't have gotten
   // this far.)
@@ -3858,17 +3842,17 @@ nsCSSRendering::DrawTableBorderSegment(n
     aStartBevelOffset = 0;
     aEndBevelOffset = 0;
   }
 
   gfxContext *ctx = aContext.ThebesContext();
   AntialiasMode oldMode = ctx->CurrentAntialiasMode();
   ctx->SetAntialiasMode(AntialiasMode::NONE);
 
-  ctx->SetColor(aBorderColor);
+  ctx->SetColor(Color::FromABGR(aBorderColor));
 
   switch (aBorderStyle) {
   case NS_STYLE_BORDER_STYLE_NONE:
   case NS_STYLE_BORDER_STYLE_HIDDEN:
     //NS_ASSERTION(false, "style of none or hidden");
     break;
   case NS_STYLE_BORDER_STYLE_DOTTED:
   case NS_STYLE_BORDER_STYLE_DASHED:
@@ -3938,17 +3922,17 @@ nsCSSRendering::DrawTableBorderSegment(n
                             ? RoundFloatToPixel(0.5f * (float)aEndBevelOffset, twipsPerPixel, true) : 0;
       mozilla::css::Side ridgeGrooveSide = (horizontal) ? NS_SIDE_TOP : NS_SIDE_LEFT;
       // FIXME: In theory, this should use the visited-dependent
       // background color, but I don't care.
       nscolor bevelColor = MakeBevelColor(ridgeGrooveSide, ridgeGroove,
                                           aBGColor->mBackgroundColor,
                                           aBorderColor);
       // XXXbz is this SetColor call still needed?
-      ctx->SetColor(bevelColor);
+      ctx->SetColor(Color::FromABGR(bevelColor));
       nsRect rect(aBorder);
       nscoord half;
       if (horizontal) { // top, bottom
         half = RoundFloatToPixel(0.5f * (float)aBorder.height, twipsPerPixel);
         rect.height = half;
         if (NS_SIDE_TOP == aStartBevelSide) {
           rect.x += startBevel;
           rect.width -= startBevel;
@@ -3975,17 +3959,17 @@ nsCSSRendering::DrawTableBorderSegment(n
 
       rect = aBorder;
       ridgeGrooveSide = (NS_SIDE_TOP == ridgeGrooveSide) ? NS_SIDE_BOTTOM : NS_SIDE_RIGHT;
       // FIXME: In theory, this should use the visited-dependent
       // background color, but I don't care.
       bevelColor = MakeBevelColor(ridgeGrooveSide, ridgeGroove,
                                   aBGColor->mBackgroundColor, aBorderColor);
       // XXXbz is this SetColor call still needed?
-      ctx->SetColor(bevelColor);
+      ctx->SetColor(Color::FromABGR(bevelColor));
       if (horizontal) {
         rect.y = rect.y + half;
         rect.height = aBorder.height - half;
         if (NS_SIDE_BOTTOM == aStartBevelSide) {
           rect.x += startBevel;
           rect.width -= startBevel;
         }
         if (NS_SIDE_BOTTOM == aEndBevelSide) {
@@ -4795,17 +4779,17 @@ nsImageRenderer::ComputeIntrinsicSize()
           result.SetSize(
             IntSizeToAppUnits(
               nsSVGIntegrationUtils::GetContinuationUnionSize(mPaintServerFrame).
                 ToNearestPixels(appUnitsPerDevPixel),
               appUnitsPerDevPixel));
         }
       } else {
         NS_ASSERTION(mImageElementSurface.mSourceSurface, "Surface should be ready.");
-        gfxIntSize surfaceSize = mImageElementSurface.mSize;
+        IntSize surfaceSize = mImageElementSurface.mSize;
         result.SetSize(
           nsSize(nsPresContext::CSSPixelsToAppUnits(surfaceSize.width),
                  nsPresContext::CSSPixelsToAppUnits(surfaceSize.height)));
       }
       break;
     }
     case eStyleImageType_Gradient:
       // Per <http://dev.w3.org/csswg/css3-images/#gradients>, gradients have no
@@ -5029,17 +5013,17 @@ nsImageRenderer::DrawableForElement(cons
                                     nsRenderingContext&  aRenderingContext)
 {
   NS_ASSERTION(mType == eStyleImageType_Element,
                "DrawableForElement only makes sense if backed by an element");
   if (mPaintServerFrame) {
     int32_t appUnitsPerDevPixel = mForFrame->PresContext()->AppUnitsPerDevPixel();
     nsRect destRect = aImageRect - aImageRect.TopLeft();
     nsIntSize roundedOut = destRect.ToOutsidePixels(appUnitsPerDevPixel).Size();
-    gfxIntSize imageSize(roundedOut.width, roundedOut.height);
+    IntSize imageSize(roundedOut.width, roundedOut.height);
     nsRefPtr<gfxDrawable> drawable =
       nsSVGIntegrationUtils::DrawableFromPaintServer(
         mPaintServerFrame, mForFrame, mSize, imageSize,
         aRenderingContext.GetDrawTarget(),
         aRenderingContext.ThebesContext()->CurrentMatrix(),
         mFlags & FLAG_SYNC_DECODE_IMAGES
           ? nsSVGIntegrationUtils::FLAG_SYNC_DECODE_IMAGES
           : 0);
@@ -5288,17 +5272,17 @@ static inline gfxPoint ComputeBlurStdDev
   gfxFloat blurStdDev = gfxFloat(aBlurRadius) / gfxFloat(aAppUnitsPerDevPixel);
 
   return gfxPoint(std::min((blurStdDev * aScaleX),
                            gfxFloat(MAX_BLUR_RADIUS)) / 2.0,
                   std::min((blurStdDev * aScaleY),
                            gfxFloat(MAX_BLUR_RADIUS)) / 2.0);
 }
 
-static inline gfxIntSize
+static inline IntSize
 ComputeBlurRadius(nscoord aBlurRadius,
                   int32_t aAppUnitsPerDevPixel,
                   gfxFloat aScaleX = 1.0,
                   gfxFloat aScaleY = 1.0)
 {
   gfxPoint scaledBlurStdDev = ComputeBlurStdDev(aBlurRadius, aAppUnitsPerDevPixel,
                                                 aScaleX, aScaleY);
   return
@@ -5317,37 +5301,22 @@ nsContextBoxBlur::Init(const nsRect& aRe
                        const gfxRect* aSkipRect,
                        uint32_t aFlags)
 {
   if (aRect.IsEmpty()) {
     mContext = nullptr;
     return nullptr;
   }
 
-  gfxFloat scaleX = 1;
-  gfxFloat scaleY = 1;
-
-  // Do blurs in device space when possible.
-  // Chrome/Skia always does the blurs in device space
-  // and will sometimes get incorrect results (e.g. rotated blurs)
-  gfxMatrix transform = aDestinationCtx->CurrentMatrix();
-  // XXX: we could probably handle negative scales but for now it's easier just to fallback
-  if (transform.HasNonAxisAlignedTransform() || transform._11 <= 0.0 || transform._22 <= 0.0) {
-    transform = gfxMatrix();
-  } else {
-    scaleX = transform._11;
-    scaleY = transform._22;
-  }
-
-  // compute a large or smaller blur radius
-  gfxIntSize blurRadius = ComputeBlurRadius(aBlurRadius, aAppUnitsPerDevPixel, scaleX, scaleY);
-  gfxIntSize spreadRadius = gfxIntSize(std::min(int32_t(aSpreadRadius * scaleX / aAppUnitsPerDevPixel),
-                                              int32_t(MAX_SPREAD_RADIUS)),
-                                       std::min(int32_t(aSpreadRadius * scaleY / aAppUnitsPerDevPixel),
-                                              int32_t(MAX_SPREAD_RADIUS)));
+  IntSize blurRadius;
+  IntSize spreadRadius;
+  GetBlurAndSpreadRadius(aDestinationCtx, aAppUnitsPerDevPixel,
+                         aBlurRadius, aSpreadRadius,
+                         blurRadius, spreadRadius);
+
   mDestinationCtx = aDestinationCtx;
 
   // If not blurring, draw directly onto the destination device
   if (blurRadius.width <= 0 && blurRadius.height <= 0 &&
       spreadRadius.width <= 0 && spreadRadius.height <= 0 &&
       !(aFlags & FORCE_MASK)) {
     mContext = aDestinationCtx;
     return mContext;
@@ -5355,16 +5324,17 @@ nsContextBoxBlur::Init(const nsRect& aRe
 
   // Convert from app units to device pixels
   gfxRect rect = nsLayoutUtils::RectToGfxRect(aRect, aAppUnitsPerDevPixel);
 
   gfxRect dirtyRect =
     nsLayoutUtils::RectToGfxRect(aDirtyRect, aAppUnitsPerDevPixel);
   dirtyRect.RoundOut();
 
+  gfxMatrix transform = aDestinationCtx->CurrentMatrix();
   rect = transform.TransformBounds(rect);
 
   mPreTransformed = !transform.IsIdentity();
 
   // Create the temporary surface for blurring
   dirtyRect = transform.TransformBounds(dirtyRect);
   if (aSkipRect) {
     gfxRect skipRect = transform.TransformBounds(*aSkipRect);
@@ -5381,18 +5351,19 @@ nsContextBoxBlur::Init(const nsRect& aRe
     mContext->Multiply(transform);
   }
   return mContext;
 }
 
 void
 nsContextBoxBlur::DoPaint()
 {
-  if (mContext == mDestinationCtx)
+  if (mContext == mDestinationCtx) {
     return;
+  }
 
   gfxContextMatrixAutoSaveRestore saveMatrix(mDestinationCtx);
 
   if (mPreTransformed) {
     mDestinationCtx->SetMatrix(gfxMatrix());
   }
 
   mAlphaBoxBlur.Paint(mDestinationCtx);
@@ -5403,17 +5374,17 @@ nsContextBoxBlur::GetContext()
 {
   return mContext;
 }
 
 /* static */ nsMargin
 nsContextBoxBlur::GetBlurRadiusMargin(nscoord aBlurRadius,
                                       int32_t aAppUnitsPerDevPixel)
 {
-  gfxIntSize blurRadius = ComputeBlurRadius(aBlurRadius, aAppUnitsPerDevPixel);
+  IntSize blurRadius = ComputeBlurRadius(aBlurRadius, aAppUnitsPerDevPixel);
 
   nsMargin result;
   result.top = result.bottom = blurRadius.height * aAppUnitsPerDevPixel;
   result.left = result.right = blurRadius.width  * aAppUnitsPerDevPixel;
   return result;
 }
 
 /* static */ void
@@ -5480,8 +5451,104 @@ nsContextBoxBlur::BlurRectangle(gfxConte
   gfxAlphaBoxBlur::BlurRectangle(aDestinationCtx,
                                  shadowThebesRect,
                                  aCornerRadii,
                                  blurStdDev,
                                  aShadowColor,
                                  dirtyRect,
                                  skipRect);
 }
+
+/* static */ void
+nsContextBoxBlur::GetBlurAndSpreadRadius(gfxContext* aDestinationCtx,
+                                         int32_t aAppUnitsPerDevPixel,
+                                         nscoord aBlurRadius,
+                                         nscoord aSpreadRadius,
+                                         IntSize& aOutBlurRadius,
+                                         IntSize& aOutSpreadRadius,
+                                         bool aConstrainSpreadRadius)
+{
+  gfxFloat scaleX = 1;
+  gfxFloat scaleY = 1;
+
+  // Do blurs in device space when possible.
+  // Chrome/Skia always does the blurs in device space
+  // and will sometimes get incorrect results (e.g. rotated blurs)
+  gfxMatrix transform = aDestinationCtx->CurrentMatrix();
+  // XXX: we could probably handle negative scales but for now it's easier just to fallback
+  if (transform.HasNonAxisAlignedTransform() || transform._11 <= 0.0 || transform._22 <= 0.0) {
+    transform = gfxMatrix();
+  } else {
+    scaleX = transform._11;
+    scaleY = transform._22;
+  }
+
+  // compute a large or smaller blur radius
+  aOutBlurRadius = ComputeBlurRadius(aBlurRadius, aAppUnitsPerDevPixel, scaleX, scaleY);
+  aOutSpreadRadius =
+      IntSize(int32_t(aSpreadRadius * scaleX / aAppUnitsPerDevPixel),
+              int32_t(aSpreadRadius * scaleY / aAppUnitsPerDevPixel));
+
+
+  if (aConstrainSpreadRadius) {
+    aOutSpreadRadius.width = std::min(aOutSpreadRadius.width, int32_t(MAX_SPREAD_RADIUS));
+    aOutSpreadRadius.height = std::min(aOutSpreadRadius.height, int32_t(MAX_SPREAD_RADIUS));
+  }
+}
+
+/* static */ bool
+nsContextBoxBlur::InsetBoxBlur(gfxContext* aDestinationCtx,
+                               Rect aDestinationRect,
+                               Rect aShadowClipRect,
+                               Color& aShadowColor,
+                               nscoord aBlurRadiusAppUnits,
+                               nscoord aSpreadDistanceAppUnits,
+                               int32_t aAppUnitsPerDevPixel,
+                               bool aHasBorderRadius,
+                               RectCornerRadii& aInnerClipRectRadii,
+                               Rect aSkipRect)
+{
+  if (aDestinationRect.IsEmpty()) {
+    mContext = nullptr;
+    return false;
+  }
+
+  IntSize blurRadius;
+  IntSize spreadRadius;
+  // Convert the blur and spread radius to device pixels
+  bool constrainSpreadRadius = false;
+  GetBlurAndSpreadRadius(aDestinationCtx, aAppUnitsPerDevPixel,
+                         aBlurRadiusAppUnits, aSpreadDistanceAppUnits,
+                         blurRadius, spreadRadius, constrainSpreadRadius);
+
+  // The blur and spread radius are scaled already, so scale all
+  // input data to the blur. This way, we don't have to scale the min
+  // inset blur to the invert of the dest context, then rescale it back
+  // when we draw to the destination surface.
+  gfxSize scale = aDestinationCtx->CurrentMatrix().ScaleFactors(true);
+  Matrix currentMatrix = ToMatrix(aDestinationCtx->CurrentMatrix());
+
+  Rect transformedDestRect = currentMatrix.TransformBounds(aDestinationRect);
+  Rect transformedShadowClipRect = currentMatrix.TransformBounds(aShadowClipRect);
+  Rect transformedSkipRect = currentMatrix.TransformBounds(aSkipRect);
+
+  transformedDestRect.Round();
+  transformedShadowClipRect.Round();
+  transformedSkipRect.RoundIn();
+
+  for (size_t i = 0; i < 4; i++) {
+    aInnerClipRectRadii[i].width = std::floor(scale.width * aInnerClipRectRadii[i].width);
+    aInnerClipRectRadii[i].height = std::floor(scale.height * aInnerClipRectRadii[i].height);
+  }
+
+  {
+    gfxContextAutoSaveRestore autoRestore(aDestinationCtx);
+    aDestinationCtx->SetMatrix(gfxMatrix());
+
+    mAlphaBoxBlur.BlurInsetBox(aDestinationCtx, transformedDestRect,
+                               transformedShadowClipRect,
+                               blurRadius, spreadRadius,
+                               aShadowColor,
+                               aHasBorderRadius,
+                               aInnerClipRectRadii, transformedSkipRect);
+  }
+  return true;
+}
--- a/layout/base/nsCSSRendering.h
+++ b/layout/base/nsCSSRendering.h
@@ -20,16 +20,17 @@
 class gfxDrawable;
 class nsStyleContext;
 class nsPresContext;
 class nsRenderingContext;
 
 namespace mozilla {
 
 namespace gfx {
+struct Color;
 class DrawTarget;
 } // namespace gfx
 
 namespace layers {
 class ImageContainer;
 } // namespace layers
 
 // A CSSSizeOrRatio represents a (possibly partially specified) size for use
@@ -939,20 +940,60 @@ public:
                             const nsRect& aRect,
                             int32_t aAppUnitsPerDevPixel,
                             RectCornerRadii* aCornerRadii,
                             nscoord aBlurRadius,
                             const gfxRGBA& aShadowColor,
                             const nsRect& aDirtyRect,
                             const gfxRect& aSkipRect);
 
+  /**
+   * Draws a blurred inset box shadow shape onto the destination surface.
+   * Like BlurRectangle, this is equivalent to calling Init(),
+   * drawing a rectangle onto the returned surface
+   * and then calling DoPaint, but may let us optimize better in the
+   * backend.
+   *
+   * @param aDestinationCtx      The destination to blur to.
+   * @param aDestinationRect     The rectangle to blur in app units.
+   * @param aShadowClipRect      The inside clip rect that creates the path.
+   * @param aShadowColor         The color of the blur
+   * @param aBlurRadiusAppUnits  The blur radius in app units
+   * @param aSpreadRadiusAppUnits The spread radius in app units.
+   * @param aAppUnitsPerDevPixel The number of app units in a device pixel,
+   *                             for conversion.  Most of the time you'll
+   *                             pass this from the current PresContext if
+   *                             available.
+   * @param aHasBorderRadius     If this inset box blur has a border radius
+   * @param aInnerClipRectRadii  The clip rect radii used for the inside rect's path.
+   * @param aSkipRect            An area in device pixels (NOT app units!) to avoid
+   *                             blurring over, to prevent unnecessary work.
+   */
+  bool InsetBoxBlur(gfxContext* aDestinationCtx,
+                    mozilla::gfx::Rect aDestinationRect,
+                    mozilla::gfx::Rect aShadowClipRect,
+                    mozilla::gfx::Color& aShadowColor,
+                    nscoord aBlurRadiusAppUnits,
+                    nscoord aSpreadRadiusAppUnits,
+                    int32_t aAppUnitsPerDevPixel,
+                    bool aHasBorderRadius,
+                    RectCornerRadii& aInnerClipRectRadii,
+                    mozilla::gfx::Rect aSkipRect);
+
 protected:
+  static void GetBlurAndSpreadRadius(gfxContext* aContext,
+                                     int32_t aAppUnitsPerDevPixel,
+                                     nscoord aBlurRadius,
+                                     nscoord aSpreadRadius,
+                                     mozilla::gfx::IntSize& aOutBlurRadius,
+                                     mozilla::gfx::IntSize& aOutSpreadRadius,
+                                     bool aConstrainSpreadRadius = true);
+
   gfxAlphaBoxBlur mAlphaBoxBlur;
   nsRefPtr<gfxContext> mContext;
   gfxContext* mDestinationCtx;
 
   /* This is true if the blur already has it's content transformed
    * by mDestinationCtx's transform */
   bool mPreTransformed;
-
 };
 
 #endif /* nsCSSRendering_h___ */
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -5604,17 +5604,17 @@ nsLayoutUtils::PaintTextShadow(const nsI
       shadowColor = aForegroundColor;
 
     // Conjure an nsRenderingContext from a gfxContext for drawing the text
     // to blur.
     nsRenderingContext renderingContext(shadowContext);
 
     aDestCtx->Save();
     aDestCtx->NewPath();
-    aDestCtx->SetColor(gfxRGBA(shadowColor));
+    aDestCtx->SetColor(Color::FromABGR(shadowColor));
 
     // The callback will draw whatever we want to blur as a shadow.
     aCallback(&renderingContext, shadowOffset, shadowColor, aCallbackData);
 
     contextBoxBlur.DoPaint();
     aDestCtx->Restore();
   }
 }
@@ -6823,17 +6823,17 @@ nsLayoutUtils::SurfaceFromElement(nsIIma
     result.mDrawInfo.mDrawingFlags = frameFlags;
   }
 
   int32_t corsmode;
   if (NS_SUCCEEDED(imgRequest->GetCORSMode(&corsmode))) {
     result.mCORSUsed = (corsmode != imgIRequest::CORS_NONE);
   }
 
-  result.mSize = gfxIntSize(imgWidth, imgHeight);
+  result.mSize = IntSize(imgWidth, imgHeight);
   result.mPrincipal = principal.forget();
   // no images, including SVG images, can load content from another domain.
   result.mIsWriteOnly = false;
   result.mImageRequest = imgRequest.forget();
 
   return result;
 }
 
@@ -6853,17 +6853,17 @@ nsLayoutUtils::SurfaceFromElement(HTMLCa
 {
   SurfaceFromElementResult result;
 
   bool* isPremultiplied = nullptr;
   if (aSurfaceFlags & SFE_PREFER_NO_PREMULTIPLY_ALPHA) {
     isPremultiplied = &result.mIsPremultiplied;
   }
 
-  gfxIntSize size = aElement->GetSize();
+  IntSize size = aElement->GetSize();
 
   result.mSourceSurface = aElement->GetSurfaceSnapshot(isPremultiplied);
   if (!result.mSourceSurface) {
      // If the element doesn't have a context then we won't get a snapshot. The canvas spec wants us to not error and just
      // draw nothing, so return an empty surface.
      DrawTarget *ref = aTarget ? aTarget : gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget();
      RefPtr<DrawTarget> dt = ref->CreateSimilarDrawTarget(IntSize(size.width, size.height),
                                                           SurfaceFormat::B8G8R8A8);
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -2061,17 +2061,17 @@ public:
     SurfaceFromElementResult();
 
     /* mSourceSurface will contain the resulting surface, or will be nullptr on error */
     mozilla::RefPtr<SourceSurface> mSourceSurface;
     /* Contains info for drawing when there is no mSourceSurface. */
     DirectDrawInfo mDrawInfo;
 
     /* The size of the surface */
-    gfxIntSize mSize;
+    mozilla::gfx::IntSize mSize;
     /* The principal associated with the element whose surface was returned.
        If there is a surface, this will never be null. */
     nsCOMPtr<nsIPrincipal> mPrincipal;
     /* The image request, if the element is an nsIImageLoadingContent */
     nsCOMPtr<imgIRequest> mImageRequest;
     /* Whether the element was "write only", that is, the bits should not be exposed to content */
     bool mIsWriteOnly;
     /* Whether the element was still loading.  Some consumers need to handle
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -4636,17 +4636,17 @@ PresShell::RenderDocument(const nsRect& 
   aThebesContext->Rectangle(r, true);
 #else
   aThebesContext->Rectangle(r);
 #endif
 
   nsIFrame* rootFrame = mFrameConstructor->GetRootFrame();
   if (!rootFrame) {
     // Nothing to paint, just fill the rect
-    aThebesContext->SetColor(gfxRGBA(aBackgroundColor));
+    aThebesContext->SetColor(Color::FromABGR(aBackgroundColor));
     aThebesContext->Fill();
     return NS_OK;
   }
 
   gfxContextAutoSaveRestore save(aThebesContext);
 
   gfxContext::GraphicsOperator oldOperator = aThebesContext->CurrentOperator();
   if (oldOperator == gfxContext::OPERATOR_OVER) {
@@ -10228,33 +10228,33 @@ void ReflowCountMgr::PaintCount(const ch
 
       char buf[16];
       int len = snprintf_literal(buf, "%d", counter->mCount);
       nscoord x = 0, y = fm->MaxAscent();
       nscoord width, height = fm->MaxHeight();
       fm->SetTextRunRTL(false);
       width = fm->GetWidth(buf, len, aRenderingContext);;
 
-      uint32_t color;
-      uint32_t color2;
+      Color color;
+      Color color2;
       if (aColor != 0) {
-        color  = aColor;
-        color2 = NS_RGB(0,0,0);
+        color  = Color::FromABGR(aColor);
+        color2 = Color(0.f, 0.f, 0.f);
       } else {
-        uint8_t rc = 0, gc = 0, bc = 0;
+        gfx::Float rc = 0.f, gc = 0.f, bc = 0.f;
         if (counter->mCount < 5) {
-          rc = 255;
-          gc = 255;
-        } else if ( counter->mCount < 11) {
-          gc = 255;
+          rc = 1.f;
+          gc = 1.f;
+        } else if (counter->mCount < 11) {
+          gc = 1.f;
         } else {
-          rc = 255;
+          rc = 1.f;
         }
-        color  = NS_RGB(rc,gc,bc);
-        color2 = NS_RGB(rc/2,gc/2,bc/2);
+        color  = Color(rc, gc, bc);
+        color2 = Color(rc/2, gc/2, bc/2);
       }
 
       nsRect rect(0,0, width+15, height+15);
       Rect devPxRect =
         NSRectToSnappedRect(rect, appUnitsPerDevPixel, *drawTarget);
       ColorPattern black(ToDeviceColor(Color(0.f, 0.f, 0.f, 1.f)));
       drawTarget->FillRect(devPxRect, black);
 
--- a/layout/generic/TextOverflow.cpp
+++ b/layout/generic/TextOverflow.cpp
@@ -212,17 +212,17 @@ nsDisplayTextOverflowMarker::Paint(nsDis
 {
   nscolor foregroundColor =
     nsLayoutUtils::GetColor(mFrame, eCSSProperty_color);
 
   // Paint the text-shadows for the overflow marker
   nsLayoutUtils::PaintTextShadow(mFrame, aCtx, mRect, mVisibleRect,
                                  foregroundColor, PaintTextShadowCallback,
                                  (void*)this);
-  aCtx->ThebesContext()->SetColor(foregroundColor);
+  aCtx->ThebesContext()->SetColor(gfx::Color::FromABGR(foregroundColor));
   PaintTextToContext(aCtx, nsPoint(0, 0));
 }
 
 void
 nsDisplayTextOverflowMarker::PaintTextToContext(nsRenderingContext* aCtx,
                                                 nsPoint aOffsetFromRect)
 {
   WritingMode wm = mFrame->GetWritingMode();
--- a/layout/generic/nsBulletFrame.cpp
+++ b/layout/generic/nsBulletFrame.cpp
@@ -405,17 +405,17 @@ nsBulletFrame::PaintBullet(nsRenderingCo
       RefPtr<Path> path = builder->Finish();
       drawTarget->Fill(path, color);
     }
     break;
 
   default:
     {
       aRenderingContext.ThebesContext()->SetColor(
-                          nsLayoutUtils::GetColor(this, eCSSProperty_color));
+        Color::FromABGR(nsLayoutUtils::GetColor(this, eCSSProperty_color)));
 
       nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm),
                                             GetFontSizeInflation());
       nsAutoString text;
       GetListItemText(text);
       WritingMode wm = GetWritingMode();
       nscoord ascent = wm.IsLineInverted()
                          ? fm->MaxDescent() : fm->MaxAscent();
--- a/layout/generic/nsImageFrame.cpp
+++ b/layout/generic/nsImageFrame.cpp
@@ -1126,17 +1126,18 @@ nsImageFrame::MeasureString(const char16
 // between words if a word would extend past the edge of the rectangle
 void
 nsImageFrame::DisplayAltText(nsPresContext*      aPresContext,
                              nsRenderingContext& aRenderingContext,
                              const nsString&      aAltText,
                              const nsRect&        aRect)
 {
   // Set font and color
-  aRenderingContext.ThebesContext()->SetColor(StyleColor()->mColor);
+  aRenderingContext.ThebesContext()->
+    SetColor(Color::FromABGR(StyleColor()->mColor));
   nsRefPtr<nsFontMetrics> fm;
   nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm),
     nsLayoutUtils::FontSizeInflationFor(this));
 
   // Format the text to display within the formatting rect
 
   nscoord maxAscent = fm->MaxAscent();
   nscoord maxDescent = fm->MaxDescent();
--- a/layout/generic/nsPageFrame.cpp
+++ b/layout/generic/nsPageFrame.cpp
@@ -385,17 +385,17 @@ nsPageFrame::DrawHeaderFooter(nsRenderin
 
     DrawTarget* drawTarget = aRenderingContext.GetDrawTarget();
     gfxContext* gfx = aRenderingContext.ThebesContext();
 
     // set up new clip and draw the text
     gfx->Save();
     gfx->Clip(NSRectToSnappedRect(aRect, PresContext()->AppUnitsPerDevPixel(),
                                   *drawTarget));
-    aRenderingContext.ThebesContext()->SetColor(NS_RGB(0,0,0));
+    aRenderingContext.ThebesContext()->SetColor(Color(0.f, 0.f, 0.f));
     nsLayoutUtils::DrawString(this, aFontMetrics, &aRenderingContext,
                               str.get(), str.Length(),
                               nsPoint(x, y + aAscent));
     gfx->Restore();
   }
 }
 
 /**
@@ -619,17 +619,17 @@ nsPageFrame::PaintHeaderFooter(nsRenderi
   if (!mPD->mPrintSettings) {
     if (pc->Type() == nsPresContext::eContext_PrintPreview || pc->IsDynamic())
       mPD->mPrintSettings = pc->GetPrintSettings();
     if (!mPD->mPrintSettings)
       return;
   }
 
   nsRect rect(aPt, mRect.Size());
-  aRenderingContext.ThebesContext()->SetColor(NS_RGB(0,0,0));
+  aRenderingContext.ThebesContext()->SetColor(Color(0.f, 0.f, 0.f));
 
   gfxContextAutoDisableSubpixelAntialiasing disable(aRenderingContext.ThebesContext(), aDisableSubpixelAA);
 
   // Get the FontMetrics to determine width.height of strings
   nsRefPtr<nsFontMetrics> fontMet;
   pc->DeviceContext()->GetMetricsFor(mPD->mHeadFootFont, nullptr, false,
                                      gfxFont::eHorizontal,
                                      pc->GetUserFontSet(),
--- a/layout/generic/nsTextFrame.cpp
+++ b/layout/generic/nsTextFrame.cpp
@@ -5686,17 +5686,17 @@ nsTextFrame::PaintOneShadow(uint32_t aOf
     decorationOverrideColor = &shadowColor;
   } else {
     shadowColor = aForegroundColor;
     decorationOverrideColor = nullptr;
   }
 
   aCtx->Save();
   aCtx->NewPath();
-  aCtx->SetColor(gfxRGBA(shadowColor));
+  aCtx->SetColor(Color::FromABGR(shadowColor));
 
   // Draw the text onto our alpha-only surface to capture the alpha values.
   // Remember that the box blur context has a device offset on it, so we don't need to
   // translate any coordinates to fit on the surface.
   gfxFloat advanceWidth;
   gfxRect dirtyRect(aDirtyRect.x, aDirtyRect.y,
                     aDirtyRect.width, aDirtyRect.height);
   DrawText(shadowContext, dirtyRect, aFramePt + shadowOffset,
@@ -6332,17 +6332,17 @@ DrawTextRun(gfxTextRun* aTextRun,
   DrawMode drawMode = aCallbacks ? DrawMode::GLYPH_PATH :
                                    DrawMode::GLYPH_FILL;
   if (aCallbacks) {
     aCallbacks->NotifyBeforeText(aTextColor);
     aTextRun->Draw(aCtx, aTextBaselinePt, drawMode, aOffset, aLength,
                    aProvider, aAdvanceWidth, aContextPaint, aCallbacks);
     aCallbacks->NotifyAfterText();
   } else {
-    aCtx->SetColor(gfxRGBA(aTextColor));
+    aCtx->SetColor(Color::FromABGR(aTextColor));
     aTextRun->Draw(aCtx, aTextBaselinePt, drawMode, aOffset, aLength,
                    aProvider, aAdvanceWidth, aContextPaint);
   }
 }
 
 void
 nsTextFrame::DrawTextRun(gfxContext* const aCtx,
                          const gfxPoint& aTextBaselinePt,
--- a/layout/mathml/nsMathMLChar.cpp
+++ b/layout/mathml/nsMathMLChar.cpp
@@ -2131,17 +2131,17 @@ nsMathMLChar::PaintForeground(nsPresCont
 
   // Set color ...
   nscolor fgColor = styleContext->GetVisitedDependentColor(eCSSProperty_color);
   if (aIsSelected) {
     // get color to use for selection from the look&feel object
     fgColor = LookAndFeel::GetColor(LookAndFeel::eColorID_TextSelectForeground,
                                     fgColor);
   }
-  thebesContext->SetColor(fgColor);
+  thebesContext->SetColor(Color::FromABGR(fgColor));
   thebesContext->Save();
   nsRect r = mRect + aPt;
   ApplyTransforms(thebesContext, aPresContext->AppUnitsPerDevPixel(), r);
 
   switch(mDraw)
   {
     case DRAW_NORMAL:
     case DRAW_VARIANT:
--- a/layout/mathml/nsMathMLContainerFrame.cpp
+++ b/layout/mathml/nsMathMLContainerFrame.cpp
@@ -103,17 +103,17 @@ void nsDisplayMathMLError::Paint(nsDispl
   int32_t appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
   DrawTarget* drawTarget = aCtx->GetDrawTarget();
   Rect rect = NSRectToSnappedRect(nsRect(pt, mFrame->GetSize()),
                                   appUnitsPerDevPixel,
                                   *drawTarget);
   ColorPattern red(ToDeviceColor(Color(1.f, 0.f, 0.f, 1.f)));
   drawTarget->FillRect(rect, red);
 
-  aCtx->ThebesContext()->SetColor(NS_RGB(255,255,255));
+  aCtx->ThebesContext()->SetColor(Color(1.f, 1.f, 1.f));
   nscoord ascent = fm->MaxAscent();
   NS_NAMED_LITERAL_STRING(errorMsg, "invalid-markup");
   nsLayoutUtils::DrawUniDirString(errorMsg.get(), uint32_t(errorMsg.Length()),
                                   nsPoint(pt.x, pt.y + ascent), *fm, *aCtx);
 }
 
 /* /////////////
  * nsIMathMLFrame - support methods for stretchy elements
new file mode 100644
--- /dev/null
+++ b/layout/reftests/box-shadow/boxshadow-color-rounding-middle-ref.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<style>
+#outerDiv {
+  width: 500px;
+  height: 500px;
+  background: lime;
+  position: absolute;
+}
+
+#middleBlur {
+  width: 300px;
+  height: 300px;
+  margin-left: 100px;
+  margin-top: 100px;
+  background: black;
+  box-shadow: inset 0 0 20px 100px lime;
+}
+</style>
+
+<div id="outerDiv">
+  <div id="middleBlur">
+  </div>
+</div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/box-shadow/boxshadow-color-rounding-middle.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<style>
+#thediv {
+  width: 500px;
+  height: 500px;
+  background: black;
+  box-shadow: inset 0 0 20px 200px lime;
+}
+</style>
+
+<div id="thediv"></div>
--- a/layout/reftests/box-shadow/reftest.list
+++ b/layout/reftests/box-shadow/reftest.list
@@ -16,16 +16,17 @@ random-if(layersGPUAccelerated) == boxsh
 random-if(d2d) fuzzy-if(B2G,12,18) == boxshadow-rounded-spread.html boxshadow-rounded-spread-ref.html
 skip-if((B2G&&browserIsRemote)||Mulet) HTTP(..) == boxshadow-dynamic.xul boxshadow-dynamic-ref.xul # Initial mulet triage: parity with B2G/B2G Desktop
 random-if(d2d) == boxshadow-onecorner.html boxshadow-onecorner-ref.html
 random-if(d2d) == boxshadow-twocorners.html boxshadow-twocorners-ref.html
 random-if(d2d) == boxshadow-threecorners.html boxshadow-threecorners-ref.html
 == boxshadow-skiprect.html boxshadow-skiprect-ref.html
 == boxshadow-opacity.html boxshadow-opacity-ref.html
 == boxshadow-color-rounding.html boxshadow-color-rounding-ref.html
+== boxshadow-color-rounding-middle.html boxshadow-color-rounding-middle-ref.html
 
 == overflow-not-scrollable-1.html overflow-not-scrollable-1-ref.html
 == overflow-not-scrollable-1.html overflow-not-scrollable-1-ref2.html
 == overflow-not-scrollable-2.html overflow-not-scrollable-2-ref.html
 fails-if(B2G||Mulet) == 611574-1.html 611574-1-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
 fails-if(B2G||Mulet) == 611574-2.html 611574-2-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
 fuzzy-if(winWidget,5,30) == fieldset.html fieldset-ref.html # minor anti-aliasing problem on Windows
 fuzzy-if(winWidget,5,30) == fieldset-inset.html fieldset-inset-ref.html # minor anti-aliasing problem on Windows
--- a/layout/svg/nsFilterInstance.cpp
+++ b/layout/svg/nsFilterInstance.cpp
@@ -526,17 +526,17 @@ nsFilterInstance::OutputFilterSpaceBound
 {
   uint32_t numPrimitives = mPrimitiveDescriptions.Length();
   if (numPrimitives <= 0)
     return nsIntRect();
 
   nsIntRect bounds =
     mPrimitiveDescriptions[numPrimitives - 1].PrimitiveSubregion();
   bool overflow;
-  gfxIntSize surfaceSize =
+  IntSize surfaceSize =
     nsSVGUtils::ConvertToSurfaceSize(bounds.Size(), &overflow);
   bounds.SizeTo(surfaceSize);
   return bounds;
 }
 
 nsIntRect
 nsFilterInstance::FrameSpaceToFilterSpace(const nsRect* aRect) const
 {
--- a/layout/svg/nsSVGIntegrationUtils.cpp
+++ b/layout/svg/nsSVGIntegrationUtils.cpp
@@ -605,31 +605,31 @@ nsSVGIntegrationUtils::GetCSSPxToDevPxMa
                    0.0, devPxPerCSSPx,
                    0.0, 0.0);
 }
 
 class PaintFrameCallback : public gfxDrawingCallback {
 public:
   PaintFrameCallback(nsIFrame* aFrame,
                      const nsSize aPaintServerSize,
-                     const gfxIntSize aRenderSize,
+                     const IntSize aRenderSize,
                      uint32_t aFlags)
    : mFrame(aFrame)
    , mPaintServerSize(aPaintServerSize)
    , mRenderSize(aRenderSize)
    , mFlags (aFlags)
   {}
   virtual bool operator()(gfxContext* aContext,
                             const gfxRect& aFillRect,
                             const GraphicsFilter& aFilter,
                             const gfxMatrix& aTransform) override;
 private:
   nsIFrame* mFrame;
   nsSize mPaintServerSize;
-  gfxIntSize mRenderSize;
+  IntSize mRenderSize;
   uint32_t mFlags;
 };
 
 bool
 PaintFrameCallback::operator()(gfxContext* aContext,
                                const gfxRect& aFillRect,
                                const GraphicsFilter& aFilter,
                                const gfxMatrix& aTransform)
@@ -690,17 +690,17 @@ PaintFrameCallback::operator()(gfxContex
 
   return true;
 }
 
 /* static */ already_AddRefed<gfxDrawable>
 nsSVGIntegrationUtils::DrawableFromPaintServer(nsIFrame*         aFrame,
                                                nsIFrame*         aTarget,
                                                const nsSize&     aPaintServerSize,
-                                               const gfxIntSize& aRenderSize,
+                                               const IntSize& aRenderSize,
                                                const DrawTarget* aDrawTarget,
                                                const gfxMatrix&  aContextMatrix,
                                                uint32_t          aFlags)
 {
   // aPaintServerSize is the size that would be filled when using
   // background-repeat:no-repeat and background-size:auto. For normal background
   // images, this would be the intrinsic size of the image; for gradients and
   // patterns this would be the whole target frame fill area.
--- a/layout/svg/nsSVGIntegrationUtils.h
+++ b/layout/svg/nsSVGIntegrationUtils.h
@@ -161,18 +161,18 @@ public:
    * @param aFlags pass FLAG_SYNC_DECODE_IMAGES and any images in the paint
    * server will be decoding synchronously if they are not decoded already.
    */
   enum {
     FLAG_SYNC_DECODE_IMAGES = 0x01,
   };
 
   static already_AddRefed<gfxDrawable>
-  DrawableFromPaintServer(nsIFrame*         aFrame,
-                          nsIFrame*         aTarget,
-                          const nsSize&     aPaintServerSize,
-                          const gfxIntSize& aRenderSize,
+  DrawableFromPaintServer(nsIFrame* aFrame,
+                          nsIFrame* aTarget,
+                          const nsSize& aPaintServerSize,
+                          const mozilla::gfx::IntSize& aRenderSize,
                           const DrawTarget* aDrawTarget,
-                          const gfxMatrix&  aContextMatrix,
-                          uint32_t          aFlags);
+                          const gfxMatrix& aContextMatrix,
+                          uint32_t aFlags);
 };
 
 #endif /*NSSVGINTEGRATIONUTILS_H_*/
--- a/layout/svg/nsSVGUtils.cpp
+++ b/layout/svg/nsSVGUtils.cpp
@@ -797,21 +797,21 @@ nsSVGUtils::TransformFrameRectToOuterSVG
                                          nsPresContext* aPresContext)
 {
   gfxRect r(aRect.x, aRect.y, aRect.width, aRect.height);
   r.Scale(1.0 / nsPresContext::AppUnitsPerCSSPixel());
   return nsLayoutUtils::RoundGfxRectToAppRect(
     aMatrix.TransformBounds(r), aPresContext->AppUnitsPerDevPixel());
 }
 
-gfxIntSize
+IntSize
 nsSVGUtils::ConvertToSurfaceSize(const gfxSize& aSize,
                                  bool *aResultOverflows)
 {
-  gfxIntSize surfaceSize(ClampToInt(ceil(aSize.width)), ClampToInt(ceil(aSize.height)));
+  IntSize surfaceSize(ClampToInt(ceil(aSize.width)), ClampToInt(ceil(aSize.height)));
 
   *aResultOverflows = surfaceSize.width != ceil(aSize.width) ||
     surfaceSize.height != ceil(aSize.height);
 
   if (!gfxASurface::CheckSurfaceSize(surfaceSize)) {
     surfaceSize.width = std::min(NS_SVG_OFFSCREEN_MAX_DIMENSION,
                                surfaceSize.width);
     surfaceSize.height = std::min(NS_SVG_OFFSCREEN_MAX_DIMENSION,
--- a/layout/svg/nsSVGUtils.h
+++ b/layout/svg/nsSVGUtils.h
@@ -346,18 +346,18 @@ public:
    * Convert a surface size to an integer for use by thebes
    * possibly making it smaller in the process so the surface does not
    * use excessive memory.
    *
    * @param aSize the desired surface size
    * @param aResultOverflows true if the desired surface size is too big
    * @return the surface size to use
    */
-  static gfxIntSize ConvertToSurfaceSize(const gfxSize& aSize,
-                                         bool *aResultOverflows);
+  static mozilla::gfx::IntSize ConvertToSurfaceSize(const gfxSize& aSize,
+                                                    bool *aResultOverflows);
 
   /*
    * Hit test a given rectangle/matrix.
    */
   static bool
   HitTestRect(const mozilla::gfx::Matrix &aMatrix,
               float aRX, float aRY, float aRWidth, float aRHeight,
               float aX, float aY);
--- a/layout/xul/nsTextBoxFrame.cpp
+++ b/layout/xul/nsTextBoxFrame.cpp
@@ -519,17 +519,17 @@ nsTextBoxFrame::DrawText(nsRenderingCont
 
     nsRenderingContext refContext(
         PresContext()->PresShell()->CreateReferenceRenderingContext());
 
     CalculateUnderline(refContext, *fontMet);
 
     nscolor c = aOverrideColor ? *aOverrideColor : StyleColor()->mColor;
     ColorPattern color(ToDeviceColor(c));
-    aRenderingContext.ThebesContext()->SetColor(c);
+    aRenderingContext.ThebesContext()->SetColor(Color::FromABGR(c));
 
     nsresult rv = NS_ERROR_FAILURE;
 
     if (mState & NS_FRAME_IS_BIDI) {
       presContext->SetBidiEnabled();
       nsBidiLevel level = nsBidiPresUtils::BidiLevelFromStyle(StyleContext());
       if (mAccessKeyInfo && mAccessKeyInfo->mAccesskeyIndex != kNotFound) {
           // We let the RenderText function calculate the mnemonic's
--- a/layout/xul/tree/nsTreeBodyFrame.cpp
+++ b/layout/xul/tree/nsTreeBodyFrame.cpp
@@ -3690,17 +3690,17 @@ nsTreeBodyFrame::PaintText(int32_t      
   }
   nsStyleContext* cellContext = GetPseudoStyleContext(nsCSSAnonBoxes::moztreecell);
 
   gfxContext* ctx = aRenderingContext.ThebesContext();
   if (opacity != 1.0f) {
     ctx->PushGroup(gfxContentType::COLOR_ALPHA);
   }
 
-  ctx->SetColor(textContext->StyleColor()->mColor);
+  ctx->SetColor(Color::FromABGR(textContext->StyleColor()->mColor));
   nsLayoutUtils::DrawString(this, *fontMet, &aRenderingContext, text.get(),
                             text.Length(),
                             textRect.TopLeft() + nsPoint(0, baseline),
                             cellContext);
 
   if (opacity != 1.0f) {
     ctx->PopGroupToSource();
     ctx->Paint(opacity);
--- a/layout/xul/tree/nsTreeContentView.cpp
+++ b/layout/xul/tree/nsTreeContentView.cpp
@@ -143,17 +143,17 @@ nsTreeContentView::GetSelection(nsITreeS
 
   return NS_OK;
 }
 
 bool
 nsTreeContentView::CanTrustTreeSelection(nsISupports* aValue)
 {
   // Untrusted content is only allowed to specify known-good views
-  if (nsContentUtils::IsCallerChrome())
+  if (nsContentUtils::LegacyIsCallerChromeOrNativeCode())
     return true;
   nsCOMPtr<nsINativeTreeSelection> nativeTreeSel = do_QueryInterface(aValue);
   return nativeTreeSel && NS_SUCCEEDED(nativeTreeSel->EnsureNative());
 }
 
 NS_IMETHODIMP
 nsTreeContentView::SetSelection(nsITreeSelection* aSelection)
 {
--- a/media/webrtc/signaling/test/FakeMediaStreamsImpl.h
+++ b/media/webrtc/signaling/test/FakeMediaStreamsImpl.h
@@ -153,29 +153,30 @@ Fake_VideoStreamSource::Notify(nsITimer*
   const uint8_t chromaBpp = 4;
 
   int len = ((WIDTH * HEIGHT) * 3 / 2);
   uint8_t* frame = (uint8_t*) PR_Malloc(len);
   memset(frame, 0x80, len); // Gray
 
   mozilla::layers::PlanarYCbCrData data;
   data.mYChannel = frame;
-  data.mYSize = gfxIntSize(WIDTH, HEIGHT);
+  data.mYSize = mozilla::gfx::IntSize(WIDTH, HEIGHT);
   data.mYStride = WIDTH * lumaBpp / 8.0;
   data.mCbCrStride = WIDTH * chromaBpp / 8.0;
   data.mCbChannel = frame + HEIGHT * data.mYStride;
   data.mCrChannel = data.mCbChannel + HEIGHT * data.mCbCrStride / 2;
-  data.mCbCrSize = gfxIntSize(WIDTH / 2, HEIGHT / 2);
+  data.mCbCrSize = mozilla::gfx::IntSize(WIDTH / 2, HEIGHT / 2);
   data.mPicX = 0;
   data.mPicY = 0;
-  data.mPicSize = gfxIntSize(WIDTH, HEIGHT);
+  data.mPicSize = mozilla::gfx::IntSize(WIDTH, HEIGHT);
   data.mStereoMode = mozilla::layers::StereoMode::MONO;
 
   mozilla::VideoSegment segment;
-  segment.AppendFrame(image.forget(), USECS_PER_S / FPS, gfxIntSize(WIDTH, HEIGHT));
+  segment.AppendFrame(image.forget(), USECS_PER_S / FPS,
+                      mozilla::gfx::IntSize(WIDTH, HEIGHT));
 
   // TODO(ekr@rtfm.com): are we leaking?
 #endif
 
   return NS_OK;
 }
 
 
--- a/mobile/android/chrome/content/WebcompatReporter.js
+++ b/mobile/android/chrome/content/WebcompatReporter.js
@@ -1,19 +1,19 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
 
-Cu.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/ctypes.jsm");
-Cu.import("resource://gre/modules/JNI.jsm");
+
+XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
+                                  "resource://gre/modules/PrivateBrowsingUtils.jsm");
 
 var WebcompatReporter = {
   menuItem: null,
   menuItemEnabled: null,
   init: function() {
     Services.obs.addObserver(this, "DesktopMode:Change", false);
     Services.obs.addObserver(this, "chrome-document-global-created", false);
     Services.obs.addObserver(this, "content-document-global-created", false);
--- a/netwerk/protocol/http/HttpBaseChannel.cpp
+++ b/netwerk/protocol/http/HttpBaseChannel.cpp
@@ -716,18 +716,23 @@ HttpBaseChannel::ExplicitSetUploadStream
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (!aStreamHasHeaders) {
     // SetRequestHeader propagates headers to chrome if HttpChannelChild
     nsAutoCString contentLengthStr;
     contentLengthStr.AppendInt(aContentLength);
     SetRequestHeader(NS_LITERAL_CSTRING("Content-Length"), contentLengthStr,
                      false);
-    SetRequestHeader(NS_LITERAL_CSTRING("Content-Type"), aContentType,
-                     false);
+
+    if (aContentType.IsEmpty()) {
+      SetEmptyRequestHeader(NS_LITERAL_CSTRING("Content-Type"));
+    } else {
+      SetRequestHeader(NS_LITERAL_CSTRING("Content-Type"), aContentType,
+                       false);
+    }
   }
 
   mUploadStreamHasHeaders = aStreamHasHeaders;
   mUploadStream = aStream;
   return NS_OK;
 }
 
 NS_IMETHODIMP
--- a/testing/mozharness/configs/developer_config.py
+++ b/testing/mozharness/configs/developer_config.py
@@ -34,16 +34,17 @@ config = {
     "find_links": ["http://pypi.pub.build.mozilla.org/pub"],
     "pip_index": False,
 
     # Talos related
     "python_webserver": True,
     "virtualenv_path": '%s/build/venv' % os.getcwd(),
 
     # Tooltool related
+    "download_tooltool": True,
     "tooltool_cache": os.path.join(LOCAL_WORKDIR, "builds/tooltool_cache"),
     "tooltool_cache_path": os.path.join(LOCAL_WORKDIR, "builds/tooltool_cache"),
 
     # VCS tools
     "hgtool.py": 'http://hg.mozilla.org/build/puppet/raw-file/faaf5abd792e/modules/packages/files/hgtool.py',
     "gittool.py": 'http://hg.mozilla.org/build/puppet/raw-file/faaf5abd792e/modules/packages/files/gittool.py',
 
     # Android related
--- a/testing/mozharness/mozharness/mozilla/l10n/locales.py
+++ b/testing/mozharness/mozharness/mozilla/l10n/locales.py
@@ -24,44 +24,91 @@ class LocalesMixin(ChunkingMixin):
     def __init__(self, **kwargs):
         """ Mixins generally don't have an __init__.
         This breaks super().__init__() for children.
         However, this is needed to override the query_abs_dirs()
         """
         self.abs_dirs = None
         self.locales = None
         self.gecko_locale_revisions = None
+        self.l10n_revisions = {}
 
     def query_locales(self):
         if self.locales is not None:
             return self.locales
         c = self.config
-        locales = c.get("locales", None)
         ignore_locales = c.get("ignore_locales", [])
         additional_locales = c.get("additional_locales", [])
+        # List of locales can be set by using different methods in the
+        # following order:
+        # 1. "locales" buildbot property: a string of locale:revision separated
+        # by space
+        # 2. "MOZ_LOCALES" env variable: a string of locale:revision separated
+        # by space
+        # 3. self.config["locales"] which can be either coming from the config
+        # or from --locale command line argument
+        # 4. using self.config["locales_file"] l10n changesets file
+        locales = None
 
-        if locales is None:
-            locales = []
-            if 'locales_file' in c:
-                # Best way to get abs/relative path to this?
-                locales_file = os.path.join(c['base_work_dir'], c['work_dir'],
-                                            c['locales_file'])
-                locales = self.parse_locales_file(locales_file)
-            else:
-                self.fatal("No way to determine locales!")
+        # Buildbot property
+        if hasattr(self, 'read_buildbot_config'):
+            self.read_buildbot_config()
+            if self.buildbot_config:
+                locales = self.buildbot_config.get("locales")
+            if locales:
+                self.info("Using locales from buildbot: %s" % locales)
+                locales = locales.split()
+        else:
+            self.info("'read_buildbot_config()' is missing, ignoring buildbot"
+                      " properties")
+
+        # Environment variable
+        if not locales and "MOZ_LOCALES" in os.environ:
+            self.debug("Using locales from environment: %s" %
+                       os.environ["MOZ_LOCALES"])
+            locales = os.environ["MOZ_LOCALES"].split()
+
+        # Command line or config
+        if not locales and c.get("locales", None):
+            locales = c["locales"]
+            self.debug("Using locales from config/CLI: %s" % locales)
+
+        # parse locale:revision if set
+        if locales:
+            for l in locales:
+                if ":" in l:
+                    # revision specified in locale string
+                    locale, revision = l.split(":", 1)
+                    self.debug("Using %s:%s" % (locale, revision))
+                    self.l10n_revisions[locale] = revision
+            # clean up locale by removing revisions
+            locales = [l.split(":")[0] for l in locales]
+
+        if not locales and 'locales_file' in c:
+            locales_file = os.path.join(c['base_work_dir'], c['work_dir'],
+                                        c['locales_file'])
+            locales = self.parse_locales_file(locales_file)
+
+        if not locales:
+            self.fatal("No locales set!")
+
         for locale in ignore_locales:
             if locale in locales:
                 self.debug("Ignoring locale %s." % locale)
                 locales.remove(locale)
+                if locale in self.l10n_revisions:
+                    del self.l10n_revisions[locale]
+
         for locale in additional_locales:
             if locale not in locales:
                 self.debug("Adding locale %s." % locale)
                 locales.append(locale)
-        if locales is None:
-            return
+
+        if not locales:
+            return None
         if 'total_locale_chunks' and 'this_locale_chunk' in c:
             self.debug("Pre-chunking locale list: %s" % str(locales))
             locales = self.query_chunked_list(locales,
                                               c['this_locale_chunk'],
                                               c['total_locale_chunks'],
                                               sort=True)
             self.debug("Post-chunking locale list: %s" % locales)
         self.locales = locales
@@ -74,25 +121,24 @@ class LocalesMixin(ChunkingMixin):
 
     def parse_locales_file(self, locales_file):
         locales = []
         c = self.config
         platform = c.get("locales_platform", None)
 
         if locales_file.endswith('json'):
             locales_json = parse_config_file(locales_file)
-            self.locale_dict = {}
             for locale in locales_json.keys():
                 if isinstance(locales_json[locale], dict):
                     if platform and platform not in locales_json[locale]['platforms']:
                         continue
-                    self.locale_dict[locale] = locales_json[locale]['revision']
+                    self.l10n_revisions[locale] = locales_json[locale]['revision']
                 else:
                     # some other way of getting this?
-                    self.locale_dict[locale] = 'default'
+                    self.l10n_revisions[locale] = 'default'
                 locales.append(locale)
         else:
             locales = self.read_from_file(locales_file).split()
         return locales
 
     def run_compare_locales(self, locale, halt_on_failure=False):
         dirs = self.query_abs_dirs()
         compare_locales_script = os.path.join(dirs['abs_compare_locales_dir'],
@@ -172,18 +218,18 @@ class LocalesMixin(ChunkingMixin):
             self.vcs_checkout_repos(repos, tag_override=c.get('tag_override'))
         # Pull locales
         locales = self.query_locales()
         locale_repos = []
         if c.get("user_repo_override"):
             hg_l10n_base = hg_l10n_base % {"user_repo_override": c["user_repo_override"]}
         for locale in locales:
             tag = c.get('hg_l10n_tag', 'default')
-            if hasattr(self, 'locale_dict'):
-                tag = self.locale_dict[locale]
+            if self.l10n_revisions.get(locale):
+                tag = self.l10n_revisions[locale]
             locale_repos.append({
                 'repo': "%s/%s" % (hg_l10n_base, locale),
                 'tag': tag,
                 'vcs': vcs
             })
         revs = self.vcs_checkout_repos(repo_list=locale_repos,
                                        parent_dir=parent_dir,
                                        tag_override=c.get('tag_override'))
--- a/testing/mozharness/mozharness/mozilla/tooltool.py
+++ b/testing/mozharness/mozharness/mozilla/tooltool.py
@@ -46,17 +46,17 @@ class TooltoolMixin(object):
         if os.path.exists(fn):
             return fn
 
     def tooltool_fetch(self, manifest,
                        output_dir=None, privileged=False, cache=None):
         """docstring for tooltool_fetch"""
         tooltool = self.query_exe('tooltool.py', return_type='list')
 
-        if self.config.get("developer_mode"):
+        if self.config.get("download_tooltool"):
             tooltool = [bin for bin in tooltool if os.path.exists(bin)]
             if tooltool:
                 cmd = [tooltool[0]]
             else:
                 cmd = [self._fetch_tooltool_py()]
         else:
             cmd = tooltool
 
--- a/testing/mozharness/mozharness/mozilla/updates/balrog.py
+++ b/testing/mozharness/mozharness/mozilla/updates/balrog.py
@@ -111,48 +111,33 @@ class BalrogMixin(object):
                 return_codes.append(return_code)
         # return the worst (max) code
         return max(return_codes)
 
     def lock_balrog_rules(self, rule_ids):
         c = self.config
         dirs = self.query_abs_dirs()
         submitter_script = os.path.join(
-            dirs["abs_tools_dir"], "scripts", "updates", "balrog-nightly-locker.py"
+            dirs["abs_tools_dir"], "scripts", "updates",
+            "balrog-nightly-locker.py"
         )
         credentials_file = os.path.join(
             dirs["base_work_dir"], c["balrog_credentials_file"]
         )
 
         cmd = [
             self.query_exe("python"),
             submitter_script,
             "--credentials-file", credentials_file,
+            "--api-root", c["balrog_api_root"],
+            "--username", c["balrog_username"],
         ]
         for r in rule_ids:
             cmd.extend(["-r", str(r)])
 
         if self._log_level_at_least(INFO):
             cmd.append("--verbose")
 
-        return_codes = []
-        for server in self.config["balrog_servers"]:
-
-            server_args = [
-                "--api-root", server["balrog_api_root"],
-                "--username", self._query_balrog_username(server)
-            ]
-
-            cmd.append("lock")
+        cmd.append("lock")
 
-            self.info("Calling Balrog rule locking script.")
-            return_code = self.retry(
-                self.run_command, attempts=5,
-                args=(cmd + server_args + ['lock'],),
-            )
-            if server["ignore_failures"]:
-                self.info("Ignoring result, ignore_failures set to True")
-            else:
-                return_codes.append(return_code)
-
-        # use the worst (max) code
-        if max(return_codes) != 0:
-            self.return_code = 1
+        self.info("Calling Balrog rule locking script.")
+        self.retry(self.run_command, attempts=5, args=cmd,
+                   kwargs={"halt_on_failure": True})
--- a/testing/mozharness/scripts/desktop_l10n.py
+++ b/testing/mozharness/scripts/desktop_l10n.py
@@ -102,17 +102,18 @@ class DesktopSingleLocale(LocalesMixin, 
          "dest": "config_files",
          "type": "string",
          "help": "Specify the platform configuration file"}
     ], [
         ['--locale', ],
         {"action": "extend",
          "dest": "locales",
          "type": "string",
-         "help": "Specify the locale(s) to sign and update"}
+         "help": "Specify the locale(s) to sign and update. Optionally pass"
+                 " revision separated by colon, en-GB:default."}
     ], [
         ['--locales-file', ],
         {"action": "store",
          "dest": "locales_file",
          "type": "string",
          "help": "Specify a file to determine which locales to sign and update"}
     ], [
         ['--tag-override', ],
@@ -328,16 +329,23 @@ class DesktopSingleLocale(LocalesMixin, 
             return self.bootstrap_env
         config = self.config
         replace_dict = self.query_abs_dirs()
         bootstrap_env = self.query_env(partial_env=config.get("bootstrap_env"),
                                        replace_dict=replace_dict)
         if config.get('en_us_binary_url') and \
            config.get('release_config_file'):
             bootstrap_env['EN_US_BINARY_URL'] = config['en_us_binary_url']
+        # Override en_us_binary_url if passed as a buildbot property
+        self.read_buildbot_config()
+        if self.buildbot_config.get("en_us_binary_url"):
+            self.info("Overriding en_us_binary_url with %s" %
+                      self.buildbot_config["en_us_binary_url"])
+            bootstrap_env['EN_US_BINARY_URL'] = \
+                self.buildbot_config["en_us_binary_url"]
         if 'MOZ_SIGNING_SERVERS' in os.environ:
             sign_cmd = self.query_moz_sign_cmd(formats=None)
             sign_cmd = subprocess.list2cmdline(sign_cmd)
             # windows fix
             bootstrap_env['MOZ_SIGN_CMD'] = sign_cmd.replace('\\', '\\\\\\\\')
         for binary in self._mar_binaries():
             # "mar -> MAR" and 'mar.exe -> MAR' (windows)
             name = binary.replace('.exe', '')
--- a/testing/mozharness/scripts/merge_day/gecko_migration.py
+++ b/testing/mozharness/scripts/merge_day/gecko_migration.py
@@ -42,21 +42,26 @@ class GeckoMigration(MercurialScript, Ba
     config_options = [
         [['--hg-user', ], {
             "action": "store",
             "dest": "hg_user",
             "type": "string",
             "default": "ffxbld <release@mozilla.com>",
             "help": "Specify what user to use to commit to hg.",
         }],
+        [['--balrog-api-root', ], {
+            "action": "store",
+            "dest": "balrog_api_root",
+            "type": "string",
+            "help": "Specify Balrog API root URL.",
+        }],
         [['--balrog-username', ], {
             "action": "store",
             "dest": "balrog_username",
             "type": "string",
-            "default": "ffxbld",
             "help": "Specify what user to connect to Balrog with.",
         }],
         [['--balrog-credentials-file', ], {
             "action": "store",
             "dest": "balrog_credentials_file",
             "type": "string",
             "help": "The file containing the Balrog credentials.",
         }],
--- a/testing/testsuite-targets.mk
+++ b/testing/testsuite-targets.mk
@@ -282,20 +282,20 @@ xpcshell-tests:
 	  -I$(DEPTH)/build \
 	  -I$(topsrcdir)/build \
 	  -I$(DEPTH)/_tests/mozbase/mozinfo \
 	  $(topsrcdir)/testing/xpcshell/runxpcshelltests.py \
 	  --manifest=$(DEPTH)/_tests/xpcshell/xpcshell.ini \
 	  --build-info-json=$(DEPTH)/mozinfo.json \
 	  --no-logfiles \
 	  --test-plugin-path='$(DIST)/plugins' \
+	  --xpcshell=$(xpcshell_path) \
 	  --testing-modules-dir=$(abspath _tests/modules) \
           $(SYMBOLS_PATH) \
-	  $(TEST_PATH_ARG) $(EXTRA_TEST_ARGS) \
-	  $(xpcshell_path)
+	  $(TEST_PATH_ARG) $(EXTRA_TEST_ARGS)
 
 B2G_XPCSHELL = \
 	rm -f ./@.log && \
 	$(PYTHON) -u $(topsrcdir)/config/pythonpath.py \
 	  -I$(DEPTH)/build \
 	  -I$(topsrcdir)/build \
 	  $(topsrcdir)/testing/xpcshell/runtestsb2g.py \
 	  --manifest=$(DEPTH)/_tests/xpcshell/xpcshell.ini \
@@ -365,17 +365,17 @@ jetpack-tests:
 pgo-profile-run:
 	$(PYTHON) $(topsrcdir)/build/pgo/profileserver.py $(EXTRA_TEST_ARGS)
 
 # Package up the tests and test harnesses
 include $(topsrcdir)/toolkit/mozapps/installer/package-name.mk
 
 PKG_STAGE = $(DIST)/test-stage
 
-package-tests: \
+stage-all: \
   stage-config \
   stage-mach \
   stage-mochitest \
   stage-talos \
   stage-reftest \
   stage-xpcshell \
   stage-jstests \
   stage-jetpack \
@@ -386,17 +386,17 @@ package-tests: \
   stage-cppunittests \
   stage-jittest \
   stage-web-platform-tests \
   stage-luciddream \
   test-packages-manifest \
   test-packages-manifest-tc \
   $(NULL)
 ifdef MOZ_WEBRTC
-package-tests: stage-steeplechase
+stage-all: stage-steeplechase
 endif
 
 TEST_PKGS := \
   cppunittest \
   mochitest \
   reftest \
   talos \
   xpcshell \
@@ -419,41 +419,54 @@ test-packages-manifest:
 	@rm -f $(MOZ_TEST_PACKAGES_FILE)
 	$(NSINSTALL) -D $(dir $(MOZ_TEST_PACKAGES_FILE))
 	$(PYTHON) $(topsrcdir)/build/gen_test_packages_manifest.py \
       --jsshell $(JSSHELL_NAME) \
       --dest-file $(MOZ_TEST_PACKAGES_FILE) \
       $(call PKG_ARG,common) \
       $(foreach pkg,$(TEST_PKGS),$(call PKG_ARG,$(pkg)))
 
-package-tests:
+package-tests-prepare-dest:
 	@rm -f '$(DIST)/$(PKG_PATH)$(TEST_PACKAGE)'
 	$(NSINSTALL) -D $(DIST)/$(PKG_PATH)
-# Exclude harness specific directories when generating the common zip.
-	$(MKDIR) -p $(abspath $(DIST))/$(PKG_PATH) && \
+
+package-tests-mozharness: stage-all package-tests-prepare-dest
 	cd $(topsrcdir)/testing/ && \
-	  zip -rq9D $(abspath $(DIST))/$(PKG_PATH)mozharness.zip mozharness && \
+	  zip -rq9D $(abspath $(DIST))/$(PKG_PATH)mozharness.zip mozharness
+package-tests: package-tests-mozharness
+
+package-tests-common: stage-all package-tests-prepare-dest
 	cd $(abspath $(PKG_STAGE)) && \
 	  zip -rq9D '$(abspath $(DIST))/$(PKG_PATH)$(TEST_PACKAGE)' \
-	  * -x \*/.mkdir.done \*.pyc $(foreach name,$(TEST_PKGS),$(name)\*) && \
-	$(foreach name,$(TEST_PKGS),rm -f '$(DIST)/$(PKG_PATH)$(PKG_BASENAME).'$(name)'.tests.zip' && \
-                                zip -rq9D '$(abspath $(DIST))/$(PKG_PATH)$(PKG_BASENAME).'$(name)'.tests.zip' \
-                                $(name) -x \*/.mkdir.done \*.pyc ;)
+	  * -x \*/.mkdir.done \*.pyc $(foreach name,$(TEST_PKGS),$(name)\*)
+package-tests: package-tests-common
+
+define package_archive
+package-tests-$(1): stage-all package-tests-prepare-dest
+	rm -f '$$(DIST)/$$(PKG_PATH)$$(PKG_BASENAME).$(1).tests.zip' && \
+		cd $$(abspath $(PKG_STAGE)) && \
+		zip -rq9D '$$(abspath $$(DIST))/$$(PKG_PATH)$$(PKG_BASENAME).$(1).tests.zip' \
+		$(1) -x \*/.mkdir.done \*.pyc ;
+.PHONY += package-tests-$(1)
+package-tests: package-tests-$(1)
+endef
+
+$(foreach name,$(TEST_PKGS),$(eval $(call package_archive,$(name))))
 
 ifeq ($(MOZ_BUILD_APP),mobile/android)
-package-tests: stage-android
-package-tests: stage-instrumentation-tests
+stage-all: stage-android
+stage-all: stage-instrumentation-tests
 endif
 
 ifeq ($(MOZ_BUILD_APP),mobile/android/b2gdroid)
-package-tests: stage-android
+stage-all: stage-android
 endif
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),gonk)
-package-tests: stage-b2g
+stage-all: stage-b2g
 endif
 
 make-stage-dir:
 	rm -rf $(PKG_STAGE)
 	$(NSINSTALL) -D $(PKG_STAGE)
 	$(NSINSTALL) -D $(PKG_STAGE)/bin
 	$(NSINSTALL) -D $(PKG_STAGE)/bin/components
 	$(NSINSTALL) -D $(PKG_STAGE)/certs
@@ -600,17 +613,21 @@ stage-instrumentation-tests: make-stage-
   mochitest-chrome \
   mochitest-devtools \
   mochitest-a11y \
   reftest \
   crashtest \
   xpcshell-tests \
   jstestbrowser \
   package-tests \
+  package-tests-prepare-dest \
+  package-tests-mozharness \
+  package-tests-common \
   make-stage-dir \
+  stage-all \
   stage-b2g \
   stage-config \
   stage-mochitest \
   stage-talos \
   stage-reftest \
   stage-xpcshell \
   stage-jstests \
   stage-android \
deleted file mode 100644
--- a/testing/web-platform/meta/XMLHttpRequest/setrequestheader-content-type.htm.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[setrequestheader-content-type.htm]
-  type: testharness
-  [XMLHttpRequest: setRequestHeader() - Content-Type header ()]
-    expected: FAIL
-
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -3697,17 +3697,19 @@ XREMain::XRE_mainStartup(bool* aExitFlag
     ToLowerCase(program);
     g_set_prgname(program.get());
   }
 
   // Initialize GTK here for splash.
 
 #if (MOZ_WIDGET_GTK == 3) && defined(MOZ_X11)
   // Disable XInput2 support due to focus bugginess. See bugs 1182700, 1170342.
-  gdk_disable_multidevice();
+  const char* useXI2 = PR_GetEnv("MOZ_USE_XINPUT2");
+  if (!useXI2 || (*useXI2 == '0'))
+    gdk_disable_multidevice();
 #endif
 
   // Open the display ourselves instead of using gtk_init, so that we can
   // close it without fear that one day gtk might clean up the display it
   // opens.
   if (!gtk_parse_args(&gArgc, &gArgv))
     return 1;
 #endif /* MOZ_WIDGET_GTK */
--- a/widget/android/nsScreenManagerAndroid.cpp
+++ b/widget/android/nsScreenManagerAndroid.cpp
@@ -24,17 +24,17 @@ nsScreenAndroid::GetId(uint32_t *outId)
 {
     *outId = 1;
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsScreenAndroid::GetRect(int32_t *outLeft, int32_t *outTop, int32_t *outWidth, int32_t *outHeight)
 {
-    gfxIntSize sz = nsWindow::GetAndroidScreenBounds();
+    gfx::IntSize sz = nsWindow::GetAndroidScreenBounds();
 
     *outLeft = 0;
     *outTop = 0;
 
     *outWidth = sz.width;
     *outHeight = sz.height;
 
     return NS_OK;
--- a/widget/android/nsWindow.cpp
+++ b/widget/android/nsWindow.cpp
@@ -78,18 +78,18 @@ using mozilla::unused;
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::widget;
 using namespace mozilla::layers;
 
 NS_IMPL_ISUPPORTS_INHERITED0(nsWindow, nsBaseWidget)
 
 // The dimensions of the current android view
-static gfxIntSize gAndroidBounds = gfxIntSize(0, 0);
-static gfxIntSize gAndroidScreenBounds;
+static gfx::IntSize gAndroidBounds = gfx::IntSize(0, 0);
+static gfx::IntSize gAndroidScreenBounds;
 
 #include "mozilla/layers/CompositorChild.h"
 #include "mozilla/layers/CompositorParent.h"
 #include "mozilla/layers/LayerTransactionParent.h"
 #include "mozilla/Mutex.h"
 #include "mozilla/Services.h"
 #include "nsThreadUtils.h"
 
@@ -618,17 +618,17 @@ nsWindow::Resize(double aX,
     bool needSizeDispatch = aWidth != mBounds.width || aHeight != mBounds.height;
 
     mBounds.x = NSToIntRound(aX);
     mBounds.y = NSToIntRound(aY);
     mBounds.width = NSToIntRound(aWidth);
     mBounds.height = NSToIntRound(aHeight);
 
     if (needSizeDispatch)
-        OnSizeChanged(gfxIntSize(aWidth, aHeight));
+        OnSizeChanged(gfx::IntSize(aWidth, aHeight));
 
     // Should we skip honoring aRepaint here?
     if (aRepaint && FindTopLevel() == nsWindow::TopWindow())
         RedrawAll();
 
     nsIWidgetListener* listener = GetWidgetListener();
     if (mAwaitingFullScreen && listener) {
       listener->FullscreenChanged(mIsFullScreen);
@@ -1040,17 +1040,17 @@ nsWindow::OnGlobalAndroidEvent(AndroidGe
             if (!sCompositorPaused) {
                 win->RedrawAll();
             }
             break;
     }
 }
 
 void
-nsWindow::OnSizeChanged(const gfxIntSize& aSize)
+nsWindow::OnSizeChanged(const gfx::IntSize& aSize)
 {
     ALOG("nsWindow: %p OnSizeChanged [%d %d]", (void*)this, aSize.width, aSize.height);
 
     mBounds.width = aSize.width;
     mBounds.height = aSize.height;
 
     if (mWidgetListener) {
         mWidgetListener->WindowResized(this, aSize.width, aSize.height);
@@ -1066,17 +1066,17 @@ nsWindow::InitEvent(WidgetGUIEvent& even
     } else {
         event.refPoint.x = 0;
         event.refPoint.y = 0;
     }
 
     event.time = PR_Now() / 1000;
 }
 
-gfxIntSize
+gfx::IntSize
 nsWindow::GetAndroidScreenBounds()
 {
     if (XRE_IsContentProcess()) {
         return ContentChild::GetSingleton()->GetScreenSize();
     }
     return gAndroidScreenBounds;
 }
 
--- a/widget/android/nsWindow.h
+++ b/widget/android/nsWindow.h
@@ -46,28 +46,28 @@ public:
 
     static void InitNatives();
     class Natives;
     // Object that implements native GeckoView calls;
     // nullptr for nsWindows that were not opened from GeckoView.
     mozilla::UniquePtr<Natives> mNatives;
 
     static void OnGlobalAndroidEvent(mozilla::AndroidGeckoEvent *ae);
-    static gfxIntSize GetAndroidScreenBounds();
+    static mozilla::gfx::IntSize GetAndroidScreenBounds();
     static nsWindow* TopWindow();
 
     bool OnContextmenuEvent(mozilla::