Merge inbound to mozilla-central a=merge
authorarthur.iakab <aiakab@mozilla.com>
Wed, 06 Jun 2018 00:58:30 +0300
changeset 478184 da28b92efe6f6acaf79545697415b82038143338
parent 478099 0bb149ce1d1a4167e7135bb8a093ebdcf1ac0595 (current diff)
parent 478183 300f70a00d0be95050e62e3e757304bd1fceeb9e (diff)
child 478185 78c1a9ad32c674dc272490993c7ec5a259ac84f5
child 478204 61000d020e272cb9486a13ada7c7691bc9200afc
child 478243 27822aace5b803327dfabd3e3b02b5cbb9e7c2ce
push id1757
push userffxbld-merge
push dateFri, 24 Aug 2018 17:02:43 +0000
treeherdermozilla-release@736023aebdb1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone62.0a1
first release with
nightly linux32
da28b92efe6f / 62.0a1 / 20180605220158 / files
nightly linux64
da28b92efe6f / 62.0a1 / 20180605220158 / files
nightly mac
da28b92efe6f / 62.0a1 / 20180605220158 / files
nightly win32
da28b92efe6f / 62.0a1 / 20180605220158 / files
nightly win64
da28b92efe6f / 62.0a1 / 20180605220158 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge inbound to mozilla-central a=merge
hal/fallback/FallbackSwitch.cpp
layout/xul/tree/nsITreeContentView.idl
testing/mozharness/scripts/mobile_partner_repack.py
testing/web-platform/meta/MANIFEST.json
testing/web-platform/meta/encrypted-media/clearkey-events-session-closed-event.https.html.ini
testing/web-platform/meta/encrypted-media/clearkey-mp4-playback-temporary-clear-encrypted.https.html.ini
testing/web-platform/meta/encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear-sources.https.html.ini
testing/web-platform/meta/encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential-readyState.https.html.ini
testing/web-platform/meta/encrypted-media/clearkey-mp4-playback-temporary-multikey.https.html.ini
testing/web-platform/meta/encrypted-media/clearkey-mp4-playback-temporary-multisession.https.html.ini
testing/web-platform/meta/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-src.https.html.ini
testing/web-platform/meta/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-update.https.html.ini
testing/web-platform/meta/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-immediately.https.html.ini
testing/web-platform/meta/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-onencrypted.https.html.ini
testing/web-platform/meta/encrypted-media/clearkey-mp4-playback-temporary-two-videos.https.html.ini
testing/web-platform/meta/encrypted-media/clearkey-mp4-playback-temporary-waitingforkey.https.html.ini
testing/web-platform/meta/encrypted-media/clearkey-mp4-playback-temporary.https.html.ini
testing/web-platform/meta/encrypted-media/clearkey-mp4-reset-src-after-setmediakeys.https.html.ini
testing/web-platform/meta/encrypted-media/clearkey-mp4-setmediakeys-again-after-resetting-src.https.html.ini
testing/web-platform/meta/encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-different-mediakeys.https.html.ini
testing/web-platform/meta/encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.https.html.ini
testing/web-platform/meta/encrypted-media/clearkey-mp4-syntax-mediakeys.https.html.ini
testing/web-platform/meta/encrypted-media/clearkey-mp4-syntax-mediakeysystemaccess.https.html.ini
testing/web-platform/meta/encrypted-media/clearkey-mp4-waiting-for-a-key.https.html.ini
testing/web-platform/meta/encrypted-media/clearkey-update-non-ascii-input.https.html.ini
testing/web-platform/meta/service-workers/service-worker/import-scripts-updated-flag.https.html.ini
testing/web-platform/tests/svg/extensibility/foreignObject/foreign-object-paints-before-rect-expected.html
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -434,41 +434,41 @@ name = "crossbeam-utils"
 version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "cssparser"
-version = "0.23.4"
+version = "0.23.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cssparser-macros 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cssparser-macros 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "dtoa-short 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "itoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
- "proc-macro2 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "procedural-masquerade 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 0.12.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "cssparser-macros"
-version = "0.3.2"
+version = "0.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
- "proc-macro2 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "procedural-masquerade 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 0.12.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "cstr"
 version = "0.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cstr-macros 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -793,17 +793,17 @@ dependencies = [
  "zip 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "geckoservo"
 version = "0.0.1"
 dependencies = [
  "atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "cssparser 0.23.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cssparser 0.23.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "cstr 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "malloc_size_of 0.0.1",
  "nsstring 0.1.0",
  "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "selectors 0.19.0",
  "servo_arc 0.1.1",
@@ -1129,17 +1129,17 @@ dependencies = [
  "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "malloc_size_of"
 version = "0.0.1"
 dependencies = [
  "app_units 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "cssparser 0.23.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cssparser 0.23.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "hashglobe 0.1.0",
  "selectors 0.19.0",
  "servo_arc 0.1.1",
  "smallbitvec 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -1765,17 +1765,17 @@ name = "scopeguard"
 version = "0.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "selectors"
 version = "0.19.0"
 dependencies = [
  "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "cssparser 0.23.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cssparser 0.23.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "servo_arc 0.1.1",
  "smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1903,17 +1903,17 @@ version = "0.0.1"
 dependencies = [
  "app_units 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "arrayvec 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bindgen 0.33.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "cssparser 0.23.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cssparser 0.23.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "debug_unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "fallible 0.0.1",
  "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "hashglobe 0.1.0",
  "itertools 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1958,30 +1958,30 @@ dependencies = [
 ]
 
 [[package]]
 name = "style_traits"
 version = "0.0.1"
 dependencies = [
  "app_units 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "cssparser 0.23.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cssparser 0.23.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "malloc_size_of 0.0.1",
  "malloc_size_of_derive 0.0.1",
  "selectors 0.19.0",
  "servo_arc 0.1.1",
 ]
 
 [[package]]
 name = "stylo_tests"
 version = "0.0.1"
 dependencies = [
  "atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "cssparser 0.23.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cssparser 0.23.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "cstr 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "geckoservo 0.0.1",
  "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "malloc_size_of 0.0.1",
  "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2537,18 +2537,18 @@ dependencies = [
 "checksum core-graphics 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fb0ed45fdc32f9ab426238fba9407dfead7bacd7900c9b4dd3f396f46eafdae3"
 "checksum core-text 9.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2bd581c37283d0c23311d179aefbb891f2324ee0405da58a26e8594ab76e5748"
 "checksum cose 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "72fa26cb151d3ae4b70f63d67d0fed57ce04220feafafbae7f503bef7aae590d"
 "checksum cose-c 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "49726015ab0ca765144fcca61e4a7a543a16b795a777fa53f554da2fffff9a94"
 "checksum crc 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bd5d02c0aac6bd68393ed69e00bbc2457f3e89075c6349db7189618dc4ddc1d7"
 "checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3"
 "checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150"
 "checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9"
-"checksum cssparser 0.23.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b906ac3f6108d8d0bfd4158469abe5909df1497116c8400346b5e08944579edd"
-"checksum cssparser-macros 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9ce714f82ed2ca0e026ee351b7f25b2d70f81cf6f0f3214537a2edb67cd4d4d0"
+"checksum cssparser 0.23.9 (registry+https://github.com/rust-lang/crates.io-index)" = "205647ffe2b63a9726a4c3bb6f31c7325e8ceff10e2f1b75a6fb7609e20419ea"
+"checksum cssparser-macros 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f3a5383ae18dbfdeb569ed62019f5bddb2a95cd2d3833313c475a0d014777805"
 "checksum cstr 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b6557bdb1dc9647eae1cf7f5601b14cd45fc3c7ccf2df618387416fe542da6ea"
 "checksum cstr-macros 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f9f316203d1ea36f4f18316822806f6999aa3dc5ed1adf51e35b77e3b3933d78"
 "checksum cubeb 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8a3502aafa1bf95c524f65d2ba46d8741700c6a8a9543ea52c6da3d8b69a2896"
 "checksum cubeb-backend 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fdcac95519416d9ec814db2dc40e6293e7da25b906023d93f48b87f0587ab138"
 "checksum cubeb-core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "37f7b20f757a4e4b6aa28863236551bff77682dc6db192eba15af615492b5445"
 "checksum cubeb-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "653b9e245d35dbe2a2da7c4586275cee75ff656ddeb02d4a73b4afdfa6d67502"
 "checksum darling 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d3effd06d4057f275cb7858889f4952920bab78dd8ff0f6e7dfe0c8d2e67ed89"
 "checksum darling_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "167dd3e235c2f1da16a635c282630452cdf49191eb05711de1bcd1d3d5068c00"
--- a/accessible/base/XULMap.h
+++ b/accessible/base/XULMap.h
@@ -167,18 +167,17 @@ XULMAP(
     if (!child)
       return nullptr;
 
     nsTreeBodyFrame* treeFrame = do_QueryFrame(child->GetPrimaryFrame());
     if (!treeFrame)
       return nullptr;
 
     RefPtr<nsTreeColumns> treeCols = treeFrame->Columns();
-    int32_t count = 0;
-    treeCols->GetCount(&count);
+    uint32_t count = treeCols->Count();
 
     // Outline of list accessible.
     if (count == 1) {
       return new XULTreeAccessible(aElement, aContext->Document(), treeFrame);
     }
 
     // Table or tree table accessible.
     return new XULTreeGridAccessibleWrap(aElement, aContext->Document(), treeFrame);
--- a/accessible/base/nsCoreUtils.cpp
+++ b/accessible/base/nsCoreUtils.cpp
@@ -28,17 +28,17 @@
 #include "mozilla/MouseEvents.h"
 #include "mozilla/TouchEvents.h"
 #include "nsView.h"
 #include "nsGkAtoms.h"
 
 #include "nsComponentManagerUtils.h"
 
 #include "nsITreeBoxObject.h"
-#include "nsITreeColumns.h"
+#include "nsTreeColumns.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/HTMLLabelElement.h"
 #include "mozilla/dom/MouseEventBinding.h"
 #include "mozilla/dom/Selection.h"
 
 using namespace mozilla;
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -517,49 +517,45 @@ nsCoreUtils::GetTreeBoxObject(nsIContent
   }
 
   return nullptr;
 }
 
 already_AddRefed<nsITreeColumn>
 nsCoreUtils::GetFirstSensibleColumn(nsITreeBoxObject *aTree)
 {
-  nsCOMPtr<nsITreeColumns> cols;
+  RefPtr<nsTreeColumns> cols;
   aTree->GetColumns(getter_AddRefs(cols));
   if (!cols)
     return nullptr;
 
-  nsCOMPtr<nsITreeColumn> column;
-  cols->GetFirstColumn(getter_AddRefs(column));
+  RefPtr<nsTreeColumn> column = cols->GetFirstColumn();
   if (column && IsColumnHidden(column))
     return GetNextSensibleColumn(column);
 
   return column.forget();
 }
 
 uint32_t
 nsCoreUtils::GetSensibleColumnCount(nsITreeBoxObject *aTree)
 {
   uint32_t count = 0;
 
-  nsCOMPtr<nsITreeColumns> cols;
+  RefPtr<nsTreeColumns> cols;
   aTree->GetColumns(getter_AddRefs(cols));
   if (!cols)
     return count;
 
-  nsCOMPtr<nsITreeColumn> column;
-  cols->GetFirstColumn(getter_AddRefs(column));
+  nsTreeColumn* column = cols->GetFirstColumn();
 
   while (column) {
     if (!IsColumnHidden(column))
       count++;
 
-    nsCOMPtr<nsITreeColumn> nextColumn;
-    column->GetNext(getter_AddRefs(nextColumn));
-    column.swap(nextColumn);
+    column = column->GetNext();
   }
 
   return count;
 }
 
 already_AddRefed<nsITreeColumn>
 nsCoreUtils::GetSensibleColumnAt(nsITreeBoxObject *aTree, uint32_t aIndex)
 {
--- a/accessible/xul/XULTreeAccessible.cpp
+++ b/accessible/xul/XULTreeAccessible.cpp
@@ -119,22 +119,22 @@ XULTreeAccessible::Value(nsString& aValu
   nsCOMPtr<nsITreeSelection> selection;
   mTreeView->GetSelection(getter_AddRefs(selection));
   if (!selection)
     return;
 
   int32_t currentIndex;
   selection->GetCurrentIndex(&currentIndex);
   if (currentIndex >= 0) {
-    nsCOMPtr<nsITreeColumn> keyCol;
+    RefPtr<nsTreeColumn> keyCol;
 
-    nsCOMPtr<nsITreeColumns> cols;
+    RefPtr<nsTreeColumns> cols;
     mTree->GetColumns(getter_AddRefs(cols));
     if (cols)
-      cols->GetKeyColumn(getter_AddRefs(keyCol));
+      keyCol = cols->GetKeyColumn();
 
     mTreeView->GetCellText(currentIndex, keyCol, aValue);
   }
 
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // XULTreeAccessible: Accessible implementation
@@ -161,18 +161,17 @@ XULTreeAccessible::NativeRole() const
   nsIContent* child = nsTreeUtils::GetDescendantChild(mContent, nsGkAtoms::treechildren);
   NS_ASSERTION(child, "tree without treechildren!");
   nsTreeBodyFrame* treeFrame = do_QueryFrame(child->GetPrimaryFrame());
   NS_ASSERTION(treeFrame, "xul tree accessible for tree without a frame!");
   if (!treeFrame)
     return roles::LIST;
 
   RefPtr<nsTreeColumns> cols = treeFrame->Columns();
-  nsCOMPtr<nsITreeColumn> primaryCol;
-  cols->GetPrimaryColumn(getter_AddRefs(primaryCol));
+  nsTreeColumn* primaryCol = cols->GetPrimaryColumn();
 
   return primaryCol ? roles::OUTLINE : roles::LIST;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // XULTreeAccessible: Accessible implementation (DON'T put methods here)
 
 Accessible*
@@ -613,30 +612,27 @@ XULTreeAccessible::TreeViewInvalidated(i
     int32_t rowCount = 0;
     rv = mTreeView->GetRowCount(&rowCount);
     if (NS_FAILED(rv))
       return;
 
     endRow = rowCount - 1;
   }
 
-  nsCOMPtr<nsITreeColumns> treeColumns;
+  RefPtr<nsTreeColumns> treeColumns;
   mTree->GetColumns(getter_AddRefs(treeColumns));
   if (!treeColumns)
     return;
 
   int32_t endCol = aEndCol;
 
   if (endCol == -1) {
-    int32_t colCount = 0;
-    rv = treeColumns->GetCount(&colCount);
-    if (NS_FAILED(rv))
-      return;
-
-    endCol = colCount - 1;
+    // We need to make sure to cast to int32_t before we do the subtraction, in
+    // case the column count is 0.
+    endCol = static_cast<int32_t>(treeColumns->Count()) - 1;
   }
 
   for (int32_t rowIdx = aStartRow; rowIdx <= endRow; ++rowIdx) {
 
     void *key = reinterpret_cast<void*>(intptr_t(rowIdx));
     Accessible* accessible = mAccessibleCache.GetWeak(key);
 
     if (accessible) {
@@ -978,31 +974,31 @@ XULTreeItemAccessibleBase::ContainerWidg
 
 void
 XULTreeItemAccessibleBase::DispatchClickEvent(nsIContent* aContent,
                                               uint32_t aActionIndex) const
 {
   if (IsDefunct())
     return;
 
-  nsCOMPtr<nsITreeColumns> columns;
+  RefPtr<nsTreeColumns> columns;
   mTree->GetColumns(getter_AddRefs(columns));
   if (!columns)
     return;
 
   // Get column and pseudo element.
-  nsCOMPtr<nsITreeColumn> column;
+  RefPtr<nsTreeColumn> column;
   nsAutoString pseudoElm;
 
   if (aActionIndex == eAction_Click) {
     // Key column is visible and clickable.
-    columns->GetKeyColumn(getter_AddRefs(column));
+    column = columns->GetKeyColumn();
   } else {
     // Primary column contains a twisty we should click on.
-    columns->GetPrimaryColumn(getter_AddRefs(column));
+    column = columns->GetPrimaryColumn();
     pseudoElm = NS_LITERAL_STRING("twisty");
   }
 
   if (column)
     nsCoreUtils::DispatchClickEvent(mTree, mRow, column, pseudoElm);
 }
 
 Accessible*
@@ -1023,21 +1019,20 @@ XULTreeItemAccessibleBase::IsExpandable(
 {
 
   bool isContainer = false;
   mTreeView->IsContainer(mRow, &isContainer);
   if (isContainer) {
     bool isEmpty = false;
     mTreeView->IsContainerEmpty(mRow, &isEmpty);
     if (!isEmpty) {
-      nsCOMPtr<nsITreeColumns> columns;
+      RefPtr<nsTreeColumns> columns;
       mTree->GetColumns(getter_AddRefs(columns));
-      nsCOMPtr<nsITreeColumn> primaryColumn;
       if (columns) {
-        columns->GetPrimaryColumn(getter_AddRefs(primaryColumn));
+        nsTreeColumn* primaryColumn = columns->GetPrimaryColumn();
         if (primaryColumn &&
             !nsCoreUtils::IsColumnHidden(primaryColumn))
           return true;
       }
     }
   }
 
   return false;
@@ -1111,25 +1106,24 @@ XULTreeItemAccessible::Shutdown()
 {
   mColumn = nullptr;
   XULTreeItemAccessibleBase::Shutdown();
 }
 
 role
 XULTreeItemAccessible::NativeRole() const
 {
-  nsCOMPtr<nsITreeColumns> columns;
+  RefPtr<nsTreeColumns> columns;
   mTree->GetColumns(getter_AddRefs(columns));
   if (!columns) {
     NS_ERROR("No tree columns object in the tree!");
     return roles::NOTHING;
   }
 
-  nsCOMPtr<nsITreeColumn> primaryColumn;
-  columns->GetPrimaryColumn(getter_AddRefs(primaryColumn));
+  nsTreeColumn* primaryColumn = columns->GetPrimaryColumn();
 
   return primaryColumn ? roles::OUTLINEITEM : roles::LISTITEM;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // XULTreeItemAccessible: XULTreeItemAccessibleBase implementation
 
 void
--- a/accessible/xul/XULTreeAccessible.h
+++ b/accessible/xul/XULTreeAccessible.h
@@ -3,20 +3,20 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_a11y_XULTreeAccessible_h__
 #define mozilla_a11y_XULTreeAccessible_h__
 
 #include "nsITreeBoxObject.h"
 #include "nsITreeView.h"
-#include "nsITreeColumns.h"
 #include "XULListboxAccessible.h"
 
 class nsTreeBodyFrame;
+class nsITreeColumn;
 
 namespace mozilla {
 namespace a11y {
 
 class XULTreeGridCellAccessible;
 
 /*
  * A class the represents the XUL Tree widget.
--- a/accessible/xul/XULTreeGridAccessible.cpp
+++ b/accessible/xul/XULTreeGridAccessible.cpp
@@ -9,16 +9,17 @@
 #include "nsAccessibilityService.h"
 #include "nsAccUtils.h"
 #include "DocAccessible.h"
 #include "nsEventShell.h"
 #include "Relation.h"
 #include "Role.h"
 #include "States.h"
 #include "nsQueryObject.h"
+#include "nsTreeColumns.h"
 
 #include "nsIBoxObject.h"
 #include "nsIMutableArray.h"
 #include "nsIPersistentProperties2.h"
 #include "nsITreeSelection.h"
 #include "nsComponentManagerUtils.h"
 #include "mozilla/dom/Element.h"
 
@@ -206,25 +207,24 @@ XULTreeGridAccessible::UnselectRow(uint3
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // XULTreeGridAccessible: Accessible implementation
 
 role
 XULTreeGridAccessible::NativeRole() const
 {
-  nsCOMPtr<nsITreeColumns> treeColumns;
+  RefPtr<nsTreeColumns> treeColumns;
   mTree->GetColumns(getter_AddRefs(treeColumns));
   if (!treeColumns) {
     NS_ERROR("No treecolumns object for tree!");
     return roles::NOTHING;
   }
 
-  nsCOMPtr<nsITreeColumn> primaryColumn;
-  treeColumns->GetPrimaryColumn(getter_AddRefs(primaryColumn));
+  nsTreeColumn* primaryColumn = treeColumns->GetPrimaryColumn();
 
   return primaryColumn ? roles::TREE_TABLE : roles::TABLE;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // XULTreeGridAccessible: XULTreeAccessible implementation
 
 already_AddRefed<Accessible>
@@ -386,25 +386,24 @@ XULTreeGridRowAccessible::GetCellAccessi
   Document()->BindToDocument(cell, nullptr);
   return cell;
 }
 
 void
 XULTreeGridRowAccessible::RowInvalidated(int32_t aStartColIdx,
                                          int32_t aEndColIdx)
 {
-  nsCOMPtr<nsITreeColumns> treeColumns;
+  RefPtr<nsTreeColumns> treeColumns;
   mTree->GetColumns(getter_AddRefs(treeColumns));
   if (!treeColumns)
     return;
 
   bool nameChanged = false;
   for (int32_t colIdx = aStartColIdx; colIdx <= aEndColIdx; ++colIdx) {
-    nsCOMPtr<nsITreeColumn> column;
-    treeColumns->GetColumnAt(colIdx, getter_AddRefs(column));
+    nsTreeColumn* column = treeColumns->GetColumnAt(colIdx);
     if (column && !nsCoreUtils::IsColumnHidden(column)) {
       XULTreeGridCellAccessible* cell = GetCellAccessible(column);
       if (cell)
         nameChanged |= cell->CellInvalidated();
     }
   }
 
   if (nameChanged)
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -858,16 +858,19 @@ nsContextMenu.prototype = {
     let referrer = gContextMenuContentData.referrer;
     openLinkIn(gContextMenuContentData.docLocation, "window",
                { charset: gContextMenuContentData.charSet,
                  referrerURI: referrer ? makeURI(referrer) : null });
   },
 
   // Open clicked-in frame in the same window.
   showOnlyThisFrame() {
+    urlSecurityCheck(gContextMenuContentData.docLocation,
+                     this.browser.contentPrincipal,
+                     Ci.nsIScriptSecurityManager.DISALLOW_SCRIPT);
     let referrer = gContextMenuContentData.referrer;
     openWebLinkIn(gContextMenuContentData.docLocation, "current", {
       disallowInheritPrincipal: true,
       referrerURI: referrer ? makeURI(referrer) : null,
       triggeringPrincipal: this.browser.contentPrincipal,
     });
   },
 
@@ -916,28 +919,35 @@ nsContextMenu.prototype = {
   },
 
   viewImageInfo() {
     BrowserPageInfo(gContextMenuContentData.docLocation, "mediaTab",
                     this.imageInfo, null, this.browser);
   },
 
   viewImageDesc(e) {
+    urlSecurityCheck(this.imageDescURL,
+                     this.principal,
+                     Ci.nsIScriptSecurityManager.DISALLOW_SCRIPT);
     openUILink(this.imageDescURL, e, { disallowInheritPrincipal: true,
                                        referrerURI: gContextMenuContentData.documentURIObject,
                                        triggeringPrincipal: this.principal,
     });
   },
 
   viewFrameInfo() {
     BrowserPageInfo(gContextMenuContentData.docLocation, null, null,
                     this.frameOuterWindowID, this.browser);
   },
 
   reloadImage() {
+    urlSecurityCheck(this.mediaURL,
+                     this.principal,
+                     Ci.nsIScriptSecurityManager.DISALLOW_SCRIPT);
+
     this.browser.messageManager.sendAsyncMessage("ContextMenu:ReloadImage",
                                                  null, { target: this.target });
   },
 
   _canvasToBlobURL(target) {
     let mm = this.browser.messageManager;
     return new Promise(function(resolve) {
       mm.sendAsyncMessage("ContextMenu:Canvas:ToBlobURL", {}, { target });
@@ -956,20 +966,23 @@ nsContextMenu.prototype = {
     let systemPrincipal = Services.scriptSecurityManager.getSystemPrincipal();
     if (this.onCanvas) {
       this._canvasToBlobURL(this.target).then(function(blobURL) {
         openUILink(blobURL, e, { disallowInheritPrincipal: true,
                                  referrerURI,
                                  triggeringPrincipal: systemPrincipal});
       }, Cu.reportError);
     } else {
+      urlSecurityCheck(this.mediaURL,
+                       this.principal,
+                       Ci.nsIScriptSecurityManager.DISALLOW_SCRIPT);
       openUILink(this.mediaURL, e, { disallowInheritPrincipal: true,
                                      referrerURI,
                                      forceAllowDataURI: true,
-                                     triggeringPrincipal: this.browser.contentPrincipal
+                                     triggeringPrincipal: this.principal,
       });
     }
   },
 
   saveVideoFrameAsImage() {
     let mm = this.browser.messageManager;
     let isPrivate = PrivateBrowsingUtils.isBrowserPrivate(this.browser);
 
@@ -1000,19 +1013,23 @@ nsContextMenu.prototype = {
   },
 
   leaveDOMFullScreen() {
     document.exitFullscreen();
   },
 
   // Change current window to the URL of the background image.
   viewBGImage(e) {
+    urlSecurityCheck(this.bgImageURL,
+                     this.principal,
+                     Ci.nsIScriptSecurityManager.DISALLOW_SCRIPT);
+
     openUILink(this.bgImageURL, e, { disallowInheritPrincipal: true,
                                      referrerURI: gContextMenuContentData.documentURIObject,
-                                     triggeringPrincipal: this.browser.contentPrincipal
+                                     triggeringPrincipal: this.principal,
     });
   },
 
   setDesktopBackground() {
     let mm = this.browser.messageManager;
 
     mm.sendAsyncMessage("ContextMenu:SetAsDesktopBackground", null,
                         { target: this.target });
--- a/browser/extensions/pocket/content/main.js
+++ b/browser/extensions/pocket/content/main.js
@@ -389,16 +389,22 @@ var pktUI = (function() {
         pktUIMessaging.addMessageListener(iframe, _showMessageId, function(panelId, data) {
             // Let panel know that it is ready
             pktUIMessaging.sendMessageToPanel(panelId, _showMessageId);
         });
 
         // Open a new tab with a given url
         var _openTabWithUrlMessageId = "openTabWithUrl";
         pktUIMessaging.addMessageListener(iframe, _openTabWithUrlMessageId, function(panelId, data, contentPrincipal) {
+            try {
+              urlSecurityCheck(data.url, contentPrincipal, Services.scriptSecurityManager.DISALLOW_INHERIT_PRINCIPAL);
+            } catch (ex) {
+              return;
+            }
+
             var url = data.url;
             openTabWithUrl(url, contentPrincipal);
             pktUIMessaging.sendResponseMessageToPanel(panelId, _openTabWithUrlMessageId, url);
         });
 
         // Close the panel
         var _closeMessageId = "close";
         pktUIMessaging.addMessageListener(iframe, _closeMessageId, function(panelId, data) {
--- a/devtools/client/inspector/markup/test/browser_markup_display_node_01.js
+++ b/devtools/client/inspector/markup/test/browser_markup_display_node_01.js
@@ -6,40 +6,58 @@
 
 // Tests that markup display node shows for only for grid and flex containers.
 
 const TEST_URI = `
   <style type="text/css">
     #grid {
       display: grid;
     }
+    #subgrid {
+      display: grid;
+      grid: subgrid;
+    }
     #flex {
       display: flex;
     }
     #block {
       display: block;
     }
   </style>
-  <div id="grid">Grid</div>
+  <div id="grid">
+    <div id="subgrid"></div>
+  </div>
   <div id="flex">Flex</div>
   <div id="block">Block</div>
   <span>HELLO WORLD</span>
 `;
 
 add_task(async function() {
+  info("Enable subgrid in order to see the subgrid display type.");
+  await pushPref("layout.css.grid-template-subgrid-value.enabled", true);
+
   const {inspector} = await openInspectorForURL("data:text/html;charset=utf-8," +
     encodeURIComponent(TEST_URI));
 
   info("Check the display node is shown and the value of #grid.");
   await selectNode("#grid", inspector);
   const gridContainer = await getContainerForSelector("#grid", inspector);
   const gridDisplayNode = gridContainer.elt.querySelector(".markupview-display-badge");
   is(gridDisplayNode.textContent, "grid", "Got the correct display type for #grid.");
   is(gridDisplayNode.style.display, "inline-block", "#grid display node is shown.");
 
+  info("Check the display node is shown and the value of #subgrid.");
+  await selectNode("#subgrid", inspector);
+  const subgridContainer = await getContainerForSelector("#subgrid", inspector);
+  const subgridDisplayNode = subgridContainer.elt.querySelector(
+    ".markupview-display-badge");
+  is(subgridDisplayNode.textContent, "subgrid",
+    "Got the correct display type for #subgrid");
+  is(subgridDisplayNode.style.display, "inline-block", "#subgrid display node is shown");
+
   info("Check the display node is shown and the value of #flex.");
   await selectNode("#flex", inspector);
   const flexContainer = await getContainerForSelector("#flex", inspector);
   const flexDisplayNode = flexContainer.elt.querySelector(".markupview-display-badge");
   is(flexDisplayNode.textContent, "flex", "Got the correct display type for #flex");
   is(flexDisplayNode.style.display, "inline-block", "#flex display node is shown.");
 
   info("Check the display node is shown and the value of #block.");
--- a/devtools/client/inspector/markup/views/element-editor.js
+++ b/devtools/client/inspector/markup/views/element-editor.js
@@ -37,16 +37,17 @@ const HTML_VOID_ELEMENTS = [
 
 // Contains only valid computed display property types of the node to display in the
 // element markup and their respective title tooltip text.
 const DISPLAY_TYPES = {
   "flex": INSPECTOR_L10N.getStr("markupView.display.flex.tooltiptext"),
   "inline-flex": INSPECTOR_L10N.getStr("markupView.display.flex.tooltiptext"),
   "grid": INSPECTOR_L10N.getStr("markupView.display.grid.tooltiptext"),
   "inline-grid": INSPECTOR_L10N.getStr("markupView.display.inlineGrid.tooltiptext"),
+  "subgrid": INSPECTOR_L10N.getStr("markupView.display.subgrid.tooltiptiptext"),
   "flow-root": INSPECTOR_L10N.getStr("markupView.display.flowRoot.tooltiptext"),
   "contents": INSPECTOR_L10N.getStr("markupView.display.contents.tooltiptext2"),
 };
 
 /**
  * Creates an editor for an Element node.
  *
  * @param  {MarkupContainer} container
--- a/devtools/client/locales/en-US/inspector.properties
+++ b/devtools/client/locales/en-US/inspector.properties
@@ -53,16 +53,21 @@ markupView.display.inlineFlex.tooltiptex
 # the markup view.
 markupView.display.grid.tooltiptext=This element behaves like a block element and lays out its content according to the grid model.
 
 # LOCALIZATION NOTE (markupView.display.inlineGrid.tooltiptext)
 # Used in a tooltip that appears when the user hovers over the display type button in
 # the markup view.
 markupView.display.inlineGrid.tooltiptext=This element behaves like an inline element and lays out its content according to the grid model.
 
+# LOCALIZATION NOTE (markupView.display.subgrid.tooltiptext)
+# Used in a tooltip that appears when the user hovers over the display type button in
+# the markup view.
+markupView.display.subgrid.tooltiptiptext=This element lays out its content according to the grid model but defers the definition of its rows and/or columns to its parent grid container.
+
 # LOCALIZATION NOTE (markupView.display.flowRoot.tooltiptext)
 # Used in a tooltip that appears when the user hovers over the display type button in
 # the markup view.
 markupView.display.flowRoot.tooltiptext=This element generates a block element box that establishes a new block formatting context.
 
 # LOCALIZATION NOTE (markupView.display.contents.tooltiptext2)
 # Used in a tooltip that appears when the user hovers over the display type button in
 # the markup view.
--- a/devtools/client/storage/test/browser.ini
+++ b/devtools/client/storage/test/browser.ini
@@ -36,16 +36,17 @@ tags = usercontextid
 [browser_storage_cache_error.js]
 [browser_storage_cookies_add.js]
 [browser_storage_cookies_delete_all.js]
 [browser_storage_cookies_domain.js]
 [browser_storage_cookies_domain_port.js]
 [browser_storage_cookies_edit.js]
 [browser_storage_cookies_edit_keyboard.js]
 [browser_storage_cookies_samesite.js]
+skip-if = (os == "win" && os_version == "10.0" && !debug) # Bug 1448484
 [browser_storage_cookies_tab_navigation.js]
 [browser_storage_delete.js]
 [browser_storage_delete_all.js]
 [browser_storage_delete_tree.js]
 [browser_storage_delete_usercontextid.js]
 tags = usercontextid
 [browser_storage_dom_cache_disabled.js]
 [browser_storage_dynamic_updates_cookies.js]
--- a/devtools/server/actors/inspector/node.js
+++ b/devtools/server/actors/inspector/node.js
@@ -1,20 +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/. */
 
 "use strict";
 
-const {Cu} = require("chrome");
-
+const { Cu } = require("chrome");
+const Services = require("Services");
+const InspectorUtils = require("InspectorUtils");
 const protocol = require("devtools/shared/protocol");
-const {nodeSpec, nodeListSpec} = require("devtools/shared/specs/node");
-
-const InspectorUtils = require("InspectorUtils");
+const { nodeSpec, nodeListSpec } = require("devtools/shared/specs/node");
 
 loader.lazyRequireGetter(this, "colorUtils", "devtools/shared/css/color", true);
 
 loader.lazyRequireGetter(this, "getCssPath", "devtools/shared/inspector/css-logic", true);
 loader.lazyRequireGetter(this, "getXPath", "devtools/shared/inspector/css-logic", true);
 loader.lazyRequireGetter(this, "findCssSelector", "devtools/shared/inspector/css-logic", true);
 
 loader.lazyRequireGetter(this, "isNativeAnonymous", "devtools/shared/layout/utils", true);
@@ -23,16 +22,19 @@ loader.lazyRequireGetter(this, "isShadow
 loader.lazyRequireGetter(this, "isAnonymous", "devtools/shared/layout/utils", true);
 
 loader.lazyRequireGetter(this, "InspectorActorUtils", "devtools/server/actors/inspector/utils");
 loader.lazyRequireGetter(this, "LongStringActor", "devtools/server/actors/string", true);
 loader.lazyRequireGetter(this, "getFontPreviewData", "devtools/server/actors/styles", true);
 loader.lazyRequireGetter(this, "CssLogic", "devtools/server/actors/inspector/css-logic", true);
 loader.lazyRequireGetter(this, "EventParsers", "devtools/server/actors/inspector/event-parsers", true);
 
+const SUBGRID_ENABLED =
+  Services.prefs.getBoolPref("layout.css.grid-template-subgrid-value.enabled");
+
 const PSEUDO_CLASSES = [":hover", ":active", ":focus"];
 const FONT_FAMILY_PREVIEW_TEXT = "The quick brown fox jumps over the lazy dog";
 const FONT_FAMILY_PREVIEW_TEXT_SIZE = 20;
 
 /**
  * Server side of the node actor.
  */
 const NodeActor = protocol.ActorClassWithSpec(nodeSpec, {
@@ -251,16 +253,24 @@ const NodeActor = protocol.ActorClassWit
     }
 
     let display = null;
     try {
       display = style.display;
     } catch (e) {
       // Fails for <scrollbar> elements.
     }
+
+    if (SUBGRID_ENABLED &&
+        (display === "grid" || display === "inline-grid") &&
+        (style.gridTemplateRows === "subgrid" ||
+         style.gridTemplateColumns === "subgrid")) {
+      display = "subgrid";
+    }
+
     return display;
   },
 
   /**
    * Is the node currently displayed?
    */
   get isDisplayed() {
     const type = this.displayType;
--- a/dom/base/test/test_data_uri.html
+++ b/dom/base/test/test_data_uri.html
@@ -140,32 +140,36 @@ function runTests()
       }
 
       resolve();
     };
     document.head.appendChild(link);
   });
 
   // Test if data:font is same-origin.
-  let p7 = new Promise(resolve => {
+  let p7 = new Promise((resolve, reject) => {
     let text = document.createElement('p');
     // Cross-domain font will not load according to [1] so we try to apply
     // data:font to this text and see if the font can be loaded.
     // [1] https://www.w3.org/TR/css-fonts-3/#same-origin-restriction
     text.style = 'font-family: DataFont';
     text.innerHTML = "This text should trigger 'TestFont' to load.";
     document.body.appendChild(text);
 
-    document.fonts.onloadingdone = function (fontFaceSetEvent) {
-      is(fontFaceSetEvent.fontfaces.length, 1);
+    document.fonts.ready.then(fontFaces => {
+      is(fontFaces.size, 1, "should FontFace entry for data:font");
+      fontFaces.forEach(fontFace => {
+        is(fontFace.status, "loaded", "data:font should be same-origin");
+      });
       resolve();
-    };
-    document.fonts.onloadingerror = function (fontFaceSetEvent) {
+    },
+    _ => {
       ok(false, "data:font is not same-origin.");
-    };
+      reject();
+    });
   });
 
   Promise.all([p1, p2, p3, p4, p5, p6, p7]).then(() => {
     SimpleTest.finish();
   }).catch((e) => {
     ok(false, "throwing " + e);
     SimpleTest.finish();
   });
--- a/dom/cache/test/mochitest/serviceworker_driver.js
+++ b/dom/cache/test/mochitest/serviceworker_driver.js
@@ -1,37 +1,40 @@
 // Any copyright is dedicated to the Public Domain.
 // http://creativecommons.org/publicdomain/zero/1.0/
 
 function serviceWorkerTestExec(testFile) {
   return new Promise(function(resolve, reject) {
     function setupSW(registration) {
-      var worker = registration.waiting ||
+      var worker = registration.installing ||
+                   registration.waiting ||
                    registration.active;
+      var iframe;
 
       window.addEventListener("message",function onMessage(event) {
         if (event.data.context != "ServiceWorker") {
           return;
         }
         if (event.data.type == 'finish') {
           window.removeEventListener("message", onMessage);
+          iframe.remove();
           registration.unregister()
             .then(resolve)
             .catch(reject);
         } else if (event.data.type == 'status') {
           ok(event.data.status, event.data.context + ": " + event.data.msg);
         }
       });
 
       worker.onerror = reject;
 
-      var iframe = document.createElement("iframe");
+      iframe = document.createElement("iframe");
       iframe.src = "message_receiver.html";
       iframe.onload = function() {
         worker.postMessage({ script: testFile });
       };
       document.body.appendChild(iframe);
     }
 
-    navigator.serviceWorker.ready.then(setupSW);
-    navigator.serviceWorker.register("worker_wrapper.js", {scope: "."});
+    navigator.serviceWorker.register("worker_wrapper.js", {scope: "."})
+      .then(setupSW);
   });
 }
--- a/dom/cache/test/mochitest/worker_wrapper.js
+++ b/dom/cache/test/mochitest/worker_wrapper.js
@@ -87,43 +87,50 @@ function workerTestGetUserAgent(cb) {
     cb(e.data.result);
   });
   client.postMessage({
     context: context,
     type: 'getUserAgent'
   });
 }
 
+var completeInstall = null;
+
 addEventListener('message', function workerWrapperOnMessage(e) {
   removeEventListener('message', workerWrapperOnMessage);
   var data = e.data;
   function runScript() {
     try {
       importScripts(data.script);
     } catch(e) {
       client.postMessage({
         type: 'status',
         status: false,
         context: context,
         msg: 'worker failed to import ' + data.script + "; error: " + e.message
       });
     }
   }
   if ("ServiceWorker" in self) {
-    self.clients.matchAll().then(function(clients) {
+    self.clients.matchAll({ includeUncontrolled: true }).then(function(clients) {
       for (var i = 0; i < clients.length; ++i) {
         if (clients[i].url.indexOf("message_receiver.html") > -1) {
           client = clients[i];
           break;
         }
       }
       if (!client) {
         dump("We couldn't find the message_receiver window, the test will fail\n");
       }
       context = "ServiceWorker";
       runScript();
+      completeInstall();
     });
   } else {
     client = self;
     context = "Worker";
     runScript();
   }
 });
+
+addEventListener("install", e => {
+  e.waitUntil(new Promise(resolve => completeInstall = resolve));
+})
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -1473,16 +1473,17 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSrcAttrStream)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSourcePointer)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLoadBlockedDoc)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSourceLoadCandidate)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAudioChannelWrapper)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mErrorSink->mError)
   for (uint32_t i = 0; i < tmp->mOutputStreams.Length(); ++i) {
     NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOutputStreams[i].mStream)
+    NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOutputStreams[i].mPreCreatedTracks)
   }
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPlayed);
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTextTrackManager)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAudioTrackList)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVideoTrackList)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaKeys)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIncomingMediaKeys)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSelectedVideoStreamTrack)
@@ -1720,16 +1721,24 @@ HTMLMediaElement::ShutdownDecoder()
 {
   RemoveMediaElementFromURITable();
   NS_ASSERTION(mDecoder, "Must have decoder to shut down");
 
   mWaitingForKeyListener.DisconnectIfExists();
   if (mMediaSource) {
     mMediaSource->CompletePendingTransactions();
   }
+  for (OutputMediaStream& out : mOutputStreams) {
+    if (!out.mCapturingDecoder) {
+      continue;
+    }
+    out.mNextAvailableTrackID = std::max<TrackID>(
+      mDecoder->NextAvailableTrackIDFor(out.mStream->GetInputStream()),
+      out.mNextAvailableTrackID);
+  }
   mDecoder->Shutdown();
   DDUNLINKCHILD(mDecoder.get());
   mDecoder = nullptr;
 }
 
 void
 HTMLMediaElement::AbortExistingLoads()
 {
@@ -3533,44 +3542,47 @@ HTMLMediaElement::CaptureStreamInternal(
     // speakers.
     mAudioCaptured = true;
   }
 
   if (mDecoder) {
     out->mCapturingDecoder = true;
     mDecoder->AddOutputStream(
       out->mStream->GetInputStream()->AsProcessedStream(),
+      out->mNextAvailableTrackID,
       aFinishBehavior == StreamCaptureBehavior::FINISH_WHEN_ENDED);
   } else if (mSrcStream) {
     out->mCapturingMediaStream = true;
   }
 
   if (mReadyState == HAVE_NOTHING) {
     // Do not expose the tracks until we have metadata.
     RefPtr<DOMMediaStream> result = out->mStream;
     return result.forget();
   }
 
   if (mDecoder) {
     if (HasAudio()) {
-      TrackID audioTrackId = mMediaInfo.mAudio.mTrackId;
+      TrackID audioTrackId = out->mNextAvailableTrackID++;
       RefPtr<MediaStreamTrackSource> trackSource =
         getter->GetMediaStreamTrackSource(audioTrackId);
       RefPtr<MediaStreamTrack> track = out->mStream->CreateDOMTrack(
         audioTrackId, MediaSegment::AUDIO, trackSource);
+      out->mPreCreatedTracks.AppendElement(track);
       out->mStream->AddTrackInternal(track);
       LOG(LogLevel::Debug,
           ("Created audio track %d for captured decoder", audioTrackId));
     }
     if (IsVideo() && HasVideo() && !out->mCapturingAudioOnly) {
-      TrackID videoTrackId = mMediaInfo.mVideo.mTrackId;
+      TrackID videoTrackId = out->mNextAvailableTrackID++;
       RefPtr<MediaStreamTrackSource> trackSource =
         getter->GetMediaStreamTrackSource(videoTrackId);
       RefPtr<MediaStreamTrack> track = out->mStream->CreateDOMTrack(
         videoTrackId, MediaSegment::VIDEO, trackSource);
+      out->mPreCreatedTracks.AppendElement(track);
       out->mStream->AddTrackInternal(track);
       LOG(LogLevel::Debug,
           ("Created video track %d for captured decoder", videoTrackId));
     }
   }
 
   if (mSrcStream) {
     for (size_t i = 0; i < AudioTracks()->Length(); ++i) {
@@ -4233,21 +4245,21 @@ HTMLMediaElement::WakeLockRelease()
     ErrorResult rv;
     mWakeLock->Unlock(rv);
     rv.SuppressException();
     mWakeLock = nullptr;
   }
 }
 
 HTMLMediaElement::OutputMediaStream::OutputMediaStream()
-  : mFinishWhenEnded(false)
+  : mNextAvailableTrackID(1)
+  , mFinishWhenEnded(false)
   , mCapturingAudioOnly(false)
   , mCapturingDecoder(false)
   , mCapturingMediaStream(false)
-  , mNextAvailableTrackID(1)
 {
 }
 
 HTMLMediaElement::OutputMediaStream::~OutputMediaStream()
 {
   for (auto pair : mTrackPorts) {
     pair.second()->Destroy();
   }
@@ -4963,16 +4975,17 @@ HTMLMediaElement::FinishDecoderSetup(Med
   for (OutputMediaStream& ms : mOutputStreams) {
     if (ms.mCapturingMediaStream) {
       MOZ_ASSERT(!ms.mCapturingDecoder);
       continue;
     }
 
     ms.mCapturingDecoder = true;
     aDecoder->AddOutputStream(ms.mStream->GetInputStream()->AsProcessedStream(),
+                              ms.mNextAvailableTrackID,
                               ms.mFinishWhenEnded);
   }
 
   if (mMediaKeys) {
     if (mMediaKeys->GetCDMProxy()) {
       mDecoder->SetCDMProxy(mMediaKeys->GetCDMProxy());
     } else {
       // CDM must have crashed.
@@ -7939,16 +7952,31 @@ HTMLMediaElement::RemoveMediaTracks()
     mAudioTrackList->RemoveTracks();
   }
 
   if (mVideoTrackList) {
     mVideoTrackList->RemoveTracks();
   }
 
   mMediaTracksConstructed = false;
+
+  for (OutputMediaStream& ms : mOutputStreams) {
+    if (!ms.mCapturingDecoder) {
+      continue;
+    }
+    for (RefPtr<MediaStreamTrack>& t : ms.mPreCreatedTracks) {
+      if (t->Ended()) {
+        continue;
+      }
+      mAbstractMainThread->Dispatch(NewRunnableMethod(
+        "dom::HTMLMediaElement::RemoveMediaTracks",
+        t, &MediaStreamTrack::OverrideEnded));
+    }
+    ms.mPreCreatedTracks.Clear();
+  }
 }
 
 class MediaElementGMPCrashHelper : public GMPCrashHelper
 {
 public:
   explicit MediaElementGMPCrashHelper(HTMLMediaElement* aElement)
     : mElement(aElement)
   {
--- a/dom/html/HTMLMediaElement.h
+++ b/dom/html/HTMLMediaElement.h
@@ -862,23 +862,28 @@ protected:
 
   // Holds references to the DOM wrappers for the MediaStreams that we're
   // writing to.
   struct OutputMediaStream {
     OutputMediaStream();
     ~OutputMediaStream();
 
     RefPtr<DOMMediaStream> mStream;
+    TrackID mNextAvailableTrackID;
     bool mFinishWhenEnded;
     bool mCapturingAudioOnly;
     bool mCapturingDecoder;
     bool mCapturingMediaStream;
 
+    // The following members are keeping state for a captured MediaDecoder.
+    // Tracks that were created on main thread before MediaDecoder fed them
+    // to the MediaStreamGraph.
+    nsTArray<RefPtr<MediaStreamTrack>> mPreCreatedTracks;
+
     // The following members are keeping state for a captured MediaStream.
-    TrackID mNextAvailableTrackID;
     nsTArray<Pair<nsString, RefPtr<MediaInputPort>>> mTrackPorts;
   };
 
   already_AddRefed<Promise> PlayInternal(ErrorResult& aRv);
 
   /** Use this method to change the mReadyState member, so required
    * events can be fired.
    */
--- a/dom/media/MediaDecoder.cpp
+++ b/dom/media/MediaDecoder.cpp
@@ -165,33 +165,44 @@ MediaDecoder::SetVolume(double aVolume)
 {
   MOZ_ASSERT(NS_IsMainThread());
   AbstractThread::AutoEnter context(AbstractMainThread());
   mVolume = aVolume;
 }
 
 void
 MediaDecoder::AddOutputStream(ProcessedMediaStream* aStream,
+                              TrackID aNextAvailableTrackID,
                               bool aFinishWhenEnded)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mDecoderStateMachine, "Must be called after Load().");
   AbstractThread::AutoEnter context(AbstractMainThread());
-  mDecoderStateMachine->AddOutputStream(aStream, aFinishWhenEnded);
+  mDecoderStateMachine->AddOutputStream(
+    aStream, aNextAvailableTrackID, aFinishWhenEnded);
 }
 
 void
 MediaDecoder::RemoveOutputStream(MediaStream* aStream)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mDecoderStateMachine, "Must be called after Load().");
   AbstractThread::AutoEnter context(AbstractMainThread());
   mDecoderStateMachine->RemoveOutputStream(aStream);
 }
 
+TrackID
+MediaDecoder::NextAvailableTrackIDFor(MediaStream* aOutputStream) const
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(mDecoderStateMachine, "Must be called after Load().");
+  AbstractThread::AutoEnter context(AbstractMainThread());
+  return mDecoderStateMachine->NextAvailableTrackIDFor(aOutputStream);
+}
+
 double
 MediaDecoder::GetDuration()
 {
   MOZ_ASSERT(NS_IsMainThread());
   AbstractThread::AutoEnter context(AbstractMainThread());
   return mDuration;
 }
 
--- a/dom/media/MediaDecoder.h
+++ b/dom/media/MediaDecoder.h
@@ -165,19 +165,22 @@ public:
   // captureStream(UntilEnded). Seeking creates a new source stream, as does
   // replaying after the input as ended. In the latter case, the new source is
   // not connected to streams created by captureStreamUntilEnded.
 
   // Add an output stream. All decoder output will be sent to the stream.
   // The stream is initially blocked. The decoder is responsible for unblocking
   // it while it is playing back.
   virtual void AddOutputStream(ProcessedMediaStream* aStream,
+                               TrackID aNextAvailableTrackID,
                                bool aFinishWhenEnded);
   // Remove an output stream added with AddOutputStream.
   virtual void RemoveOutputStream(MediaStream* aStream);
+  // The next TrackID that can be used without risk of a collision.
+  virtual TrackID NextAvailableTrackIDFor(MediaStream* aOutputStream) const;
 
   // Return the duration of the video in seconds.
   virtual double GetDuration();
 
   // Return true if the stream is infinite.
   bool IsInfinite() const;
 
   // Return true if we are currently seeking in the media resource.
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -3443,16 +3443,20 @@ MediaDecoderStateMachine::FinishDecodeFi
   mReader->ReadUpdatedMetadata(mInfo.ptr());
 
   EnqueueFirstFrameLoadedEvent();
 }
 
 RefPtr<ShutdownPromise>
 MediaDecoderStateMachine::BeginShutdown()
 {
+  MOZ_ASSERT(NS_IsMainThread());
+  if (mOutputStreamManager) {
+    mOutputStreamManager->Clear();
+  }
   return InvokeAsync(OwnerThread(), this, __func__,
                      &MediaDecoderStateMachine::Shutdown);
 }
 
 RefPtr<ShutdownPromise>
 MediaDecoderStateMachine::FinishShutdown()
 {
   MOZ_ASSERT(OnTaskQueue());
@@ -3821,21 +3825,22 @@ MediaDecoderStateMachine::RequestDebugIn
       [self, p]() { p->Resolve(self->GetDebugInfo(), __func__); }),
     AbstractThread::TailDispatch);
   MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
   Unused << rv;
   return p.forget();
 }
 
 void MediaDecoderStateMachine::AddOutputStream(ProcessedMediaStream* aStream,
+                                               TrackID aNextAvailableTrackID,
                                                bool aFinishWhenEnded)
 {
   MOZ_ASSERT(NS_IsMainThread());
   LOG("AddOutputStream aStream=%p!", aStream);
-  mOutputStreamManager->Add(aStream, aFinishWhenEnded);
+  mOutputStreamManager->Add(aStream, aNextAvailableTrackID, aFinishWhenEnded);
   nsCOMPtr<nsIRunnable> r =
     NewRunnableMethod<bool>("MediaDecoderStateMachine::SetAudioCaptured",
                             this,
                             &MediaDecoderStateMachine::SetAudioCaptured,
                             true);
   nsresult rv = OwnerThread()->Dispatch(r.forget());
   MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
   Unused << rv;
@@ -3853,16 +3858,23 @@ void MediaDecoderStateMachine::RemoveOut
                               &MediaDecoderStateMachine::SetAudioCaptured,
                               false);
     nsresult rv = OwnerThread()->Dispatch(r.forget());
     MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
     Unused << rv;
   }
 }
 
+TrackID
+MediaDecoderStateMachine::NextAvailableTrackIDFor(MediaStream* aOutputStream) const
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  return mOutputStreamManager->NextAvailableTrackIDFor(aOutputStream);
+}
+
 class VideoQueueMemoryFunctor : public nsDequeFunctor
 {
 public:
   VideoQueueMemoryFunctor()
     : mSize(0)
   {
   }
 
--- a/dom/media/MediaDecoderStateMachine.h
+++ b/dom/media/MediaDecoderStateMachine.h
@@ -196,19 +196,22 @@ public:
     DECODER_STATE_SHUTDOWN
   };
 
   // Returns the state machine task queue.
   TaskQueue* OwnerThread() const { return mTaskQueue; }
 
   RefPtr<MediaDecoder::DebugInfoPromise> RequestDebugInfo();
 
-  void AddOutputStream(ProcessedMediaStream* aStream, bool aFinishWhenEnded);
+  void AddOutputStream(ProcessedMediaStream* aStream,
+                       TrackID aNextAvailableTrackID,
+                       bool aFinishWhenEnded);
   // Remove an output stream added with AddOutputStream.
   void RemoveOutputStream(MediaStream* aStream);
+  TrackID NextAvailableTrackIDFor(MediaStream* aOutputStream) const;
 
   // Seeks to the decoder to aTarget asynchronously.
   RefPtr<MediaDecoder::SeekPromise> InvokeSeek(const SeekTarget& aTarget);
 
   void DispatchSetPlaybackRate(double aPlaybackRate)
   {
     OwnerThread()->DispatchStateChange(
       NewRunnableMethod<double>("MediaDecoderStateMachine::SetPlaybackRate",
--- a/dom/media/mediasink/DecodedStream.cpp
+++ b/dom/media/mediasink/DecodedStream.cpp
@@ -188,27 +188,32 @@ DecodedStreamData::DecodedStreamData(Out
   // mPlaying is initially true because MDSM won't start playback until playing
   // becomes true. This is consistent with the settings of AudioSink.
   , mPlaying(true)
   , mEOSVideoCompensation(false)
   , mOutputStreamManager(aOutputStreamManager)
   , mAbstractMainThread(aMainThread)
 {
   mStream->AddListener(mListener);
-  mOutputStreamManager->Connect(mStream);
+  TrackID audioTrack = TRACK_NONE;
+  TrackID videoTrack = TRACK_NONE;
 
   // Initialize tracks.
   if (aInit.mInfo.HasAudio()) {
-    mStream->AddAudioTrack(aInit.mInfo.mAudio.mTrackId,
+    audioTrack = aInit.mInfo.mAudio.mTrackId;
+    mStream->AddAudioTrack(audioTrack,
                            aInit.mInfo.mAudio.mRate,
                            0, new AudioSegment());
   }
   if (aInit.mInfo.HasVideo()) {
-    mStream->AddTrack(aInit.mInfo.mVideo.mTrackId, 0, new VideoSegment());
+    videoTrack = aInit.mInfo.mVideo.mTrackId;
+    mStream->AddTrack(videoTrack, 0, new VideoSegment());
   }
+
+  mOutputStreamManager->Connect(mStream, audioTrack, videoTrack);
 }
 
 DecodedStreamData::~DecodedStreamData()
 {
   mOutputStreamManager->Disconnect();
   mStream->Destroy();
 }
 
--- a/dom/media/mediasink/OutputStreamManager.cpp
+++ b/dom/media/mediasink/OutputStreamManager.cpp
@@ -8,126 +8,171 @@
 #include "OutputStreamManager.h"
 
 namespace mozilla {
 
 OutputStreamData::~OutputStreamData()
 {
   MOZ_ASSERT(NS_IsMainThread());
   // Break the connection to the input stream if necessary.
-  if (mPort) {
-    mPort->Destroy();
+  for (RefPtr<MediaInputPort>& port : mPorts) {
+    port->Destroy();
   }
 }
 
 void
-OutputStreamData::Init(OutputStreamManager* aOwner, ProcessedMediaStream* aStream)
+OutputStreamData::Init(OutputStreamManager* aOwner,
+                       ProcessedMediaStream* aStream,
+                       TrackID aNextAvailableTrackID)
 {
   mOwner = aOwner;
   mStream = aStream;
+  mNextAvailableTrackID = aNextAvailableTrackID;
 }
 
 bool
-OutputStreamData::Connect(MediaStream* aStream)
+OutputStreamData::Connect(MediaStream* aStream,
+                          TrackID aInputAudioTrackID,
+                          TrackID aInputVideoTrackID)
 {
   MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(!mPort, "Already connected?");
+  MOZ_ASSERT(mPorts.IsEmpty(), "Already connected?");
 
   if (mStream->IsDestroyed()) {
     return false;
   }
 
-  mPort = mStream->AllocateInputPort(aStream);
+  for (TrackID tid : {aInputAudioTrackID, aInputVideoTrackID}) {
+    if (tid == TRACK_NONE) {
+      continue;
+    }
+    MOZ_ASSERT(IsTrackIDExplicit(tid));
+    mPorts.AppendElement(mStream->AllocateInputPort(
+        aStream, tid, mNextAvailableTrackID++));
+  }
   return true;
 }
 
 bool
 OutputStreamData::Disconnect()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   // During cycle collection, DOMMediaStream can be destroyed and send
   // its Destroy message before this decoder is destroyed. So we have to
   // be careful not to send any messages after the Destroy().
   if (mStream->IsDestroyed()) {
     return false;
   }
 
-  // Disconnect the existing port if necessary.
-  if (mPort) {
-    mPort->Destroy();
-    mPort = nullptr;
+  // Disconnect any existing port.
+  for (RefPtr<MediaInputPort>& port : mPorts) {
+    port->Destroy();
   }
+  mPorts.Clear();
   return true;
 }
 
 bool
 OutputStreamData::Equals(MediaStream* aStream) const
 {
   return mStream == aStream;
 }
 
 MediaStreamGraph*
 OutputStreamData::Graph() const
 {
   return mStream->Graph();
 }
 
+TrackID
+OutputStreamData::NextAvailableTrackID() const
+{
+  return mNextAvailableTrackID;
+}
+
 void
-OutputStreamManager::Add(ProcessedMediaStream* aStream, bool aFinishWhenEnded)
+OutputStreamManager::Add(ProcessedMediaStream* aStream,
+                         TrackID aNextAvailableTrackID,
+                         bool aFinishWhenEnded)
 {
   MOZ_ASSERT(NS_IsMainThread());
   // All streams must belong to the same graph.
   MOZ_ASSERT(!Graph() || Graph() == aStream->Graph());
 
   // Ensure that aStream finishes the moment mDecodedStream does.
   if (aFinishWhenEnded) {
     aStream->QueueSetAutofinish(true);
   }
 
   OutputStreamData* p = mStreams.AppendElement();
-  p->Init(this, aStream);
+  p->Init(this, aStream, aNextAvailableTrackID);
 
   // Connect to the input stream if we have one. Otherwise the output stream
   // will be connected in Connect().
   if (mInputStream) {
-    p->Connect(mInputStream);
+    p->Connect(mInputStream, mInputAudioTrackID, mInputVideoTrackID);
   }
 }
 
 void
 OutputStreamManager::Remove(MediaStream* aStream)
 {
   MOZ_ASSERT(NS_IsMainThread());
   for (int32_t i = mStreams.Length() - 1; i >= 0; --i) {
     if (mStreams[i].Equals(aStream)) {
       mStreams.RemoveElementAt(i);
       break;
     }
   }
 }
 
 void
-OutputStreamManager::Connect(MediaStream* aStream)
+OutputStreamManager::Clear()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  mStreams.Clear();
+}
+
+TrackID
+OutputStreamManager::NextAvailableTrackIDFor(MediaStream* aOutputStream) const
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  for (const OutputStreamData& out : mStreams) {
+    if (out.Equals(aOutputStream)) {
+      return out.NextAvailableTrackID();
+    }
+  }
+  return TRACK_INVALID;
+}
+
+void
+OutputStreamManager::Connect(MediaStream* aStream,
+                             TrackID aAudioTrackID,
+                             TrackID aVideoTrackID)
 {
   MOZ_ASSERT(NS_IsMainThread());
   mInputStream = aStream;
+  mInputAudioTrackID = aAudioTrackID;
+  mInputVideoTrackID = aVideoTrackID;
   for (int32_t i = mStreams.Length() - 1; i >= 0; --i) {
-    if (!mStreams[i].Connect(aStream)) {
+    if (!mStreams[i].Connect(aStream, mInputAudioTrackID, mInputVideoTrackID)) {
       // Probably the DOMMediaStream was GCed. Clean up.
       mStreams.RemoveElementAt(i);
     }
   }
 }
 
 void
 OutputStreamManager::Disconnect()
 {
   MOZ_ASSERT(NS_IsMainThread());
   mInputStream = nullptr;
+  mInputAudioTrackID = TRACK_INVALID;
+  mInputVideoTrackID = TRACK_INVALID;
   for (int32_t i = mStreams.Length() - 1; i >= 0; --i) {
     if (!mStreams[i].Disconnect()) {
       // Probably the DOMMediaStream was GCed. Clean up.
       mStreams.RemoveElementAt(i);
     }
   }
 }
 
--- a/dom/media/mediasink/OutputStreamManager.h
+++ b/dom/media/mediasink/OutputStreamManager.h
@@ -4,77 +4,94 @@
  * 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 OutputStreamManager_h
 #define OutputStreamManager_h
 
 #include "mozilla/RefPtr.h"
 #include "nsTArray.h"
+#include "TrackID.h"
 
 namespace mozilla {
 
 class MediaInputPort;
 class MediaStream;
 class MediaStreamGraph;
 class OutputStreamManager;
 class ProcessedMediaStream;
 
 class OutputStreamData {
 public:
   ~OutputStreamData();
-  void Init(OutputStreamManager* aOwner, ProcessedMediaStream* aStream);
+  void Init(OutputStreamManager* aOwner,
+            ProcessedMediaStream* aStream,
+            TrackID aNextAvailableTrackID);
 
-  // Connect mStream to the input stream.
+  // Connect the given input stream's audio and video tracks to mStream.
   // Return false is mStream is already destroyed, otherwise true.
-  bool Connect(MediaStream* aStream);
+  bool Connect(MediaStream* aStream, TrackID aAudioTrackID, TrackID aVideoTrackID);
   // Disconnect mStream from its input stream.
   // Return false is mStream is already destroyed, otherwise true.
   bool Disconnect();
   // Return true if aStream points to the same object as mStream.
   // Used by OutputStreamManager to remove an output stream.
   bool Equals(MediaStream* aStream) const;
   // Return the graph mStream belongs to.
   MediaStreamGraph* Graph() const;
+  // The next TrackID that will not cause a collision in mStream.
+  TrackID NextAvailableTrackID() const;
 
 private:
   OutputStreamManager* mOwner;
   RefPtr<ProcessedMediaStream> mStream;
-  // mPort connects our mStream to an input stream.
-  RefPtr<MediaInputPort> mPort;
+  // mPort connects an input stream to our mStream.
+  nsTArray<RefPtr<MediaInputPort>> mPorts;
+  // For guaranteeing TrackID uniqueness in our mStream.
+  TrackID mNextAvailableTrackID = TRACK_INVALID;
 };
 
 class OutputStreamManager {
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(OutputStreamManager);
 
 public:
   // Add the output stream to the collection.
-  void Add(ProcessedMediaStream* aStream, bool aFinishWhenEnded);
+  void Add(ProcessedMediaStream* aStream,
+           TrackID aNextAvailableTrackID,
+           bool aFinishWhenEnded);
   // Remove the output stream from the collection.
   void Remove(MediaStream* aStream);
+  // Clear all output streams from the collection.
+  void Clear();
+  // The next TrackID that will not cause a collision in aOutputStream.
+  TrackID NextAvailableTrackIDFor(MediaStream* aOutputStream) const;
   // Return true if the collection empty.
   bool IsEmpty() const
   {
     MOZ_ASSERT(NS_IsMainThread());
     return mStreams.IsEmpty();
   }
-  // Connect all output streams in the collection to the input stream.
-  void Connect(MediaStream* aStream);
-  // Disconnect all output streams from the input stream.
+  // Connect the given input stream's tracks to all output streams.
+  void Connect(MediaStream* aStream,
+               TrackID aAudioTrackID,
+               TrackID aVideoTrackID);
+  // Disconnect the input stream to all output streams.
   void Disconnect();
   // Return the graph these streams belong to or null if empty.
   MediaStreamGraph* Graph() const
   {
     MOZ_ASSERT(NS_IsMainThread());
     return !IsEmpty() ? mStreams[0].Graph() : nullptr;
   }
 
 private:
   ~OutputStreamManager() {}
   // Keep the input stream so we can connect the output streams that
   // are added after Connect().
   RefPtr<MediaStream> mInputStream;
+  TrackID mInputAudioTrackID = TRACK_INVALID;
+  TrackID mInputVideoTrackID = TRACK_INVALID;
   nsTArray<OutputStreamData> mStreams;
 };
 
 } // namespace mozilla
 
 #endif // OutputStreamManager_h
--- a/dom/serviceworkers/ServiceWorkerRegistrationImpl.cpp
+++ b/dom/serviceworkers/ServiceWorkerRegistrationImpl.cpp
@@ -726,17 +726,17 @@ ServiceWorkerRegistrationWorkerThread::U
   if (NS_WARN_IF(!workerRef)) {
     return ServiceWorkerRegistrationPromise::CreateAndReject(
       NS_ERROR_DOM_INVALID_STATE_ERR, __func__);
   }
 
   // Avoid infinite update loops by ignoring update() calls during top
   // level script evaluation.  See:
   // https://github.com/slightlyoff/ServiceWorker/issues/800
-  if (workerRef->Private()->LoadScriptAsPartOfLoadingServiceWorkerScript()) {
+  if (workerRef->Private()->IsLoadingWorkerScript()) {
     return ServiceWorkerRegistrationPromise::CreateAndResolve(mDescriptor,
                                                               __func__);
   }
 
   // Eventually we need to support all workers, but for right now this
   // code assumes we're on a service worker global as self.registration.
   if (NS_WARN_IF(!workerRef->Private()->IsServiceWorker())) {
     return ServiceWorkerRegistrationPromise::CreateAndReject(
--- a/dom/serviceworkers/test/importscript_worker.js
+++ b/dom/serviceworkers/test/importscript_worker.js
@@ -22,16 +22,25 @@ onmessage = function(e) {
       dump("ERROR: no clients are currently controlled.\n");
     }
 
     if (!missingScriptFailed) {
       res[0].postMessage("KO");
     }
 
     try {
-      importScripts(['importscript.sjs']);
+      // new unique script should fail
+      importScripts(['importscript.sjs?unique=true']);
       res[0].postMessage("KO");
       return;
     } catch(e) {}
 
-    res[0].postMessage(counter == 2 ? "OK" : "KO");
+    try {
+      // duplicate script previously offlined should succeed
+      importScripts(['importscript.sjs']);
+    } catch(e) {
+      res[0].postMessage("KO");
+      return;
+    }
+
+    res[0].postMessage(counter == 3 ? "OK" : "KO");
   });
 };
--- a/dom/serviceworkers/test/serviceworker_wrapper.js
+++ b/dom/serviceworkers/test/serviceworker_wrapper.js
@@ -78,24 +78,36 @@ function workerTestGetStorageManager(cb)
     removeEventListener('message', workerTestGetStorageManagerCB);
     cb(e.data.result);
   });
   client.postMessage({
     type: 'getStorageManager'
   });
 }
 
+var completeInstall;
+
 addEventListener('message', function workerWrapperOnMessage(e) {
   removeEventListener('message', workerWrapperOnMessage);
   var data = e.data;
-  self.clients.matchAll().then(function(clients) {
-    client = clients[0];
+  self.clients.matchAll({ includeUncontrolled: true }).then(function(clients) {
+    for (var i = 0; i < clients.length; ++i) {
+      if (clients[i].url.includes("message_receiver.html")) {
+        client = clients[i];
+        break;
+      }
+    }
     try {
       importScripts(data.script);
     } catch(e) {
       client.postMessage({
         type: 'status',
         status: false,
         msg: 'worker failed to import ' + data.script + "; error: " + e.message
       });
     }
+    completeInstall();
   });
 });
+
+addEventListener('install', e => {
+  e.waitUntil(new Promise(resolve => completeInstall = resolve));
+});
--- a/dom/serviceworkers/test/test_serviceworker_interfaces.html
+++ b/dom/serviceworkers/test/test_serviceworker_interfaces.html
@@ -7,20 +7,23 @@
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
   <script type="text/javascript" src="../worker_driver.js"></script>
 </head>
 <body>
 <script class="testbody" type="text/javascript">
 
   function setupSW(registration) {
-    var worker = registration.waiting ||
+    var iframe;
+    var worker = registration.installing ||
+                 registration.waiting ||
                  registration.active;
     window.onmessage = function(event) {
       if (event.data.type == 'finish') {
+        iframe.remove();
         registration.unregister().then(function(success) {
           ok(success, "The service worker should be unregistered successfully");
 
           SimpleTest.finish();
         }, function(e) {
           dump("Unregistering the SW failed with " + e + "\n");
           SimpleTest.finish();
         });
@@ -58,27 +61,27 @@
       }
     }
 
     worker.onerror = function(event) {
       ok(false, 'Worker had an error: ' + event.data);
       SimpleTest.finish();
     };
 
-    var iframe = document.createElement("iframe");
+    iframe = document.createElement("iframe");
     iframe.src = "message_receiver.html";
     iframe.onload = function() {
       worker.postMessage({ script: "test_serviceworker_interfaces.js" });
     };
     document.body.appendChild(iframe);
   }
 
   function runTest() {
-    navigator.serviceWorker.ready.then(setupSW);
-    navigator.serviceWorker.register("serviceworker_wrapper.js", {scope: "."});
+    navigator.serviceWorker.register("serviceworker_wrapper.js", {scope: "."})
+      .then(setupSW);
   }
 
   SimpleTest.waitForExplicitFinish();
   onload = function() {
     // The handling of "dom.caches.enabled" here is a bit complicated.  What we
     // want to happen is that Cache is always enabled in service workers.  So
     // if service workers are disabled by default we want to force on both
     // service workers and "dom.caches.enabled".  But if service workers are
--- a/dom/tests/mochitest/fetch/fetch_test_framework.js
+++ b/dom/tests/mochitest/fetch/fetch_test_framework.js
@@ -69,45 +69,47 @@ function testScript(script) {
                 /Mobile|Tablet/.test(navigator.userAgent);
     if (isB2G) {
       // TODO B2G doesn't support running service workers for now due to bug 1137683.
       dump("Skipping running the test in SW until bug 1137683 gets fixed.\n");
       return Promise.resolve();
     }
     return new Promise(function(resolve, reject) {
       function setupSW(registration) {
-        var worker = registration.waiting ||
+        var worker = registration.installing ||
+                     registration.waiting ||
                      registration.active;
+        var iframe;
 
         window.addEventListener("message",function onMessage(event) {
           if (event.data.context != "ServiceWorker") {
             return;
           }
           if (event.data.type == 'finish') {
             window.removeEventListener("message", onMessage);
+            iframe.remove();
             registration.unregister()
               .then(resolve)
               .catch(reject);
           } else if (event.data.type == 'status') {
             ok(event.data.status, event.data.context + ": " + event.data.msg);
           }
         });
 
         worker.onerror = reject;
 
-        var iframe = document.createElement("iframe");
+        iframe = document.createElement("iframe");
         iframe.src = "message_receiver.html";
         iframe.onload = function() {
           worker.postMessage({ script: script });
         };
         document.body.appendChild(iframe);
       }
 
       navigator.serviceWorker.register("worker_wrapper.js", {scope: "."})
-        .then(swr => waitForState(swr.installing, 'activated', swr))
         .then(setupSW);
     });
   }
 
   function windowTest() {
     return new Promise(function(resolve, reject) {
       var scriptEl = document.createElement("script");
       scriptEl.setAttribute("src", script);
--- a/dom/tests/mochitest/fetch/sw_reroute.js
+++ b/dom/tests/mochitest/fetch/sw_reroute.js
@@ -1,32 +1,35 @@
 var gRegistration;
+var iframe;
 
 function testScript(script) {
+  var scope = "./reroute.html?" + script.replace(".js", "");
   function setupSW(registration) {
     gRegistration = registration;
 
-    var iframe = document.createElement("iframe");
-    iframe.src = "reroute.html?" + script.replace(".js", "");
+    iframe = document.createElement("iframe");
+    iframe.src = scope;
     document.body.appendChild(iframe);
   }
 
   SpecialPowers.pushPrefEnv({
     "set": [["dom.serviceWorkers.enabled", true],
             ["dom.serviceWorkers.testing.enabled", true],
             ["dom.serviceWorkers.exemptFromPerDomainMax", true]]
   }, function() {
     var scriptURL = location.href.includes("sw_empty_reroute.html")
                   ? "empty.js" : "reroute.js";
-    navigator.serviceWorker.register(scriptURL, {scope: "/"})
+    navigator.serviceWorker.register(scriptURL, {scope: scope})
       .then(swr => waitForState(swr.installing, 'activated', swr))
       .then(setupSW);
   });
 }
 
 function finishTest() {
+  iframe.remove();
   gRegistration.unregister().then(SimpleTest.finish, function(e) {
     dump("unregistration failed: " + e + "\n");
     SimpleTest.finish();
   });
 }
 
 SimpleTest.waitForExplicitFinish();
--- a/dom/tests/mochitest/fetch/worker_wrapper.js
+++ b/dom/tests/mochitest/fetch/worker_wrapper.js
@@ -7,16 +7,18 @@ function ok(a, msg) {
                       msg: a + ": " + msg, context: context});
 }
 
 function is(a, b, msg) {
   client.postMessage({type: 'status', status: a === b,
                       msg: a + " === " + b + ": " + msg, context: context});
 }
 
+var completeInstall;
+
 addEventListener('message', function workerWrapperOnMessage(e) {
   removeEventListener('message', workerWrapperOnMessage);
   var data = e.data;
 
   function loadTest(event) {
     var done = function(res) {
       client.postMessage({ type: 'finish', context: context });
       return res;
@@ -39,27 +41,32 @@ addEventListener('message', function wor
       done();
     }
   }
 
   if ("ServiceWorker" in self) {
     // Fetch requests from a service worker are not intercepted.
     self.isSWPresent = false;
 
-    e.waitUntil(self.clients.matchAll().then(function(clients) {
+    e.waitUntil(self.clients.matchAll({ includeUncontrolled: true }).then(function(clients) {
       for (var i = 0; i < clients.length; ++i) {
         if (clients[i].url.indexOf("message_receiver.html") > -1) {
           client = clients[i];
           break;
         }
       }
       if (!client) {
         dump("We couldn't find the message_receiver window, the test will fail\n");
       }
       context = "ServiceWorker";
       loadTest(e);
+      completeInstall();
     }));
   } else {
     client = self;
     context = "Worker";
     loadTest(e);
   }
 });
+
+addEventListener("install", e => {
+  e.waitUntil(new Promise(resolve => completeInstall = resolve));
+});
--- a/dom/workers/ScriptLoader.cpp
+++ b/dom/workers/ScriptLoader.cpp
@@ -404,17 +404,16 @@ class CacheCreator final : public Promis
 public:
   NS_DECL_ISUPPORTS
 
   explicit CacheCreator(WorkerPrivate* aWorkerPrivate)
     : mCacheName(aWorkerPrivate->ServiceWorkerCacheName())
     , mOriginAttributes(aWorkerPrivate->GetOriginAttributes())
   {
     MOZ_ASSERT(aWorkerPrivate->IsServiceWorker());
-    MOZ_ASSERT(aWorkerPrivate->LoadScriptAsPartOfLoadingServiceWorkerScript());
     AssertIsOnMainThread();
   }
 
   void
   AddLoader(CacheScriptLoader* aLoader)
   {
     AssertIsOnMainThread();
     MOZ_ASSERT(!mCacheStorage);
@@ -832,16 +831,22 @@ private:
   }
 
   bool
   IsMainWorkerScript() const
   {
     return mIsMainScript && mWorkerScriptType == WorkerScript;
   }
 
+  bool
+  IsDebuggerScript() const
+  {
+    return mWorkerScriptType == DebuggerScript;
+  }
+
   void
   CancelMainThreadWithBindingAborted()
   {
     CancelMainThread(NS_BINDING_ABORTED);
   }
 
   void
   CancelMainThread(nsresult aCancelResult)
@@ -903,22 +908,21 @@ private:
     mCacheCreator = nullptr;
   }
 
   nsresult
   RunInternal()
   {
     AssertIsOnMainThread();
 
-    if (IsMainWorkerScript() && mWorkerPrivate->IsServiceWorker()) {
+    if (IsMainWorkerScript()) {
       mWorkerPrivate->SetLoadingWorkerScript(true);
     }
 
-    if (!mWorkerPrivate->IsServiceWorker() ||
-        !mWorkerPrivate->LoadScriptAsPartOfLoadingServiceWorkerScript()) {
+    if (!mWorkerPrivate->IsServiceWorker() || IsDebuggerScript()) {
       for (uint32_t index = 0, len = mLoadInfos.Length(); index < len;
            ++index) {
         nsresult rv = LoadScript(index);
         if (NS_WARN_IF(NS_FAILED(rv))) {
           LoadingFinished(index, rv);
           return rv;
         }
       }
@@ -1784,19 +1788,22 @@ CacheScriptLoader::ResolvedCallback(JSCo
 
   // The ServiceWorkerScriptCache will store data for any scripts it
   // it knows about.  This is always at least the top level script.
   // Depending on if a previous version of the service worker has
   // been installed or not it may also know about importScripts().  We
   // must handle loading and offlining new importScripts() here, however.
   if (aValue.isUndefined()) {
     // If this is the main script or we're not loading a new service worker
-    // then this is an error.  The storage was probably wiped without
-    // removing the service worker registration.
-    if (NS_WARN_IF(mIsWorkerScript || mState != ServiceWorkerState::Parsed)) {
+    // then this is an error.  This can happen for internal reasons, like
+    // storage was probably wiped without removing the service worker
+    // registration.  It can also happen for exposed reasons like the
+    // service worker script calling importScripts() after install.
+    if (NS_WARN_IF(mIsWorkerScript || (mState != ServiceWorkerState::Parsed &&
+                                       mState != ServiceWorkerState::Installing))) {
       Fail(NS_ERROR_DOM_INVALID_STATE_ERR);
       return;
     }
 
     mLoadInfo.mCacheStatus = ScriptLoadInfo::ToBeCached;
     rv = mRunnable->LoadScript(mIndex);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       Fail(rv);
@@ -2174,17 +2181,17 @@ ScriptExecutorRunnable::ShutdownScriptLo
                                              WorkerPrivate* aWorkerPrivate,
                                              bool aResult,
                                              bool aMutedError)
 {
   aWorkerPrivate->AssertIsOnWorkerThread();
 
   MOZ_ASSERT(mLastIndex == mScriptLoader.mLoadInfos.Length() - 1);
 
-  if (mIsWorkerScript && aWorkerPrivate->IsServiceWorker()) {
+  if (mIsWorkerScript) {
     aWorkerPrivate->SetLoadingWorkerScript(false);
   }
 
   if (!aResult) {
     // At this point there are two possibilities:
     //
     // 1) mScriptLoader.mRv.Failed().  In that case we just want to leave it
     //    as-is, except if it has a JS exception and we need to mute JS
--- a/dom/workers/WorkerPrivate.h
+++ b/dom/workers/WorkerPrivate.h
@@ -1038,36 +1038,29 @@ public:
 
   // Determine if the SW testing per-window flag is set by devtools
   bool
   ServiceWorkersTestingInWindow() const
   {
     return mLoadInfo.mServiceWorkersTestingInWindow;
   }
 
-  // This is used to handle importScripts(). When the worker is first loaded
-  // and executed, it happens in a sync loop. At this point it sets
-  // mLoadingWorkerScript to true. importScripts() calls that occur during the
-  // execution run in nested sync loops and so this continues to return true,
-  // leading to these scripts being cached offline.
-  // mLoadingWorkerScript is set to false when the top level loop ends.
-  // importScripts() in function calls or event handlers are always fetched
-  // from the network.
+  // Determine if the worker is currently loading its top level script.
   bool
-  LoadScriptAsPartOfLoadingServiceWorkerScript()
+  IsLoadingWorkerScript() const
   {
-    MOZ_ASSERT(IsServiceWorker());
     return mLoadingWorkerScript;
   }
 
+  // Called by ScriptLoader to track when this worker is loading its
+  // top level script.
   void
   SetLoadingWorkerScript(bool aLoadingWorkerScript)
   {
     // any thread
-    MOZ_ASSERT(IsServiceWorker());
     mLoadingWorkerScript = aLoadingWorkerScript;
   }
 
   void
   QueueRunnable(nsIRunnable* aRunnable)
   {
     AssertIsOnParentThread();
     mQueuedRunnables.AppendElement(aRunnable);
--- a/hal/Hal.cpp
+++ b/hal/Hal.cpp
@@ -582,94 +582,16 @@ LockScreenOrientation(const dom::ScreenO
 
 void
 UnlockScreenOrientation()
 {
   AssertMainThread();
   PROXY_IF_SANDBOXED(UnlockScreenOrientation());
 }
 
-void
-EnableSwitchNotifications(SwitchDevice aDevice) {
-  AssertMainThread();
-  PROXY_IF_SANDBOXED(EnableSwitchNotifications(aDevice));
-}
-
-void
-DisableSwitchNotifications(SwitchDevice aDevice) {
-  AssertMainThread();
-  PROXY_IF_SANDBOXED(DisableSwitchNotifications(aDevice));
-}
-
-typedef mozilla::ObserverList<SwitchEvent> SwitchObserverList;
-
-static SwitchObserverList *sSwitchObserverLists = nullptr;
-
-static SwitchObserverList&
-GetSwitchObserverList(SwitchDevice aDevice) {
-  MOZ_ASSERT(0 <= aDevice && aDevice < NUM_SWITCH_DEVICE);
-  if (sSwitchObserverLists == nullptr) {
-    sSwitchObserverLists = new SwitchObserverList[NUM_SWITCH_DEVICE];
-  }
-  return sSwitchObserverLists[aDevice];
-}
-
-static void
-ReleaseObserversIfNeeded() {
-  for (int i = 0; i < NUM_SWITCH_DEVICE; i++) {
-    if (sSwitchObserverLists[i].Length() != 0)
-      return;
-  }
-
-  //The length of every list is 0, no observer in the list.
-  delete [] sSwitchObserverLists;
-  sSwitchObserverLists = nullptr;
-}
-
-void
-RegisterSwitchObserver(SwitchDevice aDevice, SwitchObserver *aObserver)
-{
-  AssertMainThread();
-  SwitchObserverList& observer = GetSwitchObserverList(aDevice);
-  observer.AddObserver(aObserver);
-  if (observer.Length() == 1) {
-    EnableSwitchNotifications(aDevice);
-  }
-}
-
-void
-UnregisterSwitchObserver(SwitchDevice aDevice, SwitchObserver *aObserver)
-{
-  AssertMainThread();
-
-  if (!sSwitchObserverLists) {
-    return;
-  }
-
-  SwitchObserverList& observer = GetSwitchObserverList(aDevice);
-  if (!observer.RemoveObserver(aObserver) || observer.Length() > 0) {
-    return;
-  }
-
-  DisableSwitchNotifications(aDevice);
-  ReleaseObserversIfNeeded();
-}
-
-void
-NotifySwitchChange(const SwitchEvent& aEvent)
-{
-  // When callback this notification, main thread may call unregister function
-  // first. We should check if this pointer is valid.
-  if (!sSwitchObserverLists)
-    return;
-
-  SwitchObserverList& observer = GetSwitchObserverList(aEvent.device());
-  observer.Broadcast(aEvent);
-}
-
 bool
 SetProcessPrioritySupported()
 {
   RETURN_PROXY_IF_SANDBOXED(SetProcessPrioritySupported(), false);
 }
 
 void
 SetProcessPriority(int aPid, ProcessPriority aPriority)
--- a/hal/Hal.h
+++ b/hal/Hal.h
@@ -257,36 +257,16 @@ void NotifyScreenConfigurationChange(con
 MOZ_MUST_USE bool LockScreenOrientation(const dom::ScreenOrientationInternal& aOrientation);
 
 /**
  * Unlock the screen orientation.
  */
 void UnlockScreenOrientation();
 
 /**
- * Register an observer for the switch of given SwitchDevice.
- *
- * The observer will receive data whenever the data generated by the
- * given switch.
- */
-void RegisterSwitchObserver(hal::SwitchDevice aDevice, hal::SwitchObserver *aSwitchObserver);
-
-/**
- * Unregister an observer for the switch of given SwitchDevice.
- */
-void UnregisterSwitchObserver(hal::SwitchDevice aDevice, hal::SwitchObserver *aSwitchObserver);
-
-/**
- * Notify the state of the switch.
- *
- * This API is internal to hal; clients shouldn't call it directly.
- */
-void NotifySwitchChange(const hal::SwitchEvent& aEvent);
-
-/**
  * Return true if the current platform supports the setting of process
  * priority.
  */
 bool SetProcessPrioritySupported();
 
 /**
  * Set the priority of the given process.
  *
--- a/hal/HalInternal.h
+++ b/hal/HalInternal.h
@@ -50,26 +50,16 @@ void DisableNetworkNotifications();
 void EnableScreenConfigurationNotifications();
 
 /**
  * Disables screen orientation notifications from the backend.
  */
 void DisableScreenConfigurationNotifications();
 
 /**
- * Enable switch notifications from the backend
- */
-void EnableSwitchNotifications(hal::SwitchDevice aDevice);
-
-/**
- * Disable switch notifications from the backend
- */
-void DisableSwitchNotifications(hal::SwitchDevice aDevice);
-
-/**
  * Has the child-side HAL IPC object been destroyed?  If so, you shouldn't send
  * messages to hal_sandbox.
  */
 bool HalChildDestroyed();
 } // namespace MOZ_HAL_NAMESPACE
 } // namespace mozilla
 
 #endif  // mozilla_HalInternal_h
--- a/hal/HalTypes.h
+++ b/hal/HalTypes.h
@@ -15,36 +15,16 @@ namespace hal {
 /**
  * These constants specify special values for content process IDs.  You can get
  * a content process ID by calling ContentChild::GetID() or
  * ContentParent::GetChildID().
  */
 const uint64_t CONTENT_PROCESS_ID_UNKNOWN = uint64_t(-1);
 const uint64_t CONTENT_PROCESS_ID_MAIN = 0;
 
-class SwitchEvent;
-
-enum SwitchDevice {
-  SWITCH_DEVICE_UNKNOWN = -1,
-  SWITCH_HEADPHONES,
-  SWITCH_USB,
-  NUM_SWITCH_DEVICE
-};
-
-enum SwitchState {
-  SWITCH_STATE_UNKNOWN = -1,
-  SWITCH_STATE_ON,
-  SWITCH_STATE_OFF,
-  SWITCH_STATE_HEADSET,          // Headphone with microphone
-  SWITCH_STATE_HEADPHONE,        // without microphone
-  NUM_SWITCH_STATE
-};
-
-typedef Observer<SwitchEvent> SwitchObserver;
-
 // Note that we rely on the order of this enum's entries.  Higher priorities
 // should have larger int values.
 enum ProcessPriority {
   PROCESS_PRIORITY_UNKNOWN = -1,
   PROCESS_PRIORITY_BACKGROUND,
   PROCESS_PRIORITY_BACKGROUND_PERCEIVABLE,
   PROCESS_PRIORITY_FOREGROUND_KEYBOARD,
   // The special class for the preallocated process, high memory priority but
@@ -90,38 +70,16 @@ namespace IPC {
 template <>
 struct ParamTraits<mozilla::hal::WakeLockControl>
   : public ContiguousEnumSerializer<
              mozilla::hal::WakeLockControl,
              mozilla::hal::WAKE_LOCK_REMOVE_ONE,
              mozilla::hal::NUM_WAKE_LOCK>
 {};
 
-/**
- * Serializer for SwitchState
- */
-template <>
-struct ParamTraits<mozilla::hal::SwitchState>:
-  public ContiguousEnumSerializer<
-           mozilla::hal::SwitchState,
-           mozilla::hal::SWITCH_STATE_UNKNOWN,
-           mozilla::hal::NUM_SWITCH_STATE> {
-};
-
-/**
- * Serializer for SwitchDevice
- */
-template <>
-struct ParamTraits<mozilla::hal::SwitchDevice>:
-  public ContiguousEnumSerializer<
-           mozilla::hal::SwitchDevice,
-           mozilla::hal::SWITCH_DEVICE_UNKNOWN,
-           mozilla::hal::NUM_SWITCH_DEVICE> {
-};
-
 template <>
 struct ParamTraits<mozilla::hal::ProcessPriority>:
   public ContiguousEnumSerializer<
            mozilla::hal::ProcessPriority,
            mozilla::hal::PROCESS_PRIORITY_UNKNOWN,
            mozilla::hal::NUM_PROCESS_PRIORITY> {
 };
 
deleted file mode 100644
--- a/hal/fallback/FallbackSwitch.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* 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/Hal.h"
-
-using namespace mozilla::hal;
-
-namespace mozilla {
-namespace hal_impl {
-
-void
-EnableSwitchNotifications(SwitchDevice aDevice)
-{
-}
-
-void
-DisableSwitchNotifications(SwitchDevice aDevice)
-{
-}
-
-} // namespace hal_impl
-} // namespace mozilla
--- a/hal/moz.build
+++ b/hal/moz.build
@@ -94,17 +94,16 @@ else:
         'fallback/FallbackSensor.cpp',
         'fallback/FallbackVibration.cpp',
     ]
 
 # Fallbacks for backends no longer implemented.
 UNIFIED_SOURCES += [
     'fallback/FallbackDiskSpaceWatcher.cpp',
     'fallback/FallbackProcessPriority.cpp',
-    'fallback/FallbackSwitch.cpp',
 ]
 
 # Fallbacks for backends implemented on Android only.
 if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'android':
     UNIFIED_SOURCES += [
         'fallback/FallbackNetwork.cpp',
     ]
 
--- a/hal/sandbox/PHal.ipdl
+++ b/hal/sandbox/PHal.ipdl
@@ -8,18 +8,16 @@ include protocol PContent;
 include protocol PBrowser;
 
 include "mozilla/GfxMessageUtils.h";
 
 using mozilla::dom::ScreenOrientationInternal from "mozilla/dom/ScreenOrientation.h";
 using mozilla::hal::SensorType from "mozilla/HalSensor.h";
 using mozilla::hal::SensorAccuracyType from "mozilla/HalSensor.h";
 using mozilla::hal::WakeLockControl from "mozilla/HalTypes.h";
-using mozilla::hal::SwitchState from "mozilla/HalTypes.h";
-using mozilla::hal::SwitchDevice from "mozilla/HalTypes.h";
 using mozilla::hal::ProcessPriority from "mozilla/HalTypes.h";
 using nsIntRect from "nsRect.h";
 using PRTime from "prtime.h";
 
 namespace mozilla {
 
 namespace hal {
 struct BatteryInformation {
@@ -36,21 +34,16 @@ struct SensorData {
 };
 
 struct NetworkInformation {
   uint32_t type;
   bool   isWifi;
   uint32_t dhcpGateway;
 };
 
-struct SwitchEvent {
-  SwitchDevice device;
-  SwitchState status;
-};
-
 struct WakeLockInformation {
   nsString topic;
   uint32_t numLocks;
   uint32_t numHidden;
   uint64_t[] lockingProcesses;
 };
 
 struct ScreenConfiguration {
@@ -68,17 +61,16 @@ namespace hal_sandbox {
 nested(upto inside_cpow) sync protocol PHal {
     manager PContent;
 
 child:
     async NotifyBatteryChange(BatteryInformation aBatteryInfo);
     async NotifyNetworkChange(NetworkInformation aNetworkInfo);
     async NotifyWakeLockChange(WakeLockInformation aWakeLockInfo);
     async NotifyScreenConfigurationChange(ScreenConfiguration aScreenOrientation);
-    async NotifySwitchChange(SwitchEvent aEvent);
 
 parent:
     async Vibrate(uint32_t[] pattern, uint64_t[] id, PBrowser browser);
     async CancelVibrate(uint64_t[] id, PBrowser browser);
 
     async EnableBatteryNotifications();
     async DisableBatteryNotifications();
     sync GetCurrentBatteryInformation()
@@ -98,19 +90,16 @@ parent:
     sync GetWakeLockInfo(nsString aTopic)
       returns (WakeLockInformation aWakeLockInfo);
 
     async EnableScreenConfigurationNotifications();
     async DisableScreenConfigurationNotifications();
     sync LockScreenOrientation(ScreenOrientationInternal aOrientation)
       returns (bool allowed);
     async UnlockScreenOrientation();
- 
-    async EnableSwitchNotifications(SwitchDevice aDevice);
-    async DisableSwitchNotifications(SwitchDevice aDevice);
 
 child:
     async NotifySensorChange(SensorData aSensorData);
 
 parent:
     async EnableSensorNotifications(SensorType aSensor);
     async DisableSensorNotifications(SensorType aSensor);
 
--- a/hal/sandbox/SandboxHal.cpp
+++ b/hal/sandbox/SandboxHal.cpp
@@ -169,28 +169,16 @@ ModifyWakeLock(const nsAString &aTopic,
 }
 
 void
 GetWakeLockInfo(const nsAString &aTopic, WakeLockInformation *aWakeLockInfo)
 {
   Hal()->SendGetWakeLockInfo(nsString(aTopic), aWakeLockInfo);
 }
 
-void
-EnableSwitchNotifications(SwitchDevice aDevice)
-{
-  Hal()->SendEnableSwitchNotifications(aDevice);
-}
-
-void
-DisableSwitchNotifications(SwitchDevice aDevice)
-{
-  Hal()->SendDisableSwitchNotifications(aDevice);
-}
-
 bool
 EnableAlarm()
 {
   MOZ_CRASH("Alarms can't be programmed from sandboxed contexts.  Yet.");
 }
 
 void
 DisableAlarm()
@@ -229,36 +217,31 @@ StopDiskSpaceWatcher()
 }
 
 class HalParent : public PHalParent
                 , public BatteryObserver
                 , public NetworkObserver
                 , public ISensorObserver
                 , public WakeLockObserver
                 , public ScreenConfigurationObserver
-                , public SwitchObserver
 {
 public:
   virtual void
   ActorDestroy(ActorDestroyReason aWhy) override
   {
     // NB: you *must* unconditionally unregister your observer here,
     // if it *may* be registered below.
     hal::UnregisterBatteryObserver(this);
     hal::UnregisterNetworkObserver(this);
     hal::UnregisterScreenConfigurationObserver(this);
     for (int32_t sensor = SENSOR_UNKNOWN + 1;
          sensor < NUM_SENSOR_TYPE; ++sensor) {
       hal::UnregisterSensorObserver(SensorType(sensor), this);
     }
     hal::UnregisterWakeLockObserver(this);
-    for (int32_t switchDevice = SWITCH_DEVICE_UNKNOWN + 1;
-         switchDevice < NUM_SWITCH_DEVICE; ++switchDevice) {
-      hal::UnregisterSwitchObserver(SwitchDevice(switchDevice), this);
-    }
   }
 
   virtual mozilla::ipc::IPCResult
   RecvVibrate(InfallibleTArray<unsigned int>&& pattern,
               InfallibleTArray<uint64_t>&& id,
               PBrowserParent *browserParent) override
   {
     // We give all content vibration permission.
@@ -421,36 +404,16 @@ public:
     hal::GetWakeLockInfo(aTopic, aWakeLockInfo);
     return IPC_OK();
   }
 
   void Notify(const WakeLockInformation& aWakeLockInfo) override
   {
     Unused << SendNotifyWakeLockChange(aWakeLockInfo);
   }
-
-  virtual mozilla::ipc::IPCResult
-  RecvEnableSwitchNotifications(const SwitchDevice& aDevice) override
-  {
-    // Content has no reason to listen to switch events currently.
-    hal::RegisterSwitchObserver(aDevice, this);
-    return IPC_OK();
-  }
-
-  virtual mozilla::ipc::IPCResult
-  RecvDisableSwitchNotifications(const SwitchDevice& aDevice) override
-  {
-    hal::UnregisterSwitchObserver(aDevice, this);
-    return IPC_OK();
-  }
-
-  void Notify(const SwitchEvent& aSwitchEvent) override
-  {
-    Unused << SendNotifySwitchChange(aSwitchEvent);
-  }
 };
 
 class HalChild : public PHalChild {
 public:
   virtual void
   ActorDestroy(ActorDestroyReason aWhy) override
   {
     sHalChildDestroyed = true;
@@ -477,22 +440,16 @@ public:
     return IPC_OK();
   }
 
   virtual mozilla::ipc::IPCResult
   RecvNotifyScreenConfigurationChange(const ScreenConfiguration& aScreenConfiguration) override {
     hal::NotifyScreenConfigurationChange(aScreenConfiguration);
     return IPC_OK();
   }
-
-  virtual mozilla::ipc::IPCResult
-  RecvNotifySwitchChange(const mozilla::hal::SwitchEvent& aEvent) override {
-    hal::NotifySwitchChange(aEvent);
-    return IPC_OK();
-  }
 };
 
 mozilla::ipc::IPCResult
 HalChild::RecvNotifySensorChange(const hal::SensorData &aSensorData) {
   hal::NotifySensorChange(aSensorData);
 
   return IPC_OK();
 }
--- a/image/SourceBuffer.cpp
+++ b/image/SourceBuffer.cpp
@@ -512,22 +512,26 @@ SourceBuffer::AppendFromInputStream(nsII
   }
 
   if (bytesRead == 0) {
     // The loading of the image has been canceled.
     return NS_ERROR_FAILURE;
   }
 
   if (bytesRead != aCount) {
-    // Only some of the given data was read. We must have failed in
-    // SourceBuffer::Append but ReadSegments swallowed the error.
+    // Only some of the given data was read. We may have failed in
+    // SourceBuffer::Append but ReadSegments swallowed the error. Otherwise the
+    // stream itself failed to yield the data.
     MutexAutoLock lock(mMutex);
-    MOZ_ASSERT(mStatus);
-    MOZ_ASSERT(NS_FAILED(*mStatus));
-    return *mStatus;
+    if (mStatus) {
+      MOZ_ASSERT(NS_FAILED(*mStatus));
+      return *mStatus;
+    }
+
+    MOZ_ASSERT_UNREACHABLE("AppendToSourceBuffer should consume everything");
   }
 
   return rv;
 }
 
 void
 SourceBuffer::Complete(nsresult aStatus)
 {
--- a/js/public/Utility.h
+++ b/js/public/Utility.h
@@ -413,18 +413,16 @@ static inline void* js_realloc(void* p, 
 
 static inline void js_free(void* p)
 {
     // TODO: This should call |moz_arena_free(js::MallocArena, p)| but we
     // currently can't enforce that all memory freed here was allocated by
     // js_malloc().
     free(p);
 }
-
-JS_PUBLIC_API(char*) js_strdup(const char* s);
 #endif/* JS_USE_CUSTOM_ALLOCATOR */
 
 #include <new>
 
 /*
  * Low-level memory management in SpiderMonkey:
  *
  *  ** Do not use the standard malloc/free/realloc: SpiderMonkey allows these
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -2382,18 +2382,18 @@ ReadGeckoProfilingStack(JSContext* cx, u
     // stack.
     if (!cx->isProfilerSamplingEnabled()) {
       args.rval().setObject(*stack);
       return true;
     }
 
     struct InlineFrameInfo
     {
-        InlineFrameInfo(const char* kind, char* label)
-          : kind(kind), label(label) {}
+        InlineFrameInfo(const char* kind, UniqueChars label)
+          : kind(kind), label(std::move(label)) {}
         const char* kind;
         UniqueChars label;
     };
 
     Vector<Vector<InlineFrameInfo, 0, TempAllocPolicy>, 0, TempAllocPolicy> frameInfo(cx);
 
     JS::ProfilingFrameIterator::RegisterState state;
     for (JS::ProfilingFrameIterator i(cx, state); !i.done(); ++i) {
@@ -2417,21 +2417,21 @@ ReadGeckoProfilingStack(JSContext* cx, u
                 break;
               case JS::ProfilingFrameIterator::Frame_Wasm:
                 frameKindStr = "wasm";
                 break;
               default:
                 frameKindStr = "unknown";
             }
 
-            char* label = JS_strdup(cx, frames[i].label);
+            UniqueChars label = DuplicateString(cx, frames[i].label);
             if (!label)
                 return false;
 
-            if (!frameInfo.back().emplaceBack(frameKindStr, label))
+            if (!frameInfo.back().emplaceBack(frameKindStr, std::move(label)))
                 return false;
         }
     }
 
     RootedObject inlineFrameInfo(cx);
     RootedString frameKind(cx);
     RootedString frameLabel(cx);
     RootedId idx(cx);
@@ -4375,17 +4375,17 @@ GetLcovInfo(JSContext* cx, unsigned argc
         AutoRealm ar(cx, global);
         content = js::GetCodeCoverageSummary(cx, &length);
     }
 
     if (!content)
         return false;
 
     JSString* str = JS_NewStringCopyN(cx, content, length);
-    free(content);
+    js_free(content);
 
     if (!str)
         return false;
 
     args.rval().setString(str);
     return true;
 }
 
--- a/js/src/gc/GC.cpp
+++ b/js/src/gc/GC.cpp
@@ -4661,16 +4661,19 @@ js::gc::MarkingValidator::nonIncremental
     if (!map.init())
         return;
 
     JSRuntime* runtime = gc->rt;
     GCMarker* gcmarker = &gc->marker;
 
     gc->waitBackgroundSweepEnd();
 
+    /* Wait for off-thread parsing which can allocate. */
+    HelperThreadState().waitForAllThreads();
+
     /* Save existing mark bits. */
     {
         AutoLockGC lock(runtime);
         for (auto chunk = gc->allNonEmptyChunks(lock); !chunk.done(); chunk.next()) {
             ChunkBitmap* bitmap = &chunk->bitmap;
             ChunkBitmap* entry = js_new<ChunkBitmap>();
             if (!entry)
                 return;
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/gc/bug-1459860.js
@@ -0,0 +1,10 @@
+// |jit-test| allow-overrecursed
+if (helperThreadCount() === 0)
+    quit();
+function eval(source) {
+    offThreadCompileModule(source);
+    let get = (eval("function w(){}") ++);
+};
+gczeal(21, 10);
+gczeal(11, 8);
+eval("");
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -1377,23 +1377,16 @@ JS_freeop(JSFreeOp* fop, void* p)
 }
 
 JS_PUBLIC_API(void)
 JS_updateMallocCounter(JSContext* cx, size_t nbytes)
 {
     return cx->updateMallocCounter(nbytes);
 }
 
-JS_PUBLIC_API(char*)
-JS_strdup(JSContext* cx, const char* s)
-{
-    AssertHeapIsIdle();
-    return DuplicateString(cx, s).release();
-}
-
 #undef JS_AddRoot
 
 JS_PUBLIC_API(bool)
 JS_AddExtraGCRootsTracer(JSContext* cx, JSTraceDataOp traceOp, void* data)
 {
     return cx->runtime()->gc.addBlackRootsTracer(traceOp, data);
 }
 
@@ -3988,17 +3981,17 @@ JS::OwningCompileOptions::copy(JSContext
            setIntroducerFilename(cx, rhs.introducerFilename());
 }
 
 bool
 JS::OwningCompileOptions::setFile(JSContext* cx, const char* f)
 {
     char* copy = nullptr;
     if (f) {
-        copy = JS_strdup(cx, f);
+        copy = DuplicateString(cx, f).release();
         if (!copy)
             return false;
     }
 
     // OwningCompileOptions always owns filename_, so this cast is okay.
     js_free(const_cast<char*>(filename_));
 
     filename_ = copy;
@@ -4032,17 +4025,17 @@ JS::OwningCompileOptions::setSourceMapUR
     return true;
 }
 
 bool
 JS::OwningCompileOptions::setIntroducerFilename(JSContext* cx, const char* s)
 {
     char* copy = nullptr;
     if (s) {
-        copy = JS_strdup(cx, s);
+        copy = DuplicateString(cx, s).release();
         if (!copy)
             return false;
     }
 
     // OwningCompileOptions always owns introducerFilename_, so this cast is okay.
     js_free(const_cast<char*>(introducerFilename_));
 
     introducerFilename_ = copy;
@@ -6846,17 +6839,17 @@ JS_SetDefaultLocale(JSRuntime* rt, const
     return rt->setDefaultLocale(locale);
 }
 
 JS_PUBLIC_API(UniqueChars)
 JS_GetDefaultLocale(JSContext* cx)
 {
     AssertHeapIsIdle();
     if (const char* locale = cx->runtime()->getDefaultLocale())
-        return UniqueChars(JS_strdup(cx, locale));
+        return DuplicateString(cx, locale);
 
     return nullptr;
 }
 
 JS_PUBLIC_API(void)
 JS_ResetDefaultLocale(JSRuntime* rt)
 {
     AssertHeapIsIdle();
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -1352,19 +1352,16 @@ JS_free(JSContext* cx, void* p);
  * performance optimization as specified by the given JSFreeOp instance.
  */
 extern JS_PUBLIC_API(void)
 JS_freeop(JSFreeOp* fop, void* p);
 
 extern JS_PUBLIC_API(void)
 JS_updateMallocCounter(JSContext* cx, size_t nbytes);
 
-extern JS_PUBLIC_API(char*)
-JS_strdup(JSContext* cx, const char* s);
-
 /**
  * Set the size of the native stack that should not be exceed. To disable
  * stack size checking pass 0.
  *
  * SpiderMonkey allows for a distinction between system code (such as GCs, which
  * may incidentally be triggered by script but are not strictly performed on
  * behalf of such script), trusted script (as determined by JS_SetTrustedPrincipals),
  * and untrusted script. Each kind of code may have a different stack quota,
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -12,16 +12,17 @@
 #include "mozilla/DebugOnly.h"
 #include "mozilla/GuardObjects.h"
 #include "mozilla/IntegerPrintfMacros.h"
 #include "mozilla/mozalloc.h"
 #include "mozilla/PodOperations.h"
 #include "mozilla/ScopeExit.h"
 #include "mozilla/Sprintf.h"
 #include "mozilla/TimeStamp.h"
+#include "mozilla/Unused.h"
 
 #include <chrono>
 #ifdef JS_POSIX_NSPR
 # include <dlfcn.h>
 #endif
 #ifdef XP_WIN
 # include <direct.h>
 # include <process.h>
@@ -38,16 +39,17 @@
 #include <math.h>
 #include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <thread>
+#include <utility>
 #ifdef XP_UNIX
 # include <sys/mman.h>
 # include <sys/stat.h>
 # include <sys/wait.h>
 # include <unistd.h>
 #endif
 
 #include "jsapi.h"
@@ -4965,81 +4967,82 @@ class AutoCStringVector
 {
     Vector<char*> argv_;
   public:
     explicit AutoCStringVector(JSContext* cx) : argv_(cx) {}
     ~AutoCStringVector() {
         for (size_t i = 0; i < argv_.length(); i++)
             js_free(argv_[i]);
     }
-    bool append(char* arg) {
-        if (!argv_.append(arg)) {
-            js_free(arg);
-            return false;
-        }
+    bool append(UniqueChars&& arg) {
+        if (!argv_.append(arg.get()))
+            return false;
+
+        // Now owned by this vector.
+        mozilla::Unused << arg.release();
         return true;
     }
     char* const* get() const {
         return argv_.begin();
     }
     size_t length() const {
         return argv_.length();
     }
     char* operator[](size_t i) const {
         return argv_[i];
     }
-    void replace(size_t i, char* arg) {
+    void replace(size_t i, UniqueChars arg) {
         js_free(argv_[i]);
-        argv_[i] = arg;
-    }
-    char* back() const {
+        argv_[i] = arg.release();
+    }
+    const char* back() const {
         return argv_.back();
     }
-    void replaceBack(char* arg) {
+    void replaceBack(UniqueChars arg) {
         js_free(argv_.back());
-        argv_.back() = arg;
+        argv_.back() = arg.release();
     }
 };
 
 #if defined(XP_WIN)
 static bool
-EscapeForShell(AutoCStringVector& argv)
+EscapeForShell(JSContext* cx, AutoCStringVector& argv)
 {
     // Windows will break arguments in argv by various spaces, so we wrap each
     // argument in quotes and escape quotes within. Even with quotes, \ will be
     // treated like an escape character, so inflate each \ to \\.
 
     for (size_t i = 0; i < argv.length(); i++) {
         if (!argv[i])
             continue;
 
         size_t newLen = 3;  // quotes before and after and null-terminator
         for (char* p = argv[i]; *p; p++) {
             newLen++;
             if (*p == '\"' || *p == '\\')
                 newLen++;
         }
 
-        char* escaped = (char*)js_malloc(newLen);
+        UniqueChars escaped(cx->pod_malloc<char>(newLen));
         if (!escaped)
             return false;
 
         char* src = argv[i];
-        char* dst = escaped;
+        char* dst = escaped.get();
         *dst++ = '\"';
         while (*src) {
             if (*src == '\"' || *src == '\\')
                 *dst++ = '\\';
             *dst++ = *src++;
         }
         *dst++ = '\"';
         *dst++ = '\0';
-        MOZ_ASSERT(escaped + newLen == dst);
-
-        argv.replace(i, escaped);
+        MOZ_ASSERT(escaped.get() + newLen == dst);
+
+        argv.replace(i, std::move(escaped));
     }
     return true;
 }
 #endif
 
 static Vector<const char*, 4, js::SystemAllocPolicy> sPropagatedFlags;
 
 #if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
@@ -5058,50 +5061,57 @@ NestedShell(JSContext* cx, unsigned argc
     AutoCStringVector argv(cx);
 
     // The first argument to the shell is its path, which we assume is our own
     // argv[0].
     if (sArgc < 1) {
         JS_ReportErrorNumberASCII(cx, my_GetErrorMessage, nullptr, JSSMSG_NESTED_FAIL);
         return false;
     }
-    if (!argv.append(js_strdup(sArgv[0])))
+    UniqueChars shellPath = DuplicateString(cx, sArgv[0]);
+    if (!shellPath || !argv.append(std::move(shellPath)))
         return false;
 
     // Propagate selected flags from the current shell
     for (unsigned i = 0; i < sPropagatedFlags.length(); i++) {
-        char* cstr = js_strdup(sPropagatedFlags[i]);
-        if (!cstr || !argv.append(cstr))
+        UniqueChars flags = DuplicateString(cx, sPropagatedFlags[i]);
+        if (!flags || !argv.append(std::move(flags)))
             return false;
     }
 
     // The arguments to nestedShell are stringified and append to argv.
     RootedString str(cx);
     for (unsigned i = 0; i < args.length(); i++) {
         str = ToString(cx, args[i]);
-        if (!str || !argv.append(JS_EncodeString(cx, str)))
+        if (!str)
+            return false;
+
+        UniqueChars arg(JS_EncodeString(cx, str));
+        if (!arg || !argv.append(std::move(arg)))
             return false;
 
         // As a special case, if the caller passes "--js-cache", replace that
         // with "--js-cache=$(jsCacheDir)"
         if (!strcmp(argv.back(), "--js-cache") && jsCacheDir) {
             UniqueChars newArg = JS_smprintf("--js-cache=%s", jsCacheDir);
-            if (!newArg)
+            if (!newArg) {
+                JS_ReportOutOfMemory(cx);
                 return false;
-            argv.replaceBack(newArg.release());
+            }
+            argv.replaceBack(std::move(newArg));
         }
     }
 
     // execv assumes argv is null-terminated
     if (!argv.append(nullptr))
         return false;
 
     int status = 0;
 #if defined(XP_WIN)
-    if (!EscapeForShell(argv))
+    if (!EscapeForShell(cx, argv))
         return false;
     status = _spawnv(_P_WAIT, sArgv[0], argv.get());
 #else
     pid_t pid = fork();
     switch (pid) {
       case -1:
         JS_ReportErrorNumberASCII(cx, my_GetErrorMessage, nullptr, JSSMSG_NESTED_FAIL);
         return false;
@@ -8771,24 +8781,25 @@ SetContextOptions(JSContext* cx, const O
 
     reportWarnings = op.getBoolOption('w');
     compileOnly = op.getBoolOption('c');
     printTiming = op.getBoolOption('b');
     enableCodeCoverage = op.getBoolOption("code-coverage");
     enableDisassemblyDumps = op.getBoolOption('D');
     cx->runtime()->profilingScripts = enableCodeCoverage || enableDisassemblyDumps;
 
-    jsCacheDir = op.getStringOption("js-cache");
-    if (jsCacheDir) {
+    if (const char* jsCacheOpt = op.getStringOption("js-cache")) {
+        UniqueChars jsCacheChars;
         if (!op.getBoolOption("no-js-cache-per-process"))
-            jsCacheDir = JS_smprintf("%s/%u", jsCacheDir, (unsigned)getpid()).release();
+            jsCacheChars = JS_smprintf("%s/%u", jsCacheOpt, (unsigned)getpid());
         else
-            jsCacheDir = JS_strdup(cx, jsCacheDir);
-        if (!jsCacheDir)
-            return false;
+            jsCacheChars = DuplicateString(jsCacheOpt);
+        if (!jsCacheChars)
+            return false;
+        jsCacheDir = jsCacheChars.release();
         jsCacheAsmJSPath = JS_smprintf("%s/asmjs.cache", jsCacheDir).release();
     }
 
 #ifdef DEBUG
     dumpEntrainedVariables = op.getBoolOption("dump-entrained-variables");
 #endif
 
 #ifdef JS_GC_ZEAL
@@ -8910,30 +8921,36 @@ Shell(JSContext* cx, OptionParser* op, c
      * This printing depends on atoms still existing.
      */
     for (CompartmentsIter c(cx->runtime()); !c.done(); c.next())
         PrintTypes(cx, c, false);
 
     return result;
 }
 
+// Used to allocate memory when jemalloc isn't yet initialized.
+JS_DECLARE_NEW_METHODS(SystemAlloc_New, malloc, static)
+
 static void
 SetOutputFile(const char* const envVar,
               RCFile* defaultOut,
               RCFile** outFileP)
 {
     RCFile* outFile;
 
     const char* outPath = getenv(envVar);
     FILE* newfp;
     if (outPath && *outPath && (newfp = fopen(outPath, "w")))
-        outFile = js_new<RCFile>(newfp);
+        outFile = SystemAlloc_New<RCFile>(newfp);
     else
         outFile = defaultOut;
 
+    if (!outFile)
+        MOZ_CRASH("Failed to allocate output file");
+
     outFile->acquire();
     *outFileP = outFile;
 }
 
 static void
 PreInit()
 {
 #ifdef XP_WIN
--- a/js/src/util/Text.cpp
+++ b/js/src/util/Text.cpp
@@ -31,22 +31,16 @@ js_strchr_limit(const CharT* s, char16_t
 }
 
 template const Latin1Char*
 js_strchr_limit(const Latin1Char* s, char16_t c, const Latin1Char* limit);
 
 template const char16_t*
 js_strchr_limit(const char16_t* s, char16_t c, const char16_t* limit);
 
-JS_PUBLIC_API(char*)
-js_strdup(const char* s)
-{
-    return DuplicateString(s).release();
-}
-
 int32_t
 js_fputs(const char16_t* s, FILE* f)
 {
     while (*s != 0) {
         if (fputwc(wchar_t(*s), f) == WEOF)
             return WEOF;
         s++;
     }
--- a/js/src/vm/BytecodeUtil.cpp
+++ b/js/src/vm/BytecodeUtil.cpp
@@ -31,16 +31,17 @@
 #include "builtin/String.h"
 #include "frontend/BytecodeCompiler.h"
 #include "frontend/SourceNotes.h"
 #include "gc/FreeOp.h"
 #include "gc/GCInternals.h"
 #include "js/CharacterEncoding.h"
 #include "js/Printf.h"
 #include "util/StringBuffer.h"
+#include "util/Text.h"
 #include "vm/CodeCoverage.h"
 #include "vm/EnvironmentObject.h"
 #include "vm/JSAtom.h"
 #include "vm/JSCompartment.h"
 #include "vm/JSContext.h"
 #include "vm/JSFunction.h"
 #include "vm/JSObject.h"
 #include "vm/JSScript.h"
@@ -2314,20 +2315,20 @@ js::DecompileValueGenerator(JSContext* c
         if (result) {
             if (strcmp(result, "(intermediate value)"))
                 return UniqueChars(result);
             js_free(result);
         }
     }
     if (!fallback) {
         if (v.isUndefined())
-            return UniqueChars(JS_strdup(cx, js_undefined_str)); // Prevent users from seeing "(void 0)"
+            return DuplicateString(cx, js_undefined_str); // Prevent users from seeing "(void 0)"
         fallback = ValueToSource(cx, v);
         if (!fallback)
-            return UniqueChars(nullptr);
+            return nullptr;
     }
 
     return UniqueChars(JS_EncodeString(cx, fallback));
 }
 
 static bool
 DecompileArgumentFromStack(JSContext* cx, int formalIndex, char** res)
 {
@@ -2392,37 +2393,37 @@ DecompileArgumentFromStack(JSContext* cx
     if (!ed.init())
         return false;
     if (!ed.decompilePCForStackOperand(current, formalStackIndex))
         return false;
 
     return ed.getOutput(res);
 }
 
-char*
+UniqueChars
 js::DecompileArgument(JSContext* cx, int formalIndex, HandleValue v)
 {
     {
         char* result;
         if (!DecompileArgumentFromStack(cx, formalIndex, &result))
             return nullptr;
         if (result) {
             if (strcmp(result, "(intermediate value)"))
-                return result;
+                return UniqueChars(result);
             js_free(result);
         }
     }
     if (v.isUndefined())
-        return JS_strdup(cx, js_undefined_str); // Prevent users from seeing "(void 0)"
+        return DuplicateString(cx, js_undefined_str); // Prevent users from seeing "(void 0)"
 
     RootedString fallback(cx, ValueToSource(cx, v));
     if (!fallback)
         return nullptr;
 
-    return JS_EncodeString(cx, fallback);
+    return UniqueChars(JS_EncodeString(cx, fallback));
 }
 
 bool
 js::CallResultEscapes(jsbytecode* pc)
 {
     /*
      * If we see any of these sequences, the result is unused:
      * - call / pop
--- a/js/src/vm/BytecodeUtil.h
+++ b/js/src/vm/BytecodeUtil.h
@@ -604,17 +604,17 @@ GetVariableBytecodeLength(jsbytecode* pc
 UniqueChars
 DecompileValueGenerator(JSContext* cx, int spindex, HandleValue v,
                         HandleString fallback, int skipStackHits = 0);
 
 /*
  * Decompile the formal argument at formalIndex in the nearest non-builtin
  * stack frame, falling back with converting v to source.
  */
-char*
+UniqueChars
 DecompileArgument(JSContext* cx, int formalIndex, HandleValue v);
 
 extern bool
 CallResultEscapes(jsbytecode* pc);
 
 static inline unsigned
 GetDecomposeLength(jsbytecode* pc, size_t len)
 {
--- a/js/src/vm/CodeCoverage.cpp
+++ b/js/src/vm/CodeCoverage.cpp
@@ -58,63 +58,57 @@
 //     LH:<sum of lines hits>
 //   }
 //
 // [1] http://ltp.sourceforge.net/coverage/lcov/geninfo.1.php
 //
 namespace js {
 namespace coverage {
 
-LCovSource::LCovSource(LifoAlloc* alloc, const char* name)
-  : name_(name),
+LCovSource::LCovSource(LifoAlloc* alloc, UniqueChars name)
+  : name_(std::move(name)),
     outFN_(alloc),
     outFNDA_(alloc),
     numFunctionsFound_(0),
     numFunctionsHit_(0),
     outBRDA_(alloc),
     numBranchesFound_(0),
     numBranchesHit_(0),
     numLinesInstrumented_(0),
     numLinesHit_(0),
     maxLineHit_(0),
     hasTopLevelScript_(false)
 {
 }
 
 LCovSource::LCovSource(LCovSource&& src)
-  : name_(src.name_),
+  : name_(std::move(src.name_)),
     outFN_(src.outFN_),
     outFNDA_(src.outFNDA_),
     numFunctionsFound_(src.numFunctionsFound_),
     numFunctionsHit_(src.numFunctionsHit_),
     outBRDA_(src.outBRDA_),
     numBranchesFound_(src.numBranchesFound_),
     numBranchesHit_(src.numBranchesHit_),
     linesHit_(std::move(src.linesHit_)),
     numLinesInstrumented_(src.numLinesInstrumented_),
     numLinesHit_(src.numLinesHit_),
     maxLineHit_(src.maxLineHit_),
     hasTopLevelScript_(src.hasTopLevelScript_)
 {
-    src.name_ = nullptr;
-}
-
-LCovSource::~LCovSource()
-{
-    js_delete(name_);
 }
 
 void
 LCovSource::exportInto(GenericPrinter& out) const
 {
     // Only write if everything got recorded.
     if (!hasTopLevelScript_)
         return;
 
-    out.printf("SF:%s\n", name_);
+    out.printf("SF:%s\n", name_.get());
 
     outFN_.exportInto(out);
     outFNDA_.exportInto(out);
     out.printf("FNF:%zu\n", numFunctionsFound_);
     out.printf("FNH:%zu\n", numFunctionsHit_);
 
     outBRDA_.exportInto(out);
     out.printf("BRF:%zu\n", numBranchesFound_);
@@ -504,24 +498,24 @@ LCovRealm::lookupOrAdd(JS::Realm* realm,
     } else {
         // Find the first matching source.
         for (LCovSource& source : *sources_) {
             if (source.match(name))
                 return &source;
         }
     }
 
-    char* source_name = js_strdup(name);
+    UniqueChars source_name = DuplicateString(name);
     if (!source_name) {
         outTN_.reportOutOfMemory();
         return nullptr;
     }
 
     // Allocate a new LCovSource for the current top-level.
-    if (!sources_->append(LCovSource(&alloc_, source_name))) {
+    if (!sources_->emplaceBack(&alloc_, std::move(source_name))) {
         outTN_.reportOutOfMemory();
         return nullptr;
     }
 
     return &sources_->back();
 }
 
 void
--- a/js/src/vm/CodeCoverage.h
+++ b/js/src/vm/CodeCoverage.h
@@ -8,35 +8,36 @@
 #define vm_CodeCoverage_h
 
 #include "mozilla/Vector.h"
 
 #include "ds/LifoAlloc.h"
 
 #include "js/HashTable.h"
 #include "js/TypeDecls.h"
+#include "js/Utility.h"
 
 #include "vm/Printer.h"
 
 namespace js {
 
 class ScriptSourceObject;
 
 namespace coverage {
 
 class LCovSource
 {
   public:
-    LCovSource(LifoAlloc* alloc, const char* name);
+    LCovSource(LifoAlloc* alloc, JS::UniqueChars name);
     LCovSource(LCovSource&& src);
-    ~LCovSource();
+    ~LCovSource() = default;
 
     // Whether the given script name matches this LCovSource.
     bool match(const char* name) const {
-        return strcmp(name_, name) == 0;
+        return strcmp(name_.get(), name) == 0;
     }
 
     // Whether the current source is complete and if it can be flushed.
     bool isComplete() const {
         return hasTopLevelScript_;
     }
 
     // Iterate over the bytecode and collect the lcov output based on the
@@ -48,17 +49,17 @@ class LCovSource
     void exportInto(GenericPrinter& out) const;
 
   private:
     // Write the script name in out.
     bool writeScriptName(LSprinter& out, JSScript* script);
 
   private:
     // Name of the source file.
-    const char* name_;
+    JS::UniqueChars name_;
 
     // LifoAlloc strings which hold the filename of each function as
     // well as the number of hits for each function.
     LSprinter outFN_;
     LSprinter outFNDA_;
     size_t numFunctionsFound_;
     size_t numFunctionsHit_;
 
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -6,16 +6,18 @@
 
 #include "vm/Debugger-inl.h"
 
 #include "mozilla/DebugOnly.h"
 #include "mozilla/ScopeExit.h"
 #include "mozilla/Sprintf.h"
 #include "mozilla/TypeTraits.h"
 
+#include <utility>
+
 #include "jsfriendapi.h"
 #include "jsnum.h"
 
 #include "frontend/BytecodeCompiler.h"
 #include "frontend/Parser.h"
 #include "gc/FreeOp.h"
 #include "gc/HashUtil.h"
 #include "gc/Marking.h"
@@ -23,16 +25,17 @@
 #include "gc/PublicIterators.h"
 #include "jit/BaselineDebugModeOSR.h"
 #include "jit/BaselineJIT.h"
 #include "js/Date.h"
 #include "js/UbiNodeBreadthFirst.h"
 #include "js/Vector.h"
 #include "js/Wrapper.h"
 #include "proxy/ScriptedProxyHandler.h"
+#include "util/Text.h"
 #include "vm/ArgumentsObject.h"
 #include "vm/AsyncFunction.h"
 #include "vm/AsyncIteration.h"
 #include "vm/DebuggerMemory.h"
 #include "vm/GeckoProfiler.h"
 #include "vm/GeneratorObject.h"
 #include "vm/JSCompartment.h"
 #include "vm/JSContext.h"
@@ -443,35 +446,27 @@ ValueToStableChars(JSContext* cx, const 
     RootedLinearString linear(cx, value.toString()->ensureLinear(cx));
     if (!linear)
         return false;
     if (!stableChars.initTwoByte(cx, linear))
         return false;
     return true;
 }
 
-EvalOptions::~EvalOptions()
-{
-    js_free(const_cast<char*>(filename_));
-}
-
 bool
 EvalOptions::setFilename(JSContext* cx, const char* filename)
 {
-    char* copy = nullptr;
+    JS::UniqueChars copy;
     if (filename) {
-        copy = JS_strdup(cx, filename);
+        copy = DuplicateString(cx, filename);
         if (!copy)
             return false;
     }
 
-    // EvalOptions always owns filename_, so this cast is okay.
-    js_free(const_cast<char*>(filename_));
-
-    filename_ = copy;
+    filename_ = std::move(copy);
     return true;
 }
 
 static bool
 ParseEvalOptions(JSContext* cx, HandleValue value, EvalOptions& options)
 {
     if (!value.isObject())
         return true;
--- a/js/src/vm/Debugger.h
+++ b/js/src/vm/Debugger.h
@@ -16,16 +16,17 @@
 
 #include "builtin/Promise.h"
 #include "ds/TraceableFifo.h"
 #include "gc/Barrier.h"
 #include "gc/WeakMap.h"
 #include "js/Debug.h"
 #include "js/GCVariant.h"
 #include "js/HashTable.h"
+#include "js/Utility.h"
 #include "js/Wrapper.h"
 #include "vm/GlobalObject.h"
 #include "vm/JSCompartment.h"
 #include "vm/JSContext.h"
 #include "vm/SavedStacks.h"
 #include "vm/Stack.h"
 #include "wasm/WasmJS.h"
 
@@ -250,23 +251,23 @@ class AutoSuppressDebuggeeNoExecuteCheck
 
     ~AutoSuppressDebuggeeNoExecuteChecks() {
         MOZ_ASSERT(!*stack_);
         *stack_ = prev_;
     }
 };
 
 class MOZ_RAII EvalOptions {
-    const char* filename_;
-    unsigned lineno_;
+    JS::UniqueChars filename_;
+    unsigned lineno_ = 1;
 
   public:
-    EvalOptions() : filename_(nullptr), lineno_(1) {}
-    ~EvalOptions();
-    const char* filename() const { return filename_; }
+    EvalOptions() = default;
+    ~EvalOptions() = default;
+    const char* filename() const { return filename_.get(); }
     unsigned lineno() const { return lineno_; }
     MOZ_MUST_USE bool setFilename(JSContext* cx, const char* filename);
     void setLineno(unsigned lineno) { lineno_ = lineno; }
 };
 
 /*
  * Env is the type of what ES5 calls "lexical environments" (runtime activations
  * of lexical scopes). This is currently just JSObject, and is implemented by
--- a/js/src/vm/JSScript.cpp
+++ b/js/src/vm/JSScript.cpp
@@ -2697,17 +2697,17 @@ JSScript::initScriptName(JSContext* cx)
         if (!map || !map->init()) {
             ReportOutOfMemory(cx);
             return false;
         }
 
         realm()->scriptNameMap = std::move(map);
     }
 
-    UniqueChars name(js_strdup(filename()));
+    UniqueChars name = DuplicateString(filename());
     if (!name) {
         ReportOutOfMemory(cx);
         return false;
     }
 
     // Register the script name in the realm's map.
     if (!realm()->scriptNameMap->putNew(this, std::move(name))) {
         ReportOutOfMemory(cx);
--- a/js/src/vm/Runtime.cpp
+++ b/js/src/vm/Runtime.cpp
@@ -522,19 +522,24 @@ JSContext::handleInterrupt()
     return true;
 }
 
 bool
 JSRuntime::setDefaultLocale(const char* locale)
 {
     if (!locale)
         return false;
+
+    char* newLocale = DuplicateString(mainContextFromOwnThread(), locale).release();
+    if (!newLocale)
+        return false;
+
     resetDefaultLocale();
-    defaultLocale = JS_strdup(mainContextFromOwnThread(), locale);
-    return defaultLocale != nullptr;
+    defaultLocale = newLocale;
+    return true;
 }
 
 void
 JSRuntime::resetDefaultLocale()
 {
     js_free(defaultLocale);
     defaultLocale = nullptr;
 }
@@ -546,17 +551,17 @@ JSRuntime::getDefaultLocale()
         return defaultLocale;
 
     const char* locale = setlocale(LC_ALL, nullptr);
 
     // convert to a well-formed BCP 47 language tag
     if (!locale || !strcmp(locale, "C"))
         locale = "und";
 
-    char* lang = JS_strdup(mainContextFromOwnThread(), locale);
+    char* lang = DuplicateString(mainContextFromOwnThread(), locale).release();
     if (!lang)
         return nullptr;
 
     char* p;
     if ((p = strchr(lang, '.')))
         *p = '\0';
     while ((p = strchr(lang, '_')))
         *p = '-';
--- a/js/src/vm/SelfHosting.cpp
+++ b/js/src/vm/SelfHosting.cpp
@@ -519,24 +519,24 @@ intrinsic_FinishBoundFunctionInit(JSCont
  * _cannot_ be automatically determined.
  */
 static bool
 intrinsic_DecompileArg(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     MOZ_ASSERT(args.length() == 2);
 
-    RootedValue value(cx, args[1]);
-    ScopedJSFreePtr<char> str(DecompileArgument(cx, args[0].toInt32(), value));
+    HandleValue value = args[1];
+    UniqueChars str = DecompileArgument(cx, args[0].toInt32(), value);
     if (!str)
         return false;
-    JSAtom* atom = Atomize(cx, str, strlen(str));
-    if (!atom)
+    JSString* result = NewStringCopyZ<CanGC>(cx, str.get());
+    if (!result)
         return false;
-    args.rval().setString(atom);
+    args.rval().setString(result);
     return true;
 }
 
 static bool
 intrinsic_DefineDataProperty(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
--- a/js/src/vm/SharedImmutableStringsCache.h
+++ b/js/src/vm/SharedImmutableStringsCache.h
@@ -39,29 +39,29 @@ class SharedImmutableTwoByteString;
  */
 class SharedImmutableStringsCache
 {
     friend class SharedImmutableString;
     friend class SharedImmutableTwoByteString;
     struct Hasher;
 
   public:
-    using OwnedChars = mozilla::UniquePtr<char[], JS::FreePolicy>;
-    using OwnedTwoByteChars = mozilla::UniquePtr<char16_t[], JS::FreePolicy>;
+    using OwnedChars = JS::UniqueChars;
+    using OwnedTwoByteChars = JS::UniqueTwoByteChars;
 
     /**
      * Get the canonical, shared, and de-duplicated version of the given `const
      * char*` string. If such a string does not exist, call `intoOwnedChars` and
      * add the string it returns to the cache.
      *
      * `intoOwnedChars` must create an owned version of the given string, and
      * must have one of the following types:
      *
-     *     mozilla::UniquePtr<char[], JS::FreePolicy>   intoOwnedChars();
-     *     mozilla::UniquePtr<char[], JS::FreePolicy>&& intoOwnedChars();
+     *     JS::UniqueChars   intoOwnedChars();
+     *     JS::UniqueChars&& intoOwnedChars();
      *
      * It can be used by callers to elide a copy of the string when it is safe
      * to give up ownership of the lookup string to the cache. It must return a
      * `nullptr` on failure.
      *
      * On success, `Some` is returned. In the case of OOM failure, `Nothing` is
      * returned.
      */
@@ -93,18 +93,18 @@ class SharedImmutableStringsCache
     /**
      * Get the canonical, shared, and de-duplicated version of the given `const
      * char16_t*` string. If such a string does not exist, call `intoOwnedChars`
      * and add the string it returns to the cache.
      *
      * `intoOwnedTwoByteChars` must create an owned version of the given string,
      * and must have one of the following types:
      *
-     *     mozilla::UniquePtr<char16_t[], JS::FreePolicy>   intoOwnedTwoByteChars();
-     *     mozilla::UniquePtr<char16_t[], JS::FreePolicy>&& intoOwnedTwoByteChars();
+     *     JS::UniqueTwoByteChars   intoOwnedTwoByteChars();
+     *     JS::UniqueTwoByteChars&& intoOwnedTwoByteChars();
      *
      * It can be used by callers to elide a copy of the string when it is safe
      * to give up ownership of the lookup string to the cache. It must return a
      * `nullptr` on failure.
      *
      * On success, `Some` is returned. In the case of OOM failure, `Nothing` is
      * returned.
      */
--- a/js/src/vm/TraceLogging.cpp
+++ b/js/src/vm/TraceLogging.cpp
@@ -7,22 +7,25 @@
 #include "vm/TraceLogging.h"
 
 #include "mozilla/DebugOnly.h"
 #include "mozilla/EndianUtils.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/ScopeExit.h"
 
 #include <string.h>
+#include <utility>
 
 #include "jsapi.h"
 
 #include "jit/BaselineJIT.h"
 #include "jit/CompileWrappers.h"
+#include "js/Printf.h"
 #include "threading/LockGuard.h"
+#include "util/Text.h"
 #include "vm/JSScript.h"
 #include "vm/Runtime.h"
 #include "vm/Time.h"
 #include "vm/TraceLoggingGraph.h"
 
 #include "jit/JitFrames-inl.h"
 
 using namespace js;
@@ -413,27 +416,25 @@ TraceLoggerThreadState::getOrCreateEvent
 
     PointerHashMap::AddPtr p = pointerMap.lookupForAdd((const void*)text);
     if (p) {
         MOZ_ASSERT(p->value()->textId() < nextTextId); // Sanity check.
         p->value()->use();
         return p->value();
     }
 
-    char* str = js_strdup(text);
+    UniqueChars str = DuplicateString(text);
     if (!str)
         return nullptr;
 
     uint32_t textId = nextTextId;
 
-    TraceLoggerEventPayload* payload = js_new<TraceLoggerEventPayload>(textId, str);
-    if (!payload) {
-        js_free(str);
+    auto* payload = js_new<TraceLoggerEventPayload>(textId, std::move(str));
+    if (!payload)
         return nullptr;
-    }
 
     if (!textIdPayloads.putNew(textId, payload)) {
         js_delete(payload);
         payload = nullptr;
         return nullptr;
     }
 
     payload->use();
@@ -445,56 +446,41 @@ TraceLoggerThreadState::getOrCreateEvent
 
     payload->incPointerCount();
 
     return payload;
 }
 
 TraceLoggerEventPayload*
 TraceLoggerThreadState::getOrCreateEventPayload(const char* filename,
-                                                size_t lineno, size_t colno, const void* ptr)
+                                                uint32_t lineno, uint32_t colno, const void* ptr)
 {
     if (!filename)
         filename = "<unknown>";
 
     LockGuard<Mutex> guard(lock);
 
     PointerHashMap::AddPtr p;
     if (ptr) {
         p = pointerMap.lookupForAdd(ptr);
         if (p) {
             MOZ_ASSERT(p->value()->textId() < nextTextId); // Sanity check.
             p->value()->use();
             return p->value();
         }
     }
 
-    // Compute the length of the string to create.
-    size_t lenFilename = strlen(filename);
-    size_t lenLineno = 1;
-    for (size_t i = lineno; i /= 10; lenLineno++);
-    size_t lenColno = 1;
-    for (size_t i = colno; i /= 10; lenColno++);
-
-    size_t len = 7 + lenFilename + 1 + lenLineno + 1 + lenColno;
-    char* str = js_pod_malloc<char>(len + 1);
+    UniqueChars str = JS_smprintf("script %s:%u:%u", filename, lineno, colno);
     if (!str)
         return nullptr;
 
-    DebugOnly<size_t> ret =
-        snprintf(str, len + 1, "script %s:%zu:%zu", filename, lineno, colno);
-    MOZ_ASSERT(ret == len);
-    MOZ_ASSERT(strlen(str) == len);
-
     uint32_t textId = nextTextId;
-    TraceLoggerEventPayload* payload = js_new<TraceLoggerEventPayload>(textId, str);
-    if (!payload) {
-        js_free(str);
+    auto* payload = js_new<TraceLoggerEventPayload>(textId, std::move(str));
+    if (!payload)
         return nullptr;
-    }
 
     if (!textIdPayloads.putNew(textId, payload)) {
         js_delete(payload);
         payload = nullptr;
         return nullptr;
     }
 
     payload->use();
@@ -1025,18 +1011,18 @@ js::TraceLogDisableTextId(JSContext* cx,
         return;
     traceLoggerState->disableTextId(cx, textId);
 }
 
 TraceLoggerEvent::TraceLoggerEvent(TraceLoggerTextId type, JSScript* script)
   : TraceLoggerEvent(type, script->filename(), script->lineno(), script->column())
 { }
 
-TraceLoggerEvent::TraceLoggerEvent(TraceLoggerTextId type, const char* filename, size_t line,
-                                   size_t column)
+TraceLoggerEvent::TraceLoggerEvent(TraceLoggerTextId type, const char* filename, uint32_t line,
+                                   uint32_t column)
   : payload_()
 {
     MOZ_ASSERT(type == TraceLogger_Scripts || type == TraceLogger_AnnotateScripts ||
                type == TraceLogger_InlinedScripts || type == TraceLogger_Frontend);
 
     if (!traceLoggerState)
         return;
 
--- a/js/src/vm/TraceLogging.h
+++ b/js/src/vm/TraceLogging.h
@@ -6,16 +6,18 @@
 
 #ifndef TraceLogging_h
 #define TraceLogging_h
 
 #include "mozilla/GuardObjects.h"
 #include "mozilla/LinkedList.h"
 #include "mozilla/MemoryReporting.h"
 
+#include <utility>
+
 #include "js/AllocPolicy.h"
 #include "js/HashTable.h"
 #include "js/TypeDecls.h"
 #include "js/Vector.h"
 #include "vm/MutexIDs.h"
 #include "vm/TraceLoggingGraph.h"
 #include "vm/TraceLoggingTypes.h"
 
@@ -126,17 +128,17 @@ class TraceLoggerEvent {
     EventPayloadOrTextId payload_;
 
   public:
     TraceLoggerEvent()
       : payload_()
     {}
     explicit TraceLoggerEvent(TraceLoggerTextId textId);
     TraceLoggerEvent(TraceLoggerTextId type, JSScript* script);
-    TraceLoggerEvent(TraceLoggerTextId type, const char* filename, size_t line, size_t column);
+    TraceLoggerEvent(TraceLoggerTextId type, const char* filename, uint32_t line, uint32_t column);
     explicit TraceLoggerEvent(const char* text);
     TraceLoggerEvent(const TraceLoggerEvent& event);
     TraceLoggerEvent& operator=(const TraceLoggerEvent& other);
     ~TraceLoggerEvent();
     uint32_t textId() const;
     bool hasTextId() const {
         return hasExtPayload() || payload_.isTextId();
     }
@@ -149,17 +151,17 @@ class TraceLoggerEvent {
     bool hasExtPayload() const {
         return payload_.isEventPayload() && !!payload_.eventPayload();
     }
 #else
   public:
     TraceLoggerEvent() {}
     explicit TraceLoggerEvent(TraceLoggerTextId textId) {}
     TraceLoggerEvent(TraceLoggerTextId type, JSScript* script) {}
-    TraceLoggerEvent(TraceLoggerTextId type, const char* filename, size_t line, size_t column) {}
+    TraceLoggerEvent(TraceLoggerTextId type, const char* filename, uint32_t line, uint32_t column) {}
     explicit TraceLoggerEvent(const char* text) {}
     TraceLoggerEvent(const TraceLoggerEvent& event) {}
     TraceLoggerEvent& operator=(const TraceLoggerEvent& other) { return *this; };
     ~TraceLoggerEvent() {}
     uint32_t textId() const { return 0; }
     bool hasTextId() const { return false; }
 #endif
 
@@ -180,19 +182,19 @@ bool CurrentThreadOwnsTraceLoggerThreadS
  */
 class TraceLoggerEventPayload {
     uint32_t textId_;
     UniqueChars string_;
     mozilla::Atomic<uint32_t> uses_;
     mozilla::Atomic<uint32_t> pointerCount_;
 
   public:
-    TraceLoggerEventPayload(uint32_t textId, char* string)
+    TraceLoggerEventPayload(uint32_t textId, UniqueChars string)
       : textId_(textId),
-        string_(string),
+        string_(std::move(string)),
         uses_(0)
     { }
 
     ~TraceLoggerEventPayload() {
         MOZ_ASSERT(uses_ == 0);
     }
 
     uint32_t textId() {
@@ -437,18 +439,18 @@ class TraceLoggerThreadState
     void purgeUnusedPayloads();
 
     // These functions map a unique input to a logger ID.
     // This can be used to give start and stop events. Calls to these functions should be
     // limited if possible, because of the overhead.
     // Note: it is not allowed to use them in logTimestamp.
     TraceLoggerEventPayload* getOrCreateEventPayload(const char* text);
     TraceLoggerEventPayload* getOrCreateEventPayload(JSScript* script);
-    TraceLoggerEventPayload* getOrCreateEventPayload(const char* filename, size_t lineno,
-                                                     size_t colno, const void* p);
+    TraceLoggerEventPayload* getOrCreateEventPayload(const char* filename, uint32_t lineno,
+                                                     uint32_t colno, const void* p);
 
     size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf);
     size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) {
         return mallocSizeOf(this) + sizeOfExcludingThis(mallocSizeOf);
     }
 #endif
 };
 
--- a/js/src/vm/UbiNodeCensus.cpp
+++ b/js/src/vm/UbiNodeCensus.cpp
@@ -783,17 +783,17 @@ ByAllocationStack::report(JSContext* cx,
     MOZ_ASSERT(generation == count.table.generation());
 
     report.setObject(*map);
     return true;
 }
 
 // A count type that categorizes nodes by their script's filename.
 class ByFilename : public CountType {
-    using UniqueCString = UniquePtr<char, JS::FreePolicy>;
+    using UniqueCString = JS::UniqueChars;
 
     struct UniqueCStringHasher {
         using Lookup = UniqueCString;
 
         static js::HashNumber hash(const Lookup& lookup) {
             return CStringHasher::hash(lookup.get());
         }
 
@@ -875,17 +875,17 @@ bool
 ByFilename::count(CountBase& countBase, mozilla::MallocSizeOf mallocSizeOf, const Node& node)
 {
     Count& count = static_cast<Count&>(countBase);
 
     const char* filename = node.scriptFilename();
     if (!filename)
         return count.noFilename->count(mallocSizeOf, node);
 
-    UniqueCString myFilename(js_strdup(filename));
+    UniqueCString myFilename = DuplicateString(filename);
     if (!myFilename)
         return false;
 
     Table::AddPtr p = count.table.lookupForAdd(myFilename);
     if (!p) {
         CountBasePtr thenCount(thenType->makeCount());
         if (!thenCount || !count.table.add(p, std::move(myFilename), std::move(thenCount)))
             return false;
--- a/layout/base/PresShell.cpp
+++ b/layout/base/PresShell.cpp
@@ -134,17 +134,17 @@
 #include "nsStyleChangeList.h"
 #include "nsCSSFrameConstructor.h"
 #ifdef MOZ_XUL
 #include "nsMenuFrame.h"
 #include "nsTreeBodyFrame.h"
 #include "nsIBoxObject.h"
 #include "nsITreeBoxObject.h"
 #include "nsMenuPopupFrame.h"
-#include "nsITreeColumns.h"
+#include "nsTreeColumns.h"
 #include "nsIDOMXULMultSelectCntrlEl.h"
 #include "nsIDOMXULSelectCntrlItemEl.h"
 #include "nsIDOMXULMenuListElement.h"
 #include "nsXULElement.h"
 #include "mozilla/dom/BoxObject.h"
 #endif // MOZ_XUL
 
 #include "mozilla/layers/CompositorBridgeChild.h"
@@ -8359,21 +8359,20 @@ PresShell::GetCurrentItemAndPositionForE
           int32_t firstVisibleRow, rowHeight;
           treeBox->GetFirstVisibleRow(&firstVisibleRow);
           treeBox->GetRowHeight(&rowHeight);
 
           extraTreeY += nsPresContext::CSSPixelsToAppUnits(
                           (currentIndex - firstVisibleRow + 1) * rowHeight);
           istree = true;
 
-          nsCOMPtr<nsITreeColumns> cols;
+          RefPtr<nsTreeColumns> cols;
           treeBox->GetColumns(getter_AddRefs(cols));
           if (cols) {
-            nsCOMPtr<nsITreeColumn> col;
-            cols->GetFirstColumn(getter_AddRefs(col));
+            nsTreeColumn* col = cols->GetFirstColumn();
             if (col) {
               RefPtr<Element> colElement;
               col->GetElement(getter_AddRefs(colElement));
               if (colElement) {
                 nsIFrame* frame = colElement->GetPrimaryFrame();
                 if (frame) {
                   extraTreeY += frame->GetSize().height;
                 }
--- a/layout/base/RestyleManager.cpp
+++ b/layout/base/RestyleManager.cpp
@@ -2197,32 +2197,32 @@ RestyleManager::PostRestyleEventForAnima
   CSSPseudoElementType aPseudoType,
   nsRestyleHint aRestyleHint)
 {
   Element* elementToRestyle =
     EffectCompositor::GetElementToRestyle(aElement, aPseudoType);
 
   if (!elementToRestyle) {
     // FIXME: Bug 1371107: When reframing happens,
-    // EffectCompositor::mElementsToRestyle still has unbinded old pseudo
+    // EffectCompositor::mElementsToRestyle still has unbound old pseudo
     // element. We should drop it.
     return;
   }
 
   AutoRestyleTimelineMarker marker(mPresContext->GetDocShell(),
                                    true /* animation-only */);
   Servo_NoteExplicitHints(elementToRestyle, aRestyleHint, nsChangeHint(0));
 }
 
 void
 RestyleManager::RebuildAllStyleData(nsChangeHint aExtraHint,
                                          nsRestyleHint aRestyleHint)
 {
-   // NOTE(emilio): GeckoRestlyeManager does a sync style flush, which seems not
-   // to be needed in my testing.
+  // NOTE(emilio): GeckoRestlyeManager does a sync style flush, which seems not
+  // to be needed in my testing.
   PostRebuildAllStyleDataEvent(aExtraHint, aRestyleHint);
 }
 
 void
 RestyleManager::PostRebuildAllStyleDataEvent(nsChangeHint aExtraHint,
                                                   nsRestyleHint aRestyleHint)
 {
   // NOTE(emilio): The semantics of these methods are quite funny, in the sense
--- a/layout/style/ErrorReporter.cpp
+++ b/layout/style/ErrorReporter.cpp
@@ -3,16 +3,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /* diagnostic reporting for CSS style sheet parser */
 
 #include "mozilla/css/ErrorReporter.h"
 
+#include "mozilla/StaticPrefs.h"
 #include "mozilla/StyleSheetInlines.h"
 #include "mozilla/css/Loader.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Services.h"
 #include "mozilla/SystemGroup.h"
 #include "nsCSSScanner.h"
 #include "nsIConsoleService.h"
 #include "nsIDocument.h"
@@ -63,40 +64,31 @@ public:
 private:
   nsCOMPtr<nsIURI> mURI;
   nsString mSpec;
   bool mPending;
 };
 
 } // namespace
 
-bool ErrorReporter::sReportErrors = false;
 bool ErrorReporter::sInitialized = false;
 
 static nsIConsoleService *sConsoleService;
 static nsIFactory *sScriptErrorFactory;
 static nsIStringBundle *sStringBundle;
 static ShortTermURISpecCache *sSpecCache;
 
-#define CSS_ERRORS_PREF "layout.css.report_errors"
-
 void
 ErrorReporter::InitGlobals()
 {
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(!sInitialized, "should not have been called");
 
   sInitialized = true;
 
-  if (NS_FAILED(Preferences::AddBoolVarCache(&sReportErrors,
-                                             CSS_ERRORS_PREF,
-                                             true))) {
-    return;
-  }
-
   nsCOMPtr<nsIConsoleService> cs = do_GetService(NS_CONSOLESERVICE_CONTRACTID);
   if (!cs) {
     return;
   }
 
   nsCOMPtr<nsIFactory> sf = do_GetClassObject(NS_SCRIPTERROR_CONTRACTID);
   if (!sf) {
     return;
@@ -126,27 +118,43 @@ namespace css {
 ErrorReporter::ReleaseGlobals()
 {
   NS_IF_RELEASE(sConsoleService);
   NS_IF_RELEASE(sScriptErrorFactory);
   NS_IF_RELEASE(sStringBundle);
   NS_IF_RELEASE(sSpecCache);
 }
 
+static uint64_t
+FindInnerWindowID(const StyleSheet* aSheet, const Loader* aLoader)
+{
+  uint64_t innerWindowID = 0;
+  if (aSheet) {
+    innerWindowID = aSheet->FindOwningWindowInnerID();
+  }
+  if (innerWindowID == 0 && aLoader) {
+    if (nsIDocument* doc = aLoader->GetDocument()) {
+      innerWindowID = doc->InnerWindowID();
+    }
+  }
+  return innerWindowID;
+}
+
 ErrorReporter::ErrorReporter(const StyleSheet* aSheet,
                              const Loader* aLoader,
                              nsIURI* aURI)
   : mSheet(aSheet)
   , mLoader(aLoader)
   , mURI(aURI)
-  , mInnerWindowID(0)
   , mErrorLineNumber(0)
   , mPrevErrorLineNumber(0)
   , mErrorColNumber(0)
 {
+  MOZ_ASSERT(ShouldReportErrors(mSheet, mLoader));
+  EnsureGlobalsInitialized();
 }
 
 ErrorReporter::~ErrorReporter()
 {
   MOZ_ASSERT(NS_IsMainThread());
   // Schedule deferred cleanup for cached data. We want to strike a
   // balance between performance and memory usage, so we only allow
   // short-term caching.
@@ -184,71 +192,50 @@ SheetOwner(const StyleSheet& aSheet)
     return owner;
   }
 
   auto* associated = aSheet.GetAssociatedDocumentOrShadowRoot();
   return associated ? &associated->AsNode() : nullptr;
 }
 
 bool
-ErrorReporter::ShouldReportErrors()
+ErrorReporter::ShouldReportErrors(const StyleSheet* aSheet,
+                                  const Loader* aLoader)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  EnsureGlobalsInitialized();
-  if (!sReportErrors) {
+  if (!StaticPrefs::layout_css_report_errors()) {
     return false;
   }
 
-  if (mInnerWindowID) {
-    // We already reported an error, and that has cleared mSheet and mLoader, so
-    // we'd get the bogus value otherwise.
-    return true;
-  }
-
-  if (mSheet) {
-    nsINode* owner = SheetOwner(*mSheet);
+  if (aSheet) {
+    nsINode* owner = SheetOwner(*aSheet);
     if (owner && ShouldReportErrors(*owner->OwnerDoc())) {
       return true;
     }
   }
 
-  if (mLoader && mLoader->GetDocument() &&
-      ShouldReportErrors(*mLoader->GetDocument())) {
+  if (aLoader && aLoader->GetDocument() &&
+      ShouldReportErrors(*aLoader->GetDocument())) {
     return true;
   }
 
   return false;
 }
 
 void
 ErrorReporter::OutputError()
 {
   MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(ShouldReportErrors());
+  MOZ_ASSERT(ShouldReportErrors(mSheet, mLoader));
 
   if (mError.IsEmpty()) {
     return;
   }
 
-  if (mInnerWindowID == 0 && (mSheet || mLoader)) {
-    if (mSheet) {
-      mInnerWindowID = mSheet->FindOwningWindowInnerID();
-    }
-    if (mInnerWindowID == 0 && mLoader) {
-      nsIDocument* doc = mLoader->GetDocument();
-      if (doc) {
-        mInnerWindowID = doc->InnerWindowID();
-      }
-    }
-    // don't attempt this again, even if we failed
-    mSheet = nullptr;
-    mLoader = nullptr;
-  }
-
   if (mFileName.IsEmpty()) {
     if (mURI) {
       if (!sSpecCache) {
         sSpecCache = new ShortTermURISpecCache;
         NS_ADDREF(sSpecCache);
       }
       mFileName = sSpecCache->GetSpec(mURI);
       mURI = nullptr;
@@ -266,17 +253,17 @@ ErrorReporter::OutputError()
     // an already anonymized uri spec.
     rv = errorObject->InitWithSanitizedSource(mError,
                                               mFileName,
                                               mErrorLine,
                                               mErrorLineNumber,
                                               mErrorColNumber,
                                               nsIScriptError::warningFlag,
                                               "CSS Parser",
-                                              mInnerWindowID);
+                                              FindInnerWindowID(mSheet, mLoader));
     if (NS_SUCCEEDED(rv)) {
       sConsoleService->LogMessage(errorObject);
     }
   }
 
   ClearError();
 }
 
@@ -314,41 +301,41 @@ void
 ErrorReporter::ClearError()
 {
   mError.Truncate();
 }
 
 void
 ErrorReporter::AddToError(const nsString &aErrorText)
 {
-  MOZ_ASSERT(ShouldReportErrors());
+  MOZ_ASSERT(ShouldReportErrors(mSheet, mLoader));
 
   if (mError.IsEmpty()) {
     mError = aErrorText;
   } else {
     mError.AppendLiteral("  ");
     mError.Append(aErrorText);
   }
 }
 
 void
 ErrorReporter::ReportUnexpected(const char *aMessage)
 {
-  MOZ_ASSERT(ShouldReportErrors());
+  MOZ_ASSERT(ShouldReportErrors(mSheet, mLoader));
 
   nsAutoString str;
   sStringBundle->GetStringFromName(aMessage, str);
   AddToError(str);
 }
 
 void
 ErrorReporter::ReportUnexpectedUnescaped(const char *aMessage,
                                          const nsAutoString& aParam)
 {
-  MOZ_ASSERT(ShouldReportErrors());
+  MOZ_ASSERT(ShouldReportErrors(mSheet, mLoader));
 
   const char16_t *params[1] = { aParam.get() };
 
   nsAutoString str;
   sStringBundle->FormatStringFromName(aMessage, params, ArrayLength(params),
                                       str);
   AddToError(str);
 }
--- a/layout/style/ErrorReporter.h
+++ b/layout/style/ErrorReporter.h
@@ -17,34 +17,37 @@ class nsIURI;
 
 namespace mozilla {
 class StyleSheet;
 
 namespace css {
 
 class Loader;
 
-class ErrorReporter {
+// FIXME(emilio): Probably better to call this ErrorBuilder or something?
+class MOZ_STACK_CLASS ErrorReporter final
+{
 public:
   ErrorReporter(const StyleSheet* aSheet,
                 const Loader* aLoader,
                 nsIURI* aURI);
+
   ~ErrorReporter();
 
   static void ReleaseGlobals();
   static void EnsureGlobalsInitialized()
   {
     if (MOZ_UNLIKELY(!sInitialized)) {
       InitGlobals();
     }
   }
 
   static bool ShouldReportErrors(const nsIDocument&);
-
-  bool ShouldReportErrors();
+  static bool ShouldReportErrors(const StyleSheet* aSheet,
+                                 const Loader* aLoader);
 
   void OutputError(uint32_t aLineNumber,
                    uint32_t aLineOffset,
                    const nsACString& aSource);
   void ClearError();
 
   // In all overloads of ReportUnexpected, aMessage is a stringbundle
   // name, which will be processed as a format string with the
@@ -59,23 +62,22 @@ public:
 private:
   void OutputError();
   void AddToError(const nsString &aErrorText);
   static void InitGlobals();
 
   static bool sInitialized;
   static bool sReportErrors;
 
-  nsAutoString mError;
+  nsString mError;
   nsString mErrorLine;
   nsString mFileName;
   const StyleSheet* mSheet;
   const Loader* mLoader;
-  nsIURI *mURI;
-  uint64_t mInnerWindowID;
+  nsIURI* mURI;
   uint32_t mErrorLineNumber;
   uint32_t mPrevErrorLineNumber;
   uint32_t mErrorColNumber;
 };
 
 } // namespace css
 } // namespace mozilla
 
--- a/layout/style/FontFaceSet.cpp
+++ b/layout/style/FontFaceSet.cpp
@@ -117,23 +117,16 @@ FontFaceSet::FontFaceSet(nsPIDOMWindowIn
   , mBypassCache(false)
   , mPrivateBrowsing(false)
 {
   MOZ_ASSERT(mDocument, "We should get a valid document from the caller!");
 
   mStandardFontLoadPrincipal =
     new gfxFontSrcPrincipal(mDocument->NodePrincipal());
 
-  // If the pref is not set, don't create the Promise (which the page wouldn't
-  // be able to get to anyway) as it causes the window.FontFaceSet constructor
-  // to be created.
-  if (aWindow && PrefEnabled()) {
-    mResolveLazilyCreatedReadyPromise = true;
-  }
-
   // Record the state of the "bypass cache" flags from the docshell now,
   // since we want to look at them from style worker threads, and we can
   // only get to the docshell through a weak pointer (which is only
   // possible on the main thread).
   //
   // In theory the load type of a docshell could change after the document
   // is loaded, but handling that doesn't seem too important.
   if (nsCOMPtr<nsIDocShell> docShell = mDocument->GetDocShell()) {
@@ -1693,19 +1686,22 @@ FontFaceSet::DispatchLoadingEventAndRepl
   if (PrefEnabled()) {
     if (mReady &&
         mReady->State() != Promise::PromiseState::Pending) {
       if (GetParentObject()) {
         ErrorResult rv;
         mReady = Promise::Create(GetParentObject(), rv);
       }
     }
-    if (!mReady) {
-      mResolveLazilyCreatedReadyPromise = false;
-    }
+
+    // We may previously have been in a state where all fonts had finished
+    // loading and we'd set mResolveLazilyCreatedReadyPromise to make sure that
+    // if we lazily create mReady for a consumer that we resolve it before
+    // returning it.  We're now loading fonts, so we need to clear that flag.
+    mResolveLazilyCreatedReadyPromise = false;
   }
 }
 
 void
 FontFaceSet::UpdateHasLoadingFontFaces()
 {
   mHasLoadingFontFacesIsDirty = false;
   mHasLoadingFontFaces = false;
--- a/layout/style/ServoBindings.cpp
+++ b/layout/style/ServoBindings.cpp
@@ -2780,75 +2780,65 @@ Gecko_SetJemallocThreadLocalArena(bool e
   jemalloc_thread_local_arena(enabled);
 #endif
 }
 
 #include "nsStyleStructList.h"
 
 #undef STYLE_STRUCT
 
-
-ErrorReporter*
-Gecko_CreateCSSErrorReporter(StyleSheet* aSheet,
-                             Loader* aLoader,
-                             nsIURI* aURI)
+bool
+Gecko_ErrorReportingEnabled(const StyleSheet* aSheet, const Loader* aLoader)
 {
-  MOZ_ASSERT(NS_IsMainThread());
-  return new ErrorReporter(aSheet, aLoader, aURI);
+  return ErrorReporter::ShouldReportErrors(aSheet, aLoader);
 }
 
 void
-Gecko_DestroyCSSErrorReporter(ErrorReporter* reporter)
-{
-  delete reporter;
-}
-
-void
-Gecko_ReportUnexpectedCSSError(ErrorReporter* reporter,
+Gecko_ReportUnexpectedCSSError(const StyleSheet* aSheet,
+                               const Loader* aLoader,
+                               nsIURI* aURI,
                                const char* message,
                                const char* param,
                                uint32_t paramLen,
                                const char* prefix,
                                const char* prefixParam,
                                uint32_t prefixParamLen,
                                const char* suffix,
                                const char* source,
                                uint32_t sourceLen,
                                uint32_t lineNumber,
                                uint32_t colNumber)
 {
-  if (!reporter->ShouldReportErrors()) {
-    return;
-  }
-
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
 
+  ErrorReporter reporter(aSheet, aLoader, aURI);
+
   if (prefix) {
     if (prefixParam) {
       nsDependentCSubstring paramValue(prefixParam, prefixParamLen);
       nsAutoString wideParam = NS_ConvertUTF8toUTF16(paramValue);
-      reporter->ReportUnexpectedUnescaped(prefix, wideParam);
+      reporter.ReportUnexpectedUnescaped(prefix, wideParam);
     } else {
-      reporter->ReportUnexpected(prefix);
+      reporter.ReportUnexpected(prefix);
     }
   }
 
   if (param) {
     nsDependentCSubstring paramValue(param, paramLen);
     nsAutoString wideParam = NS_ConvertUTF8toUTF16(paramValue);
-    reporter->ReportUnexpectedUnescaped(message, wideParam);
+    reporter.ReportUnexpectedUnescaped(message, wideParam);
   } else {
-    reporter->ReportUnexpected(message);
+    reporter.ReportUnexpected(message);
   }
 
   if (suffix) {
-    reporter->ReportUnexpected(suffix);
+    reporter.ReportUnexpected(suffix);
   }
   nsDependentCSubstring sourceValue(source, sourceLen);
-  reporter->OutputError(lineNumber, colNumber, sourceValue);
+  reporter.OutputError(lineNumber, colNumber, sourceValue);
 }
 
 void
 Gecko_AddBufferToCrashReport(const void* addr, size_t len)
 {
   MOZ_ASSERT(NS_IsMainThread());
   nsCOMPtr<nsICrashReporter> cr = do_GetService("@mozilla.org/toolkit/crash-reporter;1");
   NS_ENSURE_TRUE_VOID(cr);
--- a/layout/style/ServoBindings.h
+++ b/layout/style/ServoBindings.h
@@ -682,21 +682,21 @@ void Gecko_AnnotateCrashReport(const cha
   const uint32_t SERVO_CSS_PSEUDO_ELEMENT_FLAGS_##name_ = flags_;
 #include "nsCSSPseudoElementList.h"
 #undef CSS_PSEUDO_ELEMENT
 
 #define SERVO_BINDING_FUNC(name_, return_, ...) return_ name_(__VA_ARGS__);
 #include "mozilla/ServoBindingList.h"
 #undef SERVO_BINDING_FUNC
 
-mozilla::css::ErrorReporter* Gecko_CreateCSSErrorReporter(mozilla::StyleSheet* sheet,
-                                                          mozilla::css::Loader* loader,
-                                                          nsIURI* uri);
-void Gecko_DestroyCSSErrorReporter(mozilla::css::ErrorReporter* reporter);
-void Gecko_ReportUnexpectedCSSError(mozilla::css::ErrorReporter* reporter,
+bool Gecko_ErrorReportingEnabled(const mozilla::StyleSheet* sheet,
+                                 const mozilla::css::Loader* loader);
+void Gecko_ReportUnexpectedCSSError(const mozilla::StyleSheet* sheet,
+                                    const mozilla::css::Loader* loader,
+                                    nsIURI* uri,
                                     const char* message,
                                     const char* param,
                                     uint32_t paramLen,
                                     const char* prefix,
                                     const char* prefixParam,
                                     uint32_t prefixParamLen,
                                     const char* suffix,
                                     const char* source,
--- a/layout/style/ServoBindings.toml
+++ b/layout/style/ServoBindings.toml
@@ -62,17 +62,16 @@ headers = [
     "mozilla/dom/MediaList.h",
     "mozilla/dom/ShadowRoot.h",
     "mozilla/AnimationPropertySegment.h",
     "mozilla/ComputedTiming.h",
     "mozilla/ComputedTimingFunction.h",
     "mozilla/Keyframe.h",
     "mozilla/ServoElementSnapshot.h",
     "mozilla/ServoElementSnapshotTable.h",
-    "mozilla/css/ErrorReporter.h",
     "mozilla/dom/Element.h",
     "mozilla/dom/ChildIterator.h",
     "mozilla/dom/NameSpaceConstants.h",
     "mozilla/LookAndFeel.h",
     "mozilla/StaticPrefs.h",
     "mozilla/ServoBindings.h",
     "mozilla/ComputedStyle.h",
     "mozilla/ServoTraversalStatistics.h",
@@ -219,17 +218,16 @@ whitelist-types = [
     "mozilla::ComputedTimingFunction::BeforeFlag",
     "mozilla::SeenPtrs",
     "mozilla::ServoElementSnapshot.*",
     "mozilla::ComputedStyle",
     "mozilla::StyleSheet",
     "mozilla::ServoStyleSheetInner",
     "mozilla::ServoStyleSetSizes",
     "mozilla::ServoTraversalStatistics",
-    "mozilla::css::ErrorReporter",
     "mozilla::css::LoaderReusableStyleSheets",
     "mozilla::css::SheetLoadData",
     "mozilla::css::SheetLoadDataHolder",
     "mozilla::css::SheetParsingMode",
     "mozilla::css::URLMatchingFunction",
     "mozilla::dom::IterationCompositeOperation",
     "mozilla::dom::StyleChildrenIterator",
     "mozilla::HalfCorner",
@@ -448,17 +446,16 @@ raw-lines = [
     "pub type ComputedStyleBorrowed<'a> = &'a ::properties::ComputedValues;",
     "pub type ComputedStyleBorrowedOrNull<'a> = Option<&'a ::properties::ComputedValues>;",
     "pub type ServoComputedDataBorrowed<'a> = &'a ServoComputedData;",
     "pub type RawServoAnimationValueTableBorrowed<'a> = &'a ();"
 ]
 whitelist-functions = ["Servo_.*", "Gecko_.*"]
 structs-types = [
     "mozilla::css::GridTemplateAreasValue",
-    "mozilla::css::ErrorReporter",
     "mozilla::css::ImageValue",
     "mozilla::css::URLValue",
     "mozilla::css::URLValueData",
     "mozilla::dom::CallerType",
     "mozilla::dom::ShadowRoot",
     "mozilla::AnonymousCounterStyle",
     "mozilla::AtomArray",
     "mozilla::FontStretch",
--- a/layout/style/test/test_font_loading_api.html
+++ b/layout/style/test/test_font_loading_api.html
@@ -219,22 +219,22 @@ function runTest() {
     is(Object.getPrototypeOf(FontFace.prototype), Object.prototype, "FontFace should inherit from Object (TEST 1)");
 
     // (TEST 2) Some miscellaneous tests for FontFaceSetLoadEvent.
     ok(window.FontFaceSetLoadEvent, "FontFaceSetLoadEvent interface object should be present (TEST 2)");
     is(Object.getPrototypeOf(FontFaceSetLoadEvent.prototype), Event.prototype, "FontFaceSetLoadEvent should inherit from Event (TEST 2)");
 
   }).then(function() {
 
-    // (TEST 3) Test that document.fonts.ready starts out resolved with the
-    // FontFaceSet.
+    // (TEST 3) Test that document.fonts.ready is resolved with the
+    // document.fonts FontFaceSet.
     var p = Promise.resolve();
     sourceDocuments.forEach(function({ doc, what }) {
-      p = p.then(function() {
-        return is_resolved_with(doc.fonts.ready, doc.fonts, "initial value of document.fonts", "(TEST 3) (" + what + ")");
+      p = p.then(doc.fonts.ready).then(function() {
+        return is_resolved_with(doc.fonts.ready, doc.fonts, "document.fonts.ready resolves with document.fonts", "(TEST 3) (" + what + ")");
       });
     });
     return p;
 
   }).then(function() {
 
     // (TEST 4) Test that document.fonts in this test document starts out with no
     // FontFace objects in it.
--- a/layout/xul/nsXULTooltipListener.cpp
+++ b/layout/xul/nsXULTooltipListener.cpp
@@ -18,16 +18,17 @@
 #endif
 #include "nsIScriptContext.h"
 #include "nsPIDOMWindow.h"
 #ifdef MOZ_XUL
 #include "nsXULPopupManager.h"
 #endif
 #include "nsIRootBox.h"
 #include "nsIBoxObject.h"
+#include "nsTreeColumns.h"
 #include "mozilla/ErrorResult.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/LookAndFeel.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/Event.h" // for Event
 #include "mozilla/dom/BoxObject.h"
 #include "mozilla/dom/MouseEvent.h"
 #include "mozilla/TextEvents.h"
--- a/layout/xul/nsXULTooltipListener.h
+++ b/layout/xul/nsXULTooltipListener.h
@@ -8,22 +8,22 @@
 #define nsXULTooltipListener_h__
 
 #include "nsIDOMEventListener.h"
 #include "nsITimer.h"
 #include "nsCOMPtr.h"
 #include "nsString.h"
 #ifdef MOZ_XUL
 #include "nsITreeBoxObject.h"
-#include "nsITreeColumns.h"
 #endif
 #include "nsWeakPtr.h"
 #include "mozilla/Attributes.h"
 
 class nsIContent;
+class nsITreeColumn;
 
 namespace mozilla {
 namespace dom {
 class Event;
 class MouseEvent;
 } // namespace dom
 } // namespace mozilla
 
--- a/layout/xul/tree/TreeBoxObject.cpp
+++ b/layout/xul/tree/TreeBoxObject.cpp
@@ -10,17 +10,16 @@
 #include "nsIScriptableRegion.h"
 #include "nsTreeContentView.h"
 #include "nsITreeSelection.h"
 #include "ChildIterator.h"
 #include "nsContentUtils.h"
 #include "nsError.h"
 #include "nsTreeBodyFrame.h"
 #include "mozilla/dom/TreeBoxObjectBinding.h"
-#include "nsITreeColumns.h"
 #include "mozilla/dom/DOMRect.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/ToJSValue.h"
 
 namespace mozilla {
 namespace dom {
 
@@ -232,17 +231,17 @@ already_AddRefed<nsTreeColumns>
 TreeBoxObject::GetColumns()
 {
   nsTreeBodyFrame* body = GetTreeBodyFrame();
   if (body)
     return body->Columns();
   return nullptr;
 }
 
-NS_IMETHODIMP TreeBoxObject::GetColumns(nsITreeColumns** aColumns)
+NS_IMETHODIMP TreeBoxObject::GetColumns(nsTreeColumns** aColumns)
 {
   *aColumns = GetColumns().take();
   return NS_OK;
 }
 
 int32_t TreeBoxObject::RowHeight()
 {
   nsTreeBodyFrame* body = GetTreeBodyFrame();
--- a/layout/xul/tree/moz.build
+++ b/layout/xul/tree/moz.build
@@ -5,17 +5,16 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 with Files('**'):
     BUG_COMPONENT = ('Core', 'XUL')
 
 XPIDL_SOURCES += [
     'nsITreeBoxObject.idl',
     'nsITreeColumns.idl',
-    'nsITreeContentView.idl',
     'nsITreeSelection.idl',
     'nsITreeView.idl',
 ]
 
 XPIDL_MODULE = 'layout_xul_tree'
 
 EXPORTS += [
     'nsTreeColFrame.h',
--- a/layout/xul/tree/nsITreeBoxObject.idl
+++ b/layout/xul/tree/nsITreeBoxObject.idl
@@ -3,31 +3,31 @@
  * 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 "nsISupports.idl"
 
 interface nsITreeView;
 interface nsITreeSelection;
 interface nsITreeColumn;
-interface nsITreeColumns;
 interface nsIScriptableRegion;
 
 webidl Element;
+webidl TreeColumns;
 
 /**
  * This interface cannot become builtinclass until bug 1438525 is fixed.
  */
 [scriptable, uuid(f3da0c5e-51f5-45f0-b2cd-6be3ab6847ae)]
 interface nsITreeBoxObject : nsISupports
 {
   /**
    * Obtain the columns.
    */
-  readonly attribute nsITreeColumns columns;
+  readonly attribute TreeColumns columns;
 
   /**
    * The view that backs the tree and that supplies it with its data.
    * It is dynamically settable, either using a view attribute on the
    * tree tag or by setting this attribute to a new value.
    */
   attribute nsITreeView view;
 
--- a/layout/xul/tree/nsITreeColumns.idl
+++ b/layout/xul/tree/nsITreeColumns.idl
@@ -1,24 +1,23 @@
 /* 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 "nsISupports.idl"
 
-interface nsITreeColumns;
-
 webidl Element;
+webidl TreeColumns;
 
 [scriptable, uuid(ae835ecf-6b32-4660-9b43-8a270df56e02)]
 interface nsITreeColumn : nsISupports
 {
   readonly attribute Element element;
 
-  readonly attribute nsITreeColumns columns;
+  readonly attribute TreeColumns columns;
 
   readonly attribute long x;
   readonly attribute long width;
 
   readonly attribute AString id;
   [noscript] void getIdConst([shared] out wstring idConst);
 
   readonly attribute long index;
@@ -33,62 +32,8 @@ interface nsITreeColumn : nsISupports
   const short TYPE_PASSWORD            = 3;
   readonly attribute short type;
 
   nsITreeColumn getNext();
   nsITreeColumn getPrevious();
 
   void invalidate();
 };
-
-interface nsITreeBoxObject;
-
-[scriptable, uuid(f8a8d6b4-6788-438d-9009-7142798767ab)]
-interface nsITreeColumns : nsISupports
-{
-  /**
-   * The tree widget for these columns.
-   */
-  readonly attribute nsITreeBoxObject tree;
-
-  /**
-   * The number of columns.
-   */
-  readonly attribute long count;
-
-  /**
-   * An alias for count (for the benefit of scripts which treat this as an
-   * array).
-   */
-  readonly attribute long length;
-
-  /**
-   * Get the first/last column.
-   */
-  nsITreeColumn getFirstColumn();
-  nsITreeColumn getLastColumn();
-
-  /**
-   * Attribute based column getters.
-   */
-  nsITreeColumn getPrimaryColumn();
-  nsITreeColumn getSortedColumn();
-  nsITreeColumn getKeyColumn();
-
-  /**
-   * Get the column for the given element.
-   */
-  nsITreeColumn getColumnFor(in Element element);
-
-  /**
-   * Parametric column getters.
-   */
-  nsITreeColumn getNamedColumn(in AString id);
-  nsITreeColumn getColumnAt(in long index);
-
-  /**
-   * This method is called whenever a treecol is added or removed and
-   * the column cache needs to be rebuilt.
-   */
-  void invalidateColumns();
-
-  void restoreNaturalOrder();
-};
deleted file mode 100644
--- a/layout/xul/tree/nsITreeContentView.idl
+++ /dev/null
@@ -1,22 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* 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 "nsISupports.idl"
-
-webidl Element;
-
-[scriptable, uuid(5ef62896-0c0a-41f1-bb3c-44a60f5dfdab)]
-interface nsITreeContentView : nsISupports
-{
-  /**
-   * Retrieve the content item associated with the specified index.
-   */
-  Element getItemAtIndex(in long index);
-
-  /**
-   * Retrieve the index associated with the specified content item.
-   */
-  long getIndexOfItem(in Element item);
-};
--- a/layout/xul/tree/nsTreeColFrame.cpp
+++ b/layout/xul/tree/nsTreeColFrame.cpp
@@ -8,17 +8,17 @@
 #include "nsTreeColFrame.h"
 #include "nsGkAtoms.h"
 #include "nsIContent.h"
 #include "mozilla/ComputedStyle.h"
 #include "nsNameSpaceManager.h"
 #include "nsIBoxObject.h"
 #include "mozilla/ErrorResult.h"
 #include "mozilla/dom/TreeBoxObject.h"
-#include "nsITreeColumns.h"
+#include "nsTreeColumns.h"
 #include "nsDisplayList.h"
 #include "nsTreeBodyFrame.h"
 #include "nsXULElement.h"
 
 //
 // NS_NewTreeColFrame
 //
 // Creates a new col frame
@@ -180,17 +180,17 @@ nsTreeColFrame::GetTreeBoxObject()
   return result;
 }
 
 void
 nsTreeColFrame::InvalidateColumns(bool aCanWalkFrameTree)
 {
   nsITreeBoxObject* treeBoxObject = GetTreeBoxObject();
   if (treeBoxObject) {
-    nsCOMPtr<nsITreeColumns> columns;
+    RefPtr<nsTreeColumns> columns;
 
     if (aCanWalkFrameTree) {
       treeBoxObject->GetColumns(getter_AddRefs(columns));
     } else {
       nsTreeBodyFrame* body = static_cast<mozilla::dom::TreeBoxObject*>
         (treeBoxObject)->GetCachedTreeBodyFrame();
       if (body) {
         columns = body->Columns();
--- a/layout/xul/tree/nsTreeColFrame.h
+++ b/layout/xul/tree/nsTreeColFrame.h
@@ -43,13 +43,13 @@ protected:
   virtual ~nsTreeColFrame();
 
   /**
    * @return the tree box object of the tree this column belongs to, or nullptr.
    */
   nsITreeBoxObject* GetTreeBoxObject();
 
   /**
-   * Helper method that gets the nsITreeColumns object this column belongs to
+   * Helper method that gets the TreeColumns object this column belongs to
    * and calls InvalidateColumns() on it.
    */
   void InvalidateColumns(bool aCanWalkFrameTree = true);
 };
--- a/layout/xul/tree/nsTreeColumns.cpp
+++ b/layout/xul/tree/nsTreeColumns.cpp
@@ -152,17 +152,17 @@ nsTreeColumn::GetElement(Element** aElem
     element.forget(aElement);
     return NS_OK;
   }
   *aElement = nullptr;
   return NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
-nsTreeColumn::GetColumns(nsITreeColumns** aColumns)
+nsTreeColumn::GetColumns(nsTreeColumns** aColumns)
 {
   NS_IF_ADDREF(*aColumns = mColumns);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsTreeColumn::GetX(int32_t* aX)
 {
@@ -399,17 +399,16 @@ nsTreeColumns::~nsTreeColumns()
   nsTreeColumns::InvalidateColumns();
 }
 
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(nsTreeColumns)
 
 // QueryInterface implementation for nsTreeColumns
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsTreeColumns)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
-  NS_INTERFACE_MAP_ENTRY(nsITreeColumns)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsTreeColumns)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsTreeColumns)
 
 nsIContent*
 nsTreeColumns::GetParentObject() const
@@ -424,105 +423,56 @@ nsTreeColumns::WrapObject(JSContext* aCx
 }
 
 dom::TreeBoxObject*
 nsTreeColumns::GetTree() const
 {
   return mTree ? static_cast<mozilla::dom::TreeBoxObject*>(mTree->GetTreeBoxObject()) : nullptr;
 }
 
-NS_IMETHODIMP
-nsTreeColumns::GetTree(nsITreeBoxObject** _retval)
-{
-  NS_IF_ADDREF(*_retval = GetTree());
-  return NS_OK;
-}
-
 uint32_t
 nsTreeColumns::Count()
 {
   EnsureColumns();
   uint32_t count = 0;
   for (nsTreeColumn* currCol = mFirstColumn; currCol; currCol = currCol->GetNext()) {
     ++count;
   }
   return count;
 }
 
-NS_IMETHODIMP
-nsTreeColumns::GetCount(int32_t* _retval)
-{
-  *_retval = Count();
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsTreeColumns::GetLength(int32_t* _retval)
-{
-  *_retval = Length();
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsTreeColumns::GetFirstColumn(nsITreeColumn** _retval)
-{
-  NS_IF_ADDREF(*_retval = GetFirstColumn());
-  return NS_OK;
-}
-
 nsTreeColumn*
 nsTreeColumns::GetLastColumn()
 {
   EnsureColumns();
   nsTreeColumn* currCol = mFirstColumn;
   while (currCol) {
     nsTreeColumn* next = currCol->GetNext();
     if (!next) {
       return currCol;
     }
     currCol = next;
   }
   return nullptr;
 }
 
-NS_IMETHODIMP
-nsTreeColumns::GetLastColumn(nsITreeColumn** _retval)
-{
-  NS_IF_ADDREF(*_retval = GetLastColumn());
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsTreeColumns::GetPrimaryColumn(nsITreeColumn** _retval)
-{
-  NS_IF_ADDREF(*_retval = GetPrimaryColumn());
-  return NS_OK;
-}
-
 nsTreeColumn*
 nsTreeColumns::GetSortedColumn()
 {
   EnsureColumns();
   for (nsTreeColumn* currCol = mFirstColumn; currCol; currCol = currCol->GetNext()) {
     if (currCol->mContent &&
         nsContentUtils::HasNonEmptyAttr(currCol->mContent, kNameSpaceID_None,
                                         nsGkAtoms::sortDirection)) {
       return currCol;
     }
   }
   return nullptr;
 }
 
-NS_IMETHODIMP
-nsTreeColumns::GetSortedColumn(nsITreeColumn** _retval)
-{
-  NS_IF_ADDREF(*_retval = GetSortedColumn());
-  return NS_OK;
-}
-
 nsTreeColumn*
 nsTreeColumns::GetKeyColumn()
 {
   EnsureColumns();
 
   nsTreeColumn* first = nullptr;
   nsTreeColumn* primary = nullptr;
   nsTreeColumn* sorted = nullptr;
@@ -557,42 +507,28 @@ nsTreeColumns::GetKeyColumn()
 
   if (sorted)
     return sorted;
   if (primary)
     return primary;
   return first;
 }
 
-NS_IMETHODIMP
-nsTreeColumns::GetKeyColumn(nsITreeColumn** _retval)
-{
-  NS_IF_ADDREF(*_retval = GetKeyColumn());
-  return NS_OK;
-}
-
 nsTreeColumn*
 nsTreeColumns::GetColumnFor(dom::Element* aElement)
 {
   EnsureColumns();
   for (nsTreeColumn* currCol = mFirstColumn; currCol; currCol = currCol->GetNext()) {
     if (currCol->mContent == aElement) {
       return currCol;
     }
   }
   return nullptr;
 }
 
-NS_IMETHODIMP
-nsTreeColumns::GetColumnFor(dom::Element* aElement, nsITreeColumn** _retval)
-{
-  NS_IF_ADDREF(*_retval = GetColumnFor(aElement));
-  return NS_OK;
-}
-
 nsTreeColumn*
 nsTreeColumns::NamedGetter(const nsAString& aId, bool& aFound)
 {
   EnsureColumns();
   for (nsTreeColumn* currCol = mFirstColumn; currCol; currCol = currCol->GetNext()) {
     if (currCol->GetId().Equals(aId)) {
       aFound = true;
       return currCol;
@@ -604,23 +540,16 @@ nsTreeColumns::NamedGetter(const nsAStri
 
 nsTreeColumn*
 nsTreeColumns::GetNamedColumn(const nsAString& aId)
 {
   bool dummy;
   return NamedGetter(aId, dummy);
 }
 
-NS_IMETHODIMP
-nsTreeColumns::GetNamedColumn(const nsAString& aId, nsITreeColumn** _retval)
-{
-  NS_IF_ADDREF(*_retval = GetNamedColumn(aId));
-  return NS_OK;
-}
-
 void
 nsTreeColumns::GetSupportedNames(nsTArray<nsString>& aNames)
 {
   for (nsTreeColumn* currCol = mFirstColumn; currCol; currCol = currCol->GetNext()) {
     aNames.AppendElement(currCol->GetId());
   }
 }
 
@@ -641,47 +570,41 @@ nsTreeColumns::IndexedGetter(uint32_t aI
 
 nsTreeColumn*
 nsTreeColumns::GetColumnAt(uint32_t aIndex)
 {
   bool dummy;
   return IndexedGetter(aIndex, dummy);
 }
 
-NS_IMETHODIMP
-nsTreeColumns::GetColumnAt(int32_t aIndex, nsITreeColumn** _retval)
-{
-  NS_IF_ADDREF(*_retval = GetColumnAt(static_cast<uint32_t>(aIndex)));
-  return NS_OK;
-}
-
-NS_IMETHODIMP
+void
 nsTreeColumns::InvalidateColumns()
 {
   for (nsTreeColumn* currCol = mFirstColumn; currCol;
        currCol = currCol->GetNext()) {
     currCol->SetColumns(nullptr);
   }
   mFirstColumn = nullptr;
-  return NS_OK;
 }
 
-NS_IMETHODIMP
+void
 nsTreeColumns::RestoreNaturalOrder()
 {
-  if (!mTree)
-    return NS_OK;
+  if (!mTree) {
+    return;
+  }
 
   nsIContent* content = mTree->GetBaseElement();
 
   // Strong ref, since we'll be setting attributes
   nsCOMPtr<nsIContent> colsContent =
     nsTreeUtils::GetImmediateChild(content, nsGkAtoms::treecols);
-  if (!colsContent)
-    return NS_OK;
+  if (!colsContent) {
+    return;
+  }
 
   int32_t i = 0;
   for (nsINode* child = colsContent->GetFirstChild();
        child; child = child->GetNextSibling()) {
     nsAutoString ordinal;
     ordinal.AppendInt(i++);
     if (child->IsElement()) {
       child->AsElement()->SetAttr(kNameSpaceID_None, nsGkAtoms::ordinal, ordinal,
@@ -689,17 +612,16 @@ nsTreeColumns::RestoreNaturalOrder()
     }
   }
 
   nsTreeColumns::InvalidateColumns();
 
   if (mTree) {
     mTree->Invalidate();
   }
-  return NS_OK;
 }
 
 nsTreeColumn*
 nsTreeColumns::GetPrimaryColumn()
 {
   EnsureColumns();
   for (nsTreeColumn* currCol = mFirstColumn; currCol; currCol = currCol->GetNext()) {
     if (currCol->IsPrimary()) {
--- a/layout/xul/tree/nsTreeColumns.h
+++ b/layout/xul/tree/nsTreeColumns.h
@@ -12,16 +12,17 @@
 #include "mozilla/Attributes.h"
 #include "mozilla/RefPtr.h"
 #include "nsCoord.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsQueryObject.h"
 #include "nsWrapperCache.h"
 #include "nsString.h"
 
+class nsAtom;
 class nsTreeBodyFrame;
 class nsTreeColumns;
 class nsIFrame;
 class nsIContent;
 struct nsRect;
 
 namespace mozilla {
 class ErrorResult;
@@ -155,28 +156,27 @@ private:
   int8_t mTextAlignment;
 
   RefPtr<nsTreeColumn> mNext;
   nsTreeColumn* mPrevious;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsTreeColumn, NS_TREECOLUMN_IMPL_CID)
 
-class nsTreeColumns final : public nsITreeColumns
+class nsTreeColumns final : public nsISupports
                           , public nsWrapperCache
 {
 private:
   ~nsTreeColumns();
 
 public:
   explicit nsTreeColumns(nsTreeBodyFrame* aTree);
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsTreeColumns)
-  NS_DECL_NSITREECOLUMNS
 
   nsIContent* GetParentObject() const;
   virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
   // WebIDL
   mozilla::dom::TreeBoxObject* GetTree() const;
   uint32_t Count();
   uint32_t Length()
@@ -194,18 +194,18 @@ public:
   nsTreeColumn* GetColumnFor(mozilla::dom::Element* aElement);
 
   nsTreeColumn* IndexedGetter(uint32_t aIndex, bool& aFound);
   nsTreeColumn* GetColumnAt(uint32_t aIndex);
   nsTreeColumn* NamedGetter(const nsAString& aId, bool& aFound);
   nsTreeColumn* GetNamedColumn(const nsAString& aId);
   void GetSupportedNames(nsTArray<nsString>& aNames);
 
-  // Uses XPCOM InvalidateColumns().
-  // Uses XPCOM RestoreNaturalOrder().
+  void InvalidateColumns();
+  void RestoreNaturalOrder();
 
   friend class nsTreeBodyFrame;
 protected:
   void SetTree(nsTreeBodyFrame* aTree) { mTree = aTree; }
 
   // Builds our cache of column info.
   void EnsureColumns();
 
--- a/layout/xul/tree/nsTreeContentView.cpp
+++ b/layout/xul/tree/nsTreeContentView.cpp
@@ -8,16 +8,17 @@
 #include "nsGkAtoms.h"
 #include "nsIBoxObject.h"
 #include "nsTreeUtils.h"
 #include "nsTreeContentView.h"
 #include "ChildIterator.h"
 #include "nsError.h"
 #include "nsIXULSortService.h"
 #include "nsTreeBodyFrame.h"
+#include "nsTreeColumns.h"
 #include "mozilla/ErrorResult.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/TreeContentViewBinding.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIDocument.h"
 
 using namespace mozilla;
 
@@ -111,20 +112,19 @@ NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(ns
                                       mRoot,
                                       mBody)
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsTreeContentView)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsTreeContentView)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsTreeContentView)
   NS_INTERFACE_MAP_ENTRY(nsITreeView)
-  NS_INTERFACE_MAP_ENTRY(nsITreeContentView)
   NS_INTERFACE_MAP_ENTRY(nsIDocumentObserver)
   NS_INTERFACE_MAP_ENTRY(nsIMutationObserver)
-  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsITreeContentView)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsITreeView)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
 NS_INTERFACE_MAP_END
 
 JSObject*
 nsTreeContentView::WrapObject(JSContext* aCx,
                               JS::Handle<JSObject*> aGivenProto)
 {
   return TreeContentViewBinding::Wrap(aCx, this, aGivenProto);
@@ -870,42 +870,22 @@ nsTreeContentView::GetItemAtIndex(int32_
   if (!IsValidRowIndex(aIndex)) {
     aError.Throw(NS_ERROR_INVALID_ARG);
     return nullptr;
   }
 
   return mRows[aIndex]->mContent;
 }
 
-NS_IMETHODIMP
-nsTreeContentView::GetItemAtIndex(int32_t aIndex, Element** _retval)
-{
-  ErrorResult rv;
-  RefPtr<Element> element = GetItemAtIndex(aIndex, rv);
-  if (rv.Failed()) {
-    return rv.StealNSResult();
-  }
-
-  element.forget(_retval);
-  return NS_OK;
-}
-
 int32_t
 nsTreeContentView::GetIndexOfItem(Element* aItem)
 {
   return FindContent(aItem);
 }
 
-NS_IMETHODIMP
-nsTreeContentView::GetIndexOfItem(Element* aItem, int32_t* _retval)
-{
-  *_retval = GetIndexOfItem(aItem);
-  return NS_OK;
-}
-
 void
 nsTreeContentView::AttributeChanged(dom::Element* aElement,
                                     int32_t       aNameSpaceID,
                                     nsAtom*      aAttribute,
                                     int32_t       aModType,
                                     const nsAttrValue* aOldValue)
 {
   // Lots of codepaths under here that do all sorts of stuff, so be safe.
@@ -967,21 +947,20 @@ nsTreeContentView::AttributeChanged(dom:
     }
 
     return;
   }
 
   if (aElement->IsXULElement(nsGkAtoms::treecol)) {
     if (aAttribute == nsGkAtoms::properties) {
       if (mBoxObject) {
-        nsCOMPtr<nsITreeColumns> cols;
+        RefPtr<nsTreeColumns> cols;
         mBoxObject->GetColumns(getter_AddRefs(cols));
         if (cols) {
-          nsCOMPtr<nsITreeColumn> col;
-          cols->GetColumnFor(aElement, getter_AddRefs(col));
+          RefPtr<nsTreeColumn> col = cols->GetColumnFor(aElement);
           mBoxObject->InvalidateColumn(col);
         }
       }
     }
   }
   else if (aElement->IsXULElement(nsGkAtoms::treeitem)) {
     int32_t index = FindContent(aElement);
     if (index >= 0) {
--- a/layout/xul/tree/nsTreeContentView.h
+++ b/layout/xul/tree/nsTreeContentView.h
@@ -7,17 +7,16 @@
 #ifndef nsTreeContentView_h__
 #define nsTreeContentView_h__
 
 #include "nsCycleCollectionParticipant.h"
 #include "nsTArray.h"
 #include "nsStubDocumentObserver.h"
 #include "nsITreeBoxObject.h"
 #include "nsITreeView.h"
-#include "nsITreeContentView.h"
 #include "nsITreeSelection.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/UniquePtr.h"
 
 class nsIDocument;
 class nsSelection;
 class nsTreeColumn;
 class Row;
@@ -28,17 +27,16 @@ class DataTransfer;
 class Element;
 class TreeBoxObject;
 } // namespace dom
 } // namespace mozilla
 
 nsresult NS_NewTreeContentView(nsITreeView** aResult);
 
 class nsTreeContentView final : public nsITreeView,
-                                public nsITreeContentView,
                                 public nsStubDocumentObserver,
                                 public nsWrapperCache
 {
   typedef mozilla::dom::Element Element;
   public:
     nsTreeContentView(void);
 
     NS_DECL_CYCLE_COLLECTING_ISUPPORTS
@@ -114,18 +112,16 @@ class nsTreeContentView final : public n
                              nsTreeColumn& aColumn)
     {
     }
     Element* GetItemAtIndex(int32_t aRow, mozilla::ErrorResult& aError);
     int32_t GetIndexOfItem(Element* aItem);
 
     NS_DECL_NSITREEVIEW
 
-    NS_DECL_NSITREECONTENTVIEW
-
     // nsIDocumentObserver
     NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
     NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
     NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
     NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
     NS_DECL_NSIMUTATIONOBSERVER_NODEWILLBEDESTROYED
 
     static bool CanTrustTreeSelection(nsISupports* aValue);
--- a/layout/xul/tree/nsTreeImageListener.cpp
+++ b/layout/xul/tree/nsTreeImageListener.cpp
@@ -4,16 +4,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsTreeImageListener.h"
 #include "nsITreeBoxObject.h"
 #include "imgIRequest.h"
 #include "imgIContainer.h"
 #include "nsIContent.h"
+#include "nsTreeColumns.h"
 
 NS_IMPL_ISUPPORTS(nsTreeImageListener, imgINotificationObserver)
 
 nsTreeImageListener::nsTreeImageListener(nsTreeBodyFrame* aTreeFrame)
   : mTreeFrame(aTreeFrame),
     mInvalidationSuppressed(true),
     mInvalidationArea(nullptr)
 {
--- a/layout/xul/tree/nsTreeImageListener.h
+++ b/layout/xul/tree/nsTreeImageListener.h
@@ -4,20 +4,21 @@
  * 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 nsTreeImageListener_h__
 #define nsTreeImageListener_h__
 
 #include "nsString.h"
 #include "nsCOMPtr.h"
-#include "nsITreeColumns.h"
 #include "nsTreeBodyFrame.h"
 #include "mozilla/Attributes.h"
 
+class nsITreeColumn;
+
 // This class handles image load observation.
 class nsTreeImageListener final : public imgINotificationObserver
 {
 public:
   explicit nsTreeImageListener(nsTreeBodyFrame *aTreeFrame);
 
   NS_DECL_ISUPPORTS
   NS_DECL_IMGINOTIFICATIONOBSERVER
--- a/layout/xul/tree/nsTreeSelection.cpp
+++ b/layout/xul/tree/nsTreeSelection.cpp
@@ -11,16 +11,17 @@
 #include "nsIBoxObject.h"
 #include "nsITreeBoxObject.h"
 #include "nsITreeView.h"
 #include "nsString.h"
 #include "nsIContent.h"
 #include "nsNameSpaceManager.h"
 #include "nsGkAtoms.h"
 #include "nsComponentManagerUtils.h"
+#include "nsTreeColumns.h"
 
 using namespace mozilla;
 
 // A helper class for managing our ranges of selection.
 struct nsTreeRange
 {
   nsTreeSelection* mSelection;
 
--- a/layout/xul/tree/nsTreeSelection.h
+++ b/layout/xul/tree/nsTreeSelection.h
@@ -3,22 +3,22 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsTreeSelection_h__
 #define nsTreeSelection_h__
 
 #include "nsITreeSelection.h"
-#include "nsITreeColumns.h"
 #include "nsITimer.h"
 #include "nsCycleCollectionParticipant.h"
 #include "mozilla/Attributes.h"
 
 class nsITreeBoxObject;
+class nsITreeColumn;
 struct nsTreeRange;
 
 class nsTreeSelection final : public nsINativeTreeSelection
 {
 public:
   explicit nsTreeSelection(nsITreeBoxObject* aTree);
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
--- a/mfbt/Poison.h
+++ b/mfbt/Poison.h
@@ -76,18 +76,19 @@ namespace mozilla {
  * so enables us to narrow down the location where the corruption is occurring.
  * A pleasant side-effect of these additional Check() calls is that crash
  * signatures may become more regular, as crashes will ideally occur
  * consolidated at the point of a Check(), rather than scattered about at
  * various uses of the corrupted memory.
  */
 class CorruptionCanary {
 public:
-  CorruptionCanary() {
-    mValue = kCanarySet;
+  constexpr CorruptionCanary()
+    : mValue(kCanarySet)
+  {
   }
 
   ~CorruptionCanary() {
     Check();
     mValue = mozPoisonValue();
   }
 
   void Check() const {
--- a/modules/libpref/init/StaticPrefList.h
+++ b/modules/libpref/init/StaticPrefList.h
@@ -165,16 +165,23 @@ VARCACHE_PREF(
 
 // Is parallel CSS parsing enabled?
 VARCACHE_PREF(
   "layout.css.parsing.parallel",
    layout_css_parsing_parallel,
   bool, true
 )
 
+// Is CSS error reporting enabled?
+VARCACHE_PREF(
+  "layout.css.report_errors",
+  layout_css_report_errors,
+  bool, true
+)
+
 // Is support for the font-display @font-face descriptor enabled?
 VARCACHE_PREF(
   "layout.css.font-display.enabled",
    layout_css_font_display_enabled,
   bool, true
 )
 
 // Are webkit-prefixed properties & property-values supported?
--- a/security/manager/ssl/nsCertTree.cpp
+++ b/security/manager/ssl/nsCertTree.cpp
@@ -5,29 +5,29 @@
 #include "nsCertTree.h"
 
 #include "ScopedNSSTypes.h"
 #include "mozilla/Logging.h"
 #include "nsArray.h"
 #include "nsArrayUtils.h"
 #include "nsHashKeys.h"
 #include "nsISupportsPrimitives.h"
-#include "nsITreeColumns.h"
 #include "nsIX509CertDB.h"
 #include "nsIX509Cert.h"
 #include "nsIX509CertValidity.h"
 #include "nsNSSCertHelper.h"
 #include "nsNSSCertificate.h"
 #include "nsNSSCertificateDB.h"
 #include "nsNSSHelper.h"
 #include "nsReadableUtils.h"
 #include "nsTHashtable.h"
 #include "nsUnicharUtils.h"
 #include "nsXPCOMCID.h"
 #include "nsString.h"
+#include "nsTreeColumns.h"
 #include "pkix/pkixtypes.h"
 
 using namespace mozilla;
 
 extern LazyLogModule gPIPNSSLog;
 
 static NS_DEFINE_CID(kCertOverrideCID, NS_CERTOVERRIDE_CID);
 
--- a/servo/ports/geckolib/error_reporter.rs
+++ b/servo/ports/geckolib/error_reporter.rs
@@ -4,52 +4,54 @@
 
 //! Wrapper around Gecko's CSS error reporting mechanism.
 
 #![allow(unsafe_code)]
 
 use cssparser::{CowRcStr, serialize_identifier, ToCss};
 use cssparser::{SourceLocation, ParseError, ParseErrorKind, Token, BasicParseErrorKind};
 use selectors::parser::SelectorParseErrorKind;
+use std::cell::Cell;
 use std::ffi::CStr;
 use std::ptr;
 use style::error_reporting::{ParseErrorReporter, ContextualParseError};
-use style::gecko_bindings::bindings::{Gecko_CreateCSSErrorReporter, Gecko_DestroyCSSErrorReporter};
-use style::gecko_bindings::bindings::Gecko_ReportUnexpectedCSSError;
+use style::gecko_bindings::bindings;
 use style::gecko_bindings::structs::{Loader, StyleSheet as DomStyleSheet, nsIURI};
-use style::gecko_bindings::structs::ErrorReporter as GeckoErrorReporter;
 use style::gecko_bindings::structs::URLExtraData as RawUrlExtraData;
 use style::stylesheets::UrlExtraData;
 use style_traits::{StyleParseErrorKind, ValueParseErrorKind};
 
 pub type ErrorKind<'i> = ParseErrorKind<'i, StyleParseErrorKind<'i>>;
 
-/// Wrapper around an instance of Gecko's CSS error reporter.
-pub struct ErrorReporter(*mut GeckoErrorReporter);
+/// An error reporter with all the data we need to report errors.
+pub struct ErrorReporter {
+    sheet: *const DomStyleSheet,
+    loader: *const Loader,
+    uri: *mut nsIURI,
+    cached_error_reporting_enabled: Cell<Option<bool>>,
+}
 
 impl ErrorReporter {
     /// Create a new instance of the Gecko error reporter.
     pub fn new(
         sheet: *mut DomStyleSheet,
         loader: *mut Loader,
         extra_data: *mut RawUrlExtraData,
     ) -> Self {
-        unsafe {
-            let url = extra_data.as_ref()
+        let uri = unsafe {
+            extra_data.as_ref()
                 .map(|d| d.mBaseURI.raw::<nsIURI>())
-                .unwrap_or(ptr::null_mut());
-            ErrorReporter(Gecko_CreateCSSErrorReporter(sheet, loader, url))
-        }
-    }
-}
+                .unwrap_or(ptr::null_mut())
+        };
 
-impl Drop for ErrorReporter {
-    fn drop(&mut self) {
-        unsafe {
-            Gecko_DestroyCSSErrorReporter(self.0);
+        ErrorReporter {
+            sheet,
+            loader,
+            uri,
+            cached_error_reporting_enabled: Cell::new(None),
         }
     }
 }
 
 enum ErrorString<'a> {
     Snippet(CowRcStr<'a>),
     Ident(CowRcStr<'a>),
     UnexpectedToken(Token<'a>),
@@ -386,45 +388,64 @@ impl<'a> ErrorHelpers<'a> for Contextual
                 }
             }
         };
         (None, msg, action)
     }
 }
 
 impl ErrorReporter {
+    fn reporting_enabled(&self) -> bool {
+        if let Some(enabled) = self.cached_error_reporting_enabled.get() {
+            return enabled;
+        }
+        let enabled = unsafe {
+            bindings::Gecko_ErrorReportingEnabled(self.sheet, self.loader)
+        };
+        self.cached_error_reporting_enabled.set(Some(enabled));
+        enabled
+    }
+
     pub fn report(&self, location: SourceLocation, error: ContextualParseError) {
+        if !self.reporting_enabled() {
+            return;
+        }
+
         let (pre, name, action) = error.to_gecko_message();
         let suffix = match action {
             Action::Nothing => ptr::null(),
             Action::Skip => cstr!("PEDeclSkipped").as_ptr(),
             Action::Drop => cstr!("PEDeclDropped").as_ptr(),
         };
         let params = error.error_params();
         let param = params.main_param;
         let pre_param = params.prefix_param;
         let param = param.map(|p| p.into_str());
         let pre_param = pre_param.map(|p| p.into_str());
         let param_ptr = param.as_ref().map_or(ptr::null(), |p| p.as_ptr());
         let pre_param_ptr = pre_param.as_ref().map_or(ptr::null(), |p| p.as_ptr());
         // The CSS source text is unused and will be removed in bug 1381188.
         let source = "";
         unsafe {
-            Gecko_ReportUnexpectedCSSError(self.0,
-                                           name.as_ptr() as *const _,
-                                           param_ptr as *const _,
-                                           param.as_ref().map_or(0, |p| p.len()) as u32,
-                                           pre.map_or(ptr::null(), |p| p.as_ptr()) as *const _,
-                                           pre_param_ptr as *const _,
-                                           pre_param.as_ref().map_or(0, |p| p.len()) as u32,
-                                           suffix as *const _,
-                                           source.as_ptr() as *const _,
-                                           source.len() as u32,
-                                           location.line,
-                                           location.column);
+            bindings::Gecko_ReportUnexpectedCSSError(
+                self.sheet,
+                self.loader,
+                self.uri,
+                name.as_ptr() as *const _,
+                param_ptr as *const _,
+                param.as_ref().map_or(0, |p| p.len()) as u32,
+                pre.map_or(ptr::null(), |p| p.as_ptr()) as *const _,
+                pre_param_ptr as *const _,
+                pre_param.as_ref().map_or(0, |p| p.len()) as u32,
+                suffix as *const _,
+                source.as_ptr() as *const _,
+                source.len() as u32,
+                location.line,
+                location.column,
+            );
         }
     }
 }
 
 impl ParseErrorReporter for ErrorReporter {
     fn report_error(
         &self,
         _url: &UrlExtraData,
--- a/taskcluster/ci/l10n/kind.yml
+++ b/taskcluster/ci/l10n/kind.yml
@@ -156,18 +156,16 @@ job-template:
             android-api-16:
                - single_locale/{project}_android-api-16.py
                - single_locale/tc_common.py
                - single_locale/tc_android-api-16.py
                - single_locale/onchange.py
       # no default, so we fail on new entries
       options:
          - revision=$GECKO_HEAD_REV
-         - total-chunks=1
-         - this-chunk=1
       actions:
          by-build-platform:
             default: ['clone-locales', 'list-locales', 'setup', 'repack',
                       'summary']
             android-api-16: ['get-secrets',
                              'clone-locales', 'list-locales', 'setup', 'repack',
                              'upload-repacks', 'summary']
       script:
@@ -176,11 +174,12 @@ job-template:
             android-api-16: mozharness/scripts/mobile_l10n.py
    when:
       files-changed:
          - browser/locales/l10n-onchange-changesets.json
          - mobile/locales/l10n-onchange-changesets.json
          - testing/mozharness/configs/single_locale/**
          - testing/mozharness/mozharness/mozilla/l10n/locales.py
          - testing/mozharness/scripts/desktop_l10n.py
+         - testing/mozharness/scripts/mobile_l10n.py
          - third_party/python/compare-locales/**
          - toolkit/locales/**
          - toolkit/mozapps/installer/**
--- a/taskcluster/ci/nightly-l10n/kind.yml
+++ b/taskcluster/ci/nightly-l10n/kind.yml
@@ -213,16 +213,16 @@ job-template:
                - single_locale/tc_common.py
                - single_locale/tc_android-api-16.py
       # no default, so we fail on new entries
       options:
          - revision=$GECKO_HEAD_REV
       actions:
          by-build-platform:
             default: ['clone-locales', 'list-locales', 'setup', 'repack',
-                      'submit-to-balrog', 'summary']
+                      'summary']
             android-api-16-nightly: ['get-secrets',
                                      'clone-locales', 'list-locales', 'setup', 'repack',
-                                     'upload-repacks', 'submit-to-balrog', 'summary']
+                                     'upload-repacks', 'summary']
       script:
          by-build-platform:
             default: mozharness/scripts/desktop_l10n.py
             android-api-16-nightly: mozharness/scripts/mobile_l10n.py
--- a/testing/mozharness/configs/builds/releng_sub_windows_configs/32_stat_and_debug.py
+++ b/testing/mozharness/configs/builds/releng_sub_windows_configs/32_stat_and_debug.py
@@ -19,12 +19,11 @@ releng.manifest",
         'PATH': 'C:/mozilla-build/nsis-3.01;C:/mozilla-build/python27;'
                 '%s' % (os.environ.get('path')),
         'TINDERBOX_OUTPUT': '1',
         'XPCOM_DEBUG_BREAK': 'stack-and-abort',
         'TOOLTOOL_CACHE': 'c:/builds/tooltool_cache',
         'TOOLTOOL_HOME': '/c/builds',
     },
     'mozconfig_variant': 'debug-static-analysis',
-    'purge_minsize': 9,
     'artifact_flag_build_variant_in_try': None,
     #######################
 }
--- a/testing/mozharness/configs/multi_locale/ash_android-x86.json
+++ b/testing/mozharness/configs/multi_locale/ash_android-x86.json
@@ -1,24 +1,15 @@
 {
     "work_dir": ".",
     "log_name": "multilocale",
     "objdir": "obj-firefox",
     "locales_file": "build/mobile/locales/l10n-changesets.json",
     "locales_platform": "android-multilocale",
     "locales_dir": "mobile/android/locales",
     "ignore_locales": ["en-US", "multi"],
-    "repos": [{
-        "repo": "https://hg.mozilla.org/projects/ash",
-        "branch": "default",
-        "dest": "build"
-    },{
-        "repo": "https://hg.mozilla.org/build/tools",
-        "branch": "default",
-        "dest": "tools"
-    }],
     "vcs_share_base": "/builds/hg-shared",
     "hg_l10n_base": "https://hg.mozilla.org/l10n-central",
     "hg_l10n_tag": "default",
     "l10n_dir": "l10n-central",
     "mozilla_dir": "build",
     "mozconfig": "build/mobile/android/config/mozconfigs/android-x86/nightly"
 }
--- a/testing/mozharness/configs/multi_locale/ash_android.json
+++ b/testing/mozharness/configs/multi_locale/ash_android.json
@@ -1,23 +1,14 @@
 {
     "work_dir": ".",
     "log_name": "multilocale",
     "objdir": "obj-firefox",
     "locales_file": "build/mobile/locales/l10n-changesets.json",
     "locales_platform": "android-multilocale",
     "locales_dir": "mobile/android/locales",
     "ignore_locales": ["en-US", "multi"],
-    "repos": [{
-        "repo": "https://hg.mozilla.org/projects/ash",
-        "branch": "default",
-        "dest": "build"
-    },{
-        "repo": "https://hg.mozilla.org/build/tools",
-        "branch": "default",
-        "dest": "tools"
-    }],
     "vcs_share_base": "/builds/hg-shared",
     "hg_l10n_base": "https://hg.mozilla.org/l10n-central",
     "hg_l10n_tag": "default",
     "l10n_dir": "l10n-central",
     "mozilla_dir": "build"
 }
--- a/testing/mozharness/configs/multi_locale/jamun_android-armv6.json
+++ b/testing/mozharness/configs/multi_locale/jamun_android-armv6.json
@@ -1,23 +1,14 @@
 {
     "work_dir": ".",
     "log_name": "multilocale",
     "objdir": "obj-firefox",
     "locales_file": "build/mobile/locales/l10n-changesets.json",
     "locales_dir": "mobile/android/locales",
     "ignore_locales": ["en-US", "multi"],
-    "repos": [{
-        "repo": "https://hg.mozilla.org/jamun",
-        "branch": "default",
-        "dest": "build"
-    },{
-        "repo": "https://hg.mozilla.org/build/tools",
-        "branch": "default",
-        "dest": "tools"
-    }],
     "vcs_share_base": "/builds/hg-shared",
     "hg_l10n_base": "https://hg.mozilla.org/l10n-central",
     "hg_l10n_tag": "default",
     "l10n_dir": "l10n-central",
     "mozilla_dir": "build",
     "mozconfig": "build/mobile/android/config/mozconfigs/android-armv6/nightly"
 }
--- a/testing/mozharness/configs/multi_locale/jamun_android-x86.json
+++ b/testing/mozharness/configs/multi_locale/jamun_android-x86.json
@@ -1,23 +1,14 @@
 {
     "work_dir": ".",
     "log_name": "multilocale",
     "objdir": "obj-firefox",
     "locales_file": "build/mobile/locales/l10n-changesets.json",
     "locales_dir": "mobile/android/locales",
     "ignore_locales": ["en-US", "multi"],
-    "repos": [{
-        "repo": "https://hg.mozilla.org/jamun",
-        "branch": "default",
-        "dest": "build"
-    },{
-        "repo": "https://hg.mozilla.org/build/tools",
-        "branch": "default",
-        "dest": "tools"
-    }],
     "vcs_share_base": "/builds/hg-shared",
     "hg_l10n_base": "https://hg.mozilla.org/l10n-central",
     "hg_l10n_tag": "default",
     "l10n_dir": "l10n-central",
     "mozilla_dir": "build",
     "mozconfig": "build/mobile/android/config/mozconfigs/android-x86/nightly"
 }
--- a/testing/mozharness/configs/multi_locale/jamun_android.json
+++ b/testing/mozharness/configs/multi_locale/jamun_android.json
@@ -1,22 +1,13 @@
 {
     "work_dir": ".",
     "log_name": "multilocale",
     "objdir": "obj-firefox",
     "locales_file": "build/mobile/locales/l10n-changesets.json",
     "locales_dir": "mobile/android/locales",
     "ignore_locales": ["en-US", "multi"],
-    "repos": [{
-        "repo": "https://hg.mozilla.org/jamun",
-        "branch": "default",
-        "dest": "build"
-    },{
-        "repo": "https://hg.mozilla.org/build/tools",
-        "branch": "default",
-        "dest": "tools"
-    }],
     "vcs_share_base": "/builds/hg-shared",
     "hg_l10n_base": "https://hg.mozilla.org/l10n-central",
     "hg_l10n_tag": "default",
     "l10n_dir": "l10n-central",
     "mozilla_dir": "build"
 }
--- a/testing/mozharness/configs/multi_locale/mozilla-aurora_android-armv6.json
+++ b/testing/mozharness/configs/multi_locale/mozilla-aurora_android-armv6.json
@@ -1,24 +1,15 @@
 {
     "work_dir": ".",
     "log_name": "multilocale",
     "objdir": "obj-firefox",
     "locales_file": "build/mobile/locales/l10n-changesets.json",
     "locales_platform": "android-multilocale",
     "locales_dir": "mobile/android/locales",
     "ignore_locales": ["en-US", "multi"],
-    "repos": [{
-        "repo": "https://hg.mozilla.org/releases/mozilla-aurora",
-        "branch": "default",
-        "dest": "build"
-    },{
-        "repo": "https://hg.mozilla.org/build/tools",
-        "branch": "default",
-        "dest": "tools"
-    }],
     "vcs_share_base": "/builds/hg-shared",
     "hg_l10n_base": "https://hg.mozilla.org/releases/l10n/mozilla-aurora",
     "hg_l10n_tag": "default",
     "l10n_dir": "mozilla-aurora",
     "mozilla_dir": "build",
     "mozconfig": "build/mobile/android/config/mozconfigs/android-armv6/nightly"
 }
--- a/testing/mozharness/configs/multi_locale/mozilla-aurora_android-x86.json
+++ b/testing/mozharness/configs/multi_locale/mozilla-aurora_android-x86.json
@@ -1,24 +1,15 @@
 {
     "work_dir": ".",
     "log_name": "multilocale",
     "objdir": "obj-firefox",
     "locales_file": "build/mobile/locales/l10n-changesets.json",
     "locales_platform": "android-multilocale",
     "locales_dir": "mobile/android/locales",
     "ignore_locales": ["en-US", "multi"],
-    "repos": [{
-        "repo": "https://hg.mozilla.org/releases/mozilla-aurora",
-        "branch": "default",
-        "dest": "build"
-    },{
-        "repo": "https://hg.mozilla.org/build/tools",
-        "branch": "default",
-        "dest": "tools"
-    }],
     "vcs_share_base": "/builds/hg-shared",
     "hg_l10n_base": "https://hg.mozilla.org/releases/l10n/mozilla-aurora",
     "hg_l10n_tag": "default",
     "l10n_dir": "mozilla-aurora",
     "mozilla_dir": "build",
     "mozconfig": "build/mobile/android/config/mozconfigs/android-x86/nightly"
 }
--- a/testing/mozharness/configs/multi_locale/mozilla-aurora_android.json
+++ b/testing/mozharness/configs/multi_locale/mozilla-aurora_android.json
@@ -1,23 +1,14 @@
 {
     "work_dir": ".",
     "log_name": "multilocale",
     "objdir": "obj-firefox",
     "locales_file": "build/mobile/locales/l10n-changesets.json",
     "locales_platform": "android-multilocale",
     "locales_dir": "mobile/android/locales",
     "ignore_locales": ["en-US", "multi"],
-    "repos": [{
-        "repo": "https://hg.mozilla.org/releases/mozilla-aurora",
-        "branch": "default",
-        "dest": "build"
-    },{
-        "repo": "https://hg.mozilla.org/build/tools",
-        "branch": "default",
-        "dest": "tools"
-    }],
     "vcs_share_base": "/builds/hg-shared",
     "hg_l10n_base": "https://hg.mozilla.org/releases/l10n/mozilla-aurora",
     "hg_l10n_tag": "default",
     "l10n_dir": "mozilla-aurora",
     "mozilla_dir": "build"
 }
--- a/testing/mozharness/configs/multi_locale/mozilla-beta_android-armv6.json
+++ b/testing/mozharness/configs/multi_locale/mozilla-beta_android-armv6.json
@@ -1,24 +1,15 @@
 {
     "work_dir": ".",
     "log_name": "multilocale",
     "objdir": "obj-firefox",
     "locales_file": "build/mobile/locales/l10n-changesets.json",
     "locales_platform": "android-multilocale",
     "locales_dir": "mobile/android/locales",
     "ignore_locales": ["en-US", "multi"],
-    "repos": [{
-        "repo": "https://hg.mozilla.org/releases/mozilla-beta",
-        "branch": "default",
-        "dest": "build"
-    },{
-        "repo": "https://hg.mozilla.org/build/tools",
-        "branch": "default",
-        "dest": "tools"
-    }],
     "vcs_share_base": "/builds/hg-shared",
     "hg_l10n_base": "https://hg.mozilla.org/l10n-central",
     "hg_l10n_tag": "default",
     "l10n_dir": "l10n-central",
     "mozilla_dir": "build",
     "mozconfig": "build/mobile/android/config/mozconfigs/android-armv6/nightly"
 }
--- a/testing/mozharness/configs/multi_locale/mozilla-beta_android-x86.json
+++ b/testing/mozharness/configs/multi_locale/mozilla-beta_android-x86.json
@@ -1,24 +1,15 @@
 {
     "work_dir": ".",
     "log_name": "multilocale",
     "objdir": "obj-firefox",
     "locales_file": "build/mobile/locales/l10n-changesets.json",
     "locales_platform": "android-multilocale",
     "locales_dir": "mobile/android/locales",
     "ignore_locales": ["en-US", "multi"],
-    "repos": [{
-        "repo": "https://hg.mozilla.org/releases/mozilla-beta",
-        "branch": "default",
-        "dest": "build"
-    },{
-        "repo": "https://hg.mozilla.org/build/tools",
-        "branch": "default",
-        "dest": "tools"
-    }],
     "vcs_share_base": "/builds/hg-shared",
     "hg_l10n_base": "https://hg.mozilla.org/l10n-central",
     "hg_l10n_tag": "default",
     "l10n_dir": "l10n-central",
     "mozilla_dir": "build",
     "mozconfig": "build/mobile/android/config/mozconfigs/android-x86/nightly"
 }
--- a/testing/mozharness/configs/multi_locale/mozilla-beta_android.json
+++ b/testing/mozharness/configs/multi_locale/mozilla-beta_android.json
@@ -1,23 +1,14 @@
 {
     "work_dir": ".",
     "log_name": "multilocale",
     "objdir": "obj-firefox",
     "locales_file": "build/mobile/locales/l10n-changesets.json",
     "locales_platform": "android-multilocale",
     "locales_dir": "mobile/android/locales",
     "ignore_locales": ["en-US", "multi"],
-    "repos": [{
-        "repo": "https://hg.mozilla.org/releases/mozilla-beta",
-        "branch": "default",
-        "dest": "build"
-    },{
-        "repo": "https://hg.mozilla.org/build/tools",
-        "branch": "default",
-        "dest": "tools"
-    }],
     "vcs_share_base": "/builds/hg-shared",
     "hg_l10n_base": "https://hg.mozilla.org/l10n-central",
     "hg_l10n_tag": "default",
     "l10n_dir": "l10n-central",
     "mozilla_dir": "build"
 }
--- a/testing/mozharness/configs/multi_locale/mozilla-central_android-armv6.json
+++ b/testing/mozharness/configs/multi_locale/mozilla-central_android-armv6.json
@@ -1,24 +1,15 @@
 {
     "work_dir": ".",
     "log_name": "multilocale",
     "objdir": "obj-firefox",
     "locales_file": "build/mobile/locales/l10n-changesets.json",
     "locales_platform": "android-multilocale",
     "locales_dir": "mobile/android/locales",
     "ignore_locales": ["en-US", "multi"],
-    "repos": [{
-        "repo": "https://hg.mozilla.org/mozilla-central",
-        "branch": "default",
-        "dest": "build"
-    },{
-        "repo": "https://hg.mozilla.org/build/tools",
-        "branch": "default",
-        "dest": "tools"
-    }],
     "vcs_share_base": "/builds/hg-shared",
     "hg_l10n_base": "https://hg.mozilla.org/l10n-central",
     "hg_l10n_tag": "default",
     "l10n_dir": "l10n-central",
     "mozilla_dir": "build",
     "mozconfig": "build/mobile/android/config/mozconfigs/android-armv6/nightly"
 }
--- a/testing/mozharness/configs/multi_locale/mozilla-central_android-x86.json
+++ b/testing/mozharness/configs/multi_locale/mozilla-central_android-x86.json
@@ -1,24 +1,15 @@
 {
     "work_dir": ".",
     "log_name": "multilocale",
     "objdir": "obj-firefox",
     "locales_file": "build/mobile/locales/l10n-changesets.json",
     "locales_platform": "android-multilocale",
     "locales_dir": "mobile/android/locales",
     "ignore_locales": ["en-US", "multi"],
-    "repos": [{
-        "repo": "https://hg.mozilla.org/mozilla-central",
-        "branch": "default",
-        "dest": "build"
-    },{
-        "repo": "https://hg.mozilla.org/build/tools",
-        "branch": "default",
-        "dest": "tools"
-    }],
     "vcs_share_base": "/builds/hg-shared",
     "hg_l10n_base": "https://hg.mozilla.org/l10n-central",
     "hg_l10n_tag": "default",
     "l10n_dir": "l10n-central",
     "mozilla_dir": "build",
     "mozconfig": "build/mobile/android/config/mozconfigs/android-x86/nightly"
 }
--- a/testing/mozharness/configs/multi_locale/mozilla-central_android.json
+++ b/testing/mozharness/configs/multi_locale/mozilla-central_android.json
@@ -1,23 +1,14 @@
 {
     "work_dir": ".",
     "log_name": "multilocale",
     "objdir": "obj-firefox",
     "locales_file": "build/mobile/locales/l10n-changesets.json",
     "locales_platform": "android-multilocale",
     "locales_dir": "mobile/android/locales",
     "ignore_locales": ["en-US", "multi"],
-    "repos": [{
-        "repo": "https://hg.mozilla.org/mozilla-central",
-        "branch": "default",
-        "dest": "build"
-    },{
-        "repo": "https://hg.mozilla.org/build/tools",
-        "branch": "default",
-        "dest": "tools"
-    }],
     "vcs_share_base": "/builds/hg-shared",
     "hg_l10n_base": "https://hg.mozilla.org/l10n-central",
     "hg_l10n_tag": "default",
     "l10n_dir": "l10n-central",
     "mozilla_dir": "build"
 }
--- a/testing/mozharness/configs/multi_locale/mozilla-release_android-armv6.json
+++ b/testing/mozharness/configs/multi_locale/mozilla-release_android-armv6.json
@@ -1,24 +1,15 @@
 {
     "work_dir": ".",
     "log_name": "multilocale",
     "objdir": "obj-firefox",
     "locales_file": "build/mobile/locales/l10n-changesets.json",
     "locales_platform": "android-multilocale",
     "locales_dir": "mobile/android/locales",
     "ignore_locales": ["en-US", "multi"],
-    "repos": [{
-        "repo": "https://hg.mozilla.org/releases/mozilla-release",
-        "branch": "default",
-        "dest": "build"
-    },{
-        "repo": "https://hg.mozilla.org/build/tools",
-        "branch": "default",
-        "dest": "tools"
-    }],
     "vcs_share_base": "/builds/hg-shared",
     "hg_l10n_base": "https://hg.mozilla.org/l10n-central",
     "hg_l10n_tag": "default",
     "l10n_dir": "l10n-central",
     "mozilla_dir": "build",
     "mozconfig": "build/mobile/android/config/mozconfigs/android-armv6/nightly"
 }
--- a/testing/mozharness/configs/multi_locale/mozilla-release_android-x86.json
+++ b/testing/mozharness/configs/multi_locale/mozilla-release_android-x86.json
@@ -1,24 +1,15 @@
 {
     "work_dir": ".",
     "log_name": "multilocale",
     "objdir": "obj-firefox",
     "locales_file": "build/mobile/locales/l10n-changesets.json",
     "locales_platform": "android-multilocale",
     "locales_dir": "mobile/android/locales",
     "ignore_locales": ["en-US", "multi"],
-    "repos": [{
-        "repo": "https://hg.mozilla.org/releases/mozilla-release",
-        "branch": "default",
-        "dest": "build"
-    },{
-        "repo": "https://hg.mozilla.org/build/tools",
-        "branch": "default",
-        "dest": "tools"
-    }],
     "vcs_share_base": "/builds/hg-shared",
     "hg_l10n_base": "https://hg.mozilla.org/l10n-central",
     "hg_l10n_tag": "default",
     "l10n_dir": "l10n-central",
     "mozilla_dir": "build",
     "mozconfig": "build/mobile/android/config/mozconfigs/android-x86/nightly"
 }
--- a/testing/mozharness/configs/multi_locale/mozilla-release_android.json
+++ b/testing/mozharness/configs/multi_locale/mozilla-release_android.json
@@ -1,23 +1,14 @@
 {
     "work_dir": ".",
     "log_name": "multilocale",
     "objdir": "obj-firefox",
     "locales_file": "build/mobile/locales/l10n-changesets.json",
     "locales_platform": "android-multilocale",
     "locales_dir": "mobile/android/locales",
     "ignore_locales": ["en-US", "multi"],
-    "repos": [{
-        "repo": "https://hg.mozilla.org/releases/mozilla-release",
-        "branch": "default",
-        "dest": "build"
-    },{
-        "repo": "https://hg.mozilla.org/build/tools",
-        "branch": "default",
-        "dest": "tools"
-    }],
     "vcs_share_base": "/builds/hg-shared",
     "hg_l10n_base": "https://hg.mozilla.org/l10n-central",
     "hg_l10n_tag": "default",
     "l10n_dir": "l10n-central",
     "mozilla_dir": "build"
 }
--- a/testing/mozharness/configs/multi_locale/release_mozilla-beta_android-armv6.json
+++ b/testing/mozharness/configs/multi_locale/release_mozilla-beta_android-armv6.json
@@ -1,24 +1,15 @@
 {
     "work_dir": ".",
     "log_name": "multilocale",
     "objdir": "obj-firefox",
     "locales_file": "build/configs/mozilla/l10n-changesets_mobile-beta.json",
     "locales_platform": "android-multilocale",
     "locales_dir": "mobile/android/locales",
     "ignore_locales": ["en-US", "multi"],
-    "repos": [{
-        "repo": "https://hg.mozilla.org/releases/mozilla-beta",
-        "branch": "default",
-        "dest": "build"
-    },{
-        "repo": "https://hg.mozilla.org/build/tools",
-        "branch": "default",
-        "dest": "tools"
-    }],
     "vcs_share_base": "/builds/hg-shared",
     "hg_l10n_base": "https://hg.mozilla.org/l10n-central",
     "required_config_vars": ["tag_override"],
     "l10n_dir": "l10n-central",
     "mozilla_dir": "build",
     "mozconfig": "build/mobile/android/config/mozconfigs/android-armv6/release"
 }
--- a/testing/mozharness/configs/multi_locale/release_mozilla-beta_android-x86.json
+++ b/testing/mozharness/configs/multi_locale/release_mozilla-beta_android-x86.json
@@ -1,24 +1,15 @@
 {
     "work_dir": ".",
     "log_name": "multilocale",
     "objdir": "obj-firefox",
     "locales_file": "build/configs/mozilla/l10n-changesets_mobile-beta.json",
     "locales_platform": "android-multilocale",
     "locales_dir": "mobile/android/locales",
     "ignore_locales": ["en-US", "multi"],
-    "repos": [{
-        "repo": "https://hg.mozilla.org/releases/mozilla-beta",
-        "branch": "default",
-        "dest": "build"
-    },{
-        "repo": "https://hg.mozilla.org/build/tools",
-        "branch": "default",
-        "dest": "tools"
-    }],
     "vcs_share_base": "/builds/hg-shared",
     "hg_l10n_base": "https://hg.mozilla.org/l10n-central",
     "required_config_vars": ["tag_override"],
     "l10n_dir": "l10n-central",
     "mozilla_dir": "build",
     "mozconfig": "build/mobile/android/config/mozconfigs/android-x86/release"
 }
--- a/testing/mozharness/configs/multi_locale/release_mozilla-beta_android.json
+++ b/testing/mozharness/configs/multi_locale/release_mozilla-beta_android.json
@@ -1,23 +1,14 @@
 {
     "work_dir": ".",
     "log_name": "multilocale",
     "objdir": "obj-firefox",
     "locales_file": "build/configs/mozilla/l10n-changesets_mobile-beta.json",
     "locales_platform": "android-multilocale",
     "locales_dir": "mobile/android/locales",
     "ignore_locales": ["en-US", "multi"],
-    "repos": [{
-        "repo": "https://hg.mozilla.org/releases/mozilla-beta",
-        "branch": "default",
-        "dest": "build"
-    },{
-        "repo": "https://hg.mozilla.org/build/tools",
-        "branch": "default",
-        "dest": "tools"
-    }],
     "vcs_share_base": "/builds/hg-shared",
     "hg_l10n_base": "https://hg.mozilla.org/l10n-central",
     "required_config_vars": ["tag_override"],
     "l10n_dir": "l10n-central",
     "mozilla_dir": "build"
 }
--- a/testing/mozharness/configs/multi_locale/release_mozilla-release_android-armv6.json
+++ b/testing/mozharness/configs/multi_locale/release_mozilla-release_android-armv6.json
@@ -1,24 +1,15 @@
 {
     "work_dir": ".",
     "log_name": "multilocale",
     "objdir": "obj-firefox",
     "locales_file": "build/configs/mozilla/l10n-changesets_mobile-release.json",
     "locales_platform": "android-multilocale",
     "locales_dir": "mobile/android/locales",
     "ignore_locales": ["en-US", "multi"],
-    "repos": [{
-        "repo": "https://hg.mozilla.org/releases/mozilla-release",
-        "branch": "default",
-        "dest": "build"
-    },{
-        "repo": "https://hg.mozilla.org/build/tools",
-        "branch": "default",
-        "dest": "tools"
-    }],
     "vcs_share_base": "/builds/hg-shared",
     "hg_l10n_base": "https://hg.mozilla.org/l10n-central",
     "required_config_vars": ["tag_override"],
     "l10n_dir": "l10n-central",
     "mozilla_dir": "build",
     "mozconfig": "build/mobile/android/config/mozconfigs/android-armv6/release"
 }
--- a/testing/mozharness/configs/multi_locale/release_mozilla-release_android-x86.json
+++ b/testing/mozharness/configs/multi_locale/release_mozilla-release_android-x86.json
@@ -1,24 +1,15 @@
 {
     "work_dir": ".",
     "log_name": "multilocale",
     "objdir": "obj-firefox",
     "locales_file": "build/configs/mozilla/l10n-changesets_mobile-release.json",
     "locales_platform": "android-multilocale",
     "locales_dir": "mobile/android/locales",
     "ignore_locales": ["en-US", "multi"],
-    "repos": [{
-        "repo": "https://hg.mozilla.org/releases/mozilla-release",
-        "branch": "default",
-        "dest": "build"
-    },{
-        "repo": "https://hg.mozilla.org/build/tools",
-        "branch": "default",
-        "dest": "tools"
-    }],
     "vcs_share_base": "/builds/hg-shared",
     "hg_l10n_base": "https://hg.mozilla.org/l10n-central",
     "required_config_vars": ["tag_override"],
     "l10n_dir": "l10n-central",
     "mozilla_dir": "build",
     "mozconfig": "build/mobile/android/config/mozconfigs/android-x86/release"
 }
--- a/testing/mozharness/configs/multi_locale/release_mozilla-release_android.json
+++ b/testing/mozharness/configs/multi_locale/release_mozilla-release_android.json
@@ -1,23 +1,14 @@
 {
     "work_dir": ".",
     "log_name": "multilocale",
     "objdir": "obj-firefox",
     "locales_file": "build/configs/mozilla/l10n-changesets_mobile-release.json",
     "locales_platform": "android-multilocale",
     "locales_dir": "mobile/android/locales",
     "ignore_locales": ["en-US", "multi"],
-    "repos": [{
-        "repo": "https://hg.mozilla.org/releases/mozilla-release",
-        "branch": "default",
-        "dest": "build"
-    },{
-        "repo": "https://hg.mozilla.org/build/tools",
-        "branch": "default",
-        "dest": "tools"
-    }],
     "vcs_share_base": "/builds/hg-shared",
     "hg_l10n_base": "https://hg.mozilla.org/l10n-central",
     "required_config_vars": ["tag_override"],
     "l10n_dir": "l10n-central",
     "mozilla_dir": "build"
 }
--- a/testing/mozharness/configs/multi_locale/staging_release_mozilla-beta_android-armv6.json
+++ b/testing/mozharness/configs/multi_locale/staging_release_mozilla-beta_android-armv6.json
@@ -1,24 +1,15 @@
 {
     "work_dir": ".",
     "log_name": "multilocale",
     "objdir": "obj-firefox",
     "locales_file": "build/configs/mozilla/l10n-changesets_mobile-beta.json",
     "locales_platform": "android-multilocale",
     "locales_dir": "mobile/android/locales",
     "ignore_locales": ["en-US", "multi"],
-    "repos": [{
-        "repo": "https://hg.mozilla.org/%(user_repo_override)s/mozilla-beta",
-        "branch": "default",
-        "dest": "build"
-    },{
-        "repo": "https://hg.mozilla.org/%(user_repo_override)s/tools",
-        "branch": "default",
-        "dest": "tools"
-    }],
     "vcs_share_base": "/builds/hg-shared",
-    "hg_l10n_base": "https://hg.mozilla.org/%(user_repo_override)s",
-    "required_config_vars": ["tag_override", "user_repo_override"],
+    "hg_l10n_base": "https://hg.mozilla.org/",
+    "required_config_vars": ["tag_override"],
     "l10n_dir": "mozilla-beta",
     "mozilla_dir": "build",
     "mozconfig": "build/mobile/android/config/mozconfigs/android-armv6/release"
 }
--- a/testing/mozharness/configs/multi_locale/staging_release_mozilla-beta_android-x86.json
+++ b/testing/mozharness/configs/multi_locale/staging_release_mozilla-beta_android-x86.json
@@ -1,24 +1,15 @@
 {
     "work_dir": ".",
     "log_name": "multilocale",
     "objdir": "obj-firefox",
     "locales_file": "build/configs/mozilla/l10n-changesets_mobile-beta.json",
     "locales_platform": "android-multilocale",
     "locales_dir": "mobile/android/locales",
     "ignore_locales": ["en-US", "multi"],
-    "repos": [{
-        "repo": "https://hg.mozilla.org/%(user_repo_override)s/mozilla-beta",
-        "branch": "default",
-        "dest": "build"
-    },{
-        "repo": "https://hg.mozilla.org/%(user_repo_override)s/tools",
-        "branch": "default",
-        "dest": "tools"
-    }],
     "vcs_share_base": "/builds/hg-shared",
-    "hg_l10n_base": "https://hg.mozilla.org/%(user_repo_override)s",
-    "required_config_vars": ["tag_override", "user_repo_override"],
+    "hg_l10n_base": "https://hg.mozilla.org/",
+    "required_config_vars": ["tag_override"],
     "l10n_dir": "mozilla-beta",
     "mozilla_dir": "build",
     "mozconfig": "build/mobile/android/config/mozconfigs/android-x86/release"
 }
--- a/testing/mozharness/configs/multi_locale/staging_release_mozilla-beta_android.json
+++ b/testing/mozharness/configs/multi_locale/staging_release_mozilla-beta_android.json
@@ -1,23 +1,14 @@
 {
     "work_dir": ".",
     "log_name": "multilocale",
     "objdir": "obj-firefox",
     "locales_file": "build/configs/mozilla/l10n-changesets_mobile-beta.json",
     "locales_platform": "android-multilocale",
     "locales_dir": "mobile/android/locales",
     "ignore_locales": ["en-US", "multi"],
-    "repos": [{
-        "repo": "https://hg.mozilla.org/%(user_repo_override)s/mozilla-beta",
-        "branch": "default",
-        "dest": "build"
-    },{
-        "repo": "https://hg.mozilla.org/%(user_repo_override)s/tools",
-        "branch": "default",
-        "dest": "tools"
-    }],
     "vcs_share_base": "/builds/hg-shared",
-    "hg_l10n_base": "https://hg.mozilla.org/%(user_repo_override)s",
-    "required_config_vars": ["tag_override", "user_repo_override"],
+    "hg_l10n_base": "https://hg.mozilla.org/",
+    "required_config_vars": ["tag_override"],
     "l10n_dir": "mozilla-beta",
     "mozilla_dir": "build"
 }
--- a/testing/mozharness/configs/multi_locale/staging_release_mozilla-release_android-armv6.json
+++ b/testing/mozharness/configs/multi_locale/staging_release_mozilla-release_android-armv6.json
@@ -1,24 +1,15 @@
 {
     "work_dir": ".",
     "log_name": "multilocale",
     "objdir": "obj-firefox",
     "locales_file": "build/configs/mozilla/l10n-changesets_mobile-release.json",
     "locales_platform": "android-multilocale",
     "locales_dir": "mobile/android/locales",
     "ignore_locales": ["en-US", "multi"],
-    "repos": [{
-        "repo": "https://hg.mozilla.org/%(user_repo_override)s/mozilla-release",
-        "branch": "default",
-        "dest": "build"
-    },{
-        "repo": "https://hg.mozilla.org/%(user_repo_override)s/tools",
-        "branch": "default",
-        "dest": "tools"
-    }],
     "vcs_share_base": "/builds/hg-shared",
-    "hg_l10n_base": "https://hg.mozilla.org/%(user_repo_override)s",
-    "required_config_vars": ["tag_override", "user_repo_override"],
+    "hg_l10n_base": "https://hg.mozilla.org/",
+    "required_config_vars": ["tag_override"],
     "l10n_dir": "mozilla-release",
     "mozilla_dir": "build",
     "mozconfig": "build/mobile/android/config/mozconfigs/android-armv6/release"
 }
--- a/testing/mozharness/configs/multi_locale/staging_release_mozilla-release_android-x86.json
+++ b/testing/mozharness/configs/multi_locale/staging_release_mozilla-release_android-x86.json
@@ -1,24 +1,15 @@
 {
     "work_dir": ".",
     "log_name": "multilocale",
     "objdir": "obj-firefox",
     "locales_file": "build/configs/mozilla/l10n-changesets_mobile-release.json",
     "locales_platform": "android-multilocale",
     "locales_dir": "mobile/android/locales",
     "ignore_locales": ["en-US", "multi"],
-    "repos": [{
-        "repo": "https://hg.mozilla.org/%(user_repo_override)s/mozilla-release",
-        "branch": "default",
-        "dest": "build"
-    },{
-        "repo": "https://hg.mozilla.org/%(user_repo_override)s/tools",
-        "branch": "default",
-        "dest": "tools"
-    }],
     "vcs_share_base": "/builds/hg-shared",
-    "hg_l10n_base": "https://hg.mozilla.org/%(user_repo_override)s",
-    "required_config_vars": ["tag_override", "user_repo_override"],
+    "hg_l10n_base": "https://hg.mozilla.org/",
+    "required_config_vars": ["tag_override"],
     "l10n_dir": "mozilla-release",
     "mozilla_dir": "build",
     "mozconfig": "build/mobile/android/config/mozconfigs/android-x86/release"
 }
--- a/testing/mozharness/configs/multi_locale/staging_release_mozilla-release_android.json
+++ b/testing/mozharness/configs/multi_locale/staging_release_mozilla-release_android.json
@@ -1,23 +1,14 @@
 {
     "work_dir": ".",
     "log_name": "multilocale",
     "objdir": "obj-firefox",
     "locales_file": "build/configs/mozilla/l10n-changesets_mobile-release.json",
     "locales_platform": "android-multilocale",
     "locales_dir": "mobile/android/locales",
     "ignore_locales": ["en-US", "multi"],
-    "repos": [{
-        "repo": "https://hg.mozilla.org/%(user_repo_override)s/mozilla-release",
-        "branch": "default",
-        "dest": "build"
-    },{
-        "repo": "https://hg.mozilla.org/%(user_repo_override)s/tools",
-        "branch": "default",
-        "dest": "tools"
-    }],
     "vcs_share_base": "/builds/hg-shared",
-    "hg_l10n_base": "https://hg.mozilla.org/%(user_repo_override)s",
-    "required_config_vars": ["tag_override", "user_repo_override"],
+    "hg_l10n_base": "https://hg.mozilla.org/",
+    "required_config_vars": ["tag_override"],
     "l10n_dir": "mozilla-release",
     "mozilla_dir": "build"
 }
--- a/testing/mozharness/configs/multi_locale/standalone_mozilla-central.py
+++ b/testing/mozharness/configs/multi_locale/standalone_mozilla-central.py
@@ -1,15 +1,12 @@
 
 import os
 # The name of the directory we'll pull our source into.
 BUILD_DIR = "mozilla-central"
-# This is everything that comes after https://hg.mozilla.org/
-# e.g. "releases/mozilla-aurora"
-REPO_PATH = "mozilla-central"
 # This is where the l10n repos are (everything after https://hg.mozilla.org/)
 # for mozilla-central, that's "l10n-central".
 # For mozilla-aurora, that's "releases/l10n/mozilla-aurora"
 L10N_REPO_PATH = "l10n-central"
 # Currently this is assumed to be a subdirectory of your build dir
 OBJDIR = "objdir-droid"
 # Absolute path to your mozconfig.
 # By default it looks at "./mozconfig"
@@ -18,21 +15,16 @@ MOZCONFIG = os.path.join(os.getcwd(), "m
 config = {
     "work_dir": ".",
     "log_name": "multilocale",
     "objdir": OBJDIR,
     "locales_file": "%s/mobile/locales/l10n-changesets.json" % BUILD_DIR,
     "locales_platform": "android-multilocale",
     "locales_dir": "mobile/android/locales",
     "ignore_locales": ["en-US", "multi"],
-    "repos": [{
-        "repo": "https://hg.mozilla.org/%s" % REPO_PATH,
-        "branch": "default",
-        "dest": BUILD_DIR,
-    }],
     "vcs_share_base": "/builds/hg-shared",
     "l10n_repos": [],
     "hg_l10n_base": "https://hg.mozilla.org/%s" % L10N_REPO_PATH,
     "hg_l10n_tag": "default",
     "l10n_dir": "l10n",
     "mozilla_dir": BUILD_DIR,
     "mozconfig": MOZCONFIG,
     "default_actions": [
--- a/testing/mozharness/configs/single_locale/alder.py
+++ b/testing/mozharness/configs/single_locale/alder.py
@@ -22,30 +22,14 @@ config = {
     "nightly_build": True,
     "branch": "alder",
     "en_us_binary_url": "http://ftp.mozilla.org/pub/mozilla.org/firefox/nightly/latest-mozilla-central/",
     "update_channel": "nightly",
 
     # l10n
     "hg_l10n_base": "https://hg.mozilla.org/l10n-central",
 
-    # mar
-    "mar_tools_url": os.environ.get(
-        "MAR_TOOLS_URL",
-        # Default to fetching from ftp rather than setting an environ var
-        "https://ftp.mozilla.org/pub/mozilla.org/firefox/nightly/latest-mozilla-central/mar-tools/%(platform)s"
-    ),
+    # mar - passed in environ from taskcluster
+    "mar_tools_url": os.environ["MAR_TOOLS_URL"],
 
-    # repositories
-    "repos": [{
-        "vcs": "hg",
-        "repo": "https://hg.mozilla.org/build/tools",
-        "branch": "default",
-        "dest": "tools",
-    }, {
-        "vcs": "hg",
-        "repo": "https://hg.mozilla.org/mozilla-central",
-        "branch": "default",
-        "dest": "alder",
-    }],
     # purge options
     'is_automation': True,
 }
--- a/testing/mozharness/configs/single_locale/ash.py
+++ b/testing/mozharness/configs/single_locale/ash.py
@@ -22,30 +22,14 @@ config = {
     "nightly_build": True,
     "branch": "ash",
     "en_us_binary_url": "http://ftp.mozilla.org/pub/mozilla.org/firefox/nightly/latest-mozilla-central/",
     "update_channel": "nightly",
 
     # l10n
     "hg_l10n_base": "https://hg.mozilla.org/l10n-central",
 
-    # mar
-    "mar_tools_url": os.environ.get(
-        "MAR_TOOLS_URL",
-        # Default to fetching from ftp rather than setting an environ var
-        "https://ftp.mozilla.org/pub/mozilla.org/firefox/nightly/latest-mozilla-central/mar-tools/%(platform)s"
-    ),
+    # mar - passed in environ from taskcluster
+    "mar_tools_url": os.environ["MAR_TOOLS_URL"],
 
-    # repositories
-    "repos": [{
-        "vcs": "hg",
-        "repo": "https://hg.mozilla.org/build/tools",
-        "branch": "default",
-        "dest": "tools",
-    }, {
-        "vcs": "hg",
-        "repo": "https://hg.mozilla.org/mozilla-central",
-        "branch": "default",
-        "dest": "ash",
-    }],
     # purge options
     'is_automation': True,
 }
--- a/testing/mozharness/configs/single_locale/ash_android-api-16.py
+++ b/testing/mozharness/configs/single_locale/ash_android-api-16.py
@@ -9,41 +9,30 @@ config = {
     "branch": BRANCH,
     "log_name": "single_locale",
     "objdir": OBJDIR,
     "is_automation": True,
     "locales_file": "%s/mobile/locales/l10n-changesets.json" % MOZILLA_DIR,
     "locales_dir": "mobile/android/locales",
     "ignore_locales": ["en-US"],
     "nightly_build": True,
-    "tools_repo": "https://hg.mozilla.org/build/tools",
     "tooltool_config": {
         "manifest": "mobile/android/config/tooltool-manifests/android/releng.manifest",
         "output_dir": "%(abs_work_dir)s/" + MOZILLA_DIR,
     },
-    "repos": [{
-        "repo": "https://hg.mozilla.org/projects/ash",
-        "branch": "default",
-        "dest": MOZILLA_DIR,
-    }, {
-        "repo": "https://hg.mozilla.org/build/tools",
-        "branch": "default",
-        "dest": "tools"
-    }],
     "hg_l10n_base": "https://hg.mozilla.org/l10n-central",
     "hg_l10n_tag": "default",
     'vcs_share_base': HG_SHARE_BASE_DIR,
 
     "l10n_dir": "l10n-central",
     "repack_env": {
         # so ugly, bug 951238
         "LD_LIBRARY_PATH": "/lib:/tools/gcc-4.7.2-0moz1/lib:/tools/gcc-4.7.2-0moz1/lib64",
         "MOZ_OBJDIR": OBJDIR,
         "EN_US_BINARY_URL": EN_US_BINARY_URL,
         "MOZ_UPDATE_CHANNEL": MOZ_UPDATE_CHANNEL,
     },
     "upload_branch": "%s-android-api-16" % BRANCH,
-    "signature_verification_script": "tools/release/signing/verify-android-signature.sh",
     "platform": "android",
 
     # Balrog
     "build_target": "Android_arm-eabi-gcc3",
 }
--- a/testing/mozharness/configs/single_locale/autoland.py
+++ b/testing/mozharness/configs/single_locale/autoland.py
@@ -4,31 +4,14 @@ config = {
     "nightly_build": True,
     "branch": "mozilla-central",
     "en_us_binary_url": "http://archive.mozilla.org/pub/firefox/nightly/latest-mozilla-central",
     "update_channel": "nightly",
 
     # l10n
     "hg_l10n_base": "https://hg.mozilla.org/l10n-central",
 
-    # mar
-    "mar_tools_url": os.environ.get(
-        "MAR_TOOLS_URL",
-        # Default to fetching from ftp rather than setting an environ var
-        "https://ftp.mozilla.org/pub/mozilla.org/firefox/nightly/latest-mozilla-central/mar-tools/%(platform)s"
-    ),
+    # mar - passed in environ from taskcluster
+    "mar_tools_url": os.environ["MAR_TOOLS_URL"],
 
-    # repositories
-    "repos": [{
-        "vcs": "hg",
-        "repo": "https://hg.mozilla.org/build/tools",
-        "branch": "default",
-        "dest": "tools",
-    }, {
-        "vcs": "hg",
-        "repo": "https://hg.mozilla.org/integration/autoland",
-        "revision": "%(revision)s",
-        "dest": "autoland",
-        "clone_upstream_url": "https://hg.mozilla.org/mozilla-unified",
-    }],
     # purge options
     'is_automation': True,
 }
--- a/testing/mozharness/configs/single_locale/autoland_android-api-16.py
+++ b/testing/mozharness/configs/single_locale/autoland_android-api-16.py
@@ -11,43 +11,30 @@ config = {
     "branch": BRANCH,
     "log_name": "single_locale",
     "objdir": OBJDIR,
     "is_automation": True,
     "locales_file": "%s/mobile/locales/l10n-changesets.json" % MOZILLA_DIR,
     "locales_dir": "mobile/android/locales",
     "ignore_locales": ["en-US"],
     "nightly_build": True,
-    "tools_repo": "https://hg.mozilla.org/build/tools",
     "tooltool_config": {
         "manifest": "mobile/android/config/tooltool-manifests/android/releng.manifest",
         "output_dir": "%(abs_work_dir)s/" + MOZILLA_DIR,
     },
-    "repos": [{
-        "vcs": "hg",
-        "repo": "https://hg.mozilla.org/build/tools",
-        "branch": "default",
-        "dest": "tools",
-    }, {
-        "vcs": "hg",
-        "repo": "https://hg.mozilla.org/integration/autoland",
-        "revision": "%(revision)s",
-        "dest": MOZILLA_DIR,
-    }],
     "hg_l10n_base": "https://hg.mozilla.org/l10n-central",
     "hg_l10n_tag": "default",
     'vcs_share_base': HG_SHARE_BASE_DIR,
 
     "l10n_dir": "l10n-central",
     "repack_env": {
         # so ugly, bug 951238
         "LD_LIBRARY_PATH": "/lib:/tools/gcc-4.7.2-0moz1/lib:/tools/gcc-4.7.2-0moz1/lib64",
         "MOZ_OBJDIR": OBJDIR,
         "EN_US_BINARY_URL": os.environ.get("EN_US_BINARY_URL", EN_US_BINARY_URL),
         "MOZ_UPDATE_CHANNEL": MOZ_UPDATE_CHANNEL,
     },
     "upload_branch": "%s-android-api-16" % BRANCH,
-    "signature_verification_script": "tools/release/signing/verify-android-signature.sh",
     "platform": "android",
 
     # Balrog
     "build_target": "Android_arm-eabi-gcc3",
 }
--- a/testing/mozharness/configs/single_locale/dev-mozilla-beta.py
+++ b/testing/mozharness/configs/single_locale/dev-mozilla-beta.py
@@ -1,26 +1,11 @@
 config = {
     "branch": "jamun",
     "nightly_build": True,
     "update_channel": "beta",
 
     # l10n
     "hg_l10n_base": "https://hg.mozilla.org/l10n-central",
 
-    # repositories
-    # staging beta dev releases use jamun repo for now
-    "repos": [{
-        "vcs": "hg",
-        "repo": "https://hg.mozilla.org/build/tools",
-        "branch": "default",
-        "dest": "tools",
-    }, {
-        "vcs": "hg",
-        "repo": "https://hg.mozilla.org/projects/jamun",
-        "branch": "%(revision)s",
-        "dest": "jamun",
-        "clone_upstream_url": "https://hg.mozilla.org/projects/jamun",
-    }],
     # purge options
     'is_automation': True,
-    'purge_minsize': 12,
 }
--- a/testing/mozharness/configs/single_locale/dev-mozilla-release.py
+++ b/testing/mozharness/configs/single_locale/dev-mozilla-release.py
@@ -1,26 +1,11 @@
 config = {
     "branch": "jamun",
     "nightly_build": True,
     "update_channel": "release",
 
     # l10n
     "hg_l10n_base": "https://hg.mozilla.org/l10n-central",
 
-    # repositories
-    # staging release uses jamun
-    "repos": [{
-        "vcs": "hg",
-        "repo": "https://hg.mozilla.org/build/tools",
-        "branch": "default",
-        "dest": "tools",
-    }, {
-        "vcs": "hg",
-        "repo": "https://hg.mozilla.org/projects/jamun",
-        "branch": "%(revision)s",
-        "dest": "jamun",
-        "clone_upstream_url": "https://hg.mozilla.org/mozilla-unified",
-    }],
     # purge options
-    'purge_minsize': 12,
     'is_automation': True,
 }
--- a/testing/mozharness/configs/single_locale/jamun.py
+++ b/testing/mozharness/configs/single_locale/jamun.py
@@ -4,30 +4,14 @@ config = {
     "nightly_build": True,
     "branch": "jamun",
     "en_us_binary_url": "http://archive.mozilla.org/pub/firefox/nightly/latest-mozilla-central",
     "update_channel": "nightly-jamun",
 
     # l10n
     "hg_l10n_base": "https://hg.mozilla.org/l10n-central",
 
-    # mar
-    "mar_tools_url": os.environ.get(
-        "MAR_TOOLS_URL",
-        # Default to fetching from ftp rather than setting an environ var
-        "https://ftp.mozilla.org/pub/mozilla.org/firefox/nightly/latest-mozilla-central/mar-tools/%(platform)s"
-    ),
+    # mar - passed in environ from taskcluster
+    "mar_tools_url": os.environ["MAR_TOOLS_URL"],
 
-    # repositories
-    "repos": [{
-        "vcs": "hg",
-        "repo": "https://hg.mozilla.org/build/tools",
-        "branch": "default",
-        "dest": "tools",
-    }, {
-        "vcs": "hg",
-        "repo": "https://hg.mozilla.org/projects/jamun",
-        "revision": "%(revision)s",
-        "dest": "jamun",
-    }],
     # purge options
     'is_automation': True,
 }
--- a/testing/mozharness/configs/single_locale/jamun_android-api-16.py
+++ b/testing/mozharness/configs/single_locale/jamun_android-api-16.py
@@ -8,43 +8,30 @@ config = {
     "branch": BRANCH,
     "log_name": "single_locale",
     "objdir": "obj-firefox",
     "is_automation": True,
     "locales_file": "%s/mobile/locales/l10n-changesets.json" % MOZILLA_DIR,
     "locales_dir": "mobile/android/locales",
     "ignore_locales": ["en-US"],
     "nightly_build": True,
-    "tools_repo": "https://hg.mozilla.org/build/tools",
     "tooltool_config": {
         "manifest": "mobile/android/config/tooltool-manifests/android/releng.manifest",
         "output_dir": "%(abs_work_dir)s/" + MOZILLA_DIR,
     },
-    "repos": [{
-        "vcs": "hg",
-        "repo": "https://hg.mozilla.org/build/tools",
-        "branch": "default",
-        "dest": "tools",
-    }, {
-        "vcs": "hg",
-        "repo": "https://hg.mozilla.org/projects/jamun",
-        "revision": "%(revision)s",
-        "dest": MOZILLA_DIR,
-    }],
     "hg_l10n_base": "https://hg.mozilla.org/l10n-central",
     "hg_l10n_tag": "default",
     'vcs_share_base': "/builds/hg-shared",
 
     "l10n_dir": "mozilla-beta",
     "repack_env": {
         # so ugly, bug 951238
         "LD_LIBRARY_PATH": "/lib:/tools/gcc-4.7.2-0moz1/lib:/tools/gcc-4.7.2-0moz1/lib64",
         "MOZ_OBJDIR": "obj-firefox",
         "EN_US_BINARY_URL": os.environ.get("EN_US_BINARY_URL", EN_US_BINARY_URL),
         "MOZ_UPDATE_CHANNEL": "nightly-jamun",
     },
     "upload_branch": "%s-android-api-16" % BRANCH,
-    "signature_verification_script": "tools/release/signing/verify-android-signature.sh",
     "platform": "android",
 
     # Balrog
     "build_target": "Android_arm-eabi-gcc3",
 }
--- a/testing/mozharness/configs/single_locale/maple_android-api-16.py
+++ b/testing/mozharness/configs/single_locale/maple_android-api-16.py
@@ -9,43 +9,30 @@ config = {
     "branch": BRANCH,
     "log_name": "single_locale",
     "objdir": "obj-firefox",
     "is_automation": True,
     "locales_file": "%s/mobile/locales/l10n-changesets.json" % MOZILLA_DIR,
     "locales_dir": "mobile/android/locales",
     "ignore_locales": ["en-US"],
     "nightly_build": True,
-    "tools_repo": "https://hg.mozilla.org/build/tools",
     "tooltool_config": {
         "manifest": "mobile/android/config/tooltool-manifests/android/releng.manifest",
         "output_dir": "%(abs_work_dir)s/" + MOZILLA_DIR,
     },
-    "repos": [{
-        "vcs": "hg",
-        "repo": "https://hg.mozilla.org/build/tools",
-        "branch": "default",
-        "dest": "tools",
-    }, {
-        "vcs": "hg",
-        "repo": "https://hg.mozilla.org/projects/maple",
-        "revision": "%(revision)s",
-        "dest": MOZILLA_DIR,
-    }],
     "hg_l10n_base": "https://hg.mozilla.org/l10n-central",
     "hg_l10n_tag": "default",
     'vcs_share_base': "/builds/hg-shared",
 
     "l10n_dir": "l10n-central",
     "repack_env": {
         # so ugly, bug 951238
         "LD_LIBRARY_PATH": "/lib:/tools/gcc-4.7.2-0moz1/lib:/tools/gcc-4.7.2-0moz1/lib64",
         "MOZ_OBJDIR": "obj-firefox",
         "EN_US_BINARY_URL": os.environ.get("EN_US_BINARY_URL", EN_US_BINARY_URL),
         "MOZ_UPDATE_CHANNEL": "nightly-maple",
     },
     "upload_branch": "%s-android-api-16" % BRANCH,
-    "signature_verification_script": "tools/release/signing/verify-android-signature.sh",
     "platform": "android",
 
     # Balrog
     "build_target": "Android_arm-eabi-gcc3",
 }
--- a/testing/mozharness/configs/single_locale/mozilla-aurora.py
+++ b/testing/mozharness/configs/single_locale/mozilla-aurora.py
@@ -4,31 +4,14 @@ config = {
     "nightly_build": True,
     "branch": "mozilla-aurora",
     "en_us_binary_url": "http://ftp.mozilla.org/pub/mozilla.org/firefox/nightly/latest-mozilla-aurora/",
     "update_channel": "aurora",
 
     # l10n
     "hg_l10n_base": "https://hg.mozilla.org/releases/l10n/mozilla-aurora",
 
-    # mar
-    "mar_tools_url": os.environ.get(
-        "MAR_TOOLS_URL",
-        # Default to fetching from ftp rather than setting an environ var
-        "https://ftp.mozilla.org/pub/mozilla.org/firefox/nightly/latest-mozilla-aurora/mar-tools/%(platform)s"
-    ),
+    # mar - passed in environ from taskcluster
+    "mar_tools_url": os.environ["MAR_TOOLS_URL"],
 
-    # repositories
-    "repos": [{
-        "vcs": "hg",
-        "repo": "https://hg.mozilla.org/build/tools",
-        "branch": "default",
-        "dest": "tools",
-    }, {
-        "vcs": "hg",
-        "repo": "https://hg.mozilla.org/releases/mozilla-aurora",
-        "branch": "default",
-        "dest": "mozilla-aurora",
-        "clone_upstream_url": "https://hg.mozilla.org/mozilla-unified",
-    }],
     # purge options
     'is_automation': True,
 }
--- a/testing/mozharness/configs/single_locale/mozilla-aurora_android-api-16.py
+++ b/testing/mozharness/configs/single_locale/mozilla-aurora_android-api-16.py
@@ -11,43 +11,30 @@ config = {
     "branch": BRANCH,
     "log_name": "single_locale",
     "objdir": OBJDIR,
     "is_automation": True,
     "locales_file": "%s/mobile/locales/l10n-changesets.json" % MOZILLA_DIR,
     "locales_dir": "mobile/android/locales",
     "ignore_locales": ["en-US"],
     "nightly_build": True,
-    "tools_repo": "https://hg.mozilla.org/build/tools",
     "tooltool_config": {
         "manifest": "mobile/android/config/tooltool-manifests/android/releng.manifest",
         "output_dir": "%(abs_work_dir)s/" + MOZILLA_DIR,
     },
-    "repos": [{
-        "vcs": "hg",
-        "repo": "https://hg.mozilla.org/build/tools",
-        "branch": "default",
-        "dest": "tools",
-    }, {
-        "vcs": "hg",
-        "repo": "https://hg.mozilla.org/releases/mozilla-aurora",
-        "revision": "%(revision)s",
-        "dest": MOZILLA_DIR,
-    }],
     "hg_l10n_base": "https://hg.mozilla.org/releases/l10n/%s" % BRANCH,
     "hg_l10n_tag": "default",
     'vcs_share_base': HG_SHARE_BASE_DIR,
 
     "l10n_dir": MOZILLA_DIR,
     "repack_env": {
         # so ugly, bug 951238
         "LD_LIBRARY_PATH": "/lib:/tools/gcc-4.7.2-0moz1/lib:/tools/gcc-4.7.2-0moz1/lib64",
         "MOZ_OBJDIR": OBJDIR,
         "EN_US_BINARY_URL": os.environ.get("EN_US_BINARY_URL", EN_US_BINARY_URL),
         "MOZ_UPDATE_CHANNEL": MOZ_UPDATE_CHANNEL,
     },
     "upload_branch": "%s-android-api-16" % BRANCH,
-    "signature_verification_script": "tools/release/signing/verify-android-signature.sh",
     "platform": "android",
 
     # Balrog
     "build_target": "Android_arm-eabi-gcc3",
 }
--- a/testing/mozharness/configs/single_locale/mozilla-beta.py
+++ b/testing/mozharness/configs/single_locale/mozilla-beta.py
@@ -7,25 +7,11 @@ config = {
     "update_channel": "beta",
 
     # l10n
     "hg_l10n_base": "https://hg.mozilla.org/l10n-central",
 
     # mar
     "mar_tools_url": os.environ["MAR_TOOLS_URL"],
 
-    # repositories
-    "repos": [{
-        "vcs": "hg",
-        "repo": "https://hg.mozilla.org/build/tools",
-        "branch": "default",
-        "dest": "tools",
-    }, {
-        "vcs": "hg",
-        "repo": "https://hg.mozilla.org/releases/mozilla-beta",
-        "revision": "%(revision)s",
-        "dest": "mozilla-beta",
-        "clone_upstream_url": "https://hg.mozilla.org/mozilla-unified",
-    }],
     # purge options
-    'purge_minsize': 12,
     'is_automation': True,
 }
--- a/testing/mozharness/configs/single_locale/mozilla-beta_android-api-16.py
+++ b/testing/mozharness/configs/single_locale/mozilla-beta_android-api-16.py
@@ -10,41 +10,28 @@ config = {
     "branch": BRANCH,
     "log_name": "single_locale",
     "objdir": OBJDIR,
     "is_automation": True,
     "locales_file": "%s/mobile/locales/l10n-changesets.json" % MOZILLA_DIR,
     "locales_dir": "mobile/android/locales",
     "locales_platform": "android-api-16",
     "ignore_locales": ["en-US"],
-    "tools_repo": "https://hg.mozilla.org/build/tools",
     "platform": "android",
-    "is_release_or_beta": True,
     "build_target": "Android_arm-eabi-gcc3",
     "tooltool_config": {
         "manifest": "mobile/android/config/tooltool-manifests/android/releng.manifest",
         "output_dir": "%(abs_work_dir)s/" + MOZILLA_DIR,
     },
-    "repos": [{
-        "repo": "https://hg.mozilla.org/releases/mozilla-beta",
-        "branch": "default",
-        "dest": MOZILLA_DIR,
-    }, {
-        "repo": "https://hg.mozilla.org/build/tools",
-        "branch": "default",
-        "dest": "tools"
-    }],
     "hg_l10n_base": "https://hg.mozilla.org/l10n-central",
     "hg_l10n_tag": "default",
     'vcs_share_base': HG_SHARE_BASE_DIR,
     "l10n_dir": "l10n-central",
 
     "repack_env": {
         # so ugly, bug 951238
         "LD_LIBRARY_PATH": "/lib:/tools/gcc-4.7.2-0moz1/lib:/tools/gcc-4.7.2-0moz1/lib64",
         "EN_US_BINARY_URL": os.environ.get("EN_US_BINARY_URL", EN_US_BINARY_URL),
         "MOZ_OBJDIR": OBJDIR,
         "MOZ_UPDATE_CHANNEL": MOZ_UPDATE_CHANNEL,
     },
     "upload_branch": "%s-android-api-16" % BRANCH,
-    "signature_verification_script": "tools/release/signing/verify-android-signature.sh",
-    "key_alias": "release",
 }
--- a/testing/mozharness/configs/single_locale/mozilla-beta_devedition.py
+++ b/testing/mozharness/configs/single_locale/mozilla-beta_devedition.py
@@ -2,25 +2,11 @@ config = {
     "nightly_build": True,
     "branch": "mozilla-beta",
     "en_us_binary_url": "http://ftp.mozilla.org/pub/mozilla.org/firefox/nightly/latest-mozilla-beta/",
     "update_channel": "aurora",  # devedition uses aurora based branding
 
     # l10n
     "hg_l10n_base": "https://hg.mozilla.org/l10n-central",
 
-    # repositories
-    "repos": [{
-        "vcs": "hg",
-        "repo": "https://hg.mozilla.org/build/tools",
-        "branch": "default",
-        "dest": "tools",
-    }, {
-        "vcs": "hg",
-        "repo": "https://hg.mozilla.org/releases/mozilla-beta",
-        "revision": "%(revision)s",
-        "dest": "mozilla-beta",
-        "clone_upstream_url": "https://hg.mozilla.org/mozilla-unified",
-    }],
     # purge options
-    'purge_minsize': 12,
     'is_automation': True,
 }
--- a/testing/mozharness/configs/single_locale/mozilla-central.py
+++ b/testing/mozharness/configs/single_locale/mozilla-central.py
@@ -4,31 +4,14 @@ config = {
     "nightly_build": True,
     "branch": "mozilla-central",
     "en_us_binary_url": "http://archive.mozilla.org/pub/firefox/nightly/latest-mozilla-central",
     "update_channel": "nightly",
 
     # l10n
     "hg_l10n_base": "https://hg.mozilla.org/l10n-central",
 
-    # mar
-    "mar_tools_url": os.environ.get(
-        "MAR_TOOLS_URL",
-        # Default to fetching from ftp rather than setting an environ var
-        "https://ftp.mozilla.org/pub/mozilla.org/firefox/nightly/latest-mozilla-central/mar-tools/%(platform)s"
-    ),
+    # mar - passed in environ from taskcluster
+    "mar_tools_url": os.environ["MAR_TOOLS_URL"],
 
-    # repositories
-    "repos": [{
-        "vcs": "hg",
-        "repo": "https://hg.mozilla.org/build/tools",
-        "branch": "default",
-        "dest": "tools",
-    }, {
-        "vcs": "hg",
-        "repo": "https://hg.mozilla.org/mozilla-central",
-        "revision": "%(revision)s",
-        "dest": "mozilla-central",
-        "clone_upstream_url": "https://hg.mozilla.org/mozilla-unified",
-    }],
     # purge options
     'is_automation': True,
 }
--- a/testing/mozharness/configs/single_locale/mozilla-central_android-api-16.py
+++ b/testing/mozharness/configs/single_locale/mozilla-central_android-api-16.py
@@ -11,43 +11,30 @@ config = {
     "branch": BRANCH,
     "log_name": "single_locale",
     "objdir": OBJDIR,
     "is_automation": True,
     "locales_file": "%s/mobile/locales/l10n-changesets.json" % MOZILLA_DIR,
     "locales_dir": "mobile/android/locales",
     "ignore_locales": ["en-US"],
     "nightly_build": True,
-    "tools_repo": "https://hg.mozilla.org/build/tools",
     "tooltool_config": {
         "manifest": "mobile/android/config/tooltool-manifests/android/releng.manifest",
         "output_dir": "%(abs_work_dir)s/" + MOZILLA_DIR,
     },
-    "repos": [{
-        "vcs": "hg",
-        "repo": "https://hg.mozilla.org/build/tools",
-        "branch": "default",
-        "dest": "tools",
-    }, {
-        "vcs": "hg",
-        "repo": "https://hg.mozilla.org/mozilla-central",
-        "revision": "%(revision)s",
-        "dest": MOZILLA_DIR,
-    }],
     "hg_l10n_base": "https://hg.mozilla.org/l10n-central",
     "hg_l10n_tag": "default",
     'vcs_share_base': HG_SHARE_BASE_DIR,
 
     "l10n_dir": "l10n-central",
     "repack_env": {
         # so ugly, bug 951238
         "LD_LIBRARY_PATH": "/lib:/tools/gcc-4.7.2-0moz1/lib:/tools/gcc-4.7.2-0moz1/lib64",
         "MOZ_OBJDIR": OBJDIR,
         "EN_US_BINARY_URL": os.environ.get("EN_US_BINARY_URL", EN_US_BINARY_URL),
         "MOZ_UPDATE_CHANNEL": MOZ_UPDATE_CHANNEL,
     },
     "upload_branch": "%s-android-api-16" % BRANCH,
-    "signature_verification_script": "tools/release/signing/verify-android-signature.sh",
     "platform": "android",
 
     # Balrog
     "build_target": "Android_arm-eabi-gcc3",
 }
--- a/testing/mozharness/configs/single_locale/mozilla-esr52.py
+++ b/testing/mozharness/configs/single_locale/mozilla-esr52.py
@@ -7,25 +7,11 @@ config = {
     "nightly_build": True,
     "branch": "mozilla-esr52",
     "en_us_binary_url": "https://archive.mozilla.org/pub/mozilla.org/firefox/nightly/latest-mozilla-esr52/",
     "update_channel": "esr",
 
     # l10n
     "hg_l10n_base": "https://hg.mozilla.org/releases/l10n/mozilla-release",
 
-    # repositories
-    "repos": [{
-        "vcs": "hg",
-        "repo": "https://hg.mozilla.org/build/tools",
-        "branch": "default",
-        "dest": "tools",
-    }, {
-        "vcs": "hg",
-        "repo": "https://hg.mozilla.org/releases/mozilla-esr52",
-        "revision": "%(revision)s",
-        "dest": "mozilla-esr52",
-        "clone_upstream_url": "https://hg.mozilla.org/mozilla-unified",
-    }],
     # purge options
-    'purge_minsize': 12,
     'is_automation': True,
 }
--- a/testing/mozharness/configs/single_locale/mozilla-esr60.py
+++ b/testing/mozharness/configs/single_locale/mozilla-esr60.py
@@ -7,25 +7,11 @@ config = {
     "update_channel": "esr",
 
     # l10n
     "hg_l10n_base": "https://hg.mozilla.org/l10n-central",
 
     # mar
     "mar_tools_url": os.environ["MAR_TOOLS_URL"],
 
-    # repositories
-    "repos": [{
-        "vcs": "hg",
-        "repo": "https://hg.mozilla.org/build/tools",
-        "branch": "default",
-        "dest": "tools",
-    }, {
-        "vcs": "hg",
-        "repo": "https://hg.mozilla.org/releases/mozilla-esr60",
-        "revision": "%(revision)s",
-        "dest": "mozilla-esr60",
-        "clone_upstream_url": "https://hg.mozilla.org/mozilla-unified",
-    }],
     # purge options
-    'purge_minsize': 12,
     'is_automation': True,
 }
--- a/testing/mozharness/configs/single_locale/mozilla-inbound.py
+++ b/testing/mozharness/configs/single_locale/mozilla-inbound.py
@@ -4,31 +4,14 @@ config = {
     "nightly_build": True,
     "branch": "mozilla-inbound",
     "en_us_binary_url": "http://archive.mozilla.org/pub/firefox/nightly/latest-mozilla-central",
     "update_channel": "nightly",
 
     # l10n
     "hg_l10n_base": "https://hg.mozilla.org/l10n-central",
 
-    # mar
-    "mar_tools_url": os.environ.get(
-        "MAR_TOOLS_URL",
-        # Default to fetching from ftp rather than setting an environ var
-        "https://ftp.mozilla.org/pub/mozilla.org/firefox/nightly/latest-mozilla-central/mar-tools/%(platform)s"
-    ),
+    # mar - passed in environ from taskcluster
+    "mar_tools_url": os.environ["MAR_TOOLS_URL"],
 
-    # repositories
-    "repos": [{
-        "vcs": "hg",
-        "repo": "https://hg.mozilla.org/build/tools",
-        "branch": "default",
-        "dest": "tools",
-    }, {
-        "vcs": "hg",
-        "repo": "https://hg.mozilla.org/integration/mozilla-inbound",
-        "revision": "%(revision)s",
-        "dest": "mozilla-inbound",
-        "clone_upstream_url": "https://hg.mozilla.org/mozilla-unified",
-    }],
     # purge options
     'is_automation': True,
 }
--- a/testing/mozharness/configs/single_locale/mozilla-inbound_android-api-16.py
+++ b/testing/mozharness/configs/single_locale/mozilla-inbound_android-api-16.py
@@ -11,43 +11,30 @@ config = {
     "branch": BRANCH,
     "log_name": "single_locale",
     "objdir": OBJDIR,
     "is_automation": True,
     "locales_file": "%s/mobile/locales/l10n-changesets.json" % MOZILLA_DIR,
     "locales_dir": "mobile/android/locales",
     "ignore_locales": ["en-US"],
     "nightly_build": True,
-    "tools_repo": "https://hg.mozilla.org/build/tools",
     "tooltool_config": {
         "manifest": "mobile/android/config/tooltool-manifests/android/releng.manifest",
         "output_dir": "%(abs_work_dir)s/" + MOZILLA_DIR,
     },
-    "repos": [{
-        "vcs": "hg",
-        "repo": "https://hg.mozilla.org/build/tools",
-        "branch": "default",
-        "dest": "tools",
-    }, {
-        "vcs": "hg",
-        "repo": "https://hg.mozilla.org/integration/mozilla-inbound",
-        "revision": "%(revision)s",
-        "dest": MOZILLA_DIR,
-    }],
     "hg_l10n_base": "https://hg.mozilla.org/l10n-central",
     "hg_l10n_tag": "default",
     'vcs_share_base': HG_SHARE_BASE_DIR,
 
     "l10n_dir": "l10n-central",
     "repack_env": {
         # so ugly, bug 951238
         "LD_LIBRARY_PATH": "/lib:/tools/gcc-4.7.2-0moz1/lib:/tools/gcc-4.7.2-0moz1/lib64",
         "MOZ_OBJDIR": OBJDIR,
         "EN_US_BINARY_URL": os.environ.get("EN_US_BINARY_URL", EN_US_BINARY_URL),
         "MOZ_UPDATE_CHANNEL": MOZ_UPDATE_CHANNEL,
     },
     "upload_branch": "%s-android-api-16" % BRANCH,
-    "signature_verification_script": "tools/release/signing/verify-android-signature.sh",
     "platform": "android",
 
     # Balrog
     "build_target": "Android_arm-eabi-gcc3",
 }
--- a/testing/mozharness/configs/single_locale/mozilla-release.py
+++ b/testing/mozharness/configs/single_locale/mozilla-release.py
@@ -7,25 +7,11 @@ config = {
     "update_channel": "release",
 
     # l10n
     "hg_l10n_base": "https://hg.mozilla.org/l10n-central",
 
     # mar
     "mar_tools_url": os.environ["MAR_TOOLS_URL"],
 
-    # repositories
-    "repos": [{
-        "vcs": "hg",
-        "repo": "https://hg.mozilla.org/build/tools",
-        "branch": "default",
-        "dest": "tools",
-    }, {
-        "vcs": "hg",
-        "repo": "https://hg.mozilla.org/releases/mozilla-release",
-        "revision": "%(revision)s",
-        "dest": "mozilla-release",
-        "clone_upstream_url": "https://hg.mozilla.org/mozilla-unified",
-    }],
     # purge options
-    'purge_minsize': 12,
     'is_automation': True,
 }
--- a/testing/mozharness/configs/single_locale/mozilla-release_android-api-16.py
+++ b/testing/mozharness/configs/single_locale/mozilla-release_android-api-16.py
@@ -10,41 +10,28 @@ config = {
     "branch": BRANCH,
     "log_name": "single_locale",
     "objdir": OBJDIR,
     "is_automation": True,
     "locales_file": "%s/mobile/locales/l10n-changesets.json" % MOZILLA_DIR,
     "locales_dir": "mobile/android/locales",
     "locales_platform": "android-api-16",
     "ignore_locales": ["en-US"],
-    "tools_repo": "https://hg.mozilla.org/build/tools",
     "platform": "android",
-    "is_release_or_beta": True,
     "build_target": "Android_arm-eabi-gcc3",
     "tooltool_config": {
         "manifest": "mobile/android/config/tooltool-manifests/android/releng.manifest",
         "output_dir": "%(abs_work_dir)s/" + MOZILLA_DIR,
     },
-    "repos": [{
-        "repo": "https://hg.mozilla.org/releases/mozilla-release",
-        "branch": "default",
-        "dest": MOZILLA_DIR,
-    }, {
-        "repo": "https://hg.mozilla.org/build/tools",
-        "branch": "default",
-        "dest": "tools"
-    }],
     "hg_l10n_base": "https://hg.mozilla.org/l10n-central",
     "hg_l10n_tag": "default",
     'vcs_share_base': HG_SHARE_BASE_DIR,
     "l10n_dir": "l10n-central",
 
     "repack_env": {
         # so ugly, bug 951238
         "LD_LIBRARY_PATH": "/lib:/tools/gcc-4.7.2-0moz1/lib:/tools/gcc-4.7.2-0moz1/lib64",
         "EN_US_BINARY_URL": os.environ.get("EN_US_BINARY_URL", EN_US_BINARY_URL),
         "MOZ_OBJDIR": OBJDIR,
         "MOZ_UPDATE_CHANNEL": MOZ_UPDATE_CHANNEL,
     },
     "upload_branch": "%s-android-api-16" % BRANCH,
-    "signature_verification_script": "tools/release/signing/verify-android-signature.sh",
-    "key_alias": "release",
 }
--- a/testing/mozharness/configs/single_locale/tc_android-api-16.py
+++ b/testing/mozharness/configs/single_locale/tc_android-api-16.py
@@ -1,12 +1,10 @@
 config = {
-    "stage_platform": "android-api-16",
     "locales_file": "src/mobile/locales/l10n-changesets.json",
-    "tools_repo": "https://hg.mozilla.org/build/tools",
     "mozconfig": "src/mobile/android/config/mozconfigs/android-api-16/l10n-nightly",
     "tooltool_config": {
         "manifest": "mobile/android/config/tooltool-manifests/android/releng.manifest",
         "output_dir": "%(abs_work_dir)s/src",
     },
     "tooltool_servers": ['http://relengapi/tooltool/'],
 
     "upload_env": {
--- a/testing/mozharness/configs/single_locale/tc_linux32.py
+++ b/testing/mozharness/configs/single_locale/tc_linux32.py
@@ -1,15 +1,14 @@
 import os
 
 EN_US_BINARY_URL = "%(en_us_binary_url)s"
 
 config = {
     "locales_file": "src/browser/locales/all-locales",
-    "tools_repo": "https://hg.mozilla.org/build/tools",
     "bootstrap_env": {
         "NO_MERCURIAL_SETUP_CHECK": "1",
         "MOZ_OBJDIR": "obj-firefox",
         "EN_US_BINARY_URL": os.environ.get("EN_US_BINARY_URL", EN_US_BINARY_URL),
         "MOZ_UPDATE_CHANNEL": "%(update_channel)s",
         "DIST": "%(abs_objdir)s",
         "L10NBASEDIR": "../../l10n",
         'TOOLTOOL_CACHE': os.environ.get('TOOLTOOL_CACHE'),
--- a/testing/mozharness/configs/single_locale/tc_linux64.py
+++ b/testing/mozharness/configs/single_locale/tc_linux64.py
@@ -1,15 +1,14 @@
 import os
 
 EN_US_BINARY_URL = "%(en_us_binary_url)s"
 
 config = {
     "locales_file": "src/browser/locales/all-locales",
-    "tools_repo": "https://hg.mozilla.org/build/tools",
     "bootstrap_env": {
         "NO_MERCURIAL_SETUP_CHECK": "1",
         "MOZ_OBJDIR": "obj-firefox",
         "EN_US_BINARY_URL": os.environ.get("EN_US_BINARY_URL", EN_US_BINARY_URL),
         "MOZ_UPDATE_CHANNEL": "%(update_channel)s",
         "DIST": "%(abs_objdir)s",
         "L10NBASEDIR": "../../l10n",
         'TOOLTOOL_CACHE': os.environ.get('TOOLTOOL_CACHE'),
--- a/testing/mozharness/configs/single_locale/tc_macosx64.py
+++ b/testing/mozharness/configs/single_locale/tc_macosx64.py
@@ -1,15 +1,14 @@
 import os
 
 EN_US_BINARY_URL = "%(en_us_binary_url)s"
 
 config = {
     "locales_file": "src/browser/locales/all-locales",
-    "tools_repo": "https://hg.mozilla.org/build/tools",
     "bootstrap_env": {
         "NO_MERCURIAL_SETUP_CHECK": "1",
         "MOZ_OBJDIR": "obj-firefox",
         "EN_US_BINARY_URL": os.environ.get("EN_US_BINARY_URL", EN_US_BINARY_URL),
         "MOZ_UPDATE_CHANNEL": "%(update_channel)s",
         "DIST": "%(abs_objdir)s",
         "L10NBASEDIR": "../../l10n",
         'TOOLTOOL_CACHE': os.environ.get('TOOLTOOL_CACHE'),
--- a/testing/mozharness/configs/single_locale/tc_win32.py
+++ b/testing/mozharness/configs/single_locale/tc_win32.py
@@ -1,15 +1,14 @@
 import os
 
 EN_US_BINARY_URL = "%(en_us_binary_url)s"
 
 config = {
     "locales_file": "src/browser/locales/all-locales",
-    "tools_repo": "https://hg.mozilla.org/build/tools",
     'vcs_share_base': os.path.join('y:', os.sep, 'hg-shared'),
     "bootstrap_env": {
         "NO_MERCURIAL_SETUP_CHECK": "1",
         "MOZ_OBJDIR": "obj-firefox",
         "EN_US_BINARY_URL": os.environ.get("EN_US_BINARY_URL", EN_US_BINARY_URL),
         # EN_US_INSTALLER_BINARY_URL falls back on EN_US_BINARY_URL
         "EN_US_INSTALLER_BINARY_URL": os.environ.get(
             "EN_US_INSTALLER_BINARY_URL", os.environ.get(
--- a/testing/mozharness/configs/single_locale/tc_win64.py
+++ b/testing/mozharness/configs/single_locale/tc_win64.py
@@ -1,15 +1,14 @@
 import os
 
 EN_US_BINARY_URL = "%(en_us_binary_url)s"
 
 config = {
     "locales_file": "src/browser/locales/all-locales",
-    "tools_repo": "https://hg.mozilla.org/build/tools",
     'vcs_share_base': os.path.join('y:', os.sep, 'hg-shared'),
     "bootstrap_env": {
         "NO_MERCURIAL_SETUP_CHECK": "1",
         "MOZ_OBJDIR": "obj-firefox",
         "EN_US_BINARY_URL": os.environ.get("EN_US_BINARY_URL", EN_US_BINARY_URL),
         # EN_US_INSTALLER_BINARY_URL falls back on EN_US_BINARY_URL
         "EN_US_INSTALLER_BINARY_URL": os.environ.get(
             "EN_US_INSTALLER_BINARY_URL", os.environ.get(
--- a/testing/mozharness/configs/single_locale/try.py
+++ b/testing/mozharness/configs/single_locale/try.py
@@ -4,33 +4,14 @@ config = {
     "nightly_build": False,
     "branch": "try",
     "en_us_binary_url": "http://archive.mozilla.org/pub/firefox/nightly/latest-mozilla-central",
     "update_channel": "nightly-try",
 
     # l10n
     "hg_l10n_base": "https://hg.mozilla.org/l10n-central",
 
-    # mar
-    "mar_tools_url": os.environ.get(
-        "MAR_TOOLS_URL",
-        # Default to fetching from ftp rather than setting an environ var
-        "https://ftp.mozilla.org/pub/mozilla.org/firefox/nightly/latest-mozilla-central/mar-tools/%(platform)s"
-    ),
+    # mar - passed in environ from taskcluster
+    "mar_tools_url": os.environ["MAR_TOOLS_URL"],
 
-    # repositories
-    "repos": [{
-        "vcs": "hg",
-        "repo": "https://hg.mozilla.org/build/tools",
-        "branch": "default",
-        "dest": "tools",
-    }, {
-        "vcs": "hg",
-        "repo": "https://hg.mozilla.org/try",
-        "revision": "%(revision)s",
-        "dest": "try",
-        "clone_upstream_url": "https://hg.mozilla.org/mozilla-unified",
-        "clone_by_revision": True,
-        "clone_with_purge": True,
-    }],
     # purge options
     'is_automation': True,
 }
--- a/testing/mozharness/configs/single_locale/try_android-api-16.py
+++ b/testing/mozharness/configs/single_locale/try_android-api-16.py
@@ -8,47 +8,31 @@ EN_US_BINARY_URL = "http://archive.mozil
 config = {
     "branch": "try",
     "log_name": "single_locale",
     "objdir": "obj-firefox",
     "is_automation": True,
     "locales_file": "%s/mobile/locales/l10n-changesets.json" % MOZILLA_DIR,
     "locales_dir": "mobile/android/locales",
     "ignore_locales": ["en-US"],
-    "tools_repo": "https://hg.mozilla.org/build/tools",
     "tooltool_config": {
         "manifest": "mobile/android/config/tooltool-manifests/android/releng.manifest",
         "output_dir": "%(abs_work_dir)s/" + MOZILLA_DIR,
     },
     "nightly_build": True,
-    "repos": [{
-        "vcs": "hg",
-        "repo": "https://hg.mozilla.org/build/tools",
-        "branch": "default",
-        "dest": "tools",
-    }, {
-        "vcs": "hg",
-        "repo": "https://hg.mozilla.org/try",
-        "revision": "%(revision)s",
-        "dest": "try",
-        "clone_upstream_url": "https://hg.mozilla.org/mozilla-unified",
-        "clone_by_revision": True,
-        "clone_with_purge": True,
-    }],
     "hg_l10n_base": "https://hg.mozilla.org/l10n-central",
     "hg_l10n_tag": "default",
     'vcs_share_base': "/builds/hg-shared",
 
     "l10n_dir": "l10n-central",
     "repack_env": {
         # so ugly, bug 951238
         "LD_LIBRARY_PATH": "/lib:/tools/gcc-4.7.2-0moz1/lib:/tools/gcc-4.7.2-0moz1/lib64",
         "MOZ_OBJDIR": "obj-firefox",
         "EN_US_BINARY_URL": os.environ.get("EN_US_BINARY_URL", EN_US_BINARY_URL),
         "MOZ_UPDATE_CHANNEL": "try", # XXX Invalid
     },
     "upload_branch": "%s-android-api-16" % BRANCH,
-    "signature_verification_script": "tools/release/signing/verify-android-signature.sh",
     "platform": "android", # XXX Validate
 
     # Balrog
     "build_target": "Android_arm-eabi-gcc3",
 }
--- a/testing/mozharness/mozharness/base/parallel.py
+++ b/testing/mozharness/mozharness/base/parallel.py
@@ -5,17 +5,17 @@
 # You can obtain one at http://mozilla.org/MPL/2.0/.
 # ***** END LICENSE BLOCK *****
 """Generic ways to parallelize jobs.
 """
 
 
 # ChunkingMixin {{{1
 class ChunkingMixin(object):
-    """Generic signing helper methods.
+    """Generic Chunking helper methods.
     """
     def query_chunked_list(self, possible_list, this_chunk, total_chunks,
                            sort=False):
         """Split a list of items into a certain number of chunks and
         return the subset of that will occur in this chunk.
 
         Ported from build.l10n.getLocalesForChunk in build/tools.
         """
--- a/testing/mozharness/mozharness/mozilla/l10n/locales.py
+++ b/testing/mozharness/mozharness/mozilla/l10n/locales.py
@@ -11,21 +11,20 @@ import os
 from urlparse import urljoin
 import pprint
 import sys
 from copy import deepcopy
 
 sys.path.insert(1, os.path.dirname(sys.path[0]))
 
 from mozharness.base.config import parse_config_file
-from mozharness.base.parallel import ChunkingMixin
 
 
 # LocalesMixin {{{1
-class LocalesMixin(ChunkingMixin):
+class LocalesMixin(object):
     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
@@ -34,23 +33,21 @@ class LocalesMixin(ChunkingMixin):
     def query_locales(self):
         if self.locales is not None:
             return self.locales
         c = self.config
         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
+        # 1. "MOZ_LOCALES" env variable: a string of locale:revision separated
         # by space
-        # 3. self.config["locales"] which can be either coming from the config
+        # 2. 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
+        # 3. using self.config["locales_file"] l10n changesets file
         locales = None
 
         # 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()
 
@@ -87,23 +84,16 @@ class LocalesMixin(ChunkingMixin):
 
         for locale in additional_locales:
             if locale not in locales:
                 self.debug("Adding locale %s." % locale)
                 locales.append(locale)
 
         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
         return self.locales
 
     def list_locales(self):
         """ Stub action method.
         """
         self.info("Locale list: %s" % str(self.query_locales()))
 
@@ -166,55 +156,35 @@ class LocalesMixin(ChunkingMixin):
     # This requires self to inherit a VCSMixin.
     def pull_locale_source(self, hg_l10n_base=None, parent_dir=None, vcs='hg'):
         c = self.config
         if not hg_l10n_base:
             hg_l10n_base = c['hg_l10n_base']
         if parent_dir is None:
             parent_dir = self.query_abs_dirs()['abs_l10n_dir']
         self.mkdir_p(parent_dir)
-        repos = []
-        replace_dict = {}
         # This block is to allow for pulling buildbot-configs in Fennec
         # release builds, since we don't pull it in MBF anymore.
         if c.get("l10n_repos"):
-            if c.get("user_repo_override"):
-                replace_dict['user_repo_override'] = c['user_repo_override']
-                for repo_dict in deepcopy(c['l10n_repos']):
-                    repo_dict['repo'] = repo_dict['repo'] % replace_dict
-                    repos.append(repo_dict)
-            else:
-                repos = c.get("l10n_repos")
+            repos = c.get("l10n_repos")
             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 self.l10n_revisions.get(locale):
                 tag = self.l10n_revisions[locale]
             locale_repos.append({
                 'repo': "%s/%s" % (hg_l10n_base, locale),
                 'branch': tag,
                 'vcs': vcs
             })
         revs = self.vcs_checkout_repos(repo_list=locale_repos,
                                        parent_dir=parent_dir,
                                        tag_override=c.get('tag_override'))
         self.gecko_locale_revisions = revs
 
-    def query_l10n_repo(self):
-        # Find the name of our repository
-        mozilla_dir = self.config['mozilla_dir']
-        repo = None
-        for repository in self.config['repos']:
-            if repository.get('dest') == mozilla_dir:
-                repo = repository['repo']
-                break
-        return repo
-
 
 # __main__ {{{1
 
 if __name__ == '__main__':
     pass
--- a/testing/mozharness/mozharness/mozilla/l10n/multi_locale_build.py
+++ b/testing/mozharness/mozharness/mozilla/l10n/multi_locale_build.py
@@ -59,23 +59,16 @@ class MultiLocaleBuild(LocalesMixin, Mer
     ], [
         ["--tag-override"],
         {"action": "store",
          "dest": "tag_override",
          "type": "string",
          "help": "Override the tags set for all repos"
          }
     ], [
-        ["--user-repo-override"],
-        {"action": "store",
-         "dest": "user_repo_override",
-         "type": "string",
-         "help": "Override the user repo path for all repos"
-         }
-    ], [
         ["--l10n-dir"],
         {"action": "store",
          "dest": "l10n_dir",
          "type": "string",
          "default": "l10n",
          "help": "Specify the l10n dir name"
          }
     ]]
@@ -107,26 +100,17 @@ class MultiLocaleBuild(LocalesMixin, Mer
             path = os.path.join(c['base_work_dir'], c['work_dir'])
             if os.path.exists(path):
                 self.rmtree(path, error_level=FATAL)
         else:
             self.info("work_dir is '.'; skipping for now.")
 
     def pull_build_source(self):
         c = self.config
-        repos = []
-        replace_dict = {}
-        # Replace %(user_repo_override)s with c['user_repo_override']
-        if c.get("user_repo_override"):
-            replace_dict['user_repo_override'] = c['user_repo_override']
-            for repo_dict in deepcopy(c['repos']):
-                repo_dict['repo'] = repo_dict['repo'] % replace_dict
-                repos.append(repo_dict)
-        else:
-            repos = c['repos']
+        repos = c['repos']
         self.vcs_checkout_repos(repos, tag_override=c.get('tag_override'))
 
     # pull_locale_source() defined in LocalesMixin.
 
     def build(self):
         c = self.config
         dirs = self.query_abs_dirs()
         self.copyfile(os.path.join(dirs['abs_work_dir'], c['mozconfig']),
--- a/testing/mozharness/mozharness/mozilla/release.py
+++ b/testing/mozharness/mozharness/mozilla/release.py
@@ -6,52 +6,28 @@
 # ***** END LICENSE BLOCK *****
 """release.py
 
 """
 
 import os
 from distutils.version import LooseVersion, StrictVersion
 
-from mozharness.base.config import parse_config_file
 
-
-# SignAndroid {{{1
+# ReleaseMixin {{{1
 class ReleaseMixin():
     release_config = {}
 
     def query_release_config(self):
         if self.release_config:
             return self.release_config
-        c = self.config
-        dirs = self.query_abs_dirs()
-        if c.get("release_config_file"):
-            self.info("Getting release config from %s..." % c["release_config_file"])
-            rc = None
-            try:
-                rc = parse_config_file(
-                    os.path.join(dirs['abs_work_dir'],
-                                 c["release_config_file"]),
-                    config_dict_name="releaseConfig"
-                )
-            except IOError:
-                self.fatal("Release config file %s not found!" % c["release_config_file"])
-            except RuntimeError:
-                self.fatal("Invalid release config file %s!" % c["release_config_file"])
-            self.release_config['version'] = rc['version']
-            self.release_config['buildnum'] = rc['buildNumber']
-            self.release_config['ftp_server'] = rc['stagingServer']
-            self.release_config['ftp_user'] = c.get('ftp_user', rc['hgUsername'])
-            self.release_config['ftp_ssh_key'] = c.get('ftp_ssh_key', rc['hgSshKey'])
-            self.release_config['release_channel'] = rc['releaseChannel']
-        else:
-            self.info("No release config file; using default config.")
-            for key in ('version', 'buildnum',
-                        'ftp_server', 'ftp_user', 'ftp_ssh_key'):
-                self.release_config[key] = c[key]
+        self.info("No release config file; using default config.")
+        for key in ('version', 'buildnum',
+                    'ftp_server', 'ftp_user', 'ftp_ssh_key'):
+            self.release_config[key] = c[key]
         self.info("Release config:\n%s" % self.release_config)
         return self.release_config
 
 
 def get_previous_version(version, partial_versions):
     """ The patcher config bumper needs to know the exact previous version
     We use LooseVersion for ESR because StrictVersion can't parse the trailing
     'esr', but StrictVersion otherwise because it can sort X.0bN lower than X.0.
--- a/testing/mozharness/scripts/desktop_l10n.py
+++ b/testing/mozharness/scripts/desktop_l10n.py
@@ -14,28 +14,24 @@ import re
 import sys
 import shlex
 
 # load modules from parent dir
 sys.path.insert(1, os.path.dirname(sys.path[0]))
 
 from mozharness.base.errors import MakefileErrorList
 from mozharness.base.script import BaseScript
-from mozharness.base.transfer import TransferMixin
 from mozharness.base.vcs.vcsbase import VCSMixin
 from mozharness.mozilla.automation import AutomationMixin
 from mozharness.mozilla.building.buildbase import (
     MakeUploadOutputParser,
     get_mozconfig_path,
 )
 from mozharness.mozilla.l10n.locales import LocalesMixin
 from mozharness.mozilla.mar import MarMixin
-from mozharness.mozilla.release import ReleaseMixin
-from mozharness.mozilla.updates.balrog import BalrogMixin
-from mozharness.base.python import VirtualenvMixin
 
 try:
     import simplejson as json
     assert json
 except ImportError:
     import json
 
 
@@ -48,56 +44,31 @@ FAILURE_STR = "Failed"
 
 
 # mandatory configuration options, without them, this script will not work
 # it's a list of values that are already known before starting a build
 configuration_tokens = ('branch',
                         'platform',
                         'update_channel',
                         )
-# some other values such as "%(version)s", "%(buildid)s", ...
+# some other values such as "%(version)s", ...
 # are defined at run time and they cannot be enforced in the _pre_config_lock
 # phase
-runtime_config_tokens = ('buildid', 'version', 'locale', 'from_buildid',
+runtime_config_tokens = ('version', 'locale', 'from_buildid',
                          'abs_objdir', 'revision',
                          'to_buildid', 'en_us_binary_url',
                          'en_us_installer_binary_url', 'mar_tools_url',
                          'who')
 
 
 # DesktopSingleLocale {{{1
-class DesktopSingleLocale(LocalesMixin, ReleaseMixin, AutomationMixin,
-                          VCSMixin, BaseScript, BalrogMixin, MarMixin,
-                          VirtualenvMixin, TransferMixin):
+class DesktopSingleLocale(LocalesMixin, AutomationMixin,
+                          VCSMixin, BaseScript, MarMixin):
     """Manages desktop repacks"""
     config_options = [[
-        ['--balrog-config', ],
-        {"action": "extend",
-         "dest": "config_files",
-         "type": "string",
-         "help": "Specify the balrog configuration file"}
-    ], [
-        ['--branch-config', ],
-        {"action": "extend",
-         "dest": "config_files",
-         "type": "string",
-         "help": "Specify the branch configuration file"}
-    ], [
-        ['--environment-config', ],
-        {"action": "extend",
-         "dest": "config_files",
-         "type": "string",
-         "help": "Specify the environment (staging, production, ...) configuration file"}
-    ], [
-        ['--platform-config', ],
-        {"action": "extend",
-         "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. Optionally pass"
                  " revision separated by colon, en-GB:default."}
     ], [
         ['--locales-file', ],
@@ -114,40 +85,16 @@ class DesktopSingleLocale(LocalesMixin, 
     ], [
         ['--revision', ],
         {"action": "store",
          "dest": "revision",
          "type": "string",
          "help": "Override the gecko revision to use (otherwise use automation supplied"
                  " value, or en-US revision) "}
     ], [
-        ['--user-repo-override', ],
-        {"action": "store",
-         "dest": "user_repo_override",
-         "type": "string",
-         "help": "Override the user repo path for all repos"}
-    ], [
-        ['--release-config-file', ],
-        {"action": "store",
-         "dest": "release_config_file",
-         "type": "string",
-         "help": "Specify the release config file to use"}
-    ], [
-        ['--this-chunk', ],
-        {"action": "store",
-         "dest": "this_locale_chunk",
-         "type": "int",
-         "help": "Specify which chunk of locales to run"}
-    ], [
-        ['--total-chunks', ],
-        {"action": "store",
-         "dest": "total_locale_chunks",
-         "type": "int",
-         "help": "Specify the total number of chunks of locales"}
-    ], [
         ['--en-us-installer-url', ],
         {"action": "store",
          "dest": "en_us_installer_url",
          "type": "string",
          "help": "Specify the url of the en-us binary"}
     ], [
         ['--scm-level'], {  # Ignored on desktop for now: see Bug 1414678.
          "action": "store",
@@ -158,53 +105,42 @@ class DesktopSingleLocale(LocalesMixin, 
                  " See https://www.mozilla.org/en-US/about/"
                  "governance/policies/commit/access-policy/"}
     ]]
 
     def __init__(self, require_config_file=True):
         # fxbuild style:
         buildscript_kwargs = {
             'all_actions': [
-                "clobber",
-                "pull",
                 "clone-locales",
                 "list-locales",
                 "setup",
                 "repack",
-                "taskcluster-upload",
                 "funsize-props",
-                "submit-to-balrog",
                 "summary",
             ],
             'config': {
                 "ignore_locales": ["en-US"],
                 "locales_dir": "browser/locales",
                 "buildid_section": "App",
                 "buildid_option": "BuildID",
                 "application_ini": "application.ini",
                 "log_name": "single_locale",
-                "appName": "Firefox",
                 "hashType": "sha512",
-                'virtualenv_modules': [
-                    'requests==2.8.1',
-                ],
-                'virtualenv_path': 'venv',
             },
         }
 
         LocalesMixin.__init__(self)
         BaseScript.__init__(
             self,
             config_options=self.config_options,
             require_config_file=require_config_file,
             **buildscript_kwargs
         )
 
-        self.buildid = None
-        self.make_ident_output = None
         self.bootstrap_env = None
         self.upload_env = None
         self.revision = None
         self.version = None
         self.upload_urls = {}
         self.locales_property = {}
         self.pushdate = None
         # upload_files is a dictionary of files to upload, keyed by locale.
@@ -363,43 +299,16 @@ class DesktopSingleLocale(LocalesMixin, 
         self.upload_env = upload_env
         return self.upload_env
 
     def query_l10n_env(self):
         l10n_env = self._query_upload_env().copy()
         l10n_env.update(self.query_bootstrap_env())
         return l10n_env
 
-    def _query_make_ident_output(self):
-        """Get |make ident| output from the objdir.
-        Only valid after setup is run.
-       """
-        if self.make_ident_output:
-            return self.make_ident_output
-        dirs = self.query_abs_dirs()
-        self.make_ident_output = self._get_output_from_make(
-            target=["ident"],
-            cwd=dirs['abs_locales_dir'],
-            env=self.query_bootstrap_env())
-        return self.make_ident_output
-
-    def _query_buildid(self):
-        """Get buildid from the objdir.
-        Only valid after setup is run.
-       """
-        if self.buildid:
-            return self.buildid
-        r = re.compile(r"buildid (\d+)")
-        output = self._query_make_ident_output()
-        for line in output.splitlines():
-            match = r.match(line)
-            if match:
-                self.buildid = match.groups()[0]
-        return self.buildid
-
     def _query_revision(self):
         """ Get the gecko revision in this order of precedence
               * cached value
               * command line arg --revision   (development, taskcluster)
               * from the en-US build          (m-c & m-a)
 
         This will fail the last case if the build hasn't been pulled yet.
         """
@@ -434,22 +343,17 @@ class DesktopSingleLocale(LocalesMixin, 
         self.info('echo-variable-%s: %s' % (variable, output))
         return output
 
     def query_version(self):
         """Gets the version from the objdir.
         Only valid after setup is run."""
         if self.version:
             return self.version
-        config = self.config
-        if config.get('release_config_file'):
-            release_config = self.query_release_config()
-            self.version = release_config['version']
-        else:
-            self.version = self._query_make_variable("MOZ_APP_VERSION")
+        self.version = self._query_make_variable("MOZ_APP_VERSION")
         return self.version
 
     def _map(self, func, items):
         """runs func for any item in items, calls the add_failure() for each
            error. It assumes that function returns 0 when successful.
            returns a two element tuple with (success_count, total_count)"""
         success_count = 0
         total_count = len(items)
@@ -486,49 +390,16 @@ class DesktopSingleLocale(LocalesMixin, 
         BaseScript.summary(self)
         # TODO we probably want to make this configurable on/off
         locales = self.query_locales()
         for locale in locales:
             self.locales_property.setdefault(locale, SUCCESS_STR)
         self.set_property("locales", json.dumps(self.locales_property))
 
     # Actions {{{2
-    def pull(self):
-        """pulls source code"""
-        config = self.config
-        dirs = self.query_abs_dirs()
-        repos = []
-        # replace dictionary for repos
-        # we need to interpolate some values:
-        # branch, branch_repo
-        # and user_repo_override if exists
-        replace_dict = {}
-        if config.get("user_repo_override"):
-            replace_dict['user_repo_override'] = config['user_repo_override']
-        # this is OK so early because we get it from automation, or
-        # the command line for local dev
-        replace_dict['revision'] = self._query_revision()
-
-        for repository in config['repos']:
-            current_repo = {}
-            for key, value in repository.iteritems():
-                try:
-                    current_repo[key] = value % replace_dict
-                except TypeError:
-                    # pass through non-interpolables, like booleans
-                    current_repo[key] = value
-                except KeyError:
-                    self.error('not all the values in "{0}" can be replaced. Check your '
-                               'configuration'.format(value))
-                    raise
-            repos.append(current_repo)
-        self.info("repositories: %s" % repos)
-        self.vcs_checkout_repos(repos, parent_dir=dirs['abs_work_dir'],
-                                tag_override=config.get('tag_override'))
-
     def clone_locales(self):
         self.pull_locale_source()
 
     def setup(self):
         """setup step"""
         self._run_tooltool()
         self._copy_mozconfig()
         self._mach_configure()
@@ -759,44 +630,16 @@ class DesktopSingleLocale(LocalesMixin, 
         dirs['abs_tools_dir'] = os.path.join(abs_dirs['abs_work_dir'], 'tools')
         dirs['abs_src_dir'] = os.path.join(abs_dirs['abs_work_dir'], 'src')
         for key in dirs.keys():
             if key not in abs_dirs:
                 abs_dirs[key] = dirs[key]
         self.abs_dirs = abs_dirs
         return self.abs_dirs
 
-    def submit_to_balrog(self):
-        """submit to balrog"""
-        self.info("Reading build properties...")
-        # get platform, appName and hashType from configuration
-        # common values across different locales
-        config = self.config
-        platform = config["platform"]
-        appName = config['appName']
-        branch = config['branch']
-        # values from configuration
-        self.set_property("branch", branch)
-        self.set_property("appName", appName)
-        # it's hardcoded to sha512 in balrog.py
-        self.set_property("platform", platform)
-        # values common to the current repacks
-        self.set_property("buildid", self._query_buildid())
-        self.set_property("appVersion", self.query_version())
-
-        # YAY
-        def balrog_props_wrapper(locale):
-            env = self._query_upload_env()
-            props_path = os.path.join(env["UPLOAD_PATH"], locale,
-                                      'balrog_props.json')
-            self.generate_balrog_props(props_path)
-            return SUCCESS
-
-        self._map(balrog_props_wrapper, self.query_locales())
-
     def _mar_binaries(self):
         """returns a tuple with mar and mbsdiff paths"""
         config = self.config
         return (config['mar'], config['mbsdiff'])
 
     def _mar_dir(self, dirname):
         """returns the full path of dirname;
             dirname is an entry in configuration"""
--- a/testing/mozharness/scripts/mobile_l10n.py
+++ b/testing/mozharness/scripts/mobile_l10n.py
@@ -21,32 +21,26 @@ try:
 except ImportError:
     import json
 
 # load modules from parent dir
 sys.path.insert(1, os.path.dirname(sys.path[0]))
 
 from mozharness.base.errors import MakefileErrorList
 from mozharness.base.log import OutputParser
-from mozharness.base.transfer import TransferMixin
 from mozharness.mozilla.automation import AutomationMixin
-from mozharness.mozilla.release import ReleaseMixin
 from mozharness.mozilla.tooltool import TooltoolMixin
 from mozharness.base.vcs.vcsbase import MercurialScript
 from mozharness.mozilla.l10n.locales import LocalesMixin
 from mozharness.mozilla.secrets import SecretsMixin
-from mozharness.mozilla.updates.balrog import BalrogMixin
-from mozharness.base.python import VirtualenvMixin
 
 
 # MobileSingleLocale {{{1
-class MobileSingleLocale(LocalesMixin, ReleaseMixin,
-                         TransferMixin, TooltoolMixin, AutomationMixin,
-                         MercurialScript, BalrogMixin,
-                         VirtualenvMixin, SecretsMixin):
+class MobileSingleLocale(LocalesMixin, TooltoolMixin, AutomationMixin,
+                         MercurialScript, SecretsMixin):
     config_options = [[
         ['--locale', ],
         {"action": "extend",
          "dest": "locales",
          "type": "string",
          "help": "Specify the locale(s) to sign and update"
          }
     ], [
@@ -59,53 +53,16 @@ class MobileSingleLocale(LocalesMixin, R
     ], [
         ['--tag-override', ],
         {"action": "store",
          "dest": "tag_override",
          "type": "string",
          "help": "Override the tags set for all repos"
          }
     ], [
-        ['--user-repo-override', ],
-        {"action": "store",
-         "dest": "user_repo_override",
-         "type": "string",
-         "help": "Override the user repo path for all repos"
-         }
-    ], [
-        ['--release-config-file', ],
-        {"action": "store",
-         "dest": "release_config_file",
-         "type": "string",
-         "help": "Specify the release config file to use"
-         }
-    ], [
-        ['--key-alias', ],
-        {"action": "store",
-         "dest": "key_alias",
-         "type": "choice",
-         "default": "nightly",
-         "choices": ["nightly", "release"],
-         "help": "Specify the signing key alias"
-         }
-    ], [
-        ['--this-chunk', ],
-        {"action": "store",
-         "dest": "this_locale_chunk",
-         "type": "int",
-         "help": "Specify which chunk of locales to run"
-         }
-    ], [
-        ['--total-chunks', ],
-        {"action": "store",
-         "dest": "total_locale_chunks",
-         "type": "int",
-         "help": "Specify the total number of chunks of locales"
-         }
-    ], [
         ['--revision', ],
         {"action": "store",
          "dest": "revision",
          "type": "string",
          "help": "Override the gecko revision to use (otherwise use automation supplied"
                  " value, or en-US revision) "}
     ], [
         ['--scm-level'],
@@ -117,70 +74,47 @@ class MobileSingleLocale(LocalesMixin, R
                  " See https://www.mozilla.org/en-US/about/"
                  "governance/policies/commit/access-policy/"}
     ]]
 
     def __init__(self, require_config_file=True):
         buildscript_kwargs = {
             'all_actions': [
                 "get-secrets",
-                "clobber",
-                "pull",
                 "clone-locales",
                 "list-locales",
                 "setup",
                 "repack",
-                "validate-repacks-signed",
                 "upload-repacks",
-                "create-virtualenv",
-                "submit-to-balrog",
                 "summary",
             ],
             'config': {
-                'virtualenv_modules': [
-                    'requests==2.8.1',
-                ],
-                'virtualenv_path': 'venv',
             },
         }
         LocalesMixin.__init__(self)
         MercurialScript.__init__(
             self,
             config_options=self.config_options,
             require_config_file=require_config_file,
             **buildscript_kwargs
         )
         self.base_package_name = None
-        self.buildid = None
-        self.make_ident_output = None
         self.repack_env = None
         self.revision = None
         self.upload_env = None
         self.version = None
         self.upload_urls = {}
         self.locales_property = {}
 
     # Helper methods {{{2
     def query_repack_env(self):
         if self.repack_env:
             return self.repack_env
         c = self.config
-        replace_dict = {}
-        if c.get('release_config_file'):
-            rc = self.query_release_config()
-            replace_dict = {
-                'version': rc['version'],
-                'buildnum': rc['buildnum']
-            }
-        repack_env = self.query_env(partial_env=c.get("repack_env"),
-                                    replace_dict=replace_dict)
-        if c.get('base_en_us_binary_url') and c.get('release_config_file'):
-            rc = self.query_release_config()
-            repack_env['EN_US_BINARY_URL'] = c['base_en_us_binary_url'] % replace_dict
-
+        repack_env = self.query_env(partial_env=c.get("repack_env"))
         if self.query_is_nightly() or self.query_is_nightly_promotion():
             if self.query_is_nightly():
                 # Nightly promotion needs to set update_channel but not do all
                 # the 'IS_NIGHTLY' automation parts, like uploading symbols
                 # (for now).
                 repack_env["IS_NIGHTLY"] = "yes"
             # In branch_specifics.py we might set update_channel explicitly.
             if c.get('update_channel'):
@@ -193,70 +127,22 @@ class MobileSingleLocale(LocalesMixin, R
         return self.repack_env
 
     def query_l10n_env(self):
         return self.query_env()
 
     def query_upload_env(self):
         if self.upload_env:
             return self.upload_env
-        c = self.config
-        replace_dict = {
-            'buildid': self.query_buildid(),
-            'version': self.query_version(),
-        }
-        replace_dict.update(c)
 
-        # Android l10n builds use a non-standard location for l10n files.  Other
-        # builds go to 'mozilla-central-l10n', while android builds add part of
-        # the platform name as well, like 'mozilla-central-android-api-16-l10n'.
-        # So we override the branch with something that contains the platform
-        # name.
-        replace_dict['branch'] = c['upload_branch']
-
-        upload_env = self.query_env(partial_env=c.get("upload_env"),
-                                    replace_dict=replace_dict)
-        if self.query_is_release_or_beta():
-            upload_env['MOZ_PKG_VERSION'] = '%(version)s' % replace_dict
+        upload_env = self.query_env(partial_env=self.config.get("upload_env"),
+                                    replace_dict=dict(self.config))
         self.upload_env = upload_env
         return self.upload_env
 
-    def _query_make_ident_output(self):
-        """Get |make ident| output from the objdir.
-        Only valid after setup is run.
-        """
-        if self.make_ident_output:
-            return self.make_ident_output
-        env = self.query_repack_env()
-        dirs = self.query_abs_dirs()
-        output = self.get_output_from_command(["make", "ident"],
-                                              cwd=dirs['abs_locales_dir'],
-                                              env=env,
-                                              silent=True,
-                                              halt_on_failure=True)
-        parser = OutputParser(config=self.config, log_obj=self.log_obj,
-                              error_list=MakefileErrorList)
-        parser.add_lines(output)
-        self.make_ident_output = output
-        return output
-
-    def query_buildid(self):
-        """Get buildid from the objdir.
-        Only valid after setup is run.
-        """
-        if self.buildid:
-            return self.buildid
-        r = re.compile("buildid (\d+)")
-        output = self._query_make_ident_output()
-        for line in output.splitlines():
-            m = r.match(line)
-            if m:
-                self.buildid = m.groups()[0]
-        return self.buildid
-
     def query_revision(self):
         """ Get the gecko revision in this order of precedence
               * cached value
               * command line arg --revision   (development, taskcluster)
               * from the en-US build          (m-c & m-a)
 
         This will fail the last case if the build hasn't been pulled yet.
         """
@@ -302,22 +188,17 @@ class MobileSingleLocale(LocalesMixin, R
         return self.base_package_name
 
     def query_version(self):
         """Get the package name from the objdir.
         Only valid after setup is run.
         """
         if self.version:
             return self.version
-        c = self.config
-        if c.get('release_config_file'):
-            rc = self.query_release_config()
-            self.version = rc['version']
-        else:
-            self.version = self._query_make_variable("MOZ_APP_VERSION")
+        self.version = self._query_make_variable("MOZ_APP_VERSION")
         return self.version
 
     def query_upload_url(self, locale):
         if locale in self.upload_urls:
             return self.upload_urls[locale]
         else:
             self.error("Can't determine the upload url for %s!" % locale)
 
@@ -350,50 +231,22 @@ class MobileSingleLocale(LocalesMixin, R
         MercurialScript.summary(self)
         # TODO we probably want to make this configurable on/off
         locales = self.query_locales()
         for locale in locales:
             self.locales_property.setdefault(locale, "Success")
         self.set_property("locales", json.dumps(self.locales_property))
 
     # Actions {{{2
-    def pull(self):
-        c = self.config
-        dirs = self.query_abs_dirs()
-        repos = []
-        replace_dict = {}
-        if c.get("user_repo_override"):
-            replace_dict['user_repo_override'] = c['user_repo_override']
-        # this is OK so early because we get it from automation, or
-        # the command line for local dev
-        replace_dict['revision'] = self.query_revision()
-
-        for repository in c['repos']:
-            current_repo = {}
-            for key, value in repository.iteritems():
-                try:
-                    current_repo[key] = value % replace_dict
-                except TypeError:
-                    # pass through non-interpolables, like booleans
-                    current_repo[key] = value
-                except KeyError:
-                    self.error('not all the values in "{0}" can be replaced. Check '
-                               'your configuration'.format(value))
-                    raise
-            repos.append(current_repo)
-        self.info("repositories: %s" % repos)
-        self.vcs_checkout_repos(repos, parent_dir=dirs['abs_work_dir'],
-                                tag_override=c.get('tag_override'))
-
     def clone_locales(self):
         self.pull_locale_source()
 
     # list_locales() is defined in LocalesMixin.
 
-    def _setup_configure(self, buildid=None):
+    def _setup_configure(self):
         dirs = self.query_abs_dirs()
         env = self.query_repack_env()
 
         mach = os.path.join(dirs['abs_mozilla_dir'], 'mach')
 
         if self.run_command([sys.executable, mach, 'configure'],
                             cwd=dirs['abs_mozilla_dir'],
                             env=env,
@@ -401,21 +254,16 @@ class MobileSingleLocale(LocalesMixin, R
             self.fatal("Configure failed!")
 
         # Invoke the build system to get nsinstall and buildid.h.
         targets = [
             'config/export',
             'buildid.h',
         ]
 
-        # Force the buildid if one is defined.
-        if buildid:
-            env = dict(env)
-            env['MOZ_BUILD_DATE'] = str(buildid)
-
         self.run_command([sys.executable, mach, 'build'] + targets,
                          cwd=dirs['abs_mozilla_dir'],
                          env=env,
                          error_list=MakefileErrorList,
                          halt_on_failure=True)
 
     def setup(self):
         c = self.config
@@ -461,43 +309,16 @@ class MobileSingleLocale(LocalesMixin, R
                                 halt_on_failure=False):
                 self.add_failure(locale, message="%s failed in make installers-%s!" %
                                  (locale, locale))
                 continue
             success_count += 1
         self.summarize_success_count(success_count, total_count,
                                      message="Repacked %d of %d binaries successfully.")
 
-    def validate_repacks_signed(self):
-        c = self.config
-        dirs = self.query_abs_dirs()
-        locales = self.query_locales()
-        base_package_name = self.query_base_package_name()
-        base_package_dir = os.path.join(dirs['abs_objdir'], 'dist')
-        repack_env = self.query_repack_env()
-        success_count = total_count = 0
-        for locale in locales:
-            total_count += 1
-            signed_path = os.path.join(base_package_dir,
-                                       base_package_name % {'locale': locale})
-            status = self.verify_android_signature(
-                signed_path,
-                script=c['signature_verification_script'],
-                env=repack_env,
-                key_alias=c['key_alias'],
-            )
-            if status:
-                self.add_failure(locale, message="Errors verifying %s binary!" % locale)
-                # No need to rm because upload is per-locale
-                continue
-            success_count += 1
-        self.summarize_success_count(success_count, total_count,
-                                     message="Validated signatures on %d of %d "
-                                             "binaries successfully.")
-
     def upload_repacks(self):
         dirs = self.query_abs_dirs()
         locales = self.query_locales()
         make = self.query_exe("make")
         base_package_name = self.query_base_package_name()
         upload_env = self.query_upload_env()
         success_count = total_count = 0
         for locale in locales:
@@ -539,103 +360,13 @@ class MobileSingleLocale(LocalesMixin, R
                     glob_extension = f[f.rfind('.'):]
                     self.move(os.path.join(f),
                               os.path.join(target_path, "target%s" % glob_extension))
                 self.log("Converted uploads for %s to simple names" % locale)
             success_count += 1
         self.summarize_success_count(success_count, total_count,
                                      message="Make Upload for %d of %d locales successful.")
 
-    def checkout_tools(self):
-        dirs = self.query_abs_dirs()
-
-        # We need hg.m.o/build/tools checked out
-        self.info("Checking out tools")
-        repos = [{
-            'repo': self.config['tools_repo'],
-            'vcs': "hg",
-            'branch': "default",
-            'dest': dirs['abs_tools_dir'],
-        }]
-        rev = self.vcs_checkout(**repos[0])
-        self.set_property("tools_revision", rev)
-
-    def query_apkfile_path(self, locale):
-
-        dirs = self.query_abs_dirs()
-        apkdir = os.path.join(dirs['abs_objdir'], 'dist')
-        r = r"(\.)" + re.escape(locale) + r"(\.*)"
-
-        apks = []
-        for f in os.listdir(apkdir):
-            if f.endswith(".apk") and re.search(r, f):
-                apks.append(f)
-        if len(apks) == 0:
-            self.fatal("Found no apks files in %s, don't know what to do:\n%s" %
-                       (apkdir, apks), exit_code=1)
-
-        return os.path.join(apkdir, apks[0])
-
-    def query_is_release_or_beta(self):
-
-        return bool(self.config.get("is_release_or_beta"))
-
-    def submit_to_balrog(self):
-        if not self.query_is_nightly() and not self.query_is_release_or_beta():
-            self.info("Not a nightly or release build, skipping balrog submission.")
-            return
-
-        self.checkout_tools()
-
-        locales = self.query_locales()
-        if not self.config.get('taskcluster_nightly'):
-            balrogReady = True
-            for locale in locales:
-                apk_url = self.query_upload_url(locale)
-                if not apk_url:
-                    self.add_failure(locale, message="Failed to detect %s url in make upload!" %
-                                     (locale))
-                    balrogReady = False
-                    continue
-            if not balrogReady:
-                return self.fatal(message="Not all repacks successful, abort without "
-                                          "submitting to balrog.")
-
-        env = self.query_upload_env()
-        for locale in locales:
-            apkfile = self.query_apkfile_path(locale)
-            if self.config.get('taskcluster_nightly'):
-                # Taskcluster needs stage_platform
-                self.set_property("stage_platform", self.config.get("stage_platform"))
-                self.set_property("branch", self.config.get("branch"))
-            else:
-                apk_url = self.query_upload_url(locale)
-                self.set_property("completeMarUrl", apk_url)
-
-                # The Balrog submitter translates this platform into a build target
-                # via https://github.com/mozilla/build-tools/blob/master/lib/python/release/platforms.py#L23  # noqa
-                self.set_property(
-                    "platform",
-                    self.config["properties"]["platform"])
-                # TODO: Is there a better way to get this?
-
-            # Set other necessary properties for Balrog submission. None need to
-            # be passed back to automation, so we won't write them to the properties
-            # files.
-            self.set_property("locale", locale)
-
-            self.set_property("appVersion", self.query_version())
-
-            self.set_property("appName", "Fennec")
-            self.set_property("completeMarSize", self.query_filesize(apkfile))
-            self.set_property("completeMarHash", self.query_sha512sum(apkfile))
-            self.set_property("isOSUpdate", False)
-            self.set_property("buildid", self.query_buildid())
-
-            props_path = os.path.join(env["UPLOAD_PATH"], locale,
-                                      'balrog_props.json')
-            self.generate_balrog_props(props_path)
-
 
 # main {{{1
 if __name__ == '__main__':
     single_locale = MobileSingleLocale()
     single_locale.run_and_exit()
deleted file mode 100755
--- a/testing/mozharness/scripts/mobile_partner_repack.py
+++ /dev/null
@@ -1,336 +0,0 @@
-#!/usr/bin/env python
-# ***** BEGIN LICENSE BLOCK *****
-# 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/.
-# ***** END LICENSE BLOCK *****
-"""mobile_partner_repack.py
-
-"""
-
-from copy import deepcopy
-import os
-import sys
-
-# load modules from parent dir
-sys.path.insert(1, os.path.dirname(sys.path[0]))
-
-from mozharness.base.errors import ZipErrorList
-from mozharness.base.log import FATAL
-from mozharness.base.transfer import TransferMixin
-from mozharness.base.vcs.vcsbase import MercurialScript
-from mozharness.mozilla.l10n.locales import LocalesMixin
-from mozharness.mozilla.release import ReleaseMixin
-from mozharness.mozilla.signing import MobileSigningMixin
-
-SUPPORTED_PLATFORMS = ["android"]
-
-
-# MobilePartnerRepack {{{1
-class MobilePartnerRepack(LocalesMixin, ReleaseMixin, MobileSigningMixin,
-                          TransferMixin, MercurialScript):
-    config_options = [[
-        ['--locale', ],
-        {"action": "extend",
-         "dest": "locales",
-         "type": "string",
-         "help": "Specify the locale(s) to repack"
-         }
-    ], [
-        ['--partner', ],
-        {"action": "extend",
-         "dest": "partners",
-         "type": "string",
-         "help": "Specify the partner(s) to repack"
-         }
-    ], [
-        ['--locales-file', ],
-        {"action": "store",
-         "dest": "locales_file",
-         "type": "string",
-         "help": "Specify a json file to determine which locales to repack"
-         }
-    ], [
-        ['--tag-override', ],
-        {"action": "store",
-         "dest": "tag_override",
-         "type": "string",
-         "help": "Override the tags set for all repos"
-         }
-    ], [
-        ['--platform', ],
-        {"action": "extend",
-         "dest": "platforms",
-         "type": "choice",
-         "choices": SUPPORTED_PLATFORMS,
-         "help": "Specify the platform(s) to repack"
-         }
-    ], [
-        ['--user-repo-override', ],
-        {"action": "store",
-         "dest": "user_repo_override",
-         "type": "string",
-         "help": "Override the user repo path for all repos"
-         }
-    ], [
-        ['--release-config-file', ],
-        {"action": "store",
-         "dest": "release_config_file",
-         "type": "string",
-         "help": "Specify the release config file to use"
-         }
-    ], [
-        ['--version', ],
-        {"action": "store",
-         "dest": "version",
-         "type": "string",
-         "help": "Specify the current version"
-         }
-    ], [
-        ['--buildnum', ],
-        {"action": "store",
-         "dest": "buildnum",
-         "type": "int",
-         "default": 1,
-         "metavar": "INT",
-         "help": "Specify the current release build num (e.g. build1, build2)"
-         }
-    ]]
-
-    def __init__(self, require_config_file=True):
-        self.release_config = {}
-        LocalesMixin.__init__(self)
-        MercurialScript.__init__(
-            self,
-            config_options=self.config_options,
-            all_actions=[
-                "passphrase",
-                "clobber",
-                "pull",
-                "download",
-                "repack",
-                "upload-unsigned-bits",
-                "sign",
-                "upload-signed-bits",
-                "summary",
-            ],
-            require_config_file=require_config_file
-        )
-
-    # Helper methods {{{2
-    def add_failure(self, platform, locale, **kwargs):
-        s = "%s:%s" % (platform, locale)
-        if 'message' in kwargs:
-            kwargs['message'] = kwargs['message'] % {'platform': platform, 'locale': locale}
-        super(MobilePartnerRepack, self).add_failure(s, **kwargs)
-
-    def query_failure(self, platform, locale):
-        s = "%s:%s" % (platform, locale)
-        return super(MobilePartnerRepack, self).query_failure(s)
-
-    # Actions {{{2
-
-    def pull(self):
-        c = self.config
-        dirs = self.query_abs_dirs()
-        repos = []
-        replace_dict = {}
-        if c.get("user_repo_override"):
-            replace_dict['user_repo_override'] = c['user_repo_override']
-            # deepcopy() needed because of self.config lock bug :(
-            for repo_dict in deepcopy(c['repos']):
-                repo_dict['repo'] = repo_dict['repo'] % replace_dict
-                repos.append(repo_dict)
-        else:
-            repos = c['repos']
-        self.vcs_checkout_repos(repos, parent_dir=dirs['abs_work_dir'],
-                                tag_override=c.get('tag_override'))
-
-    def download(self):
-        c = self.config
-        rc = self.query_release_config()
-        dirs = self.query_abs_dirs()
-        locales = self.query_locales()
-        replace_dict = {
-            'buildnum': rc['buildnum'],
-            'version': rc['version'],
-        }
-        success_count = total_count = 0
-        for platform in c['platforms']:
-            base_installer_name = c['installer_base_names'][platform]
-            base_url = c['download_base_url'] + '/' + \
-                c['download_unsigned_base_subdir'] + '/' + \
-                base_installer_name
-            replace_dict['platform'] = platform
-            for locale in locales:
-                replace_dict['locale'] = locale
-                url = base_url % replace_dict
-                installer_name = base_installer_name % replace_dict
-                parent_dir = '%s/original/%s/%s' % (dirs['abs_work_dir'],
-                                                    platform, locale)
-                file_path = '%s/%s' % (parent_dir, installer_name)
-                self.mkdir_p(parent_dir)
-                total_count += 1
-                if not self.download_file(url, file_path):
-                    self.add_failure(platform, locale,
-                                     message="Unable to "
-                                             "download %(platform)s:%(locale)s installer!")
-                else:
-                    success_count += 1
-        self.summarize_success_count(success_count, total_count,
-                                     message="Downloaded %d of %d installers successfully.")
-
-    def _repack_apk(self, partner, orig_path, repack_path):
-        """ Repack the apk with a partner update channel.
-        Returns True for success, None for failure
-        """
-        dirs = self.query_abs_dirs()
-        zip_bin = self.query_exe("zip")
-        unzip_bin = self.query_exe("unzip")
-        file_name = os.path.basename(orig_path)
-        tmp_dir = os.path.join(dirs['abs_work_dir'], 'tmp')
-        tmp_file = os.path.join(tmp_dir, file_name)
-        tmp_prefs_dir = os.path.join(tmp_dir, 'defaults', 'pref')
-        # Error checking for each step.
-        # Ignoring the mkdir_p()s since the subsequent copyfile()s will
-        # error out if unsuccessful.
-        if self.rmtree(tmp_dir):
-            return
-        self.mkdir_p(tmp_prefs_dir)
-        if self.copyfile(orig_path, tmp_file):
-            return
-        if self.write_to_file(os.path.join(tmp_prefs_dir, 'partner.js'),
-                              'pref("app.partner.%s", "%s");' % (partner, partner)
-                              ) is None:
-            return
-        if self.run_command([unzip_bin, '-q', file_name, 'omni.ja'],
-                            error_list=ZipErrorList,
-                            return_type='num_errors',
-                            cwd=tmp_dir):
-            self.error("Can't extract omni.ja from %s!" % file_name)
-            return
-        if self.run_command([zip_bin, '-9r', 'omni.ja',
-                             'defaults/pref/partner.js'],
-                            error_list=ZipErrorList,
-                            return_type='num_errors',
-                            cwd=tmp_dir):
-            self.error("Can't add partner.js to omni.ja!")
-            return
-        if self.run_command([zip_bin, '-9r', file_name, 'omni.ja'],
-                            error_list=ZipErrorList,
-                            return_type='num_errors',
-                            cwd=tmp_dir):
-            self.error("Can't re-add omni.ja to %s!" % file_name)
-            return
-        if self.unsign_apk(tmp_file):
-            return
-        repack_dir = os.path.dirname(repack_path)
-        self.mkdir_p(repack_dir)
-        if self.copyfile(tmp_file, repack_path):
-            return
-        return True
-
-    def repack(self):
-        c = self.config
-        rc = self.query_release_config()
-        dirs = self.query_abs_dirs()
-        locales = self.query_locales()
-        success_count = total_count = 0
-        for platform in c['platforms']:
-            for locale in locales:
-                installer_name = c['installer_base_names'][platform] % \
-                    {'version': rc['version'], 'locale': locale}
-                if self.query_failure(platform, locale):
-                    self.warning("%s:%s had previous issues; skipping!" % (platform, locale))
-                    continue
-                original_path = '%s/original/%s/%s/%s' % \
-                    (dirs['abs_work_dir'], platform, locale, installer_name)
-                for partner in c['partner_config'].keys():
-                    repack_path = '%s/unsigned/partner-repacks/%s/%s/%s/%s' % \
-                        (dirs['abs_work_dir'], partner, platform, locale, installer_name)
-                    total_count += 1
-                    if self._repack_apk(partner, original_path, repack_path):
-                        success_count += 1
-                    else:
-                        self.add_failure(platform, locale,
-                                         message="Unable to repack %(platform)s:%(locale)s "
-                                                 "installer!")
-        self.summarize_success_count(success_count, total_count,
-                                     message="Repacked %d of %d installers successfully.")
-
-    def _upload(self, dir_name="unsigned/partner-repacks"):
-        c = self.config
-        dirs = self.query_abs_dirs()
-        local_path = os.path.join(dirs['abs_work_dir'], dir_name)
-        rc = self.query_release_config()
-        replace_dict = {
-            'buildnum': rc['buildnum'],
-            'version': rc['version'],
-        }
-        remote_path = '%s/%s' % (c['ftp_upload_base_dir'] % replace_dict, dir_name)
-        if self.rsync_upload_directory(local_path, c['ftp_ssh_key'],
-                                       c['ftp_user'], c['ftp_server'],
-                                       remote_path):
-            self.return_code += 1
-
-    def upload_unsigned_bits(self):
-        self._upload()
-
-    # passphrase() in AndroidSigningMixin
-    # verify_passphrases() in AndroidSigningMixin
-
-    def preflight_sign(self):
-        if 'passphrase' not in self.actions:
-            self.passphrase()
-            self.verify_passphrases()
-
-    def sign(self):
-        c = self.config
-        rc = self.query_release_config()
-        dirs = self.query_abs_dirs()
-        locales = self.query_locales()
-        success_count = total_count = 0
-        for platform in c['platforms']:
-            for locale in locales:
-                installer_name = c['installer_base_names'][platform] % \
-                    {'version': rc['version'], 'locale': locale}
-                if self.query_failure(platform, locale):
-                    self.warning("%s:%s had previous issues; skipping!" % (platform, locale))
-                    continue
-                for partner in c['partner_config'].keys():
-                    unsigned_path = '%s/unsigned/partner-repacks/%s/%s/%s/%s' % \
-                        (dirs['abs_work_dir'], partner, platform, locale, installer_name)
-                    signed_dir = '%s/partner-repacks/%s/%s/%s' % \
-                        (dirs['abs_work_dir'], partner, platform, locale)
-                    signed_path = "%s/%s" % (signed_dir, installer_name)
-                    total_count += 1
-                    self.info("Signing %s %s." % (platform, locale))
-                    if not os.path.exists(unsigned_path):
-                        self.error("Missing apk %s!" % unsigned_path)
-                        continue
-                    if self.sign_apk(unsigned_path, c['keystore'],
-                                     self.store_passphrase, self.key_passphrase,
-                                     c['key_alias']) != 0:
-                        self.add_summary("Unable to sign %s:%s apk!" % (platform, locale),
-                                         level=FATAL)
-                    else:
-                        self.mkdir_p(signed_dir)
-                        if self.align_apk(unsigned_path, signed_path):
-                            self.add_failure(platform, locale,
-                                             message="Unable to align %(platform)s%(locale)s apk!")
-                            self.rmtree(signed_dir)
-                        else:
-                            success_count += 1
-        self.summarize_success_count(success_count, total_count,
-                                     message="Signed %d of %d apks successfully.")
-
-    # TODO verify signatures.
-
-    def upload_signed_bits(self):
-        self._upload(dir_name="partner-repacks")
-
-
-# main {{{1
-if __name__ == '__main__':
-    mobile_partner_repack = MobilePartnerRepack()
-    mobile_partner_repack.run_and_exit()
--- a/testing/web-platform/meta/2dcontext/drawing-paths-to-the-canvas/drawFocusIfNeeded_001.html.ini
+++ b/testing/web-platform/meta/2dcontext/drawing-paths-to-the-canvas/drawFocusIfNeeded_001.html.ini
@@ -1,6 +1,7 @@
 [drawFocusIfNeeded_001.html]
   disabled:
     if os == "win": https://bugzilla.mozilla.org/show_bug.cgi?id=1092458
   [drawFocusIfNeeded draws a focus ring.]
     expected:
       if not debug and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
+
--- a/testing/web-platform/meta/2dcontext/drawing-paths-to-the-canvas/drawFocusIfNeeded_005.html.ini
+++ b/testing/web-platform/meta/2dcontext/drawing-paths-to-the-canvas/drawFocusIfNeeded_005.html.ini
@@ -1,6 +1,7 @@
 [drawFocusIfNeeded_005.html]
   disabled:
     if os == "win": https://bugzilla.mozilla.org/show_bug.cgi?id=1092458
   [drawFocusIfNeeded does draw a focus ring if the element is in focus and the user activated a particular focus ring.]
     expected:
       if not debug and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
+
--- a/testing/web-platform/meta/IndexedDB/interfaces.any.js.ini
+++ b/testing/web-platform/meta/IndexedDB/interfaces.any.js.ini
@@ -1,4 +1,6 @@
 [interfaces.any.worker.html]
   [ImageBitmapRenderingContext interface: existence and properties of interface object]
     expected: FAIL
 
+
+[interfaces.any.html]
--- a/testing/web-platform/meta/MANIFEST.json
+++ b/testing/web-platform/meta/MANIFEST.json
@@ -185393,17 +185393,17 @@
      {}
     ]
    ],
    "svg/extensibility/foreignObject/foreign-object-paints-before-rect.html": [
     [
      "/svg/extensibility/foreignObject/foreign-object-paints-before-rect.html",
      [
       [
-       "/svg/extensibility/foreignObject/foreign-object-paints-before-rect-expected.html",
+       "/svg/extensibility/foreignObject/foreign-object-paints-before-rect-ref.html",
        "=="
       ]
      ],
      {}
     ]
    ],
    "svg/extensibility/foreignObject/foreign-object-size.html": [
     [
@@ -276678,16 +276678,26 @@
      {}
     ]
    ],
    "feature-policy/autoplay-disabled-by-feature-policy.https.sub.html.headers": [
     [
      {}
     ]
    ],
+   "feature-policy/experimental-features/resources/common.js": [
+    [
+     {}
+    ]
+   ],
+   "feature-policy/experimental-features/resources/document-stream-insertion.html": [
+    [
+     {}
+    ]
+   ],
    "feature-policy/experimental-features/resources/feature-policy-image.html": [
     [
      {}
     ]
    ],
    "feature-policy/experimental-features/resources/image.jpg": [
     [
      {}
@@ -277453,16 +277463,41 @@
      {}
     ]
    ],
    "fetch/nosniff/resources/worker.py": [
     [
      {}
     ]
    ],
+   "fetch/sec-metadata/README.md": [
+    [
+     {}
+    ]
+   ],
+   "fetch/sec-metadata/resources/echo-as-json.py": [
+    [
+     {}
+    ]
+   ],
+   "fetch/sec-metadata/resources/echo-as-script.py": [
+    [
+     {}
+    ]
+   ],
+   "fetch/sec-metadata/resources/helper.js": [
+    [
+     {}
+    ]
+   ],
+   "fetch/sec-metadata/resources/post-to-owner.py": [
+    [
+     {}
+    ]
+   ],
    "fetch/security/support/embedded-credential-window.sub.html": [
     [
      {}
     ]
    ],
    "fonts/AD.woff": [
     [
      {}
@@ -290843,16 +290878,21 @@
      {}
     ]
    ],
    "interfaces/background-fetch.idl": [
     [
      {}
     ]
    ],
+   "interfaces/battery.idl": [
+    [
+     {}
+    ]
+   ],
    "interfaces/budget-api.idl": [
     [
      {}
     ]
    ],
    "interfaces/clipboard-apis.idl": [
     [
      {}
@@ -291043,16 +291083,21 @@
      {}
     ]
    ],
    "interfaces/url.idl": [
     [
      {}
     ]
    ],
+   "interfaces/vibration.idl": [
+    [
+     {}
+    ]
+   ],
    "interfaces/wake-lock.idl": [
     [
      {}
     ]
    ],
    "interfaces/web-animations.idl": [
     [
      {}
@@ -299463,17 +299508,17 @@
      {}
     ]
    ],
    "svg/README.md": [
     [
      {}
     ]
    ],
-   "svg/extensibility/foreignObject/foreign-object-paints-before-rect-expected.html": [
+   "svg/extensibility/foreignObject/foreign-object-paints-before-rect-ref.html": [
     [
      {}
     ]
    ],
    "svg/extensibility/foreignObject/foreign-object-size-ref.html": [
     [
      {}
     ]
@@ -326737,16 +326782,22 @@
     ]
    ],
    "css/cssom-view/elementsFromPoint-simple.html": [
     [
      "/css/cssom-view/elementsFromPoint-simple.html",
      {}
     ]
    ],
+   "css/cssom-view/elementsFromPoint-svg-text.html": [
+    [
+     "/css/cssom-view/elementsFromPoint-svg-text.html",
+     {}
+    ]
+   ],
    "css/cssom-view/elementsFromPoint-svg.html": [
     [
      "/css/cssom-view/elementsFromPoint-svg.html",
      {}
     ]
    ],
    "css/cssom-view/elementsFromPoint-table.html": [
     [
@@ -332753,16 +332804,22 @@
    "feature-policy/autoplay-disabled-by-feature-policy.https.sub.html": [
     [
      "/feature-policy/autoplay-disabled-by-feature-policy.https.sub.html",
      {
       "testdriver": true
      }
     ]
    ],
+   "feature-policy/experimental-features/document-stream-insertion.tentative.html": [
+    [
+     "/feature-policy/experimental-features/document-stream-insertion.tentative.html",
+     {}
+    ]
+   ],
    "feature-policy/experimental-features/unsized-image.tentative.https.sub.html": [
     [
      "/feature-policy/experimental-features/unsized-image.tentative.https.sub.html",
      {}
     ]
    ],
    "feature-policy/experimental-features/vertical-scroll-scrollintoview.tentative.html": [
     [
@@ -334091,16 +334148,48 @@
     ]
    ],
    "fetch/nosniff/worker.html": [
     [
      "/fetch/nosniff/worker.html",
      {}
     ]
    ],
+   "fetch/sec-metadata/fetch.tentative.https.sub.html": [
+    [
+     "/fetch/sec-metadata/fetch.tentative.https.sub.html",
+     {}
+    ]
+   ],
+   "fetch/sec-metadata/iframe.tentative.https.sub.html": [
+    [
+     "/fetch/sec-metadata/iframe.tentative.https.sub.html",
+     {}
+    ]
+   ],
+   "fetch/sec-metadata/img.tentative.https.sub.html": [
+    [
+     "/fetch/sec-metadata/img.tentative.https.sub.html",
+     {}
+    ]
+   ],
+   "fetch/sec-metadata/script.tentative.https.sub.html": [
+    [
+     "/fetch/sec-metadata/script.tentative.https.sub.html",
+     {}
+    ]
+   ],
+   "fetch/sec-metadata/window-open.tentative.https.sub.html": [
+    [
+     "/fetch/sec-metadata/window-open.tentative.https.sub.html",
+     {
+      "testdriver": true
+     }
+    ]
+   ],
    "fetch/security/dangling-markup-mitigation-data-url.tentative.sub.html": [
     [
      "/fetch/security/dangling-markup-mitigation-data-url.tentative.sub.html",
      {}
     ]
    ],
    "fetch/security/dangling-markup-mitigation.tentative.html": [
     [
@@ -334853,16 +334942,28 @@
     ]
    ],
    "html/browsers/browsing-the-web/scroll-to-fragid/forward-triggers-hashchange.html": [
     [
      "/html/browsers/browsing-the-web/scroll-to-fragid/forward-triggers-hashchange.html",
      {}
     ]
    ],
+   "html/browsers/browsing-the-web/scroll-to-fragid/fragment-and-encoding-2.html": [
+    [
+     "/html/browsers/browsing-the-web/scroll-to-fragid/fragment-and-encoding-2.html",
+     {}
+    ]
+   ],
+   "html/browsers/browsing-the-web/scroll-to-fragid/fragment-and-encoding.html": [
+    [
+     "/html/browsers/browsing-the-web/scroll-to-fragid/fragment-and-encoding.html",
+     {}
+    ]
+   ],
    "html/browsers/browsing-the-web/scroll-to-fragid/replacement-enabled.html": [
     [
      "/html/browsers/browsing-the-web/scroll-to-fragid/replacement-enabled.html",
      {}
     ]
    ],
    "html/browsers/browsing-the-web/scroll-to-fragid/scroll-frag-percent-encoded.html": [
     [
@@ -339801,16 +339902,22 @@
     ]
    ],
    "html/semantics/embedded-content/media-elements/track/track-element/track-remove-quickly.html": [
     [
      "/html/semantics/embedded-content/media-elements/track/track-element/track-remove-quickly.html",
      {}
     ]
    ],
+   "html/semantics/embedded-content/media-elements/track/track-element/track-remove-track-inband.html": [
+    [
+     "/html/semantics/embedded-content/media-elements/track/track-element/track-remove-track-inband.html",
+     {}
+    ]
+   ],
    "html/semantics/embedded-content/media-elements/track/track-element/track-remove-track.html": [
     [
      "/html/semantics/embedded-content/media-elements/track/track-element/track-remove-track.html",
      {}
     ]
    ],
    "html/semantics/embedded-content/media-elements/track/track-element/track-selection-metadata.html": [
     [
@@ -411679,17 +411786,17 @@
    "b4df9429c1ff9ace253fb40296b20c06f8eb5eb3",
    "testharness"
   ],
   "battery-status/battery-insecure-context.html": [
    "39639373d161846186cbcb7eb33466493bcc77ad",
    "testharness"
   ],
   "battery-status/battery-interface-idlharness.https.html": [
-   "6782a2da1811570e601d44422c385bc33f97cd70",
+   "0390a5ad8de487a38e9b981ae61786c33c980222",
    "testharness"
   ],
   "battery-status/battery-plugging-in-manual.https.html": [
    "1d7e354f498cf967bdf5dad3b2f696d7606dd3f6",
    "manual"
   ],
   "battery-status/battery-promise-window.https.html": [
    "47ee9801dd697228defd4e3be6a79ed6fe9af602",
@@ -434775,17 +434882,17 @@
    "9cf4e4db6b0a74fa25f1ab500e91acf90b1c9db6",
    "support"
   ],
   "cors/resources/checkandremove.py": [
    "d891a6e489124e4ef7f82faa51a5e2a7221925f9",
    "support"
   ],
   "cors/resources/cors-cookie.py": [
-   "ab7074e4617a011d87d65043c71d01e96461a10b",
+   "c130e870b243bb52823c676575721bf1fb48981b",
    "support"
   ],
   "cors/resources/cors-headers.asis": [
    "758f91ae0ce63c2f3f273a3588bea290d208e0d2",
    "support"
   ],
   "cors/resources/cors-makeheader.py": [
    "153ae440de7512da3001507010b5ef7bbbfb391e",
@@ -434799,17 +434906,17 @@
    "d57c82ffc41dd9d78ea69df75dc11aa6a626f660",
    "support"
   ],
   "cors/resources/remote-xhrer.html": [
    "c942d5cf7950ebd9b968654a06d3a616f80ce9c2",
    "support"
   ],
   "cors/resources/status.py": [
-   "e1625a72475434c8efb1fddaa6f073379227fb59",
+   "fbcf78c5ee7c8dd4904de613017edf590f486766",
    "support"
   ],
   "cors/response-headers.htm": [
    "e26f213e67940865d3d535f9fa173c999dbef31e",
    "testharness"
   ],
   "cors/simple-requests.htm": [
    "608ea76c3209d7e803b4d4c1b02035e8493d52d5",
@@ -545678,16 +545785,20 @@
   "css/cssom-view/elementsFromPoint-shadowroot.html": [
    "e87feae5f1e6add43a315b8a3a7035e75708354a",
    "testharness"
   ],
   "css/cssom-view/elementsFromPoint-simple.html": [
    "19a0b3be6c48753390e72565e5c5020b35e54da5",
    "testharness"
   ],
+  "css/cssom-view/elementsFromPoint-svg-text.html": [
+   "2558de194a2f824181bead014c78787ece2d230f",
+   "testharness"
+  ],
   "css/cssom-view/elementsFromPoint-svg.html": [
    "2aef08e76167d67ca80f2f993d249692c7cc8ff8",
    "testharness"
   ],
   "css/cssom-view/elementsFromPoint-table.html": [
    "b3edbc3743a4c62125580846346f28aa8652242e",
    "testharness"
   ],
@@ -561103,17 +561214,17 @@
    "ea956ff139f386abf52226d981dbb5ec0e3f2a38",
    "testharness"
   ],
   "encoding/api-surrogates-utf8.html": [
    "e44be4c30e9c65a4b51972efab2e161f166d58a5",
    "testharness"
   ],
   "encoding/big5-encoder.html": [
-   "c5fec0f733b77620267488917cf54554c766801f",
+   "b9635c43ce159e1961106b039dce0e3d04fade34",
    "testharness"
   ],
   "encoding/eof-shift_jis-ref.html": [
    "55ac2be8c2cce3bae0ea1e61f5c330c38adc1e9e",
    "support"
   ],
   "encoding/eof-shift_jis.html": [
    "c5f6bd10724c2186f9c3347a8eca29627c8fcb5d",
@@ -561143,29 +561254,29 @@
    "dd855efd3ea7bd865c35c105506473fb7731bc36",
    "reftest"
   ],
   "encoding/gb18030-encoder.html": [
    "6f091a64de33492bd17ecbd37f5db0fff9af499a",
    "testharness"
   ],
   "encoding/gbk-encoder.html": [
-   "d099c6f374df5e68dd44bd6fe6115c415e74e91c",
+   "30bdfc96ffaff0277ceca69aad43d82d5ac691b6",
    "testharness"
   ],
   "encoding/idlharness.any.js": [
    "d37d060ee1ab2b54cf4dccc2cb80796771324ef7",
    "testharness"
   ],
   "encoding/iso-2022-jp-decoder.html": [
    "c189c2f99ee066e9419fdebef5d620edf97cd785",
    "testharness"
   ],
   "encoding/iso-2022-jp-encoder.html": [
-   "3e1ef3ebcb1f0c15251dd968848b9e6805aa8b90",
+   "771631eca687f2d4abbf7cb9337af4ecded432e4",
    "testharness"
   ],
   "encoding/legacy-mb-japanese/euc-jp/eucjp-decode-cseucpkdfmtjapanese.html": [
    "aef28a54f483ec66edbd9b0ea500d25f3966c4cb",
    "testharness"
   ],
   "encoding/legacy-mb-japanese/euc-jp/eucjp-decode-errors.html": [
    "0bbba500ce6e111c148ecd183d53d57c73f1416a",
@@ -561187,33 +561298,33 @@
    "42ac7feefc19dc6ef09ff292bc8584dd376802a2",
    "testharness"
   ],
   "encoding/legacy-mb-japanese/euc-jp/eucjp-encode-form-cseucpkdfmtjapanese.html.headers": [
    "6234bafffab6905a737ea67db52607d73c4de007",
    "support"
   ],
   "encoding/legacy-mb-japanese/euc-jp/eucjp-encode-form-errors-han.html": [
-   "8a1e3421b49173a03f55447b13e0fa8991e0114c",
+   "64fcbe6783d68372c9a03a1e732ad7acbfff925f",
    "testharness"
   ],
   "encoding/legacy-mb-japanese/euc-jp/eucjp-encode-form-errors-han.html.headers": [
    "eb7a01db0993ccbc3c5a3463b1a579d317b7fe1f",
    "support"
   ],
   "encoding/legacy-mb-japanese/euc-jp/eucjp-encode-form-errors-hangul.html": [
-   "2d0c46478ea701ab05824b0f334da16fb42c34b0",
+   "e7897095737650b30287cf4e618f5502d8bf86e2",
    "testharness"
   ],
   "encoding/legacy-mb-japanese/euc-jp/eucjp-encode-form-errors-hangul.html.headers": [
    "eb7a01db0993ccbc3c5a3463b1a579d317b7fe1f",
    "support"
   ],
   "encoding/legacy-mb-japanese/euc-jp/eucjp-encode-form-errors-misc.html": [
-   "a838bc3715b451abf71ab6033da96ac3661a0fcb",
+   "f4245d39d4435d9c00b981d220677ff0e3579106",
    "testharness"
   ],
   "encoding/legacy-mb-japanese/euc-jp/eucjp-encode-form-errors-misc.html.headers": [
    "eb7a01db0993ccbc3c5a3463b1a579d317b7fe1f",
    "support"
   ],
   "encoding/legacy-mb-japanese/euc-jp/eucjp-encode-form-x-euc-jp.html": [
    "2b4e86fdf26006eefd3ac5093bda1d02258b0121",
@@ -561227,33 +561338,33 @@
    "18240913dc69be3419e51987315842b3168253c8",
    "testharness"
   ],
   "encoding/legacy-mb-japanese/euc-jp/eucjp-encode-form.html.headers": [
    "eb7a01db0993ccbc3c5a3463b1a579d317b7fe1f",
    "support"
   ],
   "encoding/legacy-mb-japanese/euc-jp/eucjp-encode-href-errors-han.html": [
-   "7d40adac42aa7984b271d38d08f34bdc57956e81",
+   "3ff8533d6e7c59ea4a2fe98255e140b7b583ef2c",
    "testharness"
   ],
   "encoding/legacy-mb-japanese/euc-jp/eucjp-encode-href-errors-han.html.headers": [
    "eb7a01db0993ccbc3c5a3463b1a579d317b7fe1f",
    "support"
   ],
   "encoding/legacy-mb-japanese/euc-jp/eucjp-encode-href-errors-hangul.html": [
-   "7a6264e73b6f555b55307d4316b64b685bc4eed8",
+   "eeb61c360f85949479c970652c81532d27e38892",
    "testharness"
   ],
   "encoding/legacy-mb-japanese/euc-jp/eucjp-encode-href-errors-hangul.html.headers": [
    "eb7a01db0993ccbc3c5a3463b1a579d317b7fe1f",
    "support"
   ],
   "encoding/legacy-mb-japanese/euc-jp/eucjp-encode-href-errors-misc.html": [
-   "94a2d523cca2484c1646ea38cc35463104bcdf6a",
+   "6c1e0582aae5a1dc83ea286feebebe69c6e218e8",
    "testharness"
   ],
   "encoding/legacy-mb-japanese/euc-jp/eucjp-encode-href-errors-misc.html.headers": [
    "eb7a01db0993ccbc3c5a3463b1a579d317b7fe1f",
    "support"
   ],
   "encoding/legacy-mb-japanese/euc-jp/eucjp-encode-href.html": [
    "d0e0236048f578b35a5956295d2a295660a2c297",
@@ -561327,33 +561438,33 @@
    "d3751457c76d5dacd10a7dad1f22ceb7837c68a2",
    "testharness"
   ],
   "encoding/legacy-mb-japanese/iso-2022-jp/iso2022jp-encode-form-csiso2022jp.html.headers": [
    "41346529f39267656c8061d183165a30998c8e47",
    "support"
   ],
   "encoding/legacy-mb-japanese/iso-2022-jp/iso2022jp-encode-form-errors-han.html": [
-   "56eac9997ca4620ae3f60ac94f4746f16ad69398",
+   "d2cbf81979d2755352b9f007c40a6340b60e74d3",
    "testharness"
   ],
   "encoding/legacy-mb-japanese/iso-2022-jp/iso2022jp-encode-form-errors-han.html.headers": [
    "cb27b3ae6b3fb2d85f462cb5a1d0e703a3379e5c",
    "support"
   ],
   "encoding/legacy-mb-japanese/iso-2022-jp/iso2022jp-encode-form-errors-hangul.html": [
-   "04b9ba862024429668725770249a13a93118a1ce",
+   "b6b1deba45ea2621747d292443758adfb075e27e",
    "testharness"
   ],
   "encoding/legacy-mb-japanese/iso-2022-jp/iso2022jp-encode-form-errors-hangul.html.headers": [
    "cb27b3ae6b3fb2d85f462cb5a1d0e703a3379e5c",
    "support"
   ],
   "encoding/legacy-mb-japanese/iso-2022-jp/iso2022jp-encode-form-errors-misc.html": [
-   "a10fb4f38065dce550f099b83dee5315b014d9bd",
+   "4cb2e185dedbd21c3632b7a31e883580e71b366f",
    "testharness"
   ],
   "encoding/legacy-mb-japanese/iso-2022-jp/iso2022jp-encode-form-errors-misc.html.headers": [
    "cb27b3ae6b3fb2d85f462cb5a1d0e703a3379e5c",
    "support"
   ],
   "encoding/legacy-mb-japanese/iso-2022-jp/iso2022jp-encode-form-errors-stateful.html": [
    "7bfe71aa388e967b487a0be868d1ebbdf1aef2a3",
@@ -561363,33 +561474,33 @@
    "89dd8a641b8eb05e47cc2d23dd452cdfc9f9dfc9",
    "testharness"
   ],
   "encoding/legacy-mb-japanese/iso-2022-jp/iso2022jp-encode-form.html.headers": [
    "cb27b3ae6b3fb2d85f462cb5a1d0e703a3379e5c",
    "support"
   ],
   "encoding/legacy-mb-japanese/iso-2022-jp/iso2022jp-encode-href-errors-han.html": [
-   "c250dd2597bf3e6b66d4bed1484363ee186197e3",
+   "cdc3fe8fc70539fc6415e2d3b43fda6f87d09262",
    "testharness"
   ],
   "encoding/legacy-mb-japanese/iso-2022-jp/iso2022jp-encode-href-errors-han.html.headers": [
    "cb27b3ae6b3fb2d85f462cb5a1d0e703a3379e5c",
    "support"
   ],
   "encoding/legacy-mb-japanese/iso-2022-jp/iso2022jp-encode-href-errors-hangul.html": [
-   "a54eafaa9c27429edf96650392d288805509f6a5",
+   "19c4224bda8f399f090f3ea4d77c10a0f47513e8",
    "testharness"
   ],
   "encoding/legacy-mb-japanese/iso-2022-jp/iso2022jp-encode-href-errors-hangul.html.headers": [
    "cb27b3ae6b3fb2d85f462cb5a1d0e703a3379e5c",
    "support"
   ],
   "encoding/legacy-mb-japanese/iso-2022-jp/iso2022jp-encode-href-errors-misc.html": [
-   "f4f427e139bf5d92c4982d108315733ce10c091c",
+   "a99791f74775a996f49e4b60a369d5b81d289c0d",
    "testharness"
   ],
   "encoding/legacy-mb-japanese/iso-2022-jp/iso2022jp-encode-href-errors-misc.html.headers": [
    "cb27b3ae6b3fb2d85f462cb5a1d0e703a3379e5c",
    "support"
   ],
   "encoding/legacy-mb-japanese/iso-2022-jp/iso2022jp-encode-href.html": [
    "d823114d271354e58578547d0de3b570d9705282",
@@ -561479,33 +561590,33 @@
    "22a6fef29cf831742bea680190d79a7ad9f7a344",
    "testharness"
   ],
   "encoding/legacy-mb-japanese/shift_jis/sjis-encode-form-csshiftjis.html.headers": [
    "d3b8133bd6e1dfc049db581bc8b8bb52b440cfae",
    "support"
   ],
   "encoding/legacy-mb-japanese/shift_jis/sjis-encode-form-errors-han.html": [
-   "84cd159f998e8e6ad80d0403d0128bd72718e674",
+   "034b3f10660076f877d7e78699cd5103d8c955f7",
    "testharness"
   ],
   "encoding/legacy-mb-japanese/shift_jis/sjis-encode-form-errors-han.html.headers": [
    "02a4097ff662201c4b3833abb6521c7a9e1235dc",
    "support"
   ],
   "encoding/legacy-mb-japanese/shift_jis/sjis-encode-form-errors-hangul.html": [
-   "125c9ecd59012aa5b4ad6c6dfaa7586d1f6b2593",
+   "abe031cce4bec1c40f37fcff428b874ef3ef1f76",
    "testharness"
   ],
   "encoding/legacy-mb-japanese/shift_jis/sjis-encode-form-errors-hangul.html.headers": [
    "02a4097ff662201c4b3833abb6521c7a9e1235dc",
    "support"
   ],
   "encoding/legacy-mb-japanese/shift_jis/sjis-encode-form-errors-misc.html": [
-   "0099dd77b846ad2771aa278070b85ebf1b577a77",
+   "dcba1f4b6755e55ed5dbfa3d2cff642324aa6c2a",
    "testharness"
   ],
   "encoding/legacy-mb-japanese/shift_jis/sjis-encode-form-errors-misc.html.headers": [
    "02a4097ff662201c4b3833abb6521c7a9e1235dc",
    "support"
   ],
   "encoding/legacy-mb-japanese/shift_jis/sjis-encode-form-ms932.html": [
    "81a3377b7bcef81ea1472c4751e8e8d4724a603b",
@@ -561559,33 +561670,33 @@
    "cfd117bfde470ed113357ebcb9d47a8f106c0ff0",
    "testharness"
   ],
   "encoding/legacy-mb-japanese/shift_jis/sjis-encode-form.html.headers": [
    "02a4097ff662201c4b3833abb6521c7a9e1235dc",
    "support"
   ],
   "encoding/legacy-mb-japanese/shift_jis/sjis-encode-href-errors-han.html": [
-   "a5ad64e3cfbd60d2f7df60c3708c66441a0511df",
+   "94990204891a673ed591a05bd4423b8d22a907ac",
    "testharness"
   ],
   "encoding/legacy-mb-japanese/shift_jis/sjis-encode-href-errors-han.html.headers": [
    "02a4097ff662201c4b3833abb6521c7a9e1235dc",
    "support"
   ],
   "encoding/legacy-mb-japanese/shift_jis/sjis-encode-href-errors-hangul.html": [
-   "c92ed9030f97d8e86fdafdb024fc7d32b0b87861",
+   "e3ef37abf1fb9d6a39f391c4e5a4b376cad808c8",
    "testharness"
   ],
   "encoding/legacy-mb-japanese/shift_jis/sjis-encode-href-errors-hangul.html.headers": [
    "02a4097ff662201c4b3833abb6521c7a9e1235dc",
    "support"
   ],
   "encoding/legacy-mb-japanese/shift_jis/sjis-encode-href-errors-misc.html": [
-   "cb8f12a62af6ea1be459ff8ca1c3e8846a8b9d55",
+   "a1cfb188c286c2f34d95fe2ca180dd577da1d7b5",
    "testharness"
   ],
   "encoding/legacy-mb-japanese/shift_jis/sjis-encode-href-errors-misc.html.headers": [
    "02a4097ff662201c4b3833abb6521c7a9e1235dc",
    "support"
   ],
   "encoding/legacy-mb-japanese/shift_jis/sjis-encode-href.html": [
    "8aec6118dd060483017b49e802cfe3ad30cef367",
@@ -561731,29 +561842,29 @@
    "569abb7b5211b3c404a8c5b73781fa576c471770",
    "testharness"
   ],
   "encoding/legacy-mb-korean/euc-kr/euckr-encode-form-csksc56011987.html.headers": [
    "1d83197942d969528458a09998b6070331d8ff1e",
    "support"
   ],
   "encoding/legacy-mb-korean/euc-kr/euckr-encode-form-errors-han.html": [
-   "ac3af4e3ae4831d6bbb4a10cf20165c8c6f6f0c0",
+   "f9710ba55e4f6781f14f7b292c767cf87fc40090",
    "testharness"
   ],
   "encoding/legacy-mb-korean/euc-kr/euckr-encode-form-errors-han.html.headers": [
    "c79f9150befa2f7ce67d17069da7fb66f7f22ca0",
    "support"
   ],
   "encoding/legacy-mb-korean/euc-kr/euckr-encode-form-errors-hangul.html.headers": [
    "c79f9150befa2f7ce67d17069da7fb66f7f22ca0",
    "support"
   ],
   "encoding/legacy-mb-korean/euc-kr/euckr-encode-form-errors-misc.html": [
-   "ac75e0cdb92edcec4ccbcea4e4d45329305fd4be",
+   "936dedf12d56abe3083061a68b6be806a8cb8503",
    "testharness"
   ],
   "encoding/legacy-mb-korean/euc-kr/euckr-encode-form-errors-misc.html.headers": [
    "c79f9150befa2f7ce67d17069da7fb66f7f22ca0",
    "support"
   ],
   "encoding/legacy-mb-korean/euc-kr/euckr-encode-form-iso-ir-149.html": [
    "5a480ddabd671ab24b9fbc6485ae1bb543787ddb",
@@ -561815,25 +561926,25 @@
    "934c25bf57b7a57390d38cc2f21230b16e142241",
    "testharness"
   ],
   "encoding/legacy-mb-korean/euc-kr/euckr-encode-form.html.headers": [
    "c79f9150befa2f7ce67d17069da7fb66f7f22ca0",
    "support"
   ],
   "encoding/legacy-mb-korean/euc-kr/euckr-encode-href-errors-han.html": [
-   "ad6ba78bc2ebc5b88b08ac19efe60f6220a1f636",
+   "e855d30690f5aed7043442f233cbb77fc209bca0",
    "testharness"
   ],
   "encoding/legacy-mb-korean/euc-kr/euckr-encode-href-errors-han.html.headers": [
    "c79f9150befa2f7ce67d17069da7fb66f7f22ca0",
    "support"
   ],
   "encoding/legacy-mb-korean/euc-kr/euckr-encode-href-errors-misc.html": [
-   "dce0fad843d12c98905f1bb3edbe5343f7849b0c",
+   "f4caa1544f2291f394f58a4835f1fb5962baac14",
    "testharness"
   ],
   "encoding/legacy-mb-korean/euc-kr/euckr-encode-href-errors-misc.html.headers": [
    "c79f9150befa2f7ce67d17069da7fb66f7f22ca0",
    "support"
   ],
   "encoding/legacy-mb-korean/euc-kr/euckr-encode-href.html": [
    "20b152603cbca961959653c8c042ea004f58334f",
@@ -561999,57 +562110,57 @@
    "ed5c833f250f1713193b56371298c73b4b412d50",
    "testharness"
   ],
   "encoding/legacy-mb-tchinese/big5/big5-encode-form-csbig5.html.headers": [
    "e6a39aaefd7bf7a8bccf1821248119ded43388f7",
    "support"
   ],
   "encoding/legacy-mb-tchinese/big5/big5-encode-form-errors-extBa.html": [
-   "158e2df87e89f8d10ac045a8c6d7b1a879c60c05",
+   "7201211915cb8ae3ac0b7f5656c295f3c08b3089",
    "testharness"
   ],
   "encoding/legacy-mb-tchinese/big5/big5-encode-form-errors-extBa.html.headers": [
    "17edf8b3f37188f85a7c4af654dd93026ac96825",
    "support"
   ],
   "encoding/legacy-mb-tchinese/big5/big5-encode-form-errors-extBb.html": [
-   "07fc6c15fc19b39e458670b19efc95d46822a889",
+   "3eb05f9627d84506e9d730b9e26021403963d0f9",
    "testharness"
   ],
   "encoding/legacy-mb-tchinese/big5/big5-encode-form-errors-extBb.html.headers": [
    "17edf8b3f37188f85a7c4af654dd93026ac96825",
    "support"
   ],
   "encoding/legacy-mb-tchinese/big5/big5-encode-form-errors-han.html": [
-   "0c4726348095a7b2a2954e4516bfad4b6bf64e59",
+   "d4e49734b115c0bf3f0ab2ddc7a3de4556866e9c",
    "testharness"
   ],
   "encoding/legacy-mb-tchinese/big5/big5-encode-form-errors-han.html.headers": [
    "17edf8b3f37188f85a7c4af654dd93026ac96825",
    "support"
   ],
   "encoding/legacy-mb-tchinese/big5/big5-encode-form-errors-hangul.html": [
-   "9835733d78de331c1ad9297572b321265a6a03c9",
+   "b24f67557b5e6ef966484b4c0b6b1c90a69b24ee",
    "testharness"
   ],
   "encoding/legacy-mb-tchinese/big5/big5-encode-form-errors-hangul.html.headers": [
    "17edf8b3f37188f85a7c4af654dd93026ac96825",
    "support"
   ],
   "encoding/legacy-mb-tchinese/big5/big5-encode-form-errors-misc.html": [
-   "65056fd448b1783a93866c6dfe4f0f84ecc65058",
+   "f4ce13cd0e392452ce160d0b688315ef039e2e56",
    "testharness"
   ],
   "encoding/legacy-mb-tchinese/big5/big5-encode-form-errors-misc.html.headers": [
    "17edf8b3f37188f85a7c4af654dd93026ac96825",
    "support"
   ],
   "encoding/legacy-mb-tchinese/big5/big5-encode-form-errors-pua.html": [
-   "836a669b04de5ba3a3c3c429ea7d89b67d6f58b4",
+   "4e83b4a9d2695780b0ad87ac8519f36b83778ee6",
    "testharness"
   ],
   "encoding/legacy-mb-tchinese/big5/big5-encode-form-x-x-big5.html": [
    "6014d5a50918d4d16389df0c7a07f71bd78babeb",
    "testharness"
   ],
   "encoding/legacy-mb-tchinese/big5/big5-encode-form-x-x-big5.html.headers": [
    "be6965af1c7bddb506b6fa2030d4386d1d4b1274",
@@ -562059,33 +562170,33 @@
    "3d272e5b51ca3bcd8bb34807024df71807da3c05",
    "testharness"
   ],
   "encoding/legacy-mb-tchinese/big5/big5-encode-form.html.headers": [
    "17edf8b3f37188f85a7c4af654dd93026ac96825",
    "support"
   ],
   "encoding/legacy-mb-tchinese/big5/big5-encode-href-errors-han.html": [
-   "b0f2f3bd2bad4eb4b2979bf8c11105f6c0a42dd8",
+   "90cbc57fb49501ff276c2198235f0d5c2d5561eb",
    "testharness"
   ],
   "encoding/legacy-mb-tchinese/big5/big5-encode-href-errors-han.html.headers": [
    "17edf8b3f37188f85a7c4af654dd93026ac96825",
    "support"
   ],
   "encoding/legacy-mb-tchinese/big5/big5-encode-href-errors-hangul.html": [
-   "c6850b7f03fbfd76bfc156593d7e75887799baa4",
+   "2ec76262a6bc1a789999fd51b394a66a878bc6bf",
    "testharness"
   ],
   "encoding/legacy-mb-tchinese/big5/big5-encode-href-errors-hangul.html.headers": [
    "17edf8b3f37188f85a7c4af654dd93026ac96825",
    "support"
   ],
   "encoding/legacy-mb-tchinese/big5/big5-encode-href-errors-misc.html": [
-   "493dd0361da6e0ce711e05e90fd3a40125be5ba3",
+   "ba76ce0d3d04f97074c712ce6b11a7d6b523fb33",
    "testharness"
   ],
   "encoding/legacy-mb-tchinese/big5/big5-encode-href-errors-misc.html.headers": [
    "17edf8b3f37188f85a7c4af654dd93026ac96825",
    "support"
   ],
   "encoding/legacy-mb-tchinese/big5/big5-encode-href.html": [
    "6df38fd56a6eee0b2a8fbe84dc62258fef405ea9",
@@ -563418,16 +563529,28 @@
   "feature-policy/autoplay-disabled-by-feature-policy.https.sub.html": [
    "172558a2135fc066b69d91d4b340a3fc5e49d2c1",
    "testharness"
   ],
   "feature-policy/autoplay-disabled-by-feature-policy.https.sub.html.headers": [
    "4239ec4ef240e199f15a38145d478d2c0aa43ad2",
    "support"
   ],
+  "feature-policy/experimental-features/document-stream-insertion.tentative.html": [
+   "ec2c7269eff25b93d40b233ba0e17c69d31404e9",
+   "testharness"
+  ],
+  "feature-policy/experimental-features/resources/common.js": [
+   "36dd671a85ed93f2e69927c843243cb953f82a97",
+   "support"
+  ],
+  "feature-policy/experimental-features/resources/document-stream-insertion.html": [
+   "a0e39689056dc5cc24ad2d7e6fb2c681e84fd35d",
+   "support"
+  ],
   "feature-policy/experimental-features/resources/feature-policy-image.html": [
    "7ac7a5803b60a4f95b454aa44e0a79f363cffade",
    "support"
   ],
   "feature-policy/experimental-features/resources/image.jpg": [
    "8edf07742134d02b486ee8bdb5fa8e9043875183",
    "support"
   ],
@@ -563443,37 +563566,37 @@
    "7be60c6f51698ea1e63030bf94aad995881e0049",
    "support"
   ],
   "feature-policy/experimental-features/resources/vertical-scroll-touch-action.html": [
    "a85e54c23c9e055c959a86187d07f1c0d943f37d",
    "support"
   ],
   "feature-policy/experimental-features/resources/vertical-scroll.js": [
-   "cfa86de92596fa755d2c3a001b2c33f74283665a",
+   "a62c440428fe22a7afd4d8174e47dfc483c7de90",
    "support"
   ],
   "feature-policy/experimental-features/resources/video.ogv": [
    "7c6d80135c0688eb5ef5e79351c8ebbd24cb7d77",
    "support"
   ],
   "feature-policy/experimental-features/unsized-image.tentative.https.sub.html": [
    "ac063a3e3084a9416a272bbac413016124e5289f",
    "testharness"
   ],
   "feature-policy/experimental-features/unsized-image.tentative.https.sub.html.headers": [
    "2ae1da8e026e63625a6168b842303cc156963ced",
    "support"
   ],
   "feature-policy/experimental-features/vertical-scroll-scrollintoview.tentative.html": [
-   "fe6000c242c73c81b5fc3c227f7703299fea455c",
+   "032bcf5ef253650570c3ded97090aab45da2661c",
    "testharness"
   ],
   "feature-policy/experimental-features/vertical-scroll-touch-action-manual.tentative.html": [
-   "bdaef76d16a826efebedade2127f006c5c3a49ea",
+   "32f1b7eacf4de1d7d792bb27ca439636c242c29c",
    "manual"
   ],
   "feature-policy/feature-policy-frame-policy-allowed-for-all.https.sub.html": [
    "a48c092204750e00c9aa167a9ef9d2d239445d22",
    "testharness"
   ],
   "feature-policy/feature-policy-frame-policy-allowed-for-all.https.sub.html.sub.headers": [
    "bfcf350d87faae8e6cf4b2beb9fee84957cac449",
@@ -564247,37 +564370,37 @@
    "2af02f3ecf8449c91f2f1d28effc3478a4bfc235",
    "testharness"
   ],
   "fetch/api/request/request-type-attribute-historical.html": [
    "68620f3ea16b7ae1a9f1efde1cd0bb47f1150b9f",
    "testharness"
   ],
   "fetch/api/request/resources/cache.py": [
-   "3cd7d5191fe33b2f2dab571a4b006d8332fdf42e",
+   "fa831de695ef775b03a2b89a6cb691636b26027f",
    "support"
   ],
   "fetch/api/request/resources/hello.txt": [
    "f572d396fae9206628714fb2ce00f72e94f2258f",
    "support"
   ],
   "fetch/api/request/resources/request-reset-attributes-worker.js": [
    "cde1835ecc64d416df0a25a8cdd1d2bcc3f38431",
    "support"
   ],
   "fetch/api/request/url-encoding.html": [
    "1f8a8e00c5c1ba5ae9995ca6561801479b487b3a",
    "testharness"
   ],
   "fetch/api/resources/authentication.py": [
-   "b915aef6ecaacf3484e7a1144ed4769c4ff36539",
+   "3664b86c40d0b5965aa5f9625ff65ea4960b1c30",
    "support"
   ],
   "fetch/api/resources/bad-chunk-encoding.py": [
-   "a916571cccadbe7dcc59ae1fa60f968b28d1ef47",
+   "7011a780dfe97baf32e83925bbaf8b13abcc76b8",
    "support"
   ],
   "fetch/api/resources/basic.html": [
    "eccdc121af21a750b7b75697402fc90b54c070cc",
    "support"
   ],
   "fetch/api/resources/cache.py": [
    "fe01c89d7bef1b6385f29250a0b458024b3e28ca",
@@ -564307,37 +564430,37 @@
    "da39a3ee5e6b4b0d3255bfef95601890afd80709",
    "support"
   ],
   "fetch/api/resources/infinite-slow-response.py": [
    "dee0fa986bf9ce4fd5cd5127a9945caf1b1a4e6f",
    "support"
   ],
   "fetch/api/resources/inspect-headers.py": [
-   "c062c905d538cfa96156fd38d98f586b2c4fb3b5",
+   "44e40ee48d2bfc3c49126b32027ee9db6176ec38",
    "support"
   ],
   "fetch/api/resources/keepalive-iframe.html": [
    "4bd91cabbc1bddb966320aa28b3caaa9d06a514d",
    "support"
   ],
   "fetch/api/resources/method.py": [
    "9ad4c5907e6fa4d8c4bca085f637af92db0f38f3",
    "support"
   ],
   "fetch/api/resources/preflight.py": [
-   "de99c8990074a9f248989cebe7cf1adb0f4ec84b",
+   "cbc167808023cbb09cc0a362cc27250ecabf8df8",
    "support"
   ],
   "fetch/api/resources/redirect-empty-location.py": [
    "cbf1d7b4ee75f79144114c3444337d4c1fc30402",
    "support"
   ],
   "fetch/api/resources/redirect.py": [
-   "37307bdb30853c2e824cce1fd9a190741e4975ce",
+   "0cc024ff5930697fdd7226608cb5990a614ccafd",
    "support"
   ],
   "fetch/api/resources/script-with-header.py": [
    "07a90ffa656f67c9774d8080f80456e81750dc0c",
    "support"
   ],
   "fetch/api/resources/stash-put.py": [
    "c7619b1c9d5616bfcdd4c1dc8bc680ab291c8e7e",
@@ -564355,17 +564478,17 @@
    "833e7b3a3cd91a6b0482e1a1159aaed59fd63341",
    "support"
   ],
   "fetch/api/resources/top.txt": [
    "af2c7b4ca07ae6c74d261bc745e174df8ab3ffef",
    "support"
   ],
   "fetch/api/resources/trickle.py": [
-   "87a83b390ae91e4419dc580d8426277be48c92d8",
+   "361d2743163bf55621bb0ff3feba4d99a0768beb",
    "support"
   ],
   "fetch/api/resources/utils.js": [
    "d9e65bbd408a906a4d14aa40d4ed20ea2ed9f585",
    "support"
   ],
   "fetch/api/response/multi-globals/current/current.html": [
    "2d9ab238e07a88d19365f78bfd5db84d32854de1",
@@ -564699,17 +564822,17 @@
    "848a26000ed9bf4c61516201e4006b97839bee11",
    "testharness"
   ],
   "fetch/http-cache/partial.html": [
    "685057fe8876321a5d42bcf1e7582e6f0b745f85",
    "testharness"
   ],
   "fetch/http-cache/resources/http-cache.py": [
-   "f2e102b289c8ef55628800ae07b3737367ecbf65",
+   "00b65e27915c5d16f0de04821eacc675b32e4ee7",
    "support"
   ],
   "fetch/http-cache/resources/securedimage.py": [
    "e1206a227bf8641abee0900391fd6e500973ab78",
    "support"
   ],
   "fetch/http-cache/status.html": [
    "dac72c83edb75519e8ef5c3324442def4f380349",
@@ -564731,25 +564854,25 @@
    "625178211adedea920694a0ed2687b9eea77f20e",
    "support"
   ],
   "fetch/nosniff/parsing-nosniff.html": [
    "fd2e9c181ca043cfe6c99650232d76cf27229ee4",
    "testharness"
   ],
   "fetch/nosniff/resources/css.py": [
-   "4ae9ff638587fcc96472709e31466a469061a3b0",
+   "5f581aea8cfcc09fe6efbc6eaf0695804cca32bb",
    "support"
   ],
   "fetch/nosniff/resources/image.py": [
-   "82bd978c186e3b468d5e3a15623718484fec926e",
+   "2018bb1c6058b9c7a78ec9e59e51308d52ded541",
    "support"
   ],
   "fetch/nosniff/resources/js.py": [
-   "82dfe26fa136b2158040554a752e06bdeb503909",
+   "798cfa4cec411e5620279c77f948b0a3ed48624a",
    "support"
   ],
   "fetch/nosniff/resources/nosniff-first.asis": [
    "e3c535667ddc841f828d0237bd7be6723b1281d6",
    "support"
   ],
   "fetch/nosniff/resources/nosniff-last.asis": [
    "155d7b63e3242824ddf6ed99fb6a7ae460b2f67f",
@@ -564767,31 +564890,71 @@
    "a7619448c9035ddaaba3b766b07627d383ade078",
    "support"
   ],
   "fetch/nosniff/resources/nosniff-uppercase.asis": [
    "7592cc8f686efff71900db77f1cc5033eeeaf11d",
    "support"
   ],
   "fetch/nosniff/resources/worker.py": [
-   "e6b1f991560ed3b7f09b0e78722674e83a2de870",
+   "559f693c7411f8d575282cf77380a2179c06281b",
    "support"
   ],
   "fetch/nosniff/script.html": [
    "aae78384af3ed1871602eac5a5fa26467d997578",
    "testharness"
   ],
   "fetch/nosniff/stylesheet.html": [
    "32dd5cdbc638ac7c141036633e136137854c3bb4",
    "testharness"
   ],
   "fetch/nosniff/worker.html": [
    "a9e0f5b9b70917aabbff3ad5dd03a5d5dccfa9f0",
    "testharness"
   ],
+  "fetch/sec-metadata/README.md": [
+   "75d58b35c1e5572d02dd3ad90ac65301e35c4bc7",
+   "support"
+  ],
+  "fetch/sec-metadata/fetch.tentative.https.sub.html": [
+   "6ce26d3683b78ca74a20b14ccca077cf375d742b",
+   "testharness"
+  ],
+  "fetch/sec-metadata/iframe.tentative.https.sub.html": [
+   "0308cd613a3099bf04469fba6273f46db991d49c",
+   "testharness"
+  ],
+  "fetch/sec-metadata/img.tentative.https.sub.html": [
+   "63a6c8a45102527079acb81d1c57d5dc49c07e4b",
+   "testharness"
+  ],
+  "fetch/sec-metadata/resources/echo-as-json.py": [
+   "bbe86e17580229158500722115a1347ca8fa2abb",
+   "support"
+  ],
+  "fetch/sec-metadata/resources/echo-as-script.py": [
+   "f3de57b64101ddcff326bbef8132a905d31356ce",
+   "support"
+  ],
+  "fetch/sec-metadata/resources/helper.js": [
+   "64d204e36b6ab3b7268d6fd8e0694081222b98ee",
+   "support"
+  ],
+  "fetch/sec-metadata/resources/post-to-owner.py": [
+   "2f57a1ddf411864ad2b1ba75f95453d9ed54e3f6",
+   "support"
+  ],
+  "fetch/sec-metadata/script.tentative.https.sub.html": [
+   "147291288dacf51942cadc8a85f7842c3bf19b34",
+   "testharness"
+  ],
+  "fetch/sec-metadata/window-open.tentative.https.sub.html": [
+   "116c597fb1909f7c4a67c8ada3bfeb6c011d7b04",
+   "testharness"
+  ],
   "fetch/security/dangling-markup-mitigation-data-url.tentative.sub.html": [
    "1059b1c0907444bd416889f99d766a566ba9bde3",
    "testharness"
   ],
   "fetch/security/dangling-markup-mitigation.tentative.html": [
    "f7eb7151eb44f6b879beb325e923507f9430a3a5",
    "testharness"
   ],
@@ -566746,16 +566909,24 @@
   "html/browsers/browsing-the-web/scroll-to-fragid/007.html": [
    "7e24cd47a4ae882b40f7f8798a44faf05f034c3d",
    "testharness"
   ],
   "html/browsers/browsing-the-web/scroll-to-fragid/forward-triggers-hashchange.html": [
    "fb63063e0ff1ca6aaa350fae9b8f01bed5f9771f",
    "testharness"
   ],
+  "html/browsers/browsing-the-web/scroll-to-fragid/fragment-and-encoding-2.html": [
+   "62b3f908914b6b49c9b695f544a7e6489d3b9ec7",
+   "testharness"
+  ],
+  "html/browsers/browsing-the-web/scroll-to-fragid/fragment-and-encoding.html": [
+   "9ba63dfc8f2a9310830b6b5073d994a821369c01",
+   "testharness"
+  ],
   "html/browsers/browsing-the-web/scroll-to-fragid/navigate-helpers.js": [
    "5b318196cb31c35e1b39eccd9e6a131a882f1a90",
    "support"
   ],
   "html/browsers/browsing-the-web/scroll-to-fragid/replacement-enabled.html": [
    "c74f0c4c6b2a11d51b87ef7a14bc68c4b0fe0ecd",
    "testharness"
   ],
@@ -566839,17 +567010,17 @@
    "e57a52270dfe3d9e74fce1f30b6f0901367416af",
    "support"
   ],
   "html/browsers/browsing-the-web/unloading-documents/navigation-within-beforeunload-2.html": [
    "31468eafd917b460022dcb073ed5f057d2c4178b",
    "support"
   ],
   "html/browsers/browsing-the-web/unloading-documents/navigation-within-beforeunload.html": [
-   "8e48ede5ef227e88a091f1d33b385d0b3dff713c",
+   "49a3e27670f5902309f45be654ad9e12d7f9c500",
    "testharness"
   ],
   "html/browsers/browsing-the-web/unloading-documents/pagehide-on-history-forward-1.html": [
    "3aa8b42fe7937a02c3319cced4319292842eb450",
    "support"
   ],
   "html/browsers/browsing-the-web/unloading-documents/pagehide-on-history-forward.html": [
    "2b3a56895dbe6450ed38ebbb31a915c9e8b7abd6",
@@ -575159,17 +575330,17 @@
    "da39a3ee5e6b4b0d3255bfef95601890afd80709",
    "support"
   ],
   "html/infrastructure/urls/resolving-urls/.gitkeep": [
    "da39a3ee5e6b4b0d3255bfef95601890afd80709",
    "support"
   ],
   "html/infrastructure/urls/resolving-urls/query-encoding/location.sub.html": [
-   "bc42ced67ad1368f3cf459dd113b131c69aaba78",
+   "34aa7e5a7d4daba412fa700859913cf9def77565",
    "testharness"
   ],
   "html/infrastructure/urls/resolving-urls/query-encoding/resources/blank.py": [
    "e55787bc9f46f01aece15afed2ce0686d143dc03",
    "support"
   ],
   "html/infrastructure/urls/resolving-urls/query-encoding/resources/css-tmpl.py": [
    "d3c8152013bb23c76a4ce9f96a30dc453309bc88",
@@ -575179,17 +575350,17 @@
    "ac4bab3d195d554570b3b035093a2750a4fdfa01",
    "support"
   ],
   "html/infrastructure/urls/resolving-urls/query-encoding/resources/page-using-manifest.py": [
    "349a5e8aec778ee6cabac210226a01f14be904e1",
    "support"
   ],
   "html/infrastructure/urls/resolving-urls/query-encoding/resources/resolve-url.js": [
-   "70fd863f8335a2026d5755cf2ba7a01d98222ec0",
+   "03fc73b64f0fd6f80bbb5616da4a4528162638ee",
    "support"
   ],
   "html/infrastructure/urls/resolving-urls/query-encoding/resources/resource.py": [
    "1fe80369b002489cec48913f0a59c8099cef6461",
    "support"
   ],
   "html/infrastructure/urls/resolving-urls/query-encoding/resources/stash.py": [
    "0d599936f6a0baf6d9cce8d3236c146a159f1add",
@@ -578066,18 +578237,22 @@
   "html/semantics/embedded-content/media-elements/track/track-element/track-remove-insert-ready-state