Merge mozilla-central to autoland. CLOSED TREE
authorCsoregi Natalia <ncsoregi@mozilla.com>
Fri, 16 Nov 2018 00:19:45 +0200
changeset 503113 20e31516e9bb4fdab1be492a5105cd26f91cc5e7
parent 503112 eed15f1e00944954d89865708a7bf7e759fe3d50 (current diff)
parent 503045 0051c8d339a969d80b66e6ce243091a9dbb6a319 (diff)
child 503114 8f260179cc9fe83cc36b185ed8a03c7a1848ba1a
push id10290
push userffxbld-merge
push dateMon, 03 Dec 2018 16:23:23 +0000
treeherdermozilla-beta@700bed2445e6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone65.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge mozilla-central to autoland. CLOSED TREE
build/build-clang/rename_gcov_flush.patch
devtools/client/inspector/flexbox/components/FlexContainerProperties.js
media/mtransport/third_party/nICEr/src/net/nr_proxy_tunnel.c
media/mtransport/third_party/nICEr/src/net/nr_proxy_tunnel.h
netwerk/protocol/http/nsHttpChannel.cpp
--- a/browser/config/mozconfigs/linux64/asan-fuzzing-ccov
+++ b/browser/config/mozconfigs/linux64/asan-fuzzing-ccov
@@ -18,17 +18,17 @@ ac_add_options --disable-elf-hack
 
 ac_add_options --disable-sandbox
 ac_add_options --disable-profiling
 ac_add_options --disable-warnings-as-errors
 ac_add_options --enable-coverage
 
 export CFLAGS="--coverage"
 export CXXFLAGS="--coverage"
-export LDFLAGS="--coverage"
+export LDFLAGS="--coverage -Wl,--compress-debug-sections=zlib"
 
 ac_add_options --enable-fuzzing
 unset MOZ_STDCXX_COMPAT
 
 # Package js shell.
 export MOZ_PACKAGE_JSSHELL=1
 
 # Need this to prevent name conflicts with the normal nightly build packages
--- a/browser/config/mozconfigs/linux64/fuzzing-ccov
+++ b/browser/config/mozconfigs/linux64/fuzzing-ccov
@@ -1,16 +1,3 @@
-MOZ_AUTOMATION_L10N_CHECK=0
-
-. "$topsrcdir/browser/config/mozconfigs/linux64/nightly"
+. "$topsrcdir/browser/config/mozconfigs/linux64/code-coverage-opt"
 
-ac_add_options --disable-install-strip
-ac_add_options --disable-elf-hack
-ac_add_options --disable-sandbox
-ac_add_options --disable-dmd
-ac_add_options --disable-profiling
-ac_add_options --disable-warnings-as-errors
-ac_add_options --enable-coverage
-
-export CFLAGS="--coverage"
-export CXXFLAGS="--coverage"
-export LDFLAGS="--coverage"
 ac_add_options --enable-fuzzing
--- a/build/build-clang/clang-7-linux64.json
+++ b/build/build-clang/clang-7-linux64.json
@@ -13,11 +13,11 @@
     "python_path": "/usr/bin/python2.7",
     "gcc_dir": "/builds/worker/workspace/build/src/gcc",
     "cc": "/builds/worker/workspace/build/src/gcc/bin/gcc",
     "cxx": "/builds/worker/workspace/build/src/gcc/bin/g++",
     "as": "/builds/worker/workspace/build/src/gcc/bin/gcc",
     "patches": [
       "static-llvm-symbolizer.patch",
       "find_symbolizer_linux.patch",
-      "rename_gcov_flush.patch"
+      "rename_gcov_flush_.patch"
     ]
 }
rename from build/build-clang/rename_gcov_flush.patch
rename to build/build-clang/rename_gcov_flush_.patch
--- a/build/build-clang/rename_gcov_flush.patch
+++ b/build/build-clang/rename_gcov_flush_.patch
@@ -3,12 +3,12 @@ Index: compiler-rt/lib/profile/GCDAProfi
 diff --git a/compiler-rt/lib/profile/GCDAProfiling.c b/compiler-rt/lib/profile/GCDAProfiling.c
 --- a/compiler-rt/lib/profile/GCDAProfiling.c	(revisione 336380)
 +++ b/compiler-rt/lib/profile/GCDAProfiling.c	(copia locale)
 @@ -555,7 +555,7 @@
    fn_list_insert(&flush_fn_list, fn);
  }
  
 -void __gcov_flush() {
-+void __llvm_gcov_flush() {
++void __custom_llvm_gcov_flush() {
    struct fn_node* curr = flush_fn_list.head;
  
    while (curr) {
--- a/devtools/client/debugger/new/test/mochitest/browser.ini
+++ b/devtools/client/debugger/new/test/mochitest/browser.ini
@@ -775,9 +775,9 @@ skip-if = os != "mac" || debug || !night
 skip-if = true # See bug 1481009
 [browser_dbg_rr_replay-01.js]
 skip-if = os != "mac" || debug || !nightly_build
 [browser_dbg_rr_replay-02.js]
 skip-if = os != "mac" || debug || !nightly_build
 [browser_dbg_rr_replay-03.js]
 skip-if = os != "mac" || debug || !nightly_build
 [browser_dbg_rr_console_warp-01.js]
-skip-if = os != "mac" || debug || !nightly_build
+skip-if = true # Bug 1483969
--- a/devtools/client/inspector/computed/computed.js
+++ b/devtools/client/inspector/computed/computed.js
@@ -1425,16 +1425,17 @@ SelectorView.prototype = {
 
 function ComputedViewTool(inspector, window) {
   this.inspector = inspector;
   this.document = window.document;
 
   this.computedView = new CssComputedView(this.inspector, this.document,
     this.inspector.pageStyle);
 
+  this.onDetachedFront = this.onDetachedFront.bind(this);
   this.onSelected = this.onSelected.bind(this);
   this.refresh = this.refresh.bind(this);
   this.onPanelSelected = this.onPanelSelected.bind(this);
 
   this.inspector.selection.on("detached-front", this.onDetachedFront);
   this.inspector.selection.on("new-node-front", this.onSelected);
   this.inspector.selection.on("pseudoclass", this.refresh);
   this.inspector.sidebar.on("computedview-selected", this.onPanelSelected);
--- a/devtools/client/inspector/flexbox/components/FlexContainer.js
+++ b/devtools/client/inspector/flexbox/components/FlexContainer.js
@@ -70,44 +70,65 @@ class FlexContainer extends PureComponen
 
   render() {
     const {
       color,
       flexContainer,
       onHideBoxModelHighlighter,
       onShowBoxModelHighlighterForNode,
     } = this.props;
-    const { nodeFront } = flexContainer;
+    const {
+      nodeFront,
+      properties,
+    } = flexContainer;
 
     return createElement(Fragment, null,
-      Rep({
-        defaultRep: ElementNode,
-        mode: MODE.TINY,
-        object: translateNodeFrontToGrip(nodeFront),
-        onDOMNodeMouseOut: () => onHideBoxModelHighlighter(),
-        onDOMNodeMouseOver: () => onShowBoxModelHighlighterForNode(nodeFront),
-      }),
-      dom.div({
-        className: "layout-color-swatch",
-        ref: this.swatchEl,
-        style: {
-          backgroundColor: color,
-        },
-        title: color,
-      }),
-      // The SwatchColorPicker relies on the nextSibling of the swatch element to
-      // apply the selected color. This is why we use a span in display: none for
-      // now. Ideally we should modify the SwatchColorPickerTooltip to bypass this
-      // requirement. See https://bugzilla.mozilla.org/show_bug.cgi?id=1341578
-      dom.span(
-        {
-          className: "layout-color-value",
-          ref: this.colorValueEl,
-        },
-        color
+      dom.div({ className: "flex-header-container-label" },
+        Rep({
+          defaultRep: ElementNode,
+          mode: MODE.TINY,
+          object: translateNodeFrontToGrip(nodeFront),
+          onDOMNodeMouseOut: () => onHideBoxModelHighlighter(),
+          onDOMNodeMouseOver: () => onShowBoxModelHighlighterForNode(nodeFront),
+        }),
+        dom.div({
+          className: "layout-color-swatch",
+          ref: this.swatchEl,
+          style: {
+            backgroundColor: color,
+          },
+          title: color,
+        }),
+        // The SwatchColorPicker relies on the nextSibling of the swatch element to
+        // apply the selected color. This is why we use a span in display: none for
+        // now. Ideally we should modify the SwatchColorPickerTooltip to bypass this
+        // requirement. See https://bugzilla.mozilla.org/show_bug.cgi?id=1341578
+        dom.span(
+          {
+            className: "layout-color-value",
+            ref: this.colorValueEl,
+          },
+          color
+        )
+      ),
+      dom.div({ className: "flex-header-container-properties" },
+        dom.div(
+          {
+            className: "inspector-badge",
+            title: `flex-direction: ${properties["flex-direction"]}`,
+          },
+          properties["flex-direction"]
+        ),
+        dom.div(
+          {
+            className: "inspector-badge",
+            title: `flex-wrap: ${properties["flex-wrap"]}`,
+          },
+          properties["flex-wrap"]
+        )
       )
     );
   }
 }
 
 const mapStateToProps = state => {
   return {
     color: state.flexbox.color,
deleted file mode 100644
--- a/devtools/client/inspector/flexbox/components/FlexContainerProperties.js
+++ /dev/null
@@ -1,51 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const { createFactory, PureComponent } = require("devtools/client/shared/vendor/react");
-const dom = require("devtools/client/shared/vendor/react-dom-factories");
-const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
-const { getStr } = require("devtools/client/inspector/layout/utils/l10n");
-
-const ComputedProperty = createFactory(require("devtools/client/inspector/layout/components/ComputedProperty"));
-
-const Types = require("../types");
-
-class FlexContainerProperties extends PureComponent {
-  static get propTypes() {
-    return {
-      properties: PropTypes.shape(Types.flexContainerProperties).isRequired,
-    };
-  }
-
-  render() {
-    const { properties } =  this.props;
-
-    return (
-      dom.div(
-        {
-          id: "flex-container-properties",
-          className: "flexbox-container",
-        },
-        dom.div({ className: "layout-properties-header" },
-          getStr("flexbox.flexContainerProperties")
-        ),
-        dom.div(
-          {
-            className: "layout-properties-wrapper devtools-monospace",
-            tabIndex: 0,
-          },
-          Object.entries(properties).map(([name, value]) => ComputedProperty({
-            key: name,
-            name,
-            value,
-          }))
-        )
-      )
-    );
-  }
-}
-
-module.exports = FlexContainerProperties;
--- a/devtools/client/inspector/flexbox/components/FlexItem.js
+++ b/devtools/client/inspector/flexbox/components/FlexItem.js
@@ -14,47 +14,48 @@ const { Rep } = REPS;
 const ElementNode = REPS.ElementNode;
 
 const Types = require("../types");
 
 class FlexItem extends PureComponent {
   static get propTypes() {
     return {
       flexItem: PropTypes.shape(Types.flexItem).isRequired,
+      index: PropTypes.number.isRequired,
       onHideBoxModelHighlighter: PropTypes.func.isRequired,
       onShowBoxModelHighlighterForNode: PropTypes.func.isRequired,
       setSelectedNode: PropTypes.func.isRequired,
     };
   }
 
   render() {
     const {
       flexItem,
+      index,
       onHideBoxModelHighlighter,
       onShowBoxModelHighlighterForNode,
       setSelectedNode,
     } = this.props;
     const { nodeFront } = flexItem;
 
     return (
-      dom.li({},
-        dom.button(
-          {
-            className: "devtools-button devtools-monospace",
-            onClick: () => {
-              setSelectedNode(nodeFront);
-              onHideBoxModelHighlighter();
-            },
-            onMouseOut: () => onHideBoxModelHighlighter(),
-            onMouseOver: () => onShowBoxModelHighlighterForNode(nodeFront),
+      dom.button(
+        {
+          className: "devtools-button devtools-monospace",
+          onClick: () => {
+            setSelectedNode(nodeFront);
+            onHideBoxModelHighlighter();
           },
-          Rep({
-            defaultRep: ElementNode,
-            mode: MODE.TINY,
-            object: translateNodeFrontToGrip(nodeFront),
-          })
-        )
+          onMouseOut: () => onHideBoxModelHighlighter(),
+          onMouseOver: () => onShowBoxModelHighlighterForNode(nodeFront),
+        },
+        dom.span({ className: "flex-item-index" }, index),
+        Rep({
+          defaultRep: ElementNode,
+          mode: MODE.TINY,
+          object: translateNodeFrontToGrip(nodeFront),
+        })
       )
     );
   }
 }
 
 module.exports = FlexItem;
--- a/devtools/client/inspector/flexbox/components/FlexItemList.js
+++ b/devtools/client/inspector/flexbox/components/FlexItemList.js
@@ -2,16 +2,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/. */
 
 "use strict";
 
 const { createFactory, PureComponent } = require("devtools/client/shared/vendor/react");
 const dom = require("devtools/client/shared/vendor/react-dom-factories");
 const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
+const { getStr } = require("devtools/client/inspector/layout/utils/l10n");
 
 const FlexItem = createFactory(require(("./FlexItem")));
 
 const Types = require("../types");
 
 class FlexItemList extends PureComponent {
   static get propTypes() {
     return {
@@ -26,21 +27,23 @@ class FlexItemList extends PureComponent
     const {
       flexItems,
       onHideBoxModelHighlighter,
       onShowBoxModelHighlighterForNode,
       setSelectedNode,
     } = this.props;
 
     return (
-      dom.ol(
+      dom.div(
         { className: "flex-item-list" },
-        flexItems.map(flexItem => FlexItem({
+        dom.div({ className: "flex-item-list-header" }, getStr("flexbox.flexItems")),
+        flexItems.map((flexItem, index) => FlexItem({
           key: flexItem.actorID,
           flexItem,
+          index: index + 1,
           onHideBoxModelHighlighter,
           onShowBoxModelHighlighterForNode,
           setSelectedNode,
         }))
       )
     );
   }
 }
--- a/devtools/client/inspector/flexbox/components/Flexbox.js
+++ b/devtools/client/inspector/flexbox/components/Flexbox.js
@@ -9,19 +9,16 @@ const {
   createFactory,
   Fragment,
   PureComponent,
 } = require("devtools/client/shared/vendor/react");
 const dom = require("devtools/client/shared/vendor/react-dom-factories");
 const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
 const { getStr } = require("devtools/client/inspector/layout/utils/l10n");
 
-loader.lazyGetter(this, "FlexContainerProperties", function() {
-  return createFactory(require("./FlexContainerProperties"));
-});
 loader.lazyGetter(this, "FlexItemList", function() {
   return createFactory(require("./FlexItemList"));
 });
 loader.lazyGetter(this, "FlexItemSizingOutline", function() {
   return createFactory(require("./FlexItemSizingOutline"));
 });
 loader.lazyGetter(this, "FlexItemSizingProperties", function() {
   return createFactory(require("./FlexItemSizingProperties"));
@@ -41,22 +38,16 @@ class Flexbox extends PureComponent {
       onHideBoxModelHighlighter: PropTypes.func.isRequired,
       onSetFlexboxOverlayColor: PropTypes.func.isRequired,
       onShowBoxModelHighlighterForNode: PropTypes.func.isRequired,
       onToggleFlexboxHighlighter: PropTypes.func.isRequired,
       setSelectedNode: PropTypes.func.isRequired,
     };
   }
 
-  renderFlexContainerProperties() {
-    return FlexContainerProperties({
-      properties: this.props.flexContainer.properties,
-    });
-  }
-
   renderFlexItemList() {
     const {
       onHideBoxModelHighlighter,
       onShowBoxModelHighlighterForNode,
       setSelectedNode,
     } = this.props;
     const { flexItems } = this.props.flexContainer;
 
@@ -128,15 +119,14 @@ class Flexbox extends PureComponent {
           onHideBoxModelHighlighter,
           onSetFlexboxOverlayColor,
           onShowBoxModelHighlighterForNode,
           onToggleFlexboxHighlighter,
           setSelectedNode,
         }),
         !flexItemShown && flexItems.length > 0 ? this.renderFlexItemList() : null,
         flexItemShown ? this.renderFlexItemSizing() : null,
-        !flexItemShown ? this.renderFlexContainerProperties() : null
       )
     );
   }
 }
 
 module.exports = Flexbox;
--- a/devtools/client/inspector/flexbox/components/moz.build
+++ b/devtools/client/inspector/flexbox/components/moz.build
@@ -2,16 +2,15 @@
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 DevToolsModules(
     'Flexbox.js',
     'FlexContainer.js',
-    'FlexContainerProperties.js',
     'FlexItem.js',
     'FlexItemList.js',
     'FlexItemSelector.js',
     'FlexItemSizingOutline.js',
     'FlexItemSizingProperties.js',
     'Header.js',
 )
--- a/devtools/client/inspector/flexbox/test/browser.ini
+++ b/devtools/client/inspector/flexbox/test/browser.ini
@@ -15,16 +15,17 @@ support-files =
   !/devtools/client/shared/test/shared-redux-head.js
   !/devtools/client/shared/test/telemetry-test-helpers.js
   !/devtools/client/shared/test/test-actor.js
   !/devtools/client/shared/test/test-actor-registry.js
 
 [browser_flexbox_accordion_state.js]
 [browser_flexbox_container_and_item.js]
 [browser_flexbox_container_element_rep.js]
+[browser_flexbox_container_properties.js]
 [browser_flexbox_empty_state.js]
 [browser_flexbox_highlighter_color_picker_on_ESC.js]
 [browser_flexbox_highlighter_color_picker_on_RETURN.js]
 [browser_flexbox_item_list_01.js]
 [browser_flexbox_item_list_02.js]
 [browser_flexbox_item_outline_exists.js]
 [browser_flexbox_item_outline_has_correct_layout.js]
 [browser_flexbox_item_outline_hidden_when_useless.js]
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/flexbox/test/browser_flexbox_container_properties.js
@@ -0,0 +1,45 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test that the flex container properties are shown when a flex container is selected.
+
+const TEST_URI = `
+  <style type='text/css'>
+    #container1 {
+      display: flex;
+    }
+  </style>
+  <div id="container1">
+    <div id="item"></div>
+  </div>
+`;
+
+add_task(async function() {
+  await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
+  const { inspector, flexboxInspector } = await openLayoutView();
+  const { document: doc } = flexboxInspector;
+
+  info("Selecting the flex container #container1 and checking the values of the flex " +
+    "container properties for #container1.");
+  const onFlexContainerPropertiesRendered = waitForDOM(doc,
+    ".flex-header-container-properties");
+  await selectNode("#container1", inspector);
+  const [flexContainerProperties] = await onFlexContainerPropertiesRendered;
+
+  ok(flexContainerProperties, "The flex container properties is rendered.");
+  is(flexContainerProperties.children[0].textContent, "row",
+    "Got expected flex-direction.");
+  is(flexContainerProperties.children[1].textContent, "nowrap",
+    "Got expected flex-wrap.");
+
+  info("Selecting a flex item and expecting the flex container properties to not be " +
+    "shown.");
+  const onFlexHeaderRendered = waitForDOM(doc, ".flex-header");
+  await selectNode("#item", inspector);
+  const [flexHeader] = await onFlexHeaderRendered;
+
+  ok(!flexHeader.querySelector(".flex-header-container-properties"),
+    "The flex container properties is not shown in the header.");
+});
--- a/devtools/client/inspector/flexbox/test/browser_flexbox_item_list_02.js
+++ b/devtools/client/inspector/flexbox/test/browser_flexbox_item_list_02.js
@@ -13,17 +13,17 @@ add_task(async function() {
   const { document: doc } = flexboxInspector;
 
   const onFlexItemListRendered = waitForDOM(doc, ".flex-item-list");
   await selectNode("#container", inspector);
   const [flexItemList] = await onFlexItemListRendered;
 
   info("Checking the initial state of the flex item list.");
   ok(flexItemList, "The flex item list is rendered.");
-  is(flexItemList.children.length, 1,
+  is(flexItemList.querySelectorAll("button").length, 1,
     "Got the correct number of flex items in the list.");
 
   info("Clicking on the first flex item to navigate to the flex item.");
   const onFlexItemOutlineRendered = waitForDOM(doc, ".flex-outline-container");
   flexItemList.querySelector("button").click();
   const [flexOutlineContainer] = await onFlexItemOutlineRendered;
 
   info("Checking the selected flex item state.");
--- a/devtools/client/inspector/flexbox/test/browser_flexbox_pseudo_elements_are_listed.js
+++ b/devtools/client/inspector/flexbox/test/browser_flexbox_pseudo_elements_are_listed.js
@@ -14,14 +14,14 @@ add_task(async function() {
   const { document: doc } = flexboxInspector;
 
   // Select the flex container in the inspector.
   const onItemsListRendered = waitForDOM(doc,
     "#layout-flexbox-container .flex-item-list");
   await selectNode(".container", inspector);
   const [flexItemList] = await onItemsListRendered;
 
-  const items = [...flexItemList.querySelectorAll("li")];
+  const items = [...flexItemList.querySelectorAll("button .objectBox")];
   is(items.length, 2, "There are 2 items displayed in the list");
 
   is(items[0].textContent, "::before", "The first item is ::before");
   is(items[1].textContent, "::after", "The second item is ::after");
 });
--- a/devtools/client/inspector/flexbox/test/browser_flexbox_text_nodes_are_listed.js
+++ b/devtools/client/inspector/flexbox/test/browser_flexbox_text_nodes_are_listed.js
@@ -14,14 +14,14 @@ add_task(async function() {
   const { document: doc } = flexboxInspector;
 
   // Select the flex container in the inspector.
   const onItemsListRendered = waitForDOM(doc,
     "#layout-flexbox-container .flex-item-list");
   await selectNode(".container", inspector);
   const [flexItemList] = await onItemsListRendered;
 
-  const items = [...flexItemList.querySelectorAll("li")];
+  const items = [...flexItemList.querySelectorAll("button .objectBox")];
   is(items.length, 3, "There are 3 items displayed in the list");
 
   is(items[0].textContent, "#text", "The first item is a text node");
   is(items[2].textContent, "#text", "The third item is a text node");
 });
--- a/devtools/client/inspector/index.xhtml
+++ b/devtools/client/inspector/index.xhtml
@@ -5,16 +5,17 @@
 <!DOCTYPE html>
 
 <html xmlns="http://www.w3.org/1999/xhtml" dir="">
 <head>
   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
 
   <link rel="stylesheet" href="chrome://devtools/skin/breadcrumbs.css"/>
   <link rel="stylesheet" href="chrome://devtools/skin/inspector.css"/>
+  <link rel="stylesheet" href="chrome://devtools/skin/badge.css"/>
   <link rel="stylesheet" href="chrome://devtools/skin/rules.css"/>
   <link rel="stylesheet" href="chrome://devtools/skin/computed.css"/>
   <link rel="stylesheet" href="chrome://devtools/skin/changes.css"/>
   <link rel="stylesheet" href="chrome://devtools/skin/fonts.css"/>
   <link rel="stylesheet" href="chrome://devtools/skin/boxmodel.css"/>
   <link rel="stylesheet" href="chrome://devtools/skin/layout.css"/>
   <link rel="stylesheet" href="chrome://devtools/skin/animation.css"/>
   <link rel="stylesheet" href="resource://devtools/client/shared/components/tabs/Tabs.css"/>
--- a/devtools/client/inspector/markup/markup.xhtml
+++ b/devtools/client/inspector/markup/markup.xhtml
@@ -2,16 +2,17 @@
 <!-- This Source Code Form is subject to the terms of the Mozilla Public
    - License, v. 2.0. If a copy of the MPL was not distributed with this
    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
 <!DOCTYPE html>
 
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head>
   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+  <link rel="stylesheet" href="chrome://devtools/skin/badge.css" type="text/css"/>
   <link rel="stylesheet" href="chrome://devtools/skin/markup.css" type="text/css"/>
   <link rel="stylesheet" href="chrome://devtools/content/sourceeditor/codemirror/lib/codemirror.css" type="text/css"/>
   <link rel="stylesheet" href="chrome://devtools/content/sourceeditor/codemirror/addon/dialog/dialog.css" type="text/css"/>
   <link rel="stylesheet" href="chrome://devtools/content/sourceeditor/codemirror/mozilla.css" type="text/css"/>
 
   <script type="application/javascript"
           src="chrome://devtools/content/shared/theme-switching.js"></script>
 </head>
--- a/devtools/client/inspector/markup/test/browser_markup_display_node_01.js
+++ b/devtools/client/inspector/markup/test/browser_markup_display_node_01.js
@@ -36,43 +36,43 @@ add_task(async function() {
 
   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(
-    ".markup-badge[data-display]");
+    ".inspector-badge.interactive[data-display]");
   ok(gridDisplayNode, "#grid display node is shown.");
   is(gridDisplayNode.textContent, "grid", "Got the correct display type for #grid.");
 
   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(
-    ".markup-badge[data-display]");
+    ".inspector-badge[data-display]");
   ok(subgridDisplayNode, "#subgrid display node is shown");
   is(subgridDisplayNode.textContent, "subgrid",
     "Got the correct display type for #subgrid");
 
   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(
-    ".markup-badge[data-display]");
+    ".inspector-badge.interactive[data-display]");
   ok(flexDisplayNode, "#flex display node is shown.");
   is(flexDisplayNode.textContent, "flex", "Got the correct display type for #flex");
 
   info("Check the display node is hidden for #block.");
   await selectNode("#block", inspector);
   const blockContainer = await getContainerForSelector("#block", inspector);
   const blockDisplayNode = blockContainer.elt.querySelector(
-    ".markup-badge[data-display]");
+    ".inspector-badge.interactive[data-display]");
   ok(!blockDisplayNode, "#block display node is hidden.");
 
   info("Check the display node is hidden for span.");
   await selectNode("span", inspector);
   const spanContainer = await getContainerForSelector("span", inspector);
   const spanDisplayNode = spanContainer.elt.querySelector(
-    ".markup-badge[data-display]");
+    ".inspector-badge.interactive[data-display]");
   ok(!spanDisplayNode, "span display node is hidden.");
 });
--- a/devtools/client/inspector/markup/test/browser_markup_display_node_02.js
+++ b/devtools/client/inspector/markup/test/browser_markup_display_node_02.js
@@ -107,17 +107,18 @@ add_task(async function() {
   }
 });
 
 async function runTestData(inspector, testActor,
                       {selector, before, changeStyle, after}) {
   await selectNode(selector, inspector);
   const container = await getContainerForSelector(selector, inspector);
 
-  const beforeBadge = container.elt.querySelector(".markup-badge[data-display]");
+  const beforeBadge = container.elt.querySelector(
+    ".inspector-badge.interactive[data-display]");
   is(!!beforeBadge, before.visible,
     `Display badge is visible as expected for ${selector}: ${before.visible}`);
   if (before.visible) {
     is(beforeBadge.textContent, before.textContent,
       `Got the correct before display type for ${selector}: ${beforeBadge.textContent}`);
   }
 
   info("Listening for the display-change event");
@@ -132,17 +133,18 @@ async function runTestData(inspector, te
   for (const node of nodes) {
     if (getContainerForNodeFront(node, inspector) === container) {
       foundContainer = true;
       break;
     }
   }
   ok(foundContainer, "Container is part of the list of changed nodes");
 
-  const afterBadge = container.elt.querySelector(".markup-badge[data-display]");
+  const afterBadge = container.elt.querySelector(
+    ".inspector-badge.interactive[data-display]");
   is(!!afterBadge, after.visible,
     `Display badge is visible as expected for ${selector}: ${after.visible}`);
   if (after.visible) {
     is(afterBadge.textContent, after.textContent,
       `Got the correct after display type for ${selector}: ${afterBadge.textContent}`);
   }
 }
 
--- a/devtools/client/inspector/markup/test/browser_markup_events-overflow.js
+++ b/devtools/client/inspector/markup/test/browser_markup_events-overflow.js
@@ -29,17 +29,18 @@ const TEST_DATA = [
     alignTop: false,
   },
 ];
 
 add_task(async function() {
   const { inspector } = await openInspectorForURL(TEST_URL);
 
   const markupContainer = await getContainerForSelector("#events", inspector);
-  const evHolder = markupContainer.elt.querySelector(".markup-badge[data-event]");
+  const evHolder = markupContainer.elt.querySelector(
+    ".inspector-badge.interactive[data-event]");
   const tooltip = inspector.markup.eventDetailsTooltip;
 
   info("Clicking to open event tooltip.");
   EventUtils.synthesizeMouseAtCenter(evHolder, {},
     inspector.markup.doc.defaultView);
   await tooltip.once("shown");
   info("EventTooltip visible.");
 
--- a/devtools/client/inspector/markup/test/browser_markup_events-windowed-host.js
+++ b/devtools/client/inspector/markup/test/browser_markup_events-windowed-host.js
@@ -27,17 +27,18 @@ add_task(async function() {
   await toolbox.switchHost("bottom");
   await runTests(inspector);
 
   await toolbox.destroy();
 });
 
 async function runTests(inspector) {
   const markupContainer = await getContainerForSelector("#events", inspector);
-  const evHolder = markupContainer.elt.querySelector(".markup-badge[data-event]");
+  const evHolder = markupContainer.elt.querySelector(
+    ".inspector-badge.interactive[data-event]");
   const tooltip = inspector.markup.eventDetailsTooltip;
 
   info("Clicking to open event tooltip.");
 
   let onInspectorUpdated = inspector.once("inspector-updated");
   const onTooltipShown = tooltip.once("shown");
   EventUtils.synthesizeMouseAtCenter(evHolder, {}, inspector.markup.doc.defaultView);
 
--- a/devtools/client/inspector/markup/test/browser_markup_events_click_to_close.js
+++ b/devtools/client/inspector/markup/test/browser_markup_events_click_to_close.js
@@ -22,20 +22,22 @@ const TEST_URL = `
 
 add_task(async function() {
   const {inspector, toolbox} = await openInspectorForURL(
     "data:text/html;charset=utf-8," + encodeURI(TEST_URL));
 
   await inspector.markup.expandAll();
 
   const container1 = await getContainerForSelector("#d1", inspector);
-  const evHolder1 = container1.elt.querySelector(".markup-badge[data-event]");
+  const evHolder1 = container1.elt.querySelector(
+    ".inspector-badge.interactive[data-event]");
 
   const container2 = await getContainerForSelector("#d2", inspector);
-  const evHolder2 = container2.elt.querySelector(".markup-badge[data-event]");
+  const evHolder2 = container2.elt.querySelector(
+    ".inspector-badge.interactive[data-event]");
 
   const tooltip = inspector.markup.eventDetailsTooltip;
 
   info("Click the event icon for the first element");
   let onShown = tooltip.once("shown");
   EventUtils.synthesizeMouseAtCenter(evHolder1, {}, inspector.markup.win);
   await onShown;
   info("event tooltip for the first div is shown");
--- a/devtools/client/inspector/markup/test/browser_markup_flex_display_badge.js
+++ b/devtools/client/inspector/markup/test/browser_markup_flex_display_badge.js
@@ -21,17 +21,18 @@ add_task(async function() {
   await pushPref("devtools.flexboxinspector.enabled", true);
   await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
   const { inspector } = await openLayoutView();
   const { highlighters, store } = inspector;
 
   info("Check the flex display badge is shown and not active.");
   await selectNode("#flex", inspector);
   const flexContainer = await getContainerForSelector("#flex", inspector);
-  const flexDisplayBadge = flexContainer.elt.querySelector(".markup-badge[data-display]");
+  const flexDisplayBadge = flexContainer.elt.querySelector(
+    ".inspector-badge.interactive[data-display]");
   ok(!flexDisplayBadge.classList.contains("active"), "flex display badge is not active.");
   ok(flexDisplayBadge.classList.contains("interactive"),
     "flex display badge is interactive.");
 
   info("Check the initial state of the flex highlighter.");
   ok(!highlighters.highlighters[HIGHLIGHTER_TYPE],
     "No flexbox highlighter exists in the highlighters overlay.");
   ok(!highlighters.flexboxHighlighterShown, "No flexbox highlighter is shown.");
--- a/devtools/client/inspector/markup/test/browser_markup_grid_display_badge_01.js
+++ b/devtools/client/inspector/markup/test/browser_markup_grid_display_badge_01.js
@@ -17,17 +17,18 @@ const TEST_URI = `
 add_task(async function() {
   await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
   const { inspector } = await openLayoutView();
   const { highlighters, store } = inspector;
 
   info("Check the grid display badge is shown and not active.");
   await selectNode("#grid", inspector);
   const gridContainer = await getContainerForSelector("#grid", inspector);
-  const gridDisplayBadge = gridContainer.elt.querySelector(".markup-badge[data-display]");
+  const gridDisplayBadge = gridContainer.elt.querySelector(
+    ".inspector-badge.interactive[data-display]");
   ok(!gridDisplayBadge.classList.contains("active"), "grid display badge is not active.");
   ok(gridDisplayBadge.classList.contains("interactive"),
     "grid display badge is interactive.");
 
   info("Check the initial state of the grid highlighter.");
   ok(!highlighters.gridHighlighters.size,
     "No CSS grid highlighter exists in the highlighters overlay.");
 
--- a/devtools/client/inspector/markup/test/browser_markup_grid_display_badge_02.js
+++ b/devtools/client/inspector/markup/test/browser_markup_grid_display_badge_02.js
@@ -30,19 +30,22 @@ add_task(async function() {
   await pushPref("devtools.gridinspector.maxHighlighters", 2);
   await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
   const { inspector } = await openLayoutView();
   const { highlighters } = inspector;
 
   const grid1 = await getContainerForSelector("#grid1", inspector);
   const grid2 = await getContainerForSelector("#grid2", inspector);
   const grid3 = await getContainerForSelector("#grid3", inspector);
-  const gridDisplayBadge1 = grid1.elt.querySelector(".markup-badge[data-display]");
-  const gridDisplayBadge2 = grid2.elt.querySelector(".markup-badge[data-display]");
-  const gridDisplayBadge3 = grid3.elt.querySelector(".markup-badge[data-display]");
+  const gridDisplayBadge1 = grid1.elt.querySelector(
+    ".inspector-badge.interactive[data-display]");
+  const gridDisplayBadge2 = grid2.elt.querySelector(
+    ".inspector-badge.interactive[data-display]");
+  const gridDisplayBadge3 = grid3.elt.querySelector(
+    ".inspector-badge.interactive[data-display]");
 
   info("Check the initial state of the grid display badges and grid highlighters");
   ok(!gridDisplayBadge1.classList.contains("active"),
     "#grid1 display badge is not active.");
   ok(!gridDisplayBadge2.classList.contains("active"),
     "#grid2 display badge is not active.");
   ok(!gridDisplayBadge3.classList.contains("active"),
     "#grid3 display badge is not active.");
--- a/devtools/client/inspector/markup/test/browser_markup_shadowdom_open_debugger.js
+++ b/devtools/client/inspector/markup/test/browser_markup_shadowdom_open_debugger.js
@@ -58,34 +58,36 @@ add_task(async function() {
 });
 
 async function runTest(inspector, toolbox, selector, contentMethod) {
   // Test element is a regular element (no shadow root or custom element definition).
   info(`Select <${selector}>.`);
   await selectNode(selector, inspector);
   const testFront = await getNodeFront(selector, inspector);
   const testContainer = inspector.markup.getContainer(testFront);
-  let customBadge = testContainer.elt.querySelector(".markup-badge[data-custom]");
+  let customBadge = testContainer.elt.querySelector(
+    ".inspector-badge.interactive[data-custom]");
 
   // Verify that the "custom" badge and menu item are hidden.
   ok(!customBadge, "[custom] badge is hidden");
   let menuItem = getMenuItem("node-menu-jumptodefinition", inspector);
   ok(!menuItem, selector + ": The menu item was not found in the contextual menu");
 
   info("Call the content method that should attach a custom element definition");
   const mutated = waitForMutation(inspector, "customElementDefined");
   ContentTask.spawn(gBrowser.selectedBrowser, { contentMethod }, function(args) {
     content.wrappedJSObject[args.contentMethod]();
   });
   await mutated;
 
   // Test element should now have a custom element definition.
 
   // Check that the badge opens the debugger.
-  customBadge = testContainer.elt.querySelector(".markup-badge[data-custom]");
+  customBadge = testContainer.elt.querySelector(
+    ".inspector-badge.interactive[data-custom]");
   ok(customBadge, "[custom] badge is visible");
 
   info("Click on the `custom` badge and verify that the debugger opens.");
   let onDebuggerReady = toolbox.getPanelWhenReady("jsdebugger");
   customBadge.click();
   await onDebuggerReady;
 
   const debuggerContext = createDebuggerContext(toolbox);
--- a/devtools/client/inspector/markup/test/helper_events_test_runner.js
+++ b/devtools/client/inspector/markup/test/helper_events_test_runner.js
@@ -50,17 +50,18 @@ async function runEventPopupTests(url, t
 async function checkEventsForNode(test, inspector, testActor) {
   const {selector, expected, beforeTest, isSourceMapped} = test;
   const container = await getContainerForSelector(selector, inspector);
 
   if (typeof beforeTest === "function") {
     await beforeTest(inspector, testActor);
   }
 
-  const evHolder = container.elt.querySelector(".markup-badge[data-event]");
+  const evHolder = container.elt.querySelector(
+    ".inspector-badge.interactive[data-event]");
 
   if (expected.length === 0) {
     // If no event is expected, check that event bubble is hidden.
     ok(!evHolder, "event bubble should be hidden");
     return;
   }
 
   const tooltip = inspector.markup.eventDetailsTooltip;
--- a/devtools/client/inspector/markup/views/element-editor.js
+++ b/devtools/client/inspector/markup/views/element-editor.js
@@ -282,17 +282,17 @@ ElementEditor.prototype = {
       this._eventBadge = null;
     } else if (showEventBadge && !this._eventBadge) {
       this._createEventBadge();
     }
   },
 
   _createEventBadge: function() {
     this._eventBadge = this.doc.createElement("div");
-    this._eventBadge.classList.add("markup-badge");
+    this._eventBadge.className = "inspector-badge interactive";
     this._eventBadge.dataset.event = "true";
     this._eventBadge.textContent = "event";
     this._eventBadge.title = INSPECTOR_L10N.getStr("markupView.event.tooltiptext");
     // Badges order is [event][display][custom], insert event badge before others.
     this.elt.insertBefore(this._eventBadge, this._displayBadge || this._customBadge);
   },
 
   /**
@@ -314,17 +314,17 @@ ElementEditor.prototype = {
       }
 
       this._updateDisplayBadgeContent();
     }
   },
 
   _createDisplayBadge: function() {
     this._displayBadge = this.doc.createElement("div");
-    this._displayBadge.classList.add("markup-badge");
+    this._displayBadge.className = "inspector-badge";
     this._displayBadge.addEventListener("click", this.onDisplayBadgeClick);
     // Badges order is [event][display][custom], insert display badge before custom.
     this.elt.insertBefore(this._displayBadge, this._customBadge);
 
     this.startTrackingFlexboxHighlighterEvents();
     this.startTrackingGridHighlighterEvents();
   },
 
@@ -338,16 +338,18 @@ ElementEditor.prototype = {
       this.highlighters.gridHighlighters.has(this.node));
 
     if (displayType === "flex" || displayType === "inline-flex") {
       this._displayBadge.classList.toggle("interactive",
         Services.prefs.getBoolPref("devtools.inspector.flexboxHighlighter.enabled"));
     } else if (displayType === "grid" || displayType === "inline-grid") {
       this._displayBadge.classList.toggle("interactive",
         this.highlighters.canGridHighlighterToggle(this.node));
+    } else {
+      this._displayBadge.classList.remove("interactive");
     }
   },
 
   /**
    * Update the markup custom element badge.
    */
   updateCustomBadge: function() {
     const showCustomBadge = !!this.node.customElementLocation;
@@ -356,17 +358,17 @@ ElementEditor.prototype = {
       this._customBadge = null;
     } else if (!this._customBadge && showCustomBadge) {
       this._createCustomBadge();
     }
   },
 
   _createCustomBadge: function() {
     this._customBadge = this.doc.createElement("div");
-    this._customBadge.classList.add("markup-badge");
+    this._customBadge.className = "inspector-badge interactive";
     this._customBadge.dataset.custom = "true";
     this._customBadge.textContent = "custom…";
     this._customBadge.title = INSPECTOR_L10N.getStr("markupView.custom.tooltiptext");
     this._customBadge.addEventListener("click", this.onCustomBadgeClick);
     // Badges order is [event][display][custom], insert custom badge at the end.
     this.elt.appendChild(this._customBadge);
   },
 
--- a/devtools/client/jar.mn
+++ b/devtools/client/jar.mn
@@ -88,16 +88,17 @@ devtools.jar:
     skin/light-theme.css (themes/light-theme.css)
     skin/toolbars.css (themes/toolbars.css)
     skin/toolbox.css (themes/toolbox.css)
     skin/tooltips.css (themes/tooltips.css)
     skin/images/accessibility.svg (themes/images/accessibility.svg)
     skin/images/add.svg (themes/images/add.svg)
     skin/images/alert.svg (themes/images/alert.svg)
     skin/images/arrowhead-left.svg (themes/images/arrowhead-left.svg)
+    skin/images/arrowhead-right.svg (themes/images/arrowhead-right.svg)
     skin/images/arrowhead-down.svg (themes/images/arrowhead-down.svg)
     skin/images/arrowhead-up.svg (themes/images/arrowhead-up.svg)
     skin/images/breadcrumbs-divider.svg (themes/images/breadcrumbs-divider.svg)
     skin/images/filters.svg (themes/images/filters.svg)
     skin/images/filter-swatch.svg (themes/images/filter-swatch.svg)
     skin/images/aboutdebugging-collapse-icon.svg (themes/images/aboutdebugging-collapse-icon.svg)
     skin/images/aboutdebugging-connect-icon.svg (themes/images/aboutdebugging-connect-icon.svg)
     skin/images/aboutdebugging-firefox-aurora.svg (themes/images/aboutdebugging-firefox-aurora.svg)
@@ -174,16 +175,17 @@ devtools.jar:
     skin/images/debugger-step-in.svg (themes/images/debugger-step-in.svg)
     skin/images/debugger-step-out.svg (themes/images/debugger-step-out.svg)
     skin/images/debugger-step-over.svg (themes/images/debugger-step-over.svg)
     skin/images/dock-bottom.svg (themes/images/dock-bottom.svg)
     skin/images/dock-side-left.svg (themes/images/dock-side-left.svg)
     skin/images/dock-side-right.svg (themes/images/dock-side-right.svg)
     skin/images/dock-undock.svg (themes/images/dock-undock.svg)
     skin/floating-scrollbars-responsive-design.css (themes/floating-scrollbars-responsive-design.css)
+    skin/badge.css (themes/badge.css)
     skin/inspector.css (themes/inspector.css)
     skin/images/profiler-stopwatch.svg (themes/images/profiler-stopwatch.svg)
     skin/images/debugging-addons.svg (themes/images/debugging-addons.svg)
     skin/images/debugging-tabs.svg (themes/images/debugging-tabs.svg)
     skin/images/debugging-workers.svg (themes/images/debugging-workers.svg)
     skin/images/datastore.svg (themes/images/datastore.svg)
     skin/images/globe.svg (themes/images/globe.svg)
     skin/images/folder.svg (themes/images/folder.svg)
--- a/devtools/client/locales/en-US/layout.properties
+++ b/devtools/client/locales/en-US/layout.properties
@@ -16,19 +16,18 @@ flexbox.flexContainer=Flex Container
 # LOCALIZATION NOTE) (flexbox.flexItemOf): The accordion header for the Flexbox panel
 # when a flex item is selected. %s represents the flex container selector.
 flexbox.flexItemOf=Flex Item of %S
 
 # LOCALIZATION NOTE (flexbox.noFlexboxeOnThisPage): In the case where there are no CSS
 # flex containers to display.
 flexbox.noFlexboxeOnThisPage=Select a Flex container or item to continue.
 
-# LOCALIZATION NOTE (flexbox.flexContainerProperties): Header for the flex container
-# properties in the Flexbox panel.
-flexbox.flexContainerProperties=Flex Container Properties
+# LOCALIZATION NOTE (flexbox.flexItems): Header label displayed for the flex item list.
+flexbox.flexItems=Flex Items
 
 # LOCALIZATION NOTE (flexbox.itemSizing.baseSizeSectionHeader): Header label displayed
 # at the start of the flex item sizing Base Size section.
 flexbox.itemSizing.baseSizeSectionHeader=Base Size
 
 # LOCALIZATION NOTE (flexbox.itemSizing.flexibilitySectionHeader): Header label displayed
 # at the start of the flex item sizing Flexibility section.
 flexbox.itemSizing.flexibilitySectionHeader=Flexibility
--- a/devtools/client/responsive.html/actions/devices.js
+++ b/devtools/client/responsive.html/actions/devices.js
@@ -16,17 +16,17 @@ const {
   REMOVE_DEVICE,
   UPDATE_DEVICE_DISPLAYED,
   UPDATE_DEVICE_MODAL,
 } = require("./index");
 const { post } = require("../utils/message");
 
 const { addDevice, getDevices, removeDevice } = require("devtools/client/shared/devices");
 const { changeUserAgent, toggleTouchSimulation } = require("./ui");
-const { changeDevice, changePixelRatio, resizeViewport } = require("./viewports");
+const { changeDevice, changePixelRatio } = require("./viewports");
 
 const DISPLAYED_DEVICES_PREF = "devtools.responsive.html.displayedDeviceList";
 
 /**
  * Returns an object containing the user preference of displayed devices.
  *
  * @return {Object} containing two Sets:
  * - added: Names of the devices that were explicitly enabled by the user
@@ -181,26 +181,20 @@ module.exports = {
 
       const device = devices[deviceType].find(d => d.name === deviceName);
       if (!device) {
         // Can't find device with the same device name.
         return;
       }
 
       post(window, {
-        type: "viewport-resize",
-        width: device.width,
-        height: device.height,
-      });
-      post(window, {
         type: "change-device",
         device,
       });
 
-      dispatch(resizeViewport(id, device.width, device.height));
       dispatch(changeDevice(id, device.name, deviceType));
       dispatch(changePixelRatio(id, device.pixelRatio));
       dispatch(changeUserAgent(device.userAgent));
       dispatch(toggleTouchSimulation(device.touch));
     };
   },
 
   updateDeviceModal(isOpen, modalOpenedFromViewport = null) {
--- a/devtools/client/responsive.html/test/browser/browser_device_state_restore.js
+++ b/devtools/client/responsive.html/test/browser/browser_device_state_restore.js
@@ -72,10 +72,38 @@ addRDMTask(TEST_URL, async function({ ui
 
   info("Checking the restored RDM state.");
   testViewportDeviceMenuLabel(ui, TEST_DEVICE.name);
   testViewportDimensions(ui, TEST_DEVICE.width, TEST_DEVICE.height);
   await testUserAgent(ui, TEST_DEVICE.userAgent);
   await testDevicePixelRatio(ui, TEST_DEVICE.pixelRatio);
   await testTouchEventsOverride(ui, TEST_DEVICE.touch);
 
+  info("Rotating the viewport.");
+  rotateViewport(ui);
+
   reloadOnUAChange(false);
 });
+
+addRDMTask(TEST_URL, async function({ ui }) {
+  const { store } = ui.toolWindow;
+
+  reloadOnUAChange(true);
+
+  info("Reopening RDM and checking that the previous device state is restored.");
+
+  // Wait until the viewport has been added and the device list has been loaded
+  await waitUntilState(store, state =>
+    state.viewports.length == 1 &&
+    state.viewports[0].device === TEST_DEVICE.name &&
+    state.devices.listState == Types.loadableState.LOADED);
+  await waitForViewportResizeTo(ui, TEST_DEVICE.height, TEST_DEVICE.width);
+  await waitForViewportLoad(ui);
+
+  info("Checking the restored RDM state.");
+  testViewportDeviceMenuLabel(ui, TEST_DEVICE.name);
+  testViewportDimensions(ui, TEST_DEVICE.height, TEST_DEVICE.width);
+  await testUserAgent(ui, TEST_DEVICE.userAgent);
+  await testDevicePixelRatio(ui, TEST_DEVICE.pixelRatio);
+  await testTouchEventsOverride(ui, TEST_DEVICE.touch);
+
+  reloadOnUAChange(false);
+});
--- a/devtools/client/responsive.html/test/browser/browser_state_restore.js
+++ b/devtools/client/responsive.html/test/browser/browser_state_restore.js
@@ -1,14 +1,14 @@
 /* Any copyright is dedicated to the Public Domain.
 http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
-// Test that the previous viewport size, user agent, ddppx and touch simulation properties
+// Test that the previous viewport size, user agent, dppx and touch simulation properties
 // are restored when reopening RDM.
 
 const TEST_URL = "data:text/html;charset=utf-8,";
 const DEFAULT_DPPX = window.devicePixelRatio;
 const NEW_DPPX = DEFAULT_DPPX + 1;
 const NEW_USER_AGENT = "Mozilla/5.0 (Mobile; rv:39.0) Gecko/39.0 Firefox/39.0";
 
 addRDMTask(TEST_URL, async function({ ui, manager }) {
@@ -37,20 +37,42 @@ addRDMTask(TEST_URL, async function({ ui
 });
 
 addRDMTask(TEST_URL, async function({ ui }) {
   const { store } = ui.toolWindow;
 
   reloadOnTouchChange(true);
   reloadOnUAChange(true);
 
-  info("Reopening RDM and checking that the previous device state is restored.");
+  info("Reopening RDM and checking that the previous state is restored.");
 
   await waitUntilState(store, state => state.viewports.length == 1);
 
   testViewportDimensions(ui, 90, 500);
   await testUserAgent(ui, NEW_USER_AGENT);
   await testDevicePixelRatio(ui, NEW_DPPX);
   await testTouchEventsOverride(ui, true);
 
+  info("Rotating the viewport.");
+  rotateViewport(ui);
+
   reloadOnTouchChange(false);
   reloadOnUAChange(false);
 });
+
+addRDMTask(TEST_URL, async function({ ui }) {
+  const { store } = ui.toolWindow;
+
+  reloadOnTouchChange(true);
+  reloadOnUAChange(true);
+
+  info("Reopening RDM and checking that the previous state is restored.");
+
+  await waitUntilState(store, state => state.viewports.length == 1);
+
+  testViewportDimensions(ui, 500, 90);
+  await testUserAgent(ui, NEW_USER_AGENT);
+  await testDevicePixelRatio(ui, NEW_DPPX);
+  await testTouchEventsOverride(ui, true);
+
+  reloadOnTouchChange(false);
+  reloadOnUAChange(false);
+});
--- a/devtools/client/responsive.html/test/browser/head.js
+++ b/devtools/client/responsive.html/test/browser/head.js
@@ -504,8 +504,14 @@ function reloadOnUAChange(enabled) {
   const pref = RELOAD_CONDITION_PREF_PREFIX + "userAgent";
   Services.prefs.setBoolPref(pref, enabled);
 }
 
 function reloadOnTouchChange(enabled) {
   const pref = RELOAD_CONDITION_PREF_PREFIX + "touchSimulation";
   Services.prefs.setBoolPref(pref, enabled);
 }
+
+function rotateViewport(ui) {
+  const { document } = ui.toolWindow;
+  const rotateButton = document.getElementById("rotate-button");
+  rotateButton.click();
+}
new file mode 100644
--- /dev/null
+++ b/devtools/client/themes/badge.css
@@ -0,0 +1,70 @@
+/* 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/. */
+
+:root {
+  --badge-active-background-color: var(--blue-50);
+  --badge-active-border-color: #FFFFFFB3;
+  --badge-background-color: white;
+  --badge-border-color: #CACAD1;
+  --badge-color: var(--grey-60);
+  --badge-hover-background-color: #DFDFE8;
+  --badge-interactive-background-color: var(--grey-20);
+  --badge-interactive-color: var(--grey-90);
+}
+
+.theme-dark:root {
+  --badge-active-background-color: var(--blue-60);
+  --badge-active-border-color: #FFF6;
+  --badge-background-color: var(--grey-80);
+  --badge-border-color: var(--grey-50);
+  --badge-color: var(--grey-40);
+  --badge-hover-background-color: var(--grey-80);
+  --badge-interactive-background-color: var(--grey-70);
+  --badge-interactive-color: var(--grey-30);
+}
+
+/* Inspector badge */
+.inspector-badge {
+  display: inline-block;
+  /* 9px text is too blurry on low-resolution screens */
+  font-size: 10px;
+  font-weight: normal;
+  line-height: 10px;
+  height: 12px;
+  margin-top: 1px;
+  vertical-align: top;
+  border: 1px solid var(--badge-border-color);
+  border-radius: 3px;
+  padding: 0px 2px;
+  margin-inline-start: 5px;
+  -moz-user-select: none;
+  background-color: var(--badge-background-color);
+  color: var(--badge-color);
+  box-sizing: border-box;
+}
+
+@media (min-resolution: 1.1dppx) {
+  .inspector-badge {
+    font-size: 9px;
+  }
+}
+
+/* Inspector badges that are interactive/clickable */
+.inspector-badge.interactive {
+  background-color: var(--badge-interactive-background-color);
+  color: var(--badge-interactive-color);
+  cursor: pointer;
+}
+
+.inspector-badge:not(.active).interactive:focus,
+.inspector-badge:not(.active).interactive:hover {
+  background-color: var(--badge-hover-background-color);
+}
+
+.inspector-badge.active,
+.inspector-badge.interactive.active {
+  background-color: var(--badge-active-background-color);
+  border-color: var(--badge-active-border-color);
+  color: var(--theme-selection-color);
+}
--- a/devtools/client/themes/layout.css
+++ b/devtools/client/themes/layout.css
@@ -91,78 +91,125 @@
  * Flex Container
  */
 
 #layout-flexbox-container {
   display: flex;
   flex-direction: column;
 }
 
-#layout-flexbox-container .flex-header-content:not(.flex-item-shown) {
-  overflow: hidden;
-  display: flex;
-}
-
-#layout-flexbox-container .flex-header-content:not(.flex-item-shown) .objectBox {
-  max-width: calc(100% - 20px);
-  margin-inline-end: 5px;
-  text-overflow: ellipsis;
-  overflow: hidden;
-  white-space: nowrap;
-}
-
 /**
  * Header
  */
 
 .flex-header {
   display: flex;
   align-items: center;
-  height: 32px;
-  padding: 0 3px;
+  padding: 3px;
   border-block-end: 1px solid var(--theme-splitter-color);
 }
 
 .flex-header-button-prev::before {
   background-image: url("chrome://devtools/skin/images/arrowhead-left.svg");
   background-size: 16px;
 }
 
 .flex-header-content {
+  display: flex;
   flex: 1;
-  padding-top: 2px;
+  padding: 2px 0;
   padding-inline-start: 20px;
   -moz-user-select: none;
 }
 
+.flex-header-content:not(.flex-item-shown) {
+  flex-direction: column;
+  overflow: hidden;
+}
+
+.flex-header-content:not(.flex-item-shown) .objectBox {
+  max-width: calc(100% - 20px);
+  margin-inline-end: 5px;
+  text-overflow: ellipsis;
+  overflow: hidden;
+  white-space: nowrap;
+}
+
 .flex-header-content.flex-item-shown {
-  display: flex;
   justify-content: center;
   padding: 0;
 }
 
+.flex-header-container-properties {
+  display: flex;
+}
+
+.flex-header-container-properties .inspector-badge:first-child {
+  margin-inline-start: 0;
+}
+
+.flex-header-container-label,
+.flex-header-container-properties {
+  display: flex;
+  padding: 3px 0;
+}
+
 /**
  * Flex Item List
  */
 
 .flex-item-list {
   font-size: 12px;
   margin: 0;
-  padding-inline-start: 34px;
   padding-top: 5px;
   padding-bottom: 5px;
   overflow: hidden;
 }
 
+.flex-item-list .flex-item-list-header {
+  color: var(--theme-comment);
+  padding-inline-start: 23px;
+  margin-bottom: 4px;
+  -moz-user-select: none;
+}
+
 .flex-item-list .devtools-button {
   background-color: transparent;
   text-overflow: ellipsis;
   overflow: hidden;
   inline-size: 100%;
   text-align: start;
+  height: 24px;
+  margin: 0;
+  padding-inline-start: 28px;
+  padding-inline-end: 16px;
+  position: relative;
+}
+
+.flex-item-list .devtools-button::after {
+  content: "";
+  background-image: url(chrome://devtools/skin/images/arrowhead-right.svg);
+  background-size: 16px;
+  background-repeat: no-repeat;
+  background-position: center -1px;
+  fill: var(--theme-comment);
+  -moz-context-properties: fill;
+  position: absolute;
+  right: 7px;
+  width: 16px;
+  height: 16px;
+}
+
+.flex-item-list .flex-item-index {
+  font-size: 12px;
+  font-weight: bold;
+}
+
+.flex-item-list .objectBox-node {
+  padding-inline-start: 8px;
 }
 
 /**
  * Flex Item Selector
  */
 
 #flex-item-selector {
   background-position: right 4px center;
@@ -440,30 +487,16 @@
 .flex-item-sizing .reasons li {
   grid-column: 1 / 3;
   margin: 0;
   padding: 0;
   list-style: none;
 }
 
 /**
- * Flex Container Properties
- */
-
-#flex-container-properties {
-  border-block-start: 1px solid var(--theme-splitter-color);
-  margin-bottom: 5px;
-}
-
-#flex-container-properties .layout-properties-header {
-  padding: 5px 0;
-  padding-inline-start: 20px;
-}
-
-/**
  * Grid Container
  */
 
 #layout-grid-container {
   display: flex;
   flex-direction: column;
   padding: 5px;
 }
--- a/devtools/client/themes/markup.css
+++ b/devtools/client/themes/markup.css
@@ -1,37 +1,21 @@
 /* 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/. */
 
 :root {
-  --markup-badge-active-background-color: var(--blue-50);
-  --markup-badge-active-border-color: #FFFFFFB3;
-  --markup-badge-background-color: white;
-  --markup-badge-border-color: #CACAD1;
-  --markup-badge-color: var(--grey-60);
-  --markup-badge-hover-background-color: #DFDFE8;
-  --markup-badge-interactive-background-color: var(--grey-20);
-  --markup-badge-interactive-color: var(--grey-90);
   --markup-hidden-attr-name-color: #BA89B8;
   --markup-hidden-attr-value-color: #5C6D87;
   --markup-hidden-punctuation-color: #909090;
   --markup-hidden-tag-color: #97A4B3;
   --markup-outline: var(--theme-splitter-color);
 }
 
 .theme-dark:root {
-  --markup-badge-active-background-color: var(--blue-60);
-  --markup-badge-active-border-color: #FFF6;
-  --markup-badge-background-color: var(--grey-80);
-  --markup-badge-border-color: var(--grey-50);
-  --markup-badge-color: var(--grey-40);
-  --markup-badge-hover-background-color: var(--grey-80);
-  --markup-badge-interactive-background-color: var(--grey-70);
-  --markup-badge-interactive-color: var(--grey-30);
   --markup-hidden-attr-name-color: #B07EB3;
   --markup-hidden-attr-value-color: #9893A3;
   --markup-hidden-punctuation-color: #909090;
   --markup-hidden-tag-color: #AFB5BF;
   --markup-outline: var(--theme-selection-background);
 }
 
 * {
@@ -244,31 +228,36 @@ ul.children + .tag-line::before {
   height: 16px;
   margin: -1px 0;
   padding: 3px 2px;
 }
 
 .expandable.collapsed .markup-expand-badge::before {
   /* Display an ellipsis character in collapsed nodes that can be expanded. */
   content: "";
-  background-color: var(--markup-badge-interactive-background-color);
+  background-color: var(--badge-interactive-background-color);
   background-image: url(chrome://devtools/skin/images/more.svg);
   background-repeat: no-repeat;
   background-position: center;
-  border: 1px solid var(--markup-badge-border-color);
-  color: var(--markup-badge-color);
-  fill: var(--markup-badge-interactive-color);
+  border: 1px solid var(--badge-border-color);
+  color: var(--badge-color);
+  fill: var(--badge-interactive-color);
   display: block;
   width: 12px;
   height: 8px;
   line-height: 8px;
   border-radius: 3px;
   -moz-context-properties: fill;
 }
 
+.expandable.collapsed .markup-expand-badge:focus::before,
+.expandable.collapsed .markup-expand-badge:hover::before {
+  background-color: var(--badge-hover-background-color);
+}
+
 /* Hide HTML void elements (img, hr, br, …) closing tag when the element is not
  * expanded (it can be if it has pseudo-elements attached) */
 .child.collapsed > .tag-line .void-element .close {
   display: none;
 }
 
 .closing-bracket {
   pointer-events: none;
@@ -407,67 +396,8 @@ ul.children + .tag-line::before {
 .theme-selected ~ .editor .theme-fg-color5 {
   color: var(--theme-selection-color);
 }
 
 /* Applicable to the DOCTYPE */
 .doctype {
   font-style: italic;
 }
-
-/* Markup Badges */
-.markup-badge {
-  display: inline-block;
-  /* 9px text is too blurry on low-resolution screens */
-  font-size: 10px;
-  font-weight: normal;
-  line-height: 10px;
-  height: 10px;
-  margin-top: 1px;
-  vertical-align: top;
-  border: 1px solid var(--markup-badge-border-color);
-  border-radius: 3px;
-  padding: 0px 2px;
-  margin-inline-start: 5px;
-  -moz-user-select: none;
-  background-color: var(--markup-badge-background-color);
-  color: var(--markup-badge-color);
-}
-
-@media (min-resolution: 1.1dppx) {
-  .markup-badge {
-    font-size: 9px;
-  }
-}
-
-/* Markup badges that are interactive/clickable */
-.markup-badge[data-custom],
-.markup-badge[data-display="flex"].interactive,
-.markup-badge[data-display="grid"].interactive,
-.markup-badge[data-display="inline-flex"].interactive,
-.markup-badge[data-display="inline-grid"].interactive,
-.markup-badge[data-event] {
-  background-color: var(--markup-badge-interactive-background-color);
-  color: var(--markup-badge-interactive-color);
-  cursor: pointer;
-}
-
-.markup-badge[data-display="flex"]:not(.active).interactive:focus,
-.markup-badge[data-display="flex"]:not(.active).interactive:hover,
-.markup-badge[data-display="grid"]:not(.active).interactive:focus,
-.markup-badge[data-display="grid"]:not(.active).interactive:hover,
-.markup-badge[data-display="inline-flex"]:not(.active).interactive:focus,
-.markup-badge[data-display="inline-flex"]:not(.active).interactive:hover,
-.markup-badge[data-display="inline-grid"]:not(.active).interactive:focus,
-.markup-badge[data-display="inline-grid"]:not(.active).interactive:hover,
-.markup-badge[data-event]:focus,
-.markup-badge[data-event]:hover,
-.expandable.collapsed .markup-expand-badge:focus::before,
-.expandable.collapsed .markup-expand-badge:hover::before {
-  background-color: var(--markup-badge-hover-background-color);
-}
-
-.markup-badge.active,
-.markup-badge.interactive.active {
-  background-color: var(--markup-badge-active-background-color);
-  border-color: var(--markup-badge-active-border-color);
-  color: var(--theme-selection-color);
-}
--- a/devtools/client/webconsole/reducers/messages.js
+++ b/devtools/client/webconsole/reducers/messages.js
@@ -27,16 +27,18 @@ const {
 
 const {
   processNetworkUpdates,
 } = require("devtools/client/netmonitor/src/utils/request-utils");
 
 const MessageState = overrides => Object.freeze(Object.assign({
   // List of all the messages added to the console.
   messagesById: new Map(),
+  // When recording or replaying, all progress values in messagesById.
+  replayProgressMessages: new Set(),
   // Array of the visible messages.
   visibleMessages: [],
   // Object for the filtered messages.
   filteredMessagesCount: getDefaultFiltersCounter(),
   // List of the message ids which are opened.
   messagesUiById: [],
   // Map of the form {messageId : tableData}, which represent the data passed
   // as an argument in console.table calls.
@@ -56,42 +58,54 @@ const MessageState = overrides => Object
   // `networkInformation` holds request, response, totalTime, ...
   networkMessagesUpdateById: {},
   pausedExecutionPoint: null,
 }, overrides));
 
 function cloneState(state) {
   return {
     messagesById: new Map(state.messagesById),
+    replayProgressMessages: new Set(state.replayProgressMessages),
     visibleMessages: [...state.visibleMessages],
     filteredMessagesCount: {...state.filteredMessagesCount},
     messagesUiById: [...state.messagesUiById],
     messagesTableDataById: new Map(state.messagesTableDataById),
     groupsById: new Map(state.groupsById),
     currentGroup: state.currentGroup,
     removedActors: [...state.removedActors],
     repeatById: {...state.repeatById},
     networkMessagesUpdateById: {...state.networkMessagesUpdateById},
     pausedExecutionPoint: state.pausedExecutionPoint,
   };
 }
 
 function addMessage(state, filtersState, prefsState, newMessage) {
   const {
     messagesById,
+    replayProgressMessages,
     groupsById,
     currentGroup,
     repeatById,
   } = state;
 
   if (newMessage.type === constants.MESSAGE_TYPE.NULL_MESSAGE) {
     // When the message has a NULL type, we don't add it.
     return state;
   }
 
+  if (newMessage.executionPoint) {
+    // When replaying old behaviors in a tab, we might see the same messages
+    // multiple times. Ignore duplicate messages with the same progress values.
+    const progress = newMessage.executionPoint.progress;
+    if (replayProgressMessages.has(progress)) {
+      return state;
+    }
+    state.replayProgressMessages.add(progress);
+  }
+
   if (newMessage.type === constants.MESSAGE_TYPE.END_GROUP) {
     // Compute the new current group.
     state.currentGroup = getNewCurrentGroup(currentGroup, groupsById);
     return state;
   }
 
   if (newMessage.allowRepeating && messagesById.size > 0) {
     const lastMessage = [...messagesById.values()][messagesById.size - 1];
--- a/devtools/server/actors/replay/replay.js
+++ b/devtools/server/actors/replay/replay.js
@@ -144,19 +144,19 @@ function addScriptSource(source) {
   // Tolerate redundant attempts to add the same source, as we might see
   // onNewScript calls for different scripts with the same source.
   if (!gScriptSources.getId(source)) {
     gScriptSources.add(source);
   }
 }
 
 function considerScript(script) {
-  return script.url
-      && !script.url.startsWith("resource:")
-      && !script.url.startsWith("chrome:");
+  // The set of scripts which is exposed to the debugger server is the same as
+  // the scripts for which the progress counter is updated.
+  return RecordReplayControl.shouldUpdateProgressCounter(script.url);
 }
 
 dbg.onNewScript = function(script) {
   if (RecordReplayControl.areThreadEventsDisallowed()) {
     // This script is part of an eval on behalf of the debugger.
     return;
   }
 
--- a/devtools/server/actors/webconsole.js
+++ b/devtools/server/actors/webconsole.js
@@ -548,36 +548,16 @@ WebConsoleActor.prototype =
     });
   },
 
   /**
    * When using a replaying debugger, all messages we have seen so far.
    */
   replayingMessages: null,
 
-  /**
-   * When using a replaying debugger, this helper returns whether a message has
-   * been seen before. When the process rewinds or plays back through regions
-   * of execution that have executed before, we will see the same messages
-   * again.
-   */
-  isDuplicateReplayingMessage: function(msg) {
-    if (!this.replayingMessages) {
-      this.replayingMessages = {};
-    }
-    // The progress counter on the message is unique across all messages in the
-    // replaying process.
-    const progress = msg.executionPoint.progress;
-    if (this.replayingMessages[progress]) {
-      return true;
-    }
-    this.replayingMessages[progress] = true;
-    return false;
-  },
-
   // Request handlers for known packet types.
 
   /**
    * Handler for the "startListeners" request.
    *
    * @param object request
    *        The JSON request object received from the Web Console client.
    * @return object
@@ -848,19 +828,17 @@ WebConsoleActor.prototype =
         message: "The messageTypes parameter is missing.",
       };
     }
 
     const messages = [];
 
     let replayingMessages = [];
     if (this.dbg.replaying) {
-      replayingMessages = this.dbg.findAllConsoleMessages().filter(msg => {
-        return !this.isDuplicateReplayingMessage(msg);
-      });
+      replayingMessages = this.dbg.findAllConsoleMessages();
     }
 
     while (types.length > 0) {
       const type = types.shift();
       switch (type) {
         case "ConsoleAPI": {
           replayingMessages.forEach((msg) => {
             if (msg.messageType == "ConsoleAPI") {
@@ -1431,20 +1409,16 @@ WebConsoleActor.prototype =
 
   // Event handlers for various listeners.
 
   /**
    * Handle console messages sent to us from a replaying process via the
    * debugger.
    */
   onReplayingMessage: function(msg) {
-    if (this.isDuplicateReplayingMessage(msg)) {
-      return;
-    }
-
     if (msg.messageType == "ConsoleAPI") {
       this.onConsoleAPICall(msg);
     }
 
     if (msg.messageType == "PageError") {
       const packet = {
         from: this.actorID,
         type: "pageError",
--- a/gfx/thebes/gfxDWriteFontList.cpp
+++ b/gfx/thebes/gfxDWriteFontList.cpp
@@ -1252,17 +1252,17 @@ gfxDWriteFontList::GetFontsFromCollectio
             continue;
         }
 
         fam = new gfxDWriteFontFamily(familyName, family, aCollection == mSystemFonts);
         if (!fam) {
             continue;
         }
 
-        if (mBadUnderlineFamilyNames.Contains(name)) {
+        if (mBadUnderlineFamilyNames.ContainsSorted(name)) {
             fam->SetBadUnderlineFamily();
         }
         mFontFamilies.Put(name, fam);
 
         // now add other family name localizations, if present
         uint32_t nameCount = names->GetCount();
         uint32_t nameIndex;
 
--- a/gfx/thebes/gfxFT2FontList.cpp
+++ b/gfx/thebes/gfxFT2FontList.cpp
@@ -1227,17 +1227,17 @@ gfxFT2FontList::AddFaceToList(const nsCS
         BuildKeyNameFromFontName(name);
         RefPtr<gfxFontFamily> family = mFontFamilies.GetWeak(name);
         if (!family) {
             family = new FT2FontFamily(name);
             mFontFamilies.Put(name, family);
             if (mSkipSpaceLookupCheckFamilies.Contains(name)) {
                 family->SetSkipSpaceFeatureCheck(true);
             }
-            if (mBadUnderlineFamilyNames.Contains(name)) {
+            if (mBadUnderlineFamilyNames.ContainsSorted(name)) {
                 family->SetBadUnderlineFamily();
             }
         }
         fe->mStandardFace = (aStdFile == kStandard);
         family->AddFontEntry(fe);
 
         fe->CheckForBrokenFont(family);
 
@@ -1509,17 +1509,17 @@ gfxFT2FontList::AppendFaceFromFontListEn
         fe->mStandardFace = (aStdFile == kStandard);
         RefPtr<gfxFontFamily> family = mFontFamilies.GetWeak(aFLE.familyName());
         if (!family) {
             family = new FT2FontFamily(aFLE.familyName());
             mFontFamilies.Put(aFLE.familyName(), family);
             if (mSkipSpaceLookupCheckFamilies.Contains(aFLE.familyName())) {
                 family->SetSkipSpaceFeatureCheck(true);
             }
-            if (mBadUnderlineFamilyNames.Contains(aFLE.familyName())) {
+            if (mBadUnderlineFamilyNames.ContainsSorted(aFLE.familyName())) {
                 family->SetBadUnderlineFamily();
             }
         }
         family->AddFontEntry(fe);
 
         fe->CheckForBrokenFont(family);
     }
 }
--- a/gfx/thebes/gfxGDIFontList.cpp
+++ b/gfx/thebes/gfxGDIFontList.cpp
@@ -698,18 +698,19 @@ gfxGDIFontList::EnumFontFamExProc(ENUMLO
         // if locale is such that CJK font names are the default coming from
         // GDI, then if a family name is non-ASCII immediately read in other
         // family names.  This assures that MS Gothic, MS Mincho are all found
         // before lookups begin.
         if (!IsASCII(faceName)) {
             family->ReadOtherFamilyNames(gfxPlatformFontList::PlatformFontList());
         }
 
-        if (fontList->mBadUnderlineFamilyNames.Contains(key))
+        if (fontList->mBadUnderlineFamilyNames.ContainsSorted(key)) {
             family->SetBadUnderlineFamily();
+        }
 
         family->mWindowsFamily = lf.lfPitchAndFamily & 0xF0;
         family->mWindowsPitch = lf.lfPitchAndFamily & 0x0F;
 
         // mark the charset bit
         family->mCharset.set(metrics.tmCharSet);
     }
 
--- a/gfx/thebes/gfxMacPlatformFontList.mm
+++ b/gfx/thebes/gfxMacPlatformFontList.mm
@@ -1123,17 +1123,17 @@ gfxMacPlatformFontList::AddFamily(const 
     nsAutoCString key;
     ToLowerCase(aFamilyName, key);
 
     RefPtr<gfxFontFamily> familyEntry =
         new gfxMacFontFamily(aFamilyName, sizeHint);
     table.Put(key, familyEntry);
 
     // check the bad underline blacklist
-    if (mBadUnderlineFamilyNames.Contains(key)) {
+    if (mBadUnderlineFamilyNames.ContainsSorted(key)) {
         familyEntry->SetBadUnderlineFamily();
     }
 }
 
 void
 gfxMacPlatformFontList::AddFamily(CFStringRef aFamily)
 {
     NSString* family = (NSString*)aFamily;
--- a/gfx/thebes/gfxPlatformFontList.cpp
+++ b/gfx/thebes/gfxPlatformFontList.cpp
@@ -196,17 +196,17 @@ gfxPlatformFontList::MemoryReporter::Col
             "Memory used for (platform-specific) font loader.");
     }
 
     return NS_OK;
 }
 
 gfxPlatformFontList::gfxPlatformFontList(bool aNeedFullnamePostscriptNames)
     : mFontFamiliesMutex("gfxPlatformFontList::mFontFamiliesMutex"), mFontFamilies(64),
-      mOtherFamilyNames(16), mBadUnderlineFamilyNames(8), mSharedCmaps(8),
+      mOtherFamilyNames(16), mSharedCmaps(8),
       mStartIndex(0), mNumFamilies(0), mFontlistInitCount(0),
       mFontFamilyWhitelistActive(false)
 {
     mOtherFamilyNamesInitialized = false;
 
     if (aNeedFullnamePostscriptNames) {
         mExtraNames = MakeUnique<ExtraNames>();
     }
@@ -515,24 +515,23 @@ gfxPlatformFontList::PreloadNamesList()
         }
     }
 
 }
 
 void
 gfxPlatformFontList::LoadBadUnderlineList()
 {
-    AutoTArray<nsCString, 10> blacklist;
-    gfxFontUtils::GetPrefsFontList("font.blacklist.underline_offset", blacklist);
-    uint32_t numFonts = blacklist.Length();
-    for (uint32_t i = 0; i < numFonts; i++) {
-        nsAutoCString key;
-        GenerateFontListKey(blacklist[i], key);
-        mBadUnderlineFamilyNames.PutEntry(key);
+    gfxFontUtils::GetPrefsFontList("font.blacklist.underline_offset",
+                                   mBadUnderlineFamilyNames);
+    for (auto& fam : mBadUnderlineFamilyNames) {
+        ToLowerCase(fam);
     }
+    mBadUnderlineFamilyNames.Compact();
+    mBadUnderlineFamilyNames.Sort();
 }
 
 void
 gfxPlatformFontList::UpdateFontList()
 {
     InitFontList();
     RebuildLocalFonts();
 }
@@ -849,18 +848,19 @@ gfxPlatformFontList::AddOtherFamilyName(
     GenerateFontListKey(aOtherFamilyName, key);
 
     if (!mOtherFamilyNames.GetWeak(key)) {
         mOtherFamilyNames.Put(key, aFamilyEntry);
         LOG_FONTLIST(("(fontlist-otherfamily) canonical family: %s, "
                       "other family: %s\n",
                       aFamilyEntry->Name().get(),
                       aOtherFamilyName.get()));
-        if (mBadUnderlineFamilyNames.Contains(key))
+        if (mBadUnderlineFamilyNames.ContainsSorted(key)) {
             aFamilyEntry->SetBadUnderlineFamily();
+        }
     }
 }
 
 void
 gfxPlatformFontList::AddFullname(gfxFontEntry *aFontEntry, const nsCString& aFullname)
 {
     if (!mExtraNames->mFullnames.GetWeak(aFullname)) {
         mExtraNames->mFullnames.Put(aFullname, aFontEntry);
@@ -1677,17 +1677,21 @@ gfxPlatformFontList::AddSizeOfExcludingT
     }
 
     aSizes->mFontListSize +=
         mCodepointsWithNoFonts.SizeOfExcludingThis(aMallocSizeOf);
     aSizes->mFontListSize +=
         mFontFamiliesToLoad.ShallowSizeOfExcludingThis(aMallocSizeOf);
 
     aSizes->mFontListSize +=
-        mBadUnderlineFamilyNames.SizeOfExcludingThis(aMallocSizeOf);
+        mBadUnderlineFamilyNames.ShallowSizeOfExcludingThis(aMallocSizeOf);
+    for (const auto& i : mBadUnderlineFamilyNames) {
+        aSizes->mFontListSize +=
+            i.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
+    }
 
     aSizes->mFontListSize +=
         mSharedCmaps.ShallowSizeOfExcludingThis(aMallocSizeOf);
     for (auto iter = mSharedCmaps.ConstIter(); !iter.Done(); iter.Next()) {
         aSizes->mCharMapsSize +=
             iter.Get()->GetKey()->SizeOfIncludingThis(aMallocSizeOf);
     }
 }
--- a/gfx/thebes/gfxPlatformFontList.h
+++ b/gfx/thebes/gfxPlatformFontList.h
@@ -592,17 +592,18 @@ protected:
 
     // when system-wide font lookup fails for a character, cache it to skip future searches
     gfxSparseBitSet mCodepointsWithNoFonts;
 
     // the family to use for U+FFFD fallback, to avoid expensive search every time
     // on pages with lots of problems
     RefPtr<gfxFontFamily> mReplacementCharFallbackFamily;
 
-    nsTHashtable<nsCStringHashKey> mBadUnderlineFamilyNames;
+    // Sorted array of lowercased family names; use ContainsSorted to test
+    nsTArray<nsCString> mBadUnderlineFamilyNames;
 
     // character map data shared across families
     // contains weak ptrs to cmaps shared by font entry objects
     nsTHashtable<CharMapHashKey> mSharedCmaps;
 
     // data used as part of the font cmap loading process
     nsTArray<RefPtr<gfxFontFamily> > mFontFamiliesToLoad;
     uint32_t mStartIndex;
--- a/image/test/mochitest/bug496292-1.sjs
+++ b/image/test/mochitest/bug496292-1.sjs
@@ -4,17 +4,17 @@ function handleRequest(request, response
              .getService(Components.interfaces.nsIProperties)
              .get("CurWorkD", Components.interfaces.nsIFile);
 
   file.append("tests");
   file.append("image");
   file.append("test");
   file.append("mochitest");
 
-  if (request.getHeader("Accept") == "*/*") {
+  if (request.getHeader("Accept") == "image/webp,*/*") {
     file.append('blue.png');
   } else {
     file.append('red.png');
   }
   response.setStatusLine(request.httpVersion, 200, "OK");
   response.setHeader("Content-Type", "image/png", false);
   response.setHeader("Cache-Control", "no-cache", false);
 
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..6db376d6e176f94b8d152f491a779370b3ea45bc
GIT binary patch
literal 202
zc$^FJbaOkzz`zjh>J$(bU=hIuWD5atG8j4fdHS*edH;cc5y<m((_w%Ch>8>j1}30B
zA7P+~e)0hc0d@gFK?b2i|NlC<{15H~>(Rs1!vNAF3f05FF7UViAA3W~hx+{j7ypMS
Hk!2GA*Dx&M
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..e4a3e2efabe2c963cd186dcd064dd1fd139aa7ab
GIT binary patch
literal 228
zc$^FJbaT7Iz`zjh>J$(bU=hIuWD5atG6RDb1B0WVr!O0j_a6utfjnO~Jq8$nr~s;G
z0_yV-1&Zh=HwZDXU-;kgkG-Mg!~cCk7yoaO1naWGp-Ty>OMqYCv;1dy9@kuH!>9eL
z&Uhu<sc`*L&-B4d^KEB7$OH?ZN<Ib#VK9<Km>>@_LD+#^fZyQ1AlQW44iEWv{gsn$
O==kT)ps;@e3j+YMkvPu)
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..4219e179b0bb3c7727f78cdcabcfd8562729c017
GIT binary patch
literal 3742
zc$@*A4q@?9Nk&GN4gdgGMM6+kP&il$0000I0001E003hE06|VkO$Gn}00000{{R3%
zPEAJC1poj5000000Am0EV*mi?0{{Y6P&iDx1pojqW55^yw;>Qn+8=ri#%&up0=#?q
z`fu!dxMvQwFAdv(ZQJnwUp-ZlDVYEGf8$T8_2~)5uq+4q$`6JV1gQ>WInWyivOv%e
zir_JXR0t_Zz+8|51p+}v=73}ek~uHwvWj$=AT35wP5(dT&;b1a+O};+ZLEMmm@Xlh
zMwrHg0)oY*P4NGJ8xj((d+I%+{|+QciXyu98gYPe9grtj=#3ZBov7@_b$bF7R^JX%
zHS?M^{klOdM<e!<n$8=%FD7~u<HY6n0MGcLsX|oE^3$45Kft~acSmeATyk%r87tyq
z^mfA7&!C`n>YEayg0LHZQBW*>TSU$YV|af+Vp}I#-#$&LOEbK8pxD--y+_UoN>~TC
z--%X<hmn*ox`1-FEq#+-CAAb}M-?>I;k%4n9SPBF!nFgc7T4HCQ^iE(WBLVFYiNtm
zkzfTyJFKwynJCLPLeRxen|^lztg$+IKQ+q$V;!2CrwdVaC+22lXe8eLRqW!LHv@Rk
z#k<x0431QmYgFAO6`g)JX!wQ%%?gX%1u)v|Y9d8a>zXz_FvhkBEy)CcFmthhVw>m}
zadgQl2D^j<(wCXmiD!swshSi2fyUZ5Szu~n7n&Vc6dGg4&C0S_=6_(@^`eW4d|)IY
zs_4A^&2xX&by?PzQ*-K@ND<;h<?C#mc7M|_P}+6f<K;V)yLrS|Y`#3rVNA<34LyCd
z&7ZQ!(p#FpK9zN4EOCL%pm@wD;I79qjXkB`ZBtiemXbK|UDvi9_f(9<T8FOO-77*a
ze$kHWCe|;zAU$oHs?5`bM3L`1&gFtN4eio|V><ph=6Rl`X=a+H;ZbM4DFJ)8nvT<a
zc%KHoZjqAs`sq5Ri8+6&dhG1B9mh1!<IwlCYuiSw`hE)?EKAK!m{#?nTXkKPMViEc
z=U9fWA<m!jCe}1fBMSiS+J@_8nh+94Ofj$U`fg#Q$X5Hde~rU9jQ01?_umh7_lTWS
z%?BV)Z-fL_@56CS(=hP<E)d3=yw@tybOZD6Sl19&_XUMf5c<CRZac<B*R?~8RiVTo
z7gtwUkJ!8N_Oh^n4}Uw>)i<DG<39`ut_1-<S4Bv}h7EH}oIj*tY+9~&jS`R%)3IS#
z_J<dSB*}}aZUJ3x{(6|U>s^DGB)6ihnzp0;FwUn!yi4Zl#hXK6=d#<>a=joTX?|y^
zr+f7MI4vuePtROF4eOZQ`x4<@x~?JhMAS5F94>bzh}bl*>(3^bdR3Jl5gQXWO~?KG
z41zG^a@bK3Qy7JT=NOtQDF|EMl_XhFHQ$s)jEzY?uNxP`G#%T0_x&g$NtTyYRo8WM
zN_G8}#UF+wWg^V-a!dPRuX}#Y5D`L>TbdVTRdW&kZy3jk%_(9{yoSDIPph)Wi7;>a
zd3|k3(lkxmb`RPQ!!$1}#4l>;xkb1bm((w>j;EQ8NHC<o@=V+nfh9!6UfK>X7Jfv3
zb*;8dUCGujVzPFGww<@lw2W*q#%JEm0I4LP%e8pGW1&^-h%v*GLZl`VESU5h;@gw0
zTQ^{=Quc#vzXcwDA{(7~RE6g(67PH?<Ad980oUj~Fl75Jqyk8ndsvKSGxyLK+f26K
z!tLWi<7a4Y94E2>>`fho-^T?<n|@x9BE*X8euYOa+dt5pq#2<(_#LH>s*3JqAg7p`
zh+U{g_|>mZc!_y$(GY<w!kfUk$Ua3VnwNJAJbuO<tO`vPZvvNUQcu(lvYA7G3=MIF
zCgu<zYhQ&I0mukSy1-*w9)+iiOjfkl0m#%Ow$S8|8X`Y^6&Yd@20&B3o5ZVpkc>^@
z2y+=w*4<=ENC2`e^zIv~9C!}7m4)=+6Ji}tmjbV>LzB2Nk|$6!G0qbreJ$k)6e31>
zLM0LN1dXu#0|%eLITXkwj;8PhG~~b&I4;K%I@|*M`7dxN(A#<b3upjAPEAIR2mk;8
z000000Am0EV*mi?0{{S4P&iC>2mk;tW55^?zabDv+8=ri#%&}iTJ<sHpV;MaPloP3
z8nyx3w&DN3da5K-F#jRR{~Ld@TA!X^49jw$ul!)hf*`8{Sq}8Zfh-X8gCckgAuEI|
zNWff>1quX$jLZR<9Z2T9WS3QBhY7O9D5~lIryLrfA0W}%_L{L$Nkk7i<4{Tu#@HCc
zDAk?b|E)><(dY$4^dF)mNp%~Tjjk|0{L%qOz98IEY+$<flCtAZQPC2WKe{?Uds|9Y
z>WT?59cmzi46+W=`o0)^Xv-wD88MVC2BB>G;oAfuiS03OhNoP$>)wp58;WOG=Eez5
zNoFG?L-%pf4txoCUuV&tkvToKZj|I@)7oT(q>4?Lr%oTYDh+oO&*-uB;<T)9_Xl^W
zF@dnpIB)J#bo#jZ8>LT7*v^Z;%BCAQM<}rHYHCtD%IbcKF8viJ*CHy5TDE^mB};mB
zXIpw<lPBzs8D#2FlgA%SAwsQvaL&r67nW2~pJ52HJLZ4G6g`S;id8-K;U%xy{xP)>
zD$jc=zbx6b<Ki|gPYusd${?m4T=L)c&LIn-HV?N1#<^6zF8HlD?WqBZZrnJlZiB)?
z=w7G31%j<09b<qNcwb!|SeV*DQi>kxSJ+iokC7E%kZqK=|FtkQ-+_fev3-=)-G7c|
z)c;+1aX}2aKbJQS@KRf}Bd{Flww@gz%Bu(6S_m`eTy_x8*=@hqPq2+x?pcJV*&oDc
zCjJ`6y=q`+vat=6cP(#^QL_<G@IjL>PsPl(7;GbJKl$l6fAOdJb9GD%VR_ddm{}e#
zU>mXgr0O`*aEsY=1u%KB&)Ei-?lcT}bFUhN(4)<xEm83G+s}rNox%-)Zu$MGoG<0e
z4c0L0Lt5Wq6!YzI2YuSooy>L3qKR+8Y{N{&6P#~ts1vq=tQkkuLsumph=~1JGborS
zJ%W-W>nL56R~SU?D4zlEsx;ifH~lUuZlkm@iDuw$D9T$Ey#GxPTLQ)vsSP2G+{%l`
zVDlp`+6Raj^{`e%M=ud=nz_1QWWx00RDi)>9u=19oTagJb9NaBbKv05yE5Lvk`{vx
zq`UsV6(`4p@u1+(hdObo0otF^Qt-7hD+2OITf`p}28w24ssh`j)#l#|dMU~dBYO}L
z&FY>{uAdat$4otE)OpLnJhtH*Z!?Kzyc1W@oBGk`>^gh3reGV2Kr_CcFNYeCH%V|`
zo#lxJRjggnZ6sEdeHm{Fn!c8uhzr1b(pD6Acou>)jI^R``!)}lfe;*kpZcpRj0Es6
zmwukhx=I|1kPO|QtNW<M@huSMUGps75hR0I@b5NiY5FSh7={-kr`WSFk}I)K)&04A
z6~W(O2v|~*?Wb!~V^XN|)$r##a4X|I@McDsWfCM8g9Z8REz0xJ7Lg4@$n-^!O;j%1
zTQz}f37S=jeW`&x#Tz(3ShFyw_uWpf@8Wz$!Rx5#CgnYxpB-}sbbt9B-lI%ssu<j(
zO|Di5?7rT_L0iacW3YkP(pFVx7}nu@va1IpvzIm+uJCNB!vTucih|i8Yx(PQl-}|j
zs(3>be~_EhcRsuCG6nTzG~G2r(_&V4lPBuQAZS=twAq0vvq{trzoh-Y-h!SlB^ab^
zk&=xk<uMd2Sa}O=o0a*PYti&@<AS<Z7b#aX$FQ6z{b}LG1+V{rtNKZ3=bv+tGg%rw
zR9En7C>z;+9J2w(T<V&K;MSZFtRB;iv)}HqXd}P>UZBJnHa8oKVr5=ejM)xL@_=(O
z2Hp9gzh^`}rj%w{4rwO^JdW4FHA_$4R@Er7xW}y4!3$X{$Aoe*`%}?0Wg2~0#DFpA
zHvC=+uF6_r7Uaz^baj3?>=cbiN>eNZS7mOfeXe@W`OsEb?2L^HgxN2ESVDY2i4u8U
zmy&FKQ(ObvBrxNH=>mwQkjtPp(@lQweDdYpezVx!5JT~VAgwyhD02+rzy#d>^ZQ?!
z1PYf1*&LDzi~^cGgm4ORd(7c2Cm+Ym<ODyQGrSbq^Y=R_g(w|h4P5mBH^tet6fh_L
zC+1~7BY&@Bvul{n70$&>U6xmW4TDWPycSbKhv3YBNFm<%%tTwDaF6NQIVO26Pt32M
zrR*tIbov`+{^n~{3JoD58AUDq=(Nf@NS)@Ag*L??hA^U3tYn@VAH~d@k<V3RO(O-8
zvGGoM-A|aCKv8Lu7<+|rT&!5^i<L~6{ItVtwS`Kilo;c$eWk_8fo@PVG1l%mNBv_?
zR-QkEOtl97@}c3yTPs1B*(fQbQ%OD}{yMPeJ{B2S9f!mLFk_-AXdE-iD{*kBJalrI
zLJ_FfjyqCuh-)ZV5h_lJ)3LiM{`wYq*`7OYlb;VZBUph!sI_yCNui3r8#3R1z1L3`
z`#Z@%0IL-i-6L?mEn=I_k|zH5P5C_<CQ%`}Z=lb)Jb%L3dwVKv#-ndbG5f<zA{2aF
z0eXO>)8O~N;(FLpLk-~J8&1ZNU6{er=ccRE<Bnn_lTakjw~EQ|{*qpdX$~VufxN`2
zGjWun`+(quD3}C@QGy|+|IM+3PivMqAW$qZ&?R)XV}mh4TBn`;jlz2@oz^S{y0=yS
z6$j47Bv^urmCdI`40yg(cwfe4*Hn2DdmAbt`2geZN<PS2R_Mw3<9=((^e87O)&He{
znJar(n5Ssy>pZsU<bNEn@<2#*S{%s`x%>@5C=b^}A?QG8@dwA!NpTS=G9;LNC=Y~|
z90&Eczq+`%45KW7q9b9>>237r+p5UY%W*#zXai*s%R9f1y1F<=zVGbUqhsmd7Gnbw
zW(P_6E|QLtoh>sdC1i!#;_TZNW7bZjkh+Ij%LU8GHVHQ5pV+-A(>OdFj;FL}`o%41
I5`+&sRwd~LoB#j-
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..342982be06630473c1b83cba69eec5324adc5869
GIT binary patch
literal 152
zc$^FJbaR`)z`zjh>J$(bU=hIuWHSMAG8j4fdHS*edH;cc5y<m((_?@Eh>8@Ta-cpR
qQJ{!^@&O43c7ebB|JWN^KGg3QxcEOr39GIXKo+X53;#P%bO8Y7!6n@Q
--- a/image/test/mochitest/mochitest.ini
+++ b/image/test/mochitest/mochitest.ini
@@ -41,34 +41,38 @@ support-files =
   bug1180105.sjs
   bug1180105-waiter.sjs
   bug1217571-iframe.html
   bug1217571.jpg
   bug1319025.png
   bug1319025-ref.png
   clear.gif
   clear.png
+  clear.webp
   clear2.gif
+  clear2.webp
   clear2-results.gif
   damon.jpg
   error-early.png
   filter-final.svg
   filter.svg
   first-frame-padding.gif
   green.png
   green-background.html
   grey.png
   ico-bmp-opaque.ico
   ico-bmp-transparent.ico
   iframe.html
   imgutils.js
+  infinite.webp
   infinite-apng.png
   invalid.jpg
   keep.gif
   keep.png
+  keep.webp
   lime100x100.svg
   lime-anim-100x100.svg
   lime-anim-100x100-2.svg
   lime-css-anim-100x100.svg
   opaque.bmp
   purple.gif
   rainbow.gif
   red.gif
@@ -87,16 +91,17 @@ support-files =
   webcam-simulacrum.sjs
   6M-pixels.png
   12M-pixels-1.png
   12M-pixels-2.png
 
 [test_animation.html]
 skip-if = os == 'android'
 [test_animation_operators.html]
+skip-if = os == 'android'
 [test_animation2.html]
 skip-if = os == 'android'
 [test_animSVGImage.html]
 skip-if = os == 'android' || os == 'win' # Bug 1370784
 [test_animSVGImage2.html]
 skip-if = os == 'android' || (webrender && os == 'win') #Bug 1354561
 [test_background_image_anim.html]
 skip-if = os == 'android'
--- a/image/test/mochitest/test_animation_operators.html
+++ b/image/test/mochitest/test_animation_operators.html
@@ -24,33 +24,36 @@ https://bugzilla.mozilla.org/show_bug.cg
 // (Note that we do _not_ poll the reference, so it must not be animated.)
 
 var gTests = [
   // IMPORTANT NOTE: For these tests, the test and reference are not
   // snapshotted in the same way.  The REFERENCE (second file) is
   // assumed to be complete when loaded, but we poll the TEST
   // (first file) until the test passes.
 
-  // Tests of the allowed disposal operators for both GIF and APNG: keep, clear,
+  // Tests of the allowed disposal operators for GIF, APNG and WebP: keep, clear,
   // and restore previous.
   "== green-background.html?clear.gif green.png",
   "== green-background.html?clear.png green.png",
+  "== green-background.html?clear.webp green.png",
   "== keep.gif green.png",
   "== keep.png green.png",
+  "== keep.webp green.png",
   "== restore-previous.gif green.png",
   "== restore-previous.png green.png",
 
   // Tests of the blending/compositing operators that only APNG supports.
   "== over.png grey.png",
   "!= source.png grey.png",
   "== bug900200.png bug900200-ref.png",
   "== bug1319025.png bug1319025-ref.png",
 
   // Test of subframe updates.
   "== clear2.gif clear2-results.gif",
+  "== clear2.webp clear2-results.gif",
 ];
 
 // Maintain a reference count of how many things we're waiting for until
 // we can say the tests are done.
 var gDelayCount = 0;
 function AddFinishDependency()
   { ++gDelayCount; }
 function RemoveFinishDependency()
@@ -140,20 +143,25 @@ function startTest(i)
     return iframe;
   }
 
   AddFinishDependency();
   var test = startIframe(testData.test);
   var reference = startIframe(testData.reference);
 }
 
+function runTests()
+{
+  // Run the tests.
+  for (var i = 0; i < gTests.length; ++i) {
+    startTest(i);
+  }
+}
+
 SimpleTest.waitForExplicitFinish();
 SimpleTest.requestFlakyTimeout("untriaged");
 
-// Run the tests.
-for (var i = 0; i < gTests.length; ++i) {
-  startTest(i);
-}
+SpecialPowers.pushPrefEnv({"set": [["image.webp.enabled", true]]}, runTests);
 
 </script>
 </pre>
 </body>
 </html>
--- a/image/test/mochitest/test_discardAnimatedImage.html
+++ b/image/test/mochitest/test_discardAnimatedImage.html
@@ -13,51 +13,55 @@ https://bugzilla.mozilla.org/show_bug.cg
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=686905">Mozilla Bug 686905</a>
 <p id="display"></p>
 <div id="content">
   <div id="container">
     <canvas id="canvas" width="100" height="100"></canvas>
     <img id="infinitepng" src="infinite-apng.png">
     <img id="infinitegif" src="animated1.gif">
+    <img id="infinitewebp" src="infinite.webp">
     <img id="finitepng" src="restore-previous.png">
     <img id="finitegif" src="animated-gif.gif">
+    <img id="finitewebp" src="keep.webp">
   </div>
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
 /** Test for Bug 686905. **/
 SimpleTest.waitForExplicitFinish();
 
 var gFinished = false;
 
 var gNumDiscards = 0;
 
 window.onload = function() {
   // Enable discarding for the test.
   SpecialPowers.pushPrefEnv({
-    'set':[['image.mem.discardable',true]]
+    'set':[['image.mem.discardable',true],
+           ['image.webp.enabled',true]]
   }, runTest);
 }
 
-var gImgs = ['infinitepng', 'infinitegif', 'finitepng', 'finitegif'];
+var gImgs = ['infinitepng', 'infinitegif', 'infinitewebp',
+             'finitepng',   'finitegif',   'finitewebp'];
 // If we are currently counting frame updates.
 var gCountingFrameUpdates = false;
 // The number of frame update notifications for the images in gImgs that happen
 // after discarding. (The last two images are finite looping so we don't expect
 // them to get incremented but it's possible if they don't finish their
 // animation before we discard them.)
-var gNumFrameUpdates = [0, 0, 0, 0];
+var gNumFrameUpdates = [0, 0, 0, 0, 0, 0];
 // The last snapshot of the image. Used to check that the image actually changes.
-var gLastSnapShot = [null, null, null, null];
+var gLastSnapShot = [null, null, null, null, null, null];
 // Number of observed changes in the snapshot.
-var gNumSnapShotChanges = [0, 0, 0, 0];
+var gNumSnapShotChanges = [0, 0, 0, 0, 0, 0];
 // If we've removed the observer.
-var gRemovedObserver = [false, false, false, false];
+var gRemovedObserver = [false, false, false, false, false, false];
 
 // 2 would probably be a good enough test, we arbitrarily choose 4.
 var kNumFrameUpdatesToExpect = 4;
 
 function runTest() {
   var animatedDiscardable =
     SpecialPowers.getBoolPref('image.mem.animated.discardable');
   if (!animatedDiscardable) {
--- a/js/src/gc/GC.cpp
+++ b/js/src/gc/GC.cpp
@@ -7553,16 +7553,19 @@ GCRuntime::incrementalSlice(SliceBudget&
         incrementalState = State::Sweep;
         lastMarkSlice = false;
         beginSweepPhase(reason, session);
 
         MOZ_FALLTHROUGH;
 
       case State::Sweep:
         MOZ_ASSERT(nursery().isEmpty());
+
+        AutoGCRooter::traceAllWrappers(rt->mainContextFromOwnThread(), &marker);
+
         if (performSweepActions(budget) == NotFinished) {
             break;
         }
 
         endSweepPhase(destroyingRuntime);
 
         incrementalState = State::Finalize;
 
--- a/js/src/vm/JSScript-inl.h
+++ b/js/src/vm/JSScript-inl.h
@@ -217,18 +217,16 @@ JSScript::isDebuggee() const
 }
 
 inline bool
 JSScript::trackRecordReplayProgress() const
 {
     // Progress is only tracked when recording or replaying, and only for
     // scripts associated with the main thread's runtime. Whether self hosted
     // scripts execute may depend on performed Ion optimizations (for example,
-    // self hosted TypedObject logic), so they are ignored. Some scripts are
-    // internal to record/replay and run non-deterministically, so are also
-    // ignored.
+    // self hosted TypedObject logic), so they are ignored.
     return MOZ_UNLIKELY(mozilla::recordreplay::IsRecordingOrReplaying())
         && !runtimeFromAnyThread()->parentRuntime
         && !selfHosted()
-        && !mozilla::recordreplay::IsInternalScript(filename());
+        && mozilla::recordreplay::ShouldUpdateProgressCounter(filename());
 }
 
 #endif /* vm_JSScript_inl_h */
new file mode 100644
--- /dev/null
+++ b/media/mtransport/WebrtcProxyChannelWrapper.cpp
@@ -0,0 +1,155 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=8 et tw=80 ft=cpp : */
+/* 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 "WebrtcProxyChannelWrapper.h"
+
+#include "mozilla/net/WebrtcProxyChannelChild.h"
+
+#include "nsIEventTarget.h"
+#include "nsNetCID.h"
+#include "nsProxyRelease.h"
+
+#include "nr_socket_proxy_config.h"
+
+namespace mozilla {
+namespace net {
+
+using std::shared_ptr;
+
+WebrtcProxyChannelWrapper::WebrtcProxyChannelWrapper(
+  WebrtcProxyChannelCallback* aCallbacks)
+  : mProxyCallbacks(aCallbacks)
+  , mWebrtcProxyChannel(nullptr)
+  , mMainThread(nullptr)
+  , mSocketThread(nullptr)
+{
+  mMainThread = GetMainThreadEventTarget();
+  mSocketThread = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID);
+  MOZ_RELEASE_ASSERT(mMainThread, "no main thread");
+  MOZ_RELEASE_ASSERT(mSocketThread, "no socket thread");
+}
+
+WebrtcProxyChannelWrapper::~WebrtcProxyChannelWrapper()
+{
+  MOZ_ASSERT(!mWebrtcProxyChannel, "webrtc proxy channel non-null");
+
+  // If we're never opened then we never get an OnClose from our parent process.
+  // We need to release our callbacks here safely.
+  NS_ProxyRelease("WebrtcProxyChannelWrapper::CleanUpCallbacks",
+                  mSocketThread,
+                  mProxyCallbacks.forget());
+}
+
+void
+WebrtcProxyChannelWrapper::AsyncOpen(
+  const nsCString& aHost,
+  const int& aPort,
+  const shared_ptr<NrSocketProxyConfig>& aConfig)
+{
+  if (!NS_IsMainThread()) {
+    MOZ_ALWAYS_SUCCEEDS(mMainThread->Dispatch(
+      NewRunnableMethod<const nsCString,
+                        const int,
+                        const shared_ptr<NrSocketProxyConfig>>(
+        "WebrtcProxyChannelWrapper::AsyncOpen",
+        this,
+        &WebrtcProxyChannelWrapper::AsyncOpen,
+        aHost,
+        aPort,
+        aConfig)));
+    return;
+  }
+
+  MOZ_ASSERT(!mWebrtcProxyChannel, "wrapper already open");
+  mWebrtcProxyChannel = new WebrtcProxyChannelChild(this);
+  mWebrtcProxyChannel->AsyncOpen(aHost,
+                                 aPort,
+                                 aConfig->GetBrowser(),
+                                 nsContentUtils::GetSystemPrincipal(),
+                                 aConfig->GetAlpn());
+}
+
+void
+WebrtcProxyChannelWrapper::SendWrite(nsTArray<uint8_t>&& aReadData)
+{
+  if (!NS_IsMainThread()) {
+    MOZ_ALWAYS_SUCCEEDS(mMainThread->Dispatch(
+      NewRunnableMethod<nsTArray<uint8_t>&&>(
+        "WebrtcProxyChannelWrapper::SendWrite",
+        this,
+        &WebrtcProxyChannelWrapper::SendWrite,
+        std::move(aReadData))));
+    return;
+  }
+
+  MOZ_ASSERT(mWebrtcProxyChannel, "webrtc proxy channel should be non-null");
+  mWebrtcProxyChannel->SendWrite(aReadData);
+}
+
+void
+WebrtcProxyChannelWrapper::Close()
+{
+  if (!NS_IsMainThread()) {
+    MOZ_ALWAYS_SUCCEEDS(mMainThread->Dispatch(
+      NewRunnableMethod("WebrtcProxyChannelWrapper::Close",
+                        this,
+                        &WebrtcProxyChannelWrapper::Close)));
+    return;
+  }
+
+  // We're only open if we have a channel. Also Close() should be idempotent.
+  if (mWebrtcProxyChannel) {
+    RefPtr<WebrtcProxyChannelChild> child = mWebrtcProxyChannel;
+    mWebrtcProxyChannel = nullptr;
+    child->SendClose();
+  }
+}
+
+void
+WebrtcProxyChannelWrapper::OnClose(nsresult aReason)
+{
+  MOZ_ASSERT(NS_IsMainThread(), "not on main thread");
+  MOZ_ASSERT(mProxyCallbacks, "webrtc proxy callbacks should be non-null");
+
+  MOZ_ALWAYS_SUCCEEDS(mSocketThread->Dispatch(
+    NewRunnableMethod<nsresult>("WebrtcProxyChannelWrapper::OnClose",
+                                mProxyCallbacks,
+                                &WebrtcProxyChannelCallback::OnClose,
+                                aReason)));
+
+  NS_ProxyRelease("WebrtcProxyChannelWrapper::CleanUpCallbacks",
+                  mSocketThread,
+                  mProxyCallbacks.forget());
+}
+
+void
+WebrtcProxyChannelWrapper::OnRead(nsTArray<uint8_t>&& aReadData)
+{
+  MOZ_ASSERT(NS_IsMainThread(), "not on main thread");
+  MOZ_ASSERT(mProxyCallbacks, "webrtc proxy callbacks should be non-null");
+
+  MOZ_ALWAYS_SUCCEEDS(mSocketThread->Dispatch(
+    NewRunnableMethod<nsTArray<uint8_t>&&>(
+      "WebrtcProxyChannelWrapper::OnRead",
+      mProxyCallbacks,
+      &WebrtcProxyChannelCallback::OnRead,
+      std::move(aReadData))));
+}
+
+void
+WebrtcProxyChannelWrapper::OnConnected()
+{
+  MOZ_ASSERT(NS_IsMainThread(), "not on main thread");
+  MOZ_ASSERT(mProxyCallbacks, "webrtc proxy callbacks should be non-null");
+
+  MOZ_ALWAYS_SUCCEEDS(mSocketThread->Dispatch(
+    NewRunnableMethod("WebrtcProxyChannelWrapper::OnConnected",
+                      mProxyCallbacks,
+                      &WebrtcProxyChannelCallback::OnConnected)));
+}
+
+} // namespace net
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/media/mtransport/WebrtcProxyChannelWrapper.h
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=8 et tw=80 ft=cpp : */
+/* 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 webrtc_proxy_channel_wrapper__
+#define webrtc_proxy_channel_wrapper__
+
+#include <memory>
+
+#include "nsCOMPtr.h"
+#include "nsTArray.h"
+
+#include "mozilla/net/WebrtcProxyChannelCallback.h"
+
+class nsIEventTarget;
+
+namespace mozilla {
+
+class NrSocketProxyConfig;
+
+namespace net {
+
+class WebrtcProxyChannelChild;
+
+/**
+ * WebrtcProxyChannelWrapper is a protector class for mtransport and IPDL.
+ * mtransport and IPDL cannot include headers from each other due to conflicting
+ * typedefs. Also it helps users by dispatching calls to the appropriate thread
+ * based on mtransport's and IPDL's threading requirements.
+ *
+ * WebrtcProxyChannelWrapper is only used in the child process.
+ * WebrtcProxyChannelWrapper does not dispatch for the parent process.
+ * WebrtcProxyChannelCallback calls are dispatched to the STS thread.
+ * IPDL calls are dispatched to the main thread.
+ */
+class WebrtcProxyChannelWrapper : public WebrtcProxyChannelCallback
+{
+public:
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WebrtcProxyChannelWrapper, override)
+
+  explicit WebrtcProxyChannelWrapper(WebrtcProxyChannelCallback* aCallbacks);
+
+  virtual void AsyncOpen(const nsCString& aHost,
+                         const int& aPort,
+                         const std::shared_ptr<NrSocketProxyConfig>& aConfig);
+  virtual void SendWrite(nsTArray<uint8_t>&& aReadData);
+  virtual void Close();
+
+  // WebrtcProxyChannelCallback
+  virtual void OnClose(nsresult aReason) override;
+  virtual void OnConnected() override;
+  virtual void OnRead(nsTArray<uint8_t>&& aReadData) override;
+
+protected:
+  RefPtr<WebrtcProxyChannelCallback> mProxyCallbacks;
+  RefPtr<WebrtcProxyChannelChild> mWebrtcProxyChannel;
+
+  nsCOMPtr<nsIEventTarget>      mMainThread;
+  nsCOMPtr<nsIEventTarget>      mSocketThread;
+
+  virtual ~WebrtcProxyChannelWrapper();
+};
+
+} // namespace net
+} // namespace mozilla
+
+#endif // webrtc_proxy_channel_wrapper__
--- a/media/mtransport/build/moz.build
+++ b/media/mtransport/build/moz.build
@@ -5,16 +5,17 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 include("/ipc/chromium/chromium-config.mozbuild")
 
 EXPORTS.mtransport += [
     '../dtlsidentity.h',
     '../m_cpp_utils.h',
     '../mediapacket.h',
+    '../nr_socket_proxy_config.h',
     '../nricectx.h',
     '../nricemediastream.h',
     '../nriceresolverfake.h',
     '../nricestunaddr.h',
     '../rlogconnector.h',
     '../runnable_utils.h',
     '../sigslot.h',
     '../simpletokenbucket.h',
@@ -31,12 +32,13 @@ EXPORTS.mtransport += [
 
 include('../common.build')
 
 # Add libFuzzer configuration directives
 include('/tools/fuzzing/libfuzzer-config.mozbuild')
 
 # These files cannot be built in unified mode because of the redefinition of
 # getLogModule, UNIMPLEMENTED, nr_socket_long_term_violation_time,
-# nr_socket_short_term_violation_time.
+# nr_socket_short_term_violation_time, nrappkit/IPDL typedef conflicts in
+# PBrowserOrId and WebrtcProxyChannelChild.
 SOURCES += mtransport_cppsrcs
 
 FINAL_LIBRARY = 'xul'
--- a/media/mtransport/common.build
+++ b/media/mtransport/common.build
@@ -2,16 +2,18 @@
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 mtransport_lcppsrcs = [
     'dtlsidentity.cpp',
     'mediapacket.cpp',
+    'nr_socket_proxy.cpp',
+    'nr_socket_proxy_config.cpp',
     'nr_socket_prsock.cpp',
     'nr_timer.cpp',
     'nricectx.cpp',
     'nricemediastream.cpp',
     'nriceresolver.cpp',
     'nriceresolverfake.cpp',
     'nricestunaddr.cpp',
     'nrinterfaceprioritizer.cpp',
@@ -22,16 +24,17 @@ mtransport_lcppsrcs = [
     'test_nr_socket.cpp',
     'transportflow.cpp',
     'transportlayer.cpp',
     'transportlayerdtls.cpp',
     'transportlayerice.cpp',
     'transportlayerlog.cpp',
     'transportlayerloopback.cpp',
     'transportlayersrtp.cpp',
+    'WebrtcProxyChannelWrapper.cpp',
 ]
 
 mtransport_cppsrcs = [
     '/media/mtransport/%s' % s for s in sorted(mtransport_lcppsrcs)
 ]
 
 LOCAL_INCLUDES += [
     '/media/mtransport/',
new file mode 100644
--- /dev/null
+++ b/media/mtransport/ipc/PWebrtcProxyChannel.ipdl
@@ -0,0 +1,36 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=8 et tw=80 ft=cpp : */
+
+/* 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 protocol PNecko;
+
+include NeckoChannelParams;
+
+namespace mozilla {
+namespace net {
+
+async protocol PWebrtcProxyChannel
+{
+  manager PNecko;
+
+parent:
+  async AsyncOpen(nsCString aHost,
+                  int32_t aPort,
+                  OptionalLoadInfoArgs aLoadInfoArgs,
+                  nsCString aAlpn);
+  async Write(uint8_t[] aWriteData);
+  async Close();
+
+child:
+  async OnClose(nsresult aReason);
+  async OnConnected();
+  async OnRead(uint8_t[] aReadData);
+
+  async __delete__();
+};
+
+} // namespace net
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/media/mtransport/ipc/WebrtcProxyChannel.cpp
@@ -0,0 +1,549 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=8 et tw=80 ft=cpp : */
+/* 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 "WebrtcProxyChannel.h"
+
+#include "nsHttpChannel.h"
+#include "nsIChannel.h"
+#include "nsIClassOfService.h"
+#include "nsIContentPolicy.h"
+#include "nsIEventTarget.h"
+#include "nsIIOService.h"
+#include "nsILoadInfo.h"
+#include "nsIProtocolProxyService.h"
+#include "nsIURIMutator.h"
+#include "nsProxyRelease.h"
+#include "nsString.h"
+
+#include "WebrtcProxyChannelCallback.h"
+#include "WebrtcProxyLog.h"
+
+namespace mozilla {
+namespace net {
+
+class WebrtcProxyData
+{
+public:
+  explicit WebrtcProxyData(nsTArray<uint8_t>&& aData)
+    : mData(aData)
+  {
+    MOZ_COUNT_CTOR(WebrtcProxyData);
+  }
+
+  ~WebrtcProxyData()
+  {
+    MOZ_COUNT_DTOR(WebrtcProxyData);
+  }
+
+  const nsTArray<uint8_t>& GetData() const
+  {
+    return mData;
+  }
+
+private:
+  nsTArray<uint8_t> mData;
+};
+
+NS_IMPL_ISUPPORTS(WebrtcProxyChannel,
+                  nsIAuthPromptProvider,
+                  nsIHttpUpgradeListener,
+                  nsIInputStreamCallback,
+                  nsIInterfaceRequestor,
+                  nsIOutputStreamCallback,
+                  nsIRequestObserver,
+                  nsIStreamListener)
+
+WebrtcProxyChannel::WebrtcProxyChannel(nsIAuthPromptProvider* aAuthProvider,
+                                       WebrtcProxyChannelCallback* aCallbacks)
+    : mProxyCallbacks(aCallbacks)
+    , mClosed(false)
+    , mOpened(false)
+    , mWriteOffset(0)
+    , mAuthProvider(aAuthProvider)
+    , mTransport(nullptr)
+    , mSocketIn(nullptr)
+    , mSocketOut(nullptr)
+{
+  LOG(("WebrtcProxyChannel::WebrtcProxyChannel %p\n", this));
+  mMainThread = GetMainThreadEventTarget();
+  mSocketThread = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID);
+  MOZ_RELEASE_ASSERT(mMainThread, "no main thread");
+  MOZ_RELEASE_ASSERT(mSocketThread, "no socket thread");
+}
+
+WebrtcProxyChannel::~WebrtcProxyChannel()
+{
+  LOG(("WebrtcProxyChannel::~WebrtcProxyChannel %p\n", this));
+
+  NS_ProxyRelease("WebrtcProxyChannel::CleanUpAuthProvider",
+                  mMainThread,
+                  mAuthProvider.forget());
+}
+
+nsresult
+WebrtcProxyChannel::Write(nsTArray<uint8_t>&& aWriteData)
+{
+  LOG(("WebrtcProxyChannel::Write %p\n", this));
+  MOZ_ALWAYS_SUCCEEDS(mSocketThread->Dispatch(
+    NewRunnableMethod<nsTArray<uint8_t>&&>("WebrtcProxyChannel::Write",
+                                           this,
+                                           &WebrtcProxyChannel::EnqueueWrite_s,
+                                           std::move(aWriteData))));
+
+  return NS_OK;
+}
+
+nsresult
+WebrtcProxyChannel::Close()
+{
+  LOG(("WebrtcProxyChannel::Close %p\n", this));
+
+  CloseWithReason(NS_OK);
+
+  return NS_OK;
+}
+
+void
+WebrtcProxyChannel::CloseWithReason(nsresult aReason)
+{
+  LOG(("WebrtcProxyChannel::CloseWithReason %p reason=%u\n",
+       this,
+       static_cast<uint32_t>(aReason)));
+
+  if (!OnSocketThread()) {
+    MOZ_ASSERT(NS_IsMainThread(), "not on main thread");
+
+    // Let's pretend we got an open even if we didn't to prevent an Open later.
+    mOpened = true;
+
+    MOZ_ALWAYS_SUCCEEDS(mSocketThread->Dispatch(
+      NewRunnableMethod<nsresult>("WebrtcProxyChannel::CloseWithReason",
+                                  this,
+                                  &WebrtcProxyChannel::CloseWithReason,
+                                  aReason)));
+    return;
+  }
+
+  if (mClosed) {
+    return;
+  }
+
+  mClosed = true;
+
+  if (mSocketIn) {
+    mSocketIn->AsyncWait(nullptr, 0, 0, nullptr);
+    mSocketIn = nullptr;
+  }
+
+  if (mSocketOut) {
+    mSocketOut->AsyncWait(nullptr, 0, 0, nullptr);
+    mSocketOut = nullptr;
+  }
+
+  if (mTransport) {
+    mTransport->Close(NS_BASE_STREAM_CLOSED);
+    mTransport = nullptr;
+  }
+
+  NS_ProxyRelease("WebrtcProxyChannel::CleanUpAuthProvider",
+                  mMainThread,
+                  mAuthProvider.forget());
+  InvokeOnClose(aReason);
+}
+
+nsresult WebrtcProxyChannel::Open(const nsCString& aHost,
+                                  const int& aPort,
+                                  nsILoadInfo* aLoadInfo,
+                                  const nsCString& aAlpn)
+{
+  LOG(("WebrtcProxyChannel::AsyncOpen %p\n", this));
+
+  if (mOpened) {
+    LOG(("WebrtcProxyChannel %p: proxy channel already open\n", this));
+    CloseWithReason(NS_ERROR_FAILURE);
+    return NS_ERROR_FAILURE;
+  }
+
+  mOpened = true;
+
+  nsresult rv;
+  nsCString spec = NS_LITERAL_CSTRING("http://") + aHost;
+
+  nsCOMPtr<nsIURI> uri;
+  rv = NS_MutateURI(NS_STANDARDURLMUTATOR_CONTRACTID)
+         .SetSpec(spec)
+         .SetPort(aPort)
+         .Finalize(uri);
+
+  if (NS_FAILED(rv)) {
+    LOG(("WebrtcProxyChannel %p: bad proxy connect uri set\n", this));
+    CloseWithReason(rv);
+    return rv;
+  }
+
+  nsCOMPtr<nsIIOService> ioService;
+  ioService = do_GetService(NS_IOSERVICE_CONTRACTID, &rv);
+  if (NS_FAILED(rv)) {
+    LOG(("WebrtcProxyChannel %p: io service missing\n", this));
+    CloseWithReason(rv);
+    return rv;
+  }
+
+  // -need to always tunnel since we're using a proxy
+  // -there shouldn't be an opportunity to send cookies, but explicitly disallow
+  // them anyway.
+  // -the previous proxy tunnel didn't support redirects e.g. 307. don't need to
+  // introduce new behavior. can't follow redirects on connect anyway.
+  nsCOMPtr<nsIChannel> localChannel;
+  rv = ioService->NewChannelFromURIWithProxyFlags2(
+         uri,
+         nullptr,
+         // Proxy flags are overridden by SetConnectOnly()
+         0,
+         aLoadInfo->LoadingNode(),
+         aLoadInfo->LoadingPrincipal(),
+         aLoadInfo->TriggeringPrincipal(),
+         nsILoadInfo::SEC_DONT_FOLLOW_REDIRECTS |
+         nsILoadInfo::SEC_COOKIES_OMIT |
+         // We need this flag to allow loads from any origin since this channel
+         // is being used to CONNECT to an HTTP proxy.
+         nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
+         nsIContentPolicy::TYPE_OTHER,
+         getter_AddRefs(localChannel));
+  if (NS_FAILED(rv)) {
+    LOG(("WebrtcProxyChannel %p: bad open channel\n", this));
+    CloseWithReason(rv);
+    return rv;
+  }
+
+  RefPtr<nsHttpChannel> httpChannel;
+  CallQueryInterface(localChannel, httpChannel.StartAssignment());
+
+  if (!httpChannel) {
+    LOG(("WebrtcProxyChannel %p: not an http channel\n", this));
+    CloseWithReason(NS_ERROR_FAILURE);
+    return NS_ERROR_FAILURE;
+  }
+
+  httpChannel->SetNotificationCallbacks(this);
+
+  // don't block webrtc proxy setup with other requests
+  // often more than one of these channels will be created all at once by ICE
+  nsCOMPtr<nsIClassOfService> cos = do_QueryInterface(localChannel);
+  if (cos) {
+    cos->AddClassFlags(nsIClassOfService::Unblocked |
+                       nsIClassOfService::DontThrottle);
+  } else {
+    LOG(("WebrtcProxyChannel %p: could not set class of service\n", this));
+    CloseWithReason(NS_ERROR_FAILURE);
+    return NS_ERROR_FAILURE;
+  }
+
+  rv = httpChannel->HTTPUpgrade(aAlpn, this);
+  NS_ENSURE_SUCCESS(rv, rv);
+  rv = httpChannel->SetConnectOnly();
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = NS_MaybeOpenChannelUsingAsyncOpen2(httpChannel, this);
+
+  if (NS_FAILED(rv)) {
+    LOG(("WebrtcProxyChannel %p: cannot async open\n", this));
+    CloseWithReason(rv);
+    return rv;
+  }
+
+  return NS_OK;
+}
+
+void
+WebrtcProxyChannel::EnqueueWrite_s(nsTArray<uint8_t>&& aWriteData)
+{
+  LOG(("WebrtcProxyChannel::EnqueueWrite %p\n", this));
+  MOZ_ASSERT(OnSocketThread(), "not on socket thread");
+  MOZ_ASSERT(!mClosed, "webrtc proxy channel closed");
+
+  mWriteQueue.emplace_back(std::move(aWriteData));
+
+  if (mSocketOut) {
+    mSocketOut->AsyncWait(this, 0, 0, nullptr);
+  }
+}
+
+void
+WebrtcProxyChannel::InvokeOnClose(nsresult aReason)
+{
+  LOG(("WebrtcProxyChannel::InvokeOnClose %p\n", this));
+
+  if (!NS_IsMainThread()) {
+    MOZ_ALWAYS_SUCCEEDS(mMainThread->Dispatch(
+      NewRunnableMethod<nsresult>("WebrtcProxyChannel::InvokeOnClose",
+                                  this,
+                                  &WebrtcProxyChannel::InvokeOnClose,
+                                  aReason)));
+    return;
+  }
+
+  MOZ_ASSERT(mProxyCallbacks, "webrtc proxy callback should be non-null");
+
+  mProxyCallbacks->OnClose(aReason);
+  mProxyCallbacks = nullptr;
+}
+
+void
+WebrtcProxyChannel::InvokeOnConnected()
+{
+  LOG(("WebrtcProxyChannel::InvokeOnConnected %p\n", this));
+
+  if (!NS_IsMainThread()) {
+    MOZ_ALWAYS_SUCCEEDS(mMainThread->Dispatch(
+      NewRunnableMethod("WebrtcProxyChannel::InvokeOnConnected",
+                        this,
+                        &WebrtcProxyChannel::InvokeOnConnected)));
+    return;
+  }
+
+  MOZ_ASSERT(mProxyCallbacks, "webrtc proxy callback should be non-null");
+
+  mProxyCallbacks->OnConnected();
+}
+
+void
+WebrtcProxyChannel::InvokeOnRead(nsTArray<uint8_t>&& aReadData)
+{
+  LOG(("WebrtcProxyChannel::InvokeOnRead %p count=%zu\n",
+       this,
+       aReadData.Length()));
+
+  if (!NS_IsMainThread()) {
+    MOZ_ALWAYS_SUCCEEDS(mMainThread->Dispatch(
+      NewRunnableMethod<nsTArray<uint8_t>&&>(
+        "WebrtcProxyChannel::InvokeOnRead",
+         this,
+         &WebrtcProxyChannel::InvokeOnRead,
+         std::move(aReadData))));
+    return;
+  }
+
+  MOZ_ASSERT(mProxyCallbacks, "webrtc proxy callback should be non-null");
+
+  mProxyCallbacks->OnRead(std::move(aReadData));
+}
+
+// nsIHttpUpgradeListener
+NS_IMETHODIMP
+WebrtcProxyChannel::OnTransportAvailable(nsISocketTransport* aTransport,
+                                         nsIAsyncInputStream* aSocketIn,
+                                         nsIAsyncOutputStream* aSocketOut)
+{
+  LOG(("WebrtcProxyChannel::OnTransportAvailable %p\n", this));
+  MOZ_ASSERT(OnSocketThread(), "not on socket thread");
+  MOZ_ASSERT(!mTransport, "already called transport available on webrtc proxy");
+
+  // Cancel any pending callbacks. The caller doesn't always cancel these
+  // awaits. We need to make sure they don't get them.
+  aSocketIn->AsyncWait(nullptr, 0, 0, nullptr);
+  aSocketOut->AsyncWait(nullptr, 0, 0, nullptr);
+
+  if (mClosed) {
+    LOG(("WebrtcProxyChannel::OnTransportAvailable %p closed\n", this));
+    return NS_OK;
+  }
+
+  mTransport = aTransport;
+  mSocketIn = aSocketIn;
+  mSocketOut = aSocketOut;
+
+  // pulled from nr_socket_prsock.cpp
+  uint32_t minBufferSize = 256 * 1024;
+  nsresult rv = mTransport->SetSendBufferSize(minBufferSize);
+  if (NS_FAILED(rv)) {
+    LOG(("WebrtcProxyChannel::OnTransportAvailable %p send failed\n", this));
+    CloseWithReason(rv);
+    return rv;
+  }
+  rv = mTransport->SetRecvBufferSize(minBufferSize);
+  if (NS_FAILED(rv)) {
+    LOG(("WebrtcProxyChannel::OnTransportAvailable %p recv failed\n", this));
+    CloseWithReason(rv);
+    return rv;
+  }
+
+  mSocketIn->AsyncWait(this, 0, 0, nullptr);
+
+  InvokeOnConnected();
+
+  return NS_OK;
+}
+
+// nsIRequestObserver (from nsIStreamListener)
+NS_IMETHODIMP
+WebrtcProxyChannel::OnStartRequest(nsIRequest* aRequest,
+                                   nsISupports* aContext)
+{
+  LOG(("WebrtcProxyChannel::OnStartRequest %p\n", this));
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+WebrtcProxyChannel::OnStopRequest(nsIRequest* aRequest,
+                                  nsISupports* aContext,
+                                  nsresult aStatusCode)
+{
+  LOG(("WebrtcProxyChannel::OnStopRequest %p status=%u\n",
+       this,
+       static_cast<uint32_t>(aStatusCode)));
+
+  // see nsHttpChannel::ProcessFailedProxyConnect for most error codes
+  if (NS_FAILED(aStatusCode)) {
+    CloseWithReason(aStatusCode);
+    return aStatusCode;
+  }
+
+  return NS_OK;
+}
+
+// nsIStreamListener
+NS_IMETHODIMP
+WebrtcProxyChannel::OnDataAvailable(nsIRequest* aRequest,
+                                    nsISupports* aContext,
+                                    nsIInputStream* aInputStream,
+                                    uint64_t aOffset,
+                                    uint32_t aCount)
+{
+  LOG(("WebrtcProxyChannel::OnDataAvailable %p count=%u\n", this, aCount));
+  MOZ_ASSERT(0, "unreachable data available");
+  return NS_OK;
+}
+
+// nsIInputStreamCallback
+NS_IMETHODIMP
+WebrtcProxyChannel::OnInputStreamReady(nsIAsyncInputStream* in)
+{
+  LOG(("WebrtcProxyChannel::OnInputStreamReady %p unwritten=%zu\n",
+       this,
+       CountUnwrittenBytes()));
+  MOZ_ASSERT(OnSocketThread(), "not on socket thread");
+  MOZ_ASSERT(!mClosed, "webrtc proxy channel closed");
+  MOZ_ASSERT(mTransport, "webrtc proxy channel not connected");
+  MOZ_ASSERT(mSocketIn == in, "wrong input stream");
+
+  char      buffer[9216];
+  uint32_t  remainingCapacity = sizeof(buffer);
+  uint32_t  read = 0;
+
+  while(remainingCapacity > 0) {
+    uint32_t count = 0;
+    nsresult rv = mSocketIn->Read(buffer + read, remainingCapacity, &count);
+    if (rv == NS_BASE_STREAM_WOULD_BLOCK) {
+      break;
+    }
+
+    if (NS_FAILED(rv)) {
+      LOG(("WebrtcProxyChannel::OnInputStreamReady %p failed %u\n",
+           this,
+           static_cast<uint32_t>(rv)));
+      CloseWithReason(rv);
+      return rv;
+    }
+
+    // base stream closed
+    if (count == 0) {
+      LOG(("WebrtcProxyChannel::OnInputStreamReady %p connection closed\n",
+           this));
+      CloseWithReason(NS_ERROR_FAILURE);
+      return NS_OK;
+    }
+
+    remainingCapacity -= count;
+    read += count;
+  }
+
+  if (read > 0) {
+    nsTArray<uint8_t> array(read);
+    array.AppendElements(buffer, read);
+
+    InvokeOnRead(std::move(array));
+  }
+
+  mSocketIn->AsyncWait(this, 0, 0, nullptr);
+
+  return NS_OK;
+}
+
+// nsIOutputStreamCallback
+NS_IMETHODIMP
+WebrtcProxyChannel::OnOutputStreamReady(nsIAsyncOutputStream* out)
+{
+  LOG(("WebrtcProxyChannel::OnOutputStreamReady %p unwritten=%zu\n",
+       this,
+       CountUnwrittenBytes()));
+  MOZ_ASSERT(OnSocketThread(), "not on socket thread");
+  MOZ_ASSERT(!mClosed, "webrtc proxy channel closed");
+  MOZ_ASSERT(mTransport, "webrtc proxy channel not connected");
+  MOZ_ASSERT(mSocketOut == out, "wrong output stream");
+
+  while(!mWriteQueue.empty()) {
+    const WebrtcProxyData& data = mWriteQueue.front();
+
+    char* buffer = reinterpret_cast<char*>(
+      const_cast<uint8_t*>(data.GetData().Elements())) + mWriteOffset;
+    uint32_t toWrite = data.GetData().Length() - mWriteOffset;
+
+    uint32_t wrote = 0;
+    nsresult rv = mSocketOut->Write(buffer, toWrite, &wrote);
+    if (rv == NS_BASE_STREAM_WOULD_BLOCK) {
+      mSocketOut->AsyncWait(this, 0, 0, nullptr);
+      return NS_OK;
+    }
+
+    if(NS_FAILED(rv)) {
+      LOG(("WebrtcProxyChannel::OnOutputStreamReady %p failed %u\n",
+           this,
+           static_cast<uint32_t>(rv)));
+      CloseWithReason(rv);
+      return NS_OK;
+    }
+
+    mWriteOffset += wrote;
+
+    if (toWrite == wrote) {
+      mWriteOffset = 0;
+      mWriteQueue.pop_front();
+    }
+  }
+
+  return NS_OK;
+}
+
+// nsIInterfaceRequestor
+NS_IMETHODIMP
+WebrtcProxyChannel::GetInterface(const nsIID& iid, void** result)
+{
+  LOG(("WebrtcProxyChannel::GetInterface %p\n", this));
+
+  return QueryInterface(iid, result);
+}
+
+size_t
+WebrtcProxyChannel::CountUnwrittenBytes() const
+{
+  size_t count = 0;
+
+  for(const WebrtcProxyData& data : mWriteQueue) {
+    count += data.GetData().Length();
+  }
+
+  MOZ_ASSERT(count >= mWriteOffset, "offset exceeds write buffer length");
+
+  count -= mWriteOffset;
+
+  return count;
+}
+
+} // namespace net
+} // namespace mozilla
+
new file mode 100644
--- /dev/null
+++ b/media/mtransport/ipc/WebrtcProxyChannel.h
@@ -0,0 +1,94 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=8 et tw=80 ft=cpp : */
+/* 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 webrtc_proxy_channel_h__
+#define webrtc_proxy_channel_h__
+
+#include <list>
+
+#include "nsCOMPtr.h"
+#include "nsIAsyncInputStream.h"
+#include "nsIAsyncOutputStream.h"
+#include "nsIAuthPromptProvider.h"
+#include "nsIHttpChannelInternal.h"
+#include "nsIInterfaceRequestor.h"
+#include "nsIStreamListener.h"
+#include "nsStringFwd.h"
+#include "nsTArray.h"
+
+class nsILoadInfo;
+class nsISocketTransport;
+
+namespace mozilla {
+namespace net {
+
+class WebrtcProxyChannelCallback;
+class WebrtcProxyData;
+
+class WebrtcProxyChannel : public nsIHttpUpgradeListener,
+                           public nsIStreamListener,
+                           public nsIInputStreamCallback,
+                           public nsIOutputStreamCallback,
+                           public nsIInterfaceRequestor,
+                           public nsIAuthPromptProvider
+{
+public:
+  NS_DECL_NSIHTTPUPGRADELISTENER
+  NS_DECL_NSIINPUTSTREAMCALLBACK
+  NS_DECL_NSIINTERFACEREQUESTOR
+  NS_DECL_NSIOUTPUTSTREAMCALLBACK
+  NS_DECL_NSIREQUESTOBSERVER
+  NS_DECL_NSISTREAMLISTENER
+  NS_DECL_THREADSAFE_ISUPPORTS
+  NS_FORWARD_SAFE_NSIAUTHPROMPTPROVIDER(mAuthProvider)
+
+  WebrtcProxyChannel(nsIAuthPromptProvider* aAuthProvider,
+                     WebrtcProxyChannelCallback* aProxyCallbacks);
+
+  nsresult Open(const nsCString& aHost,
+                const int& aPort,
+                nsILoadInfo* aLoadInfo,
+                const nsCString& aAlpn);
+  nsresult Write(nsTArray<uint8_t>&& aBytes);
+  nsresult Close();
+
+  size_t CountUnwrittenBytes() const;
+
+protected:
+  virtual ~WebrtcProxyChannel();
+
+  // protected for gtests
+  virtual void InvokeOnClose(nsresult aReason);
+  virtual void InvokeOnConnected();
+  virtual void InvokeOnRead(nsTArray<uint8_t>&& aReadData);
+
+  RefPtr<WebrtcProxyChannelCallback> mProxyCallbacks;
+
+private:
+  bool mClosed;
+  bool mOpened;
+
+  void EnqueueWrite_s(nsTArray<uint8_t>&& aWriteData);
+
+  void CloseWithReason(nsresult aReason);
+
+  size_t                          mWriteOffset;
+  std::list<WebrtcProxyData>      mWriteQueue;
+  nsCOMPtr<nsIAuthPromptProvider> mAuthProvider;
+
+  // Indicates that the channel is CONNECTed
+  nsCOMPtr<nsISocketTransport>    mTransport;
+  nsCOMPtr<nsIAsyncInputStream>   mSocketIn;
+  nsCOMPtr<nsIAsyncOutputStream>  mSocketOut;
+  nsCOMPtr<nsIEventTarget>        mMainThread;
+  nsCOMPtr<nsIEventTarget>        mSocketThread;
+};
+
+} // namespace net
+} // namespace mozilla
+
+#endif // webrtc_proxy_channel_h__
+
new file mode 100644
--- /dev/null
+++ b/media/mtransport/ipc/WebrtcProxyChannelCallback.h
@@ -0,0 +1,31 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=8 et tw=80 ft=cpp : */
+/* 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 webrtc_proxy_channel_callback_h__
+#define webrtc_proxy_channel_callback_h__
+
+#include "nsTArray.h"
+
+namespace mozilla {
+namespace net {
+
+class WebrtcProxyChannelCallback
+{
+public:
+  NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING
+
+  virtual void OnClose(nsresult aReason) = 0;
+  virtual void OnConnected() = 0;
+  virtual void OnRead(nsTArray<uint8_t>&& aReadData) = 0;
+
+protected:
+  virtual ~WebrtcProxyChannelCallback() = default;
+};
+
+} // namespace net
+} // namespace mozilla
+
+#endif // webrtc_proxy_channel_callback_h__
new file mode 100644
--- /dev/null
+++ b/media/mtransport/ipc/WebrtcProxyChannelChild.cpp
@@ -0,0 +1,106 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=8 et tw=80 ft=cpp : */
+/* 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 "WebrtcProxyChannelChild.h"
+
+#include "mozilla/dom/PBrowserOrId.h"
+#include "mozilla/net/NeckoChild.h"
+
+#include "LoadInfo.h"
+
+#include "WebrtcProxyLog.h"
+#include "WebrtcProxyChannelCallback.h"
+
+using namespace mozilla::ipc;
+
+using mozilla::dom::PBrowserOrId;
+
+namespace mozilla {
+namespace net {
+
+mozilla::ipc::IPCResult
+WebrtcProxyChannelChild::RecvOnClose(const nsresult& aReason)
+{
+  LOG(("WebrtcProxyChannelChild::RecvOnClose %p\n", this));
+
+  MOZ_ASSERT(mProxyCallbacks, "webrtc proxy callbacks should be non-null");
+  mProxyCallbacks->OnClose(aReason);
+  mProxyCallbacks = nullptr;
+
+  return IPC_OK();
+}
+
+mozilla::ipc::IPCResult
+WebrtcProxyChannelChild::RecvOnConnected()
+{
+  LOG(("WebrtcProxyChannelChild::RecvOnConnected %p\n", this));
+
+  MOZ_ASSERT(mProxyCallbacks, "webrtc proxy callbacks should be non-null");
+  mProxyCallbacks->OnConnected();
+
+  return IPC_OK();
+}
+
+mozilla::ipc::IPCResult
+WebrtcProxyChannelChild::RecvOnRead(nsTArray<uint8_t>&& aReadData)
+{
+  LOG(("WebrtcProxyChannelChild::RecvOnRead %p\n", this));
+
+  MOZ_ASSERT(mProxyCallbacks, "webrtc proxy callbacks should be non-null");
+  mProxyCallbacks->OnRead(std::move(aReadData));
+
+  return IPC_OK();
+}
+
+WebrtcProxyChannelChild::WebrtcProxyChannelChild(
+  WebrtcProxyChannelCallback* aProxyCallbacks)
+  : mProxyCallbacks(aProxyCallbacks)
+{
+  MOZ_COUNT_CTOR(WebrtcProxyChannelChild);
+
+  LOG(("WebrtcProxyChannelChild::WebrtcProxyChannelChild %p\n", this));
+}
+
+WebrtcProxyChannelChild::~WebrtcProxyChannelChild()
+{
+  MOZ_COUNT_DTOR(WebrtcProxyChannelChild);
+
+  LOG(("WebrtcProxyChannelChild::~WebrtcProxyChannelChild %p\n", this));
+}
+
+void
+WebrtcProxyChannelChild::AsyncOpen(const nsCString& aHost,
+                                   const int& aPort,
+                                   const PBrowserOrId& aBrowser,
+                                   nsIPrincipal* aLoadingPrincipal,
+                                   const nsCString& aAlpn)
+{
+  LOG(("WebrtcProxyChannelChild::AsyncOpen %p %s:%d\n",
+       this,
+       aHost.get(),
+       aPort));
+
+  MOZ_ASSERT(NS_IsMainThread(), "not main thread");
+
+  AddIPDLReference();
+
+  gNeckoChild->SetEventTargetForActor(this, GetMainThreadEventTarget());
+  gNeckoChild->SendPWebrtcProxyChannelConstructor(this, aBrowser);
+
+  nsCOMPtr<nsILoadInfo> loadInfo = new LoadInfo(aLoadingPrincipal,
+                                                nullptr,
+                                                nullptr,
+                                                0,
+                                                0);
+
+  OptionalLoadInfoArgs loadInfoArgs;
+  MOZ_ALWAYS_SUCCEEDS(LoadInfoToLoadInfoArgs(loadInfo, &loadInfoArgs));
+
+  SendAsyncOpen(aHost, aPort, loadInfoArgs, aAlpn);
+}
+
+} // namespace net
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/media/mtransport/ipc/WebrtcProxyChannelChild.h
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=8 et tw=80 ft=cpp : */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_net_WebrtcProxyChannelChild_h
+#define mozilla_net_WebrtcProxyChannelChild_h
+
+#include "mozilla/net/PWebrtcProxyChannelChild.h"
+
+namespace mozilla {
+
+namespace dom {
+class PBrowserOrId;
+} // namespace dom
+
+namespace net {
+
+class WebrtcProxyChannelCallback;
+
+class WebrtcProxyChannelChild : public PWebrtcProxyChannelChild
+{
+public:
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WebrtcProxyChannelChild)
+
+  mozilla::ipc::IPCResult
+  RecvOnClose(const nsresult& aReason) override;
+
+  mozilla::ipc::IPCResult
+  RecvOnConnected() override;
+
+  mozilla::ipc::IPCResult
+  RecvOnRead(nsTArray<uint8_t>&& aReadData) override;
+
+  explicit WebrtcProxyChannelChild(WebrtcProxyChannelCallback* aProxyCallbacks);
+
+  void AsyncOpen(const nsCString& aHost,
+                 const int& aPort,
+                 const dom::PBrowserOrId& aBrowser,
+                 nsIPrincipal* aLoadingPrincipal,
+                 const nsCString& aAlpn);
+
+  void AddIPDLReference() { AddRef(); }
+  void ReleaseIPDLReference() { Release(); }
+
+protected:
+  virtual ~WebrtcProxyChannelChild();
+
+  RefPtr<WebrtcProxyChannelCallback> mProxyCallbacks;
+};
+
+} // namespace net
+} // namespace mozilla
+
+#endif // mozilla_net_WebrtcProxyChannelChild_h
new file mode 100644
--- /dev/null
+++ b/media/mtransport/ipc/WebrtcProxyChannelParent.cpp
@@ -0,0 +1,149 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=8 et tw=80 ft=cpp : */
+/* 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 "WebrtcProxyChannelParent.h"
+
+#include "mozilla/net/NeckoParent.h"
+
+#include "WebrtcProxyChannel.h"
+#include "WebrtcProxyLog.h"
+
+using namespace mozilla::dom;
+using namespace mozilla::ipc;
+
+namespace mozilla {
+namespace net {
+
+mozilla::ipc::IPCResult
+WebrtcProxyChannelParent::RecvAsyncOpen(
+        const nsCString& aHost,
+        const int& aPort,
+        const OptionalLoadInfoArgs& aLoadInfoArgs,
+        const nsCString& aAlpn)
+{
+  LOG(("WebrtcProxyChannelParent::RecvAsyncOpen %p to %s:%d\n",
+      this,
+      aHost.get(),
+      aPort));
+
+  nsresult rv;
+
+  nsCOMPtr<nsILoadInfo> loadInfo;
+
+  rv = LoadInfoArgsToLoadInfo(aLoadInfoArgs, getter_AddRefs(loadInfo));
+  if (NS_FAILED(rv)) {
+    IProtocol* mgr = Manager();
+    OnClose(rv);
+    return IPC_FAIL_NO_REASON(mgr);
+  }
+
+  MOZ_ASSERT(mChannel, "webrtc proxy channel should be non-null");
+  mChannel->Open(aHost, aPort, loadInfo, aAlpn);
+
+  return IPC_OK();
+}
+
+mozilla::ipc::IPCResult
+WebrtcProxyChannelParent::RecvWrite(nsTArray<uint8_t>&& aWriteData)
+{
+  LOG(("WebrtcProxyChannelParent::RecvWrite %p for %zu\n",
+      this,
+      aWriteData.Length()));
+
+  // Need to check this here in case there are Writes in the queue after OnClose
+  if (mChannel) {
+    mChannel->Write(std::move(aWriteData));
+  }
+
+  return IPC_OK();
+}
+
+mozilla::ipc::IPCResult
+WebrtcProxyChannelParent::RecvClose()
+{
+  LOG(("WebrtcProxyChannelParent::RecvClose %p\n", this));
+
+  CleanupChannel();
+
+  IProtocol* mgr = Manager();
+  if (!Send__delete__(this)) {
+    return IPC_FAIL_NO_REASON(mgr);
+  }
+
+  return IPC_OK();
+}
+
+void
+WebrtcProxyChannelParent::ActorDestroy(ActorDestroyReason aWhy)
+{
+  LOG(("WebrtcProxyChannelParent::ActorDestroy %p for %d\n", this, aWhy));
+
+  CleanupChannel();
+}
+
+WebrtcProxyChannelParent::WebrtcProxyChannelParent(
+  nsIAuthPromptProvider* aAuthProvider)
+{
+  MOZ_COUNT_CTOR(WebrtcProxyChannelParent);
+
+  LOG(("WebrtcProxyChannelParent::WebrtcProxyChannelParent %p\n", this));
+
+  mChannel = new WebrtcProxyChannel(aAuthProvider, this);
+}
+
+WebrtcProxyChannelParent::~WebrtcProxyChannelParent()
+{
+  MOZ_COUNT_DTOR(WebrtcProxyChannelParent);
+
+  LOG(("WebrtcProxyChannelParent::~WebrtcProxyChannelParent %p\n", this));
+
+  CleanupChannel();
+}
+
+// WebrtcProxyChannelCallback
+void
+WebrtcProxyChannelParent::OnClose(nsresult aReason)
+{
+  LOG(("WebrtcProxyChannelParent::OnClose %p\n", this));
+
+  if (mChannel) {
+    Unused << SendOnClose(aReason);
+  }
+
+  CleanupChannel();
+}
+
+void
+WebrtcProxyChannelParent::OnRead(nsTArray<uint8_t>&& aReadData)
+{
+  LOG(("WebrtcProxyChannelParent::OnRead %p %zu\n", this, aReadData.Length()));
+
+  if(mChannel && !SendOnRead(std::move(aReadData))) {
+    CleanupChannel();
+  }
+}
+
+void
+WebrtcProxyChannelParent::OnConnected()
+{
+  LOG(("WebrtcProxyChannelParent::OnConnected %p\n", this));
+
+  if(mChannel && !SendOnConnected()) {
+    CleanupChannel();
+  }
+}
+
+void
+WebrtcProxyChannelParent::CleanupChannel()
+{
+  if (mChannel) {
+    mChannel->Close();
+    mChannel = nullptr;
+  }
+}
+
+} // namespace net
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/media/mtransport/ipc/WebrtcProxyChannelParent.h
@@ -0,0 +1,65 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=8 et tw=80 ft=cpp : */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_net_WebrtcProxyChannelParent_h
+#define mozilla_net_WebrtcProxyChannelParent_h
+
+#include "mozilla/net/PWebrtcProxyChannelParent.h"
+
+#include "WebrtcProxyChannelCallback.h"
+
+class nsIAuthPromptProvider;
+
+namespace mozilla {
+namespace net {
+
+class WebrtcProxyChannel;
+
+class WebrtcProxyChannelParent : public PWebrtcProxyChannelParent,
+                                 public WebrtcProxyChannelCallback
+{
+public:
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WebrtcProxyChannelParent, override)
+
+  mozilla::ipc::IPCResult
+  RecvAsyncOpen(const nsCString& aHost,
+                const int& aPort,
+                const OptionalLoadInfoArgs& aLoadInfoArgs,
+                const nsCString& aAlpn) override;
+
+  mozilla::ipc::IPCResult
+  RecvWrite(nsTArray<uint8_t>&& aWriteData) override;
+
+  mozilla::ipc::IPCResult
+  RecvClose() override;
+
+  void
+  ActorDestroy(ActorDestroyReason aWhy) override;
+
+  explicit WebrtcProxyChannelParent(nsIAuthPromptProvider* aAuthProvider);
+
+  // WebrtcProxyChannelCallback
+  void OnClose(nsresult aReason) override;
+  void OnConnected() override;
+  void OnRead(nsTArray<uint8_t>&& bytes) override;
+
+  void AddIPDLReference() { AddRef(); }
+  void ReleaseIPDLReference() { Release(); }
+
+protected:
+  virtual ~WebrtcProxyChannelParent();
+
+private:
+  void CleanupChannel();
+
+  // Indicates that IPC is open.
+  RefPtr<WebrtcProxyChannel> mChannel;
+};
+
+} // namespace net
+} // namespace mozilla
+
+#endif // mozilla_net_WebrtcProxyChannelParent_h
new file mode 100644
--- /dev/null
+++ b/media/mtransport/ipc/WebrtcProxyLog.cpp
@@ -0,0 +1,13 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=8 et tw=80 ft=cpp : */
+/* 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 "WebrtcProxyLog.h"
+
+namespace mozilla {
+namespace net {
+LazyLogModule webrtcProxyLog("webrtcProxy");
+} // namespace net
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/media/mtransport/ipc/WebrtcProxyLog.h
@@ -0,0 +1,21 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=8 et tw=80 ft=cpp : */
+/* 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 webrtc_proxy_log_h__
+#define webrtc_proxy_log_h__
+
+#include "mozilla/Logging.h"
+
+namespace mozilla {
+namespace net {
+extern LazyLogModule webrtcProxyLog;
+} // namespace net
+} // namespace mozilla
+
+#undef LOG
+#define LOG(args) MOZ_LOG(mozilla::net::webrtcProxyLog, mozilla::LogLevel::Debug, args)
+
+#endif // webrtc_proxy_log_h__
--- a/media/mtransport/ipc/moz.build
+++ b/media/mtransport/ipc/moz.build
@@ -2,23 +2,36 @@
 # 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/.
 
 EXPORTS.mozilla.net += [
     'NrIceStunAddrMessageUtils.h',
     'PStunAddrsParams.h',
     'StunAddrsRequestChild.h',
     'StunAddrsRequestParent.h',
+    'WebrtcProxyChannel.h',
+    'WebrtcProxyChannelCallback.h',
+    'WebrtcProxyChannelChild.h',
+    'WebrtcProxyChannelParent.h',
 ]
 
 UNIFIED_SOURCES += [
     'StunAddrsRequestChild.cpp',
     'StunAddrsRequestParent.cpp',
+    'WebrtcProxyChannel.cpp',
+    'WebrtcProxyChannelChild.cpp',
+    'WebrtcProxyChannelParent.cpp',
+    'WebrtcProxyLog.cpp',
 ]
 
 IPDL_SOURCES += [
     'PStunAddrsRequest.ipdl',
+    'PWebrtcProxyChannel.ipdl',
 ]
 
 include("/ipc/chromium/chromium-config.mozbuild")
 
 FINAL_LIBRARY = 'xul'
 
+LOCAL_INCLUDES += [
+    '/netwerk/base',
+    '/netwerk/protocol/http',
+]
new file mode 100644
--- /dev/null
+++ b/media/mtransport/nr_socket_proxy.cpp
@@ -0,0 +1,343 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=8 et tw=80 ft=cpp : */
+/* 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/. */
+
+ /*
+Copyright (c) 2007, Adobe Systems, Incorporated
+Copyright (c) 2013, Mozilla
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance, Mozilla nor
+  the names of its contributors may be used to endorse or promote
+  products derived from this software without specific prior written
+  permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "nr_socket_proxy.h"
+
+#include "mozilla/ErrorNames.h"
+
+#include "WebrtcProxyChannelWrapper.h"
+
+namespace mozilla
+{
+using namespace net;
+
+using std::shared_ptr;
+
+class NrSocketProxyData
+{
+public:
+  explicit NrSocketProxyData(nsTArray<uint8_t>&& aData)
+    : mData(aData)
+  {
+    MOZ_COUNT_CTOR(NrSocketProxyData);
+  }
+
+  ~NrSocketProxyData()
+  {
+    MOZ_COUNT_DTOR(NrSocketProxyData);
+  }
+
+  const nsTArray<uint8_t>& GetData() const
+  {
+    return mData;
+  }
+
+private:
+  nsTArray<uint8_t> mData;
+};
+
+NrSocketProxy::NrSocketProxy(const shared_ptr<NrSocketProxyConfig>& aConfig)
+  : mClosed(false)
+  , mReadOffset(0)
+  , mConfig(aConfig)
+  , mWebrtcProxyChannel(nullptr)
+{
+  r_log(LOG_GENERIC,LOG_DEBUG,"NrSocketProxy::NrSocketProxy %p\n", this);
+  MOZ_ASSERT(mConfig, "config should not be null");
+}
+
+NrSocketProxy::~NrSocketProxy()
+{
+  r_log(LOG_GENERIC,LOG_DEBUG,"NrSocketProxy::~NrSocketProxy %p\n", this);
+  MOZ_ASSERT(!mWebrtcProxyChannel, "webrtc proxy channel not null");
+}
+
+int
+NrSocketProxy::create(nr_transport_addr* aAddr)
+{
+  int32_t port;
+  nsCString host;
+
+  // Sanity check
+  if (nr_transport_addr_get_addrstring_and_port(aAddr, &host, &port)) {
+    return R_FAILED;
+  }
+
+  if (nr_transport_addr_copy(&my_addr_, aAddr)) {
+    return R_FAILED;
+  }
+
+  return 0;
+}
+
+int
+NrSocketProxy::connect(nr_transport_addr* aAddr)
+{
+  r_log(LOG_GENERIC,LOG_DEBUG,"NrSocketProxy::Connect %p\n", this);
+
+  nsCString host;
+  int port;
+
+  if (nr_transport_addr_get_addrstring_and_port(aAddr, &host, &port)) {
+    return R_FAILED;
+  }
+
+  mWebrtcProxyChannel = new WebrtcProxyChannelWrapper(this);
+
+  mWebrtcProxyChannel->AsyncOpen(host, port, mConfig);
+
+  // trigger nr_socket_buffered to set write/read callback
+  return R_WOULDBLOCK;
+}
+
+void
+NrSocketProxy::close()
+{
+  r_log(LOG_GENERIC,LOG_DEBUG,"NrSocketProxy::Close %p\n", this);
+
+  if (mClosed) {
+    return;
+  }
+
+  mClosed = true;
+
+  // We're not always open at this point.
+  if (mWebrtcProxyChannel) {
+    mWebrtcProxyChannel->Close();
+    mWebrtcProxyChannel = nullptr;
+  }
+}
+
+int
+NrSocketProxy::write(const void* aBuffer, size_t aCount, size_t* aWrote)
+{
+  r_log(LOG_GENERIC,LOG_DEBUG,
+        "NrSocketProxy::Write %p count=%zu\n",
+        this,
+        aCount);
+
+  if (mClosed) {
+    return R_FAILED;
+  }
+
+  if (!aWrote) {
+    return R_FAILED;
+  }
+
+  *aWrote = aCount;
+
+  if (aCount > 0) {
+    nsTArray<uint8_t> writeData;
+    writeData.SetLength(aCount);
+    memcpy(writeData.Elements(), aBuffer, aCount);
+
+    mWebrtcProxyChannel->SendWrite(std::move(writeData));
+  }
+
+  return 0;
+}
+
+int
+NrSocketProxy::read(void* aBuffer, size_t aCount, size_t* aRead)
+{
+  r_log(LOG_GENERIC,LOG_DEBUG,"NrSocketProxy::Read %p\n", this);
+
+  if (mClosed) {
+    return R_FAILED;
+  }
+
+  if (!aRead) {
+    return R_FAILED;
+  }
+
+  *aRead = 0;
+
+  if (mReadQueue.empty()) {
+    return R_WOULDBLOCK;
+  }
+
+  while(aCount > 0 && !mReadQueue.empty()) {
+    const NrSocketProxyData& data = mReadQueue.front();
+
+    size_t remainingCount = data.GetData().Length() - mReadOffset;
+    size_t amountToCopy = std::min(aCount, remainingCount);
+
+    char* buffer = static_cast<char*>(aBuffer) + (*aRead);
+
+    memcpy(buffer, data.GetData().Elements() + mReadOffset, amountToCopy);
+
+    mReadOffset += amountToCopy;
+    *aRead += amountToCopy;
+    aCount -= amountToCopy;
+
+    if (remainingCount == amountToCopy) {
+      mReadOffset = 0;
+      mReadQueue.pop_front();
+    }
+  }
+
+  return 0;
+}
+
+int
+NrSocketProxy::getaddr(nr_transport_addr* aAddr)
+{
+  r_log(LOG_GENERIC,LOG_DEBUG,"NrSocketProxy::GetAddr %p\n", this);
+  return nr_transport_addr_copy(aAddr, &my_addr_);
+}
+
+int
+NrSocketProxy::sendto(const void* aBuffer,
+                      size_t aCount,
+                      int aFlags,
+                      nr_transport_addr* aAddr)
+{
+  // never call this
+  MOZ_ASSERT(0);
+  return R_FAILED;
+}
+
+int
+NrSocketProxy::recvfrom(void* aBuffer,
+                        size_t aCount,
+                        size_t* aRead,
+                        int aFlags,
+                        nr_transport_addr* aAddr)
+{
+  // never call this
+  MOZ_ASSERT(0);
+  return R_FAILED;
+}
+
+int
+NrSocketProxy::listen(int aBacklog)
+{
+  return R_INTERNAL;
+}
+
+int
+NrSocketProxy::accept(nr_transport_addr* aAddr, nr_socket** aSocket)
+{
+  return R_INTERNAL;
+}
+
+// WebrtcProxyChannelCallback
+void
+NrSocketProxy::OnClose(nsresult aReason)
+{
+  nsCString errorName;
+  GetErrorName(aReason, errorName);
+
+  r_log(LOG_GENERIC,LOG_ERR,
+        "NrSocketProxy::OnClose %p reason=%u name=%s\n",
+        this,
+        static_cast<uint32_t>(aReason),
+        errorName.get());
+
+  close();
+
+  DoCallbacks();
+}
+
+void
+NrSocketProxy::OnConnected()
+{
+  r_log(LOG_GENERIC,LOG_DEBUG,"NrSocketProxy::OnConnected %p\n", this);
+
+  DoCallbacks();
+}
+
+void
+NrSocketProxy::OnRead(nsTArray<uint8_t>&& aReadData)
+{
+  r_log(LOG_GENERIC,LOG_DEBUG,
+        "NrSocketProxy::OnRead %p read=%zu\n",
+        this,
+        aReadData.Length());
+
+  mReadQueue.emplace_back(std::move(aReadData));
+
+  DoCallbacks();
+}
+
+void
+NrSocketProxy::DoCallbacks()
+{
+  size_t lastCount = -1;
+  size_t currentCount = 0;
+  while ((poll_flags() & PR_POLL_READ) != 0 &&
+         // Make sure whatever is reading knows we're closed. This doesn't need
+         // to happen for writes since ICE doesn't like a failing writable.
+         (mClosed || (currentCount = CountUnreadBytes()) > 0) &&
+         lastCount != currentCount) {
+    fire_callback(NR_ASYNC_WAIT_READ);
+    lastCount = currentCount;
+  }
+
+  // We're always ready to write after we're connected. The parent process will
+  // buffer writes for us.
+  if (!mClosed && mWebrtcProxyChannel && (poll_flags() & PR_POLL_WRITE) != 0) {
+    fire_callback(NR_ASYNC_WAIT_WRITE);
+  }
+}
+
+size_t
+NrSocketProxy::CountUnreadBytes() const
+{
+  size_t count = 0;
+
+  for(const NrSocketProxyData& data : mReadQueue) {
+    count += data.GetData().Length();
+  }
+
+  MOZ_ASSERT(count >= mReadOffset, "offset exceeds read buffer length");
+
+  count -= mReadOffset;
+
+  return count;
+}
+
+void
+NrSocketProxy::AssignChannel_DoNotUse(WebrtcProxyChannelWrapper* aWrapper) {
+  mWebrtcProxyChannel = aWrapper;
+}
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/media/mtransport/nr_socket_proxy.h
@@ -0,0 +1,128 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=8 et tw=80 ft=cpp : */
+/* 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/. */
+
+ /*
+Copyright (c) 2007, Adobe Systems, Incorporated
+Copyright (c) 2013, Mozilla
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance, Mozilla nor
+  the names of its contributors may be used to endorse or promote
+  products derived from this software without specific prior written
+  permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef nr_socket_proxy_h__
+#define nr_socket_proxy_h__
+
+#include <list>
+
+#include "mozilla/net/WebrtcProxyChannelCallback.h"
+
+#include "nsTArray.h"
+
+extern "C" {
+#include "nr_api.h"
+#include "nr_socket.h"
+#include "transport_addr.h"
+}
+
+#include "nr_socket_prsock.h"
+
+namespace mozilla
+{
+using namespace net;
+
+namespace net
+{
+class WebrtcProxyChannelWrapper;
+} // namespace net
+
+class NrSocketProxyData;
+class NrSocketProxyConfig;
+
+class NrSocketProxy : public NrSocketBase,
+                      public WebrtcProxyChannelCallback
+{
+public:
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(NrSocketProxy, override)
+
+  explicit NrSocketProxy(const std::shared_ptr<NrSocketProxyConfig>& aConfig);
+
+  // NrSocketBase
+  int create(nr_transport_addr *aAddr) override;
+  int connect(nr_transport_addr *aAddr) override;
+  void close() override;
+  int write(const void* aBuffer,
+            size_t aCount,
+            size_t* aWrote) override;
+  int read(void* aBuffer, size_t aCount, size_t* aRead) override;
+  int getaddr(nr_transport_addr* aAddr) override;
+  int sendto(const void* aBuffer,
+             size_t aCount,
+             int aFlags,
+             nr_transport_addr* aAddr) override;
+  int recvfrom(void* aBuffer,
+               size_t aCount,
+               size_t* aRead,
+               int aFlags,
+               nr_transport_addr* aAddr) override;
+  int listen(int aBacklog) override;
+  int accept(nr_transport_addr* aAddr, nr_socket** aSocket) override;
+
+  // WebrtcProxyChannelCallback
+  void OnClose(nsresult aReason) override;
+  void OnConnected() override;
+  void OnRead(nsTArray<uint8_t>&& aReadData) override;
+
+  size_t CountUnreadBytes() const;
+
+  // for gtests
+  void AssignChannel_DoNotUse(WebrtcProxyChannelWrapper* aWrapper);
+
+protected:
+  virtual ~NrSocketProxy();
+
+private:
+  void DoCallbacks();
+
+  bool mClosed;
+
+  size_t                        mReadOffset;
+  std::list<NrSocketProxyData>  mReadQueue;
+
+  std::shared_ptr<NrSocketProxyConfig> mConfig;
+
+  RefPtr<WebrtcProxyChannelWrapper> mWebrtcProxyChannel;
+};
+
+} // namespace mozilla
+
+#endif // nr_socket_proxy_h__
new file mode 100644
--- /dev/null
+++ b/media/mtransport/nr_socket_proxy_config.cpp
@@ -0,0 +1,44 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=8 et tw=80 ft=cpp : */
+/* 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 "nr_socket_proxy_config.h"
+
+#include "mozilla/dom/PBrowserOrId.h"
+
+namespace mozilla
+{
+
+class NrSocketProxyConfig::Private {
+public:
+  dom::PBrowserOrId mBrowser;
+  nsCString mAlpn;
+};
+
+NrSocketProxyConfig::NrSocketProxyConfig(const dom::PBrowserOrId& aBrowser,
+                                         const nsCString& aAlpn)
+    : mPrivate(new Private({aBrowser, aAlpn}))
+{}
+
+NrSocketProxyConfig::NrSocketProxyConfig(NrSocketProxyConfig&& aOrig)
+    : mPrivate(std::move(aOrig.mPrivate))
+{}
+
+NrSocketProxyConfig::~NrSocketProxyConfig()
+{}
+
+const dom::PBrowserOrId&
+NrSocketProxyConfig::GetBrowser() const
+{
+  return mPrivate->mBrowser;
+}
+
+const nsCString&
+NrSocketProxyConfig::GetAlpn() const
+{
+  return mPrivate->mAlpn;
+}
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/media/mtransport/nr_socket_proxy_config.h
@@ -0,0 +1,47 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=8 et tw=80 ft=cpp : */
+/* 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 nr_socket_proxy_config__
+#define nr_socket_proxy_config__
+
+#include <memory>
+#include "nsString.h"
+
+class nsIPrincipal;
+
+namespace mozilla
+{
+namespace dom
+{
+class PBrowserOrId;
+}
+
+class NrSocketProxyConfig
+{
+public:
+  NrSocketProxyConfig(const dom::PBrowserOrId& aBrowser,
+                      const nsCString& aAlpn);
+  // We need to actually write the default impl ourselves, because the compiler
+  // needs to know how to destroy mPrivate in case an exception is thrown, even
+  // though we disable exceptions in our build.
+  NrSocketProxyConfig(NrSocketProxyConfig&& aOrig);
+
+  ~NrSocketProxyConfig();
+
+  const dom::PBrowserOrId& GetBrowser() const;
+  const nsCString& GetAlpn() const;
+
+private:
+  // PBrowserOrId includes stuff that conflicts with nICEr includes.
+  // Make it possible to include this header file without tripping over this
+  // problem.
+  class Private;
+  std::unique_ptr<Private> mPrivate;
+};
+
+} // namespace mozilla
+
+#endif // nr_socket_proxy_config__
--- a/media/mtransport/nr_socket_prsock.cpp
+++ b/media/mtransport/nr_socket_prsock.cpp
@@ -134,16 +134,17 @@ nrappkit copyright:
 #if defined(LOG_DEBUG)
 #define LOG_TEMP_DEBUG LOG_DEBUG
 #undef LOG_DEBUG
 #endif
 #undef strlcpy
 
 #include "mozilla/dom/network/TCPSocketChild.h"
 #include "mozilla/dom/network/UDPSocketChild.h"
+#include "nr_socket_proxy.h"
 
 #ifdef LOG_TEMP_INFO
 #define LOG_INFO LOG_TEMP_INFO
 #endif
 #ifdef LOG_TEMP_WARNING
 #define LOG_WARNING LOG_TEMP_WARNING
 #endif
 
@@ -2148,34 +2149,38 @@ static nr_socket_vtbl nr_socket_local_vt
   nr_socket_local_read,
   nr_socket_local_close,
   nr_socket_local_listen,
   nr_socket_local_accept
 };
 
 /* static */
 int
-NrSocketBase::CreateSocket(nr_transport_addr *addr, RefPtr<NrSocketBase> *sock)
+NrSocketBase::CreateSocket(nr_transport_addr *addr,
+                           RefPtr<NrSocketBase> *sock,
+                           const std::shared_ptr<NrSocketProxyConfig>& config)
 {
   int r, _status;
 
   // create IPC bridge for content process
   if (XRE_IsParentProcess()) {
     *sock = new NrSocket();
   } else {
     switch (addr->protocol) {
       case IPPROTO_UDP:
         *sock = new NrUdpSocketIpc();
         break;
       case IPPROTO_TCP:
 #if defined(MOZILLA_INTERNAL_API)
-        {
+        if (!config) {
           nsCOMPtr<nsIThread> main_thread;
           NS_GetMainThread(getter_AddRefs(main_thread));
           *sock = new NrTcpSocketIpc(main_thread.get());
+        } else {
+          *sock = new NrSocketProxy(config);
         }
 #else
         ABORT(R_REJECTED);
 #endif
         break;
     }
   }
 
@@ -2186,43 +2191,16 @@ NrSocketBase::CreateSocket(nr_transport_
   _status = 0;
 abort:
   if (_status) {
     *sock = nullptr;
   }
   return _status;
 }
 
-int nr_socket_local_create(void *obj, nr_transport_addr *addr, nr_socket **sockp) {
-  RefPtr<NrSocketBase> sock;
-  int r, _status;
-
-  r = NrSocketBase::CreateSocket(addr, &sock);
-  if (r) {
-    ABORT(r);
-  }
-
-  r = nr_socket_create_int(static_cast<void *>(sock),
-                           sock->vtbl(), sockp);
-  if (r)
-    ABORT(r);
-
-  _status = 0;
-
-  {
-    // We will release this reference in destroy(), not exactly the normal
-    // ownership model, but it is what it is.
-    NrSocketBase* dummy = sock.forget().take();
-    (void)dummy;
-  }
-
-abort:
-  return _status;
-}
-
 
 static int nr_socket_local_destroy(void **objp) {
   if(!objp || !*objp)
     return 0;
 
   NrSocketBase *sock = static_cast<NrSocketBase *>(*objp);
   *objp = nullptr;
 
--- a/media/mtransport/nr_socket_prsock.h
+++ b/media/mtransport/nr_socket_prsock.h
@@ -41,16 +41,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 
 
 // Implementation of nICEr/nr_socket that is tied to the Gecko
 // SocketTransportService.
 
 #ifndef nr_socket_prsock__
 #define nr_socket_prsock__
 
+#include <memory>
 #include <queue>
 
 #include "nspr.h"
 #include "prio.h"
 
 #include "nsAutoPtr.h"
 #include "nsCOMPtr.h"
 #include "nsASocketHandler.h"
@@ -70,16 +71,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 #include "mozilla/ClearOnShutdown.h"
 
 // Stub declaration for nICEr type
 typedef struct nr_socket_vtbl_ nr_socket_vtbl;
 typedef struct nr_socket_ nr_socket;
 
 #if defined(MOZILLA_INTERNAL_API)
 namespace mozilla {
+class NrSocketProxyConfig;
 namespace dom {
 class TCPSocketChild;
 }
 }
 #endif
 
 namespace mozilla {
 
@@ -93,17 +95,19 @@ public:
     memset(cbs_, 0, sizeof(cbs_));
     memset(cb_args_, 0, sizeof(cb_args_));
     memset(&my_addr_, 0, sizeof(my_addr_));
   }
   virtual ~NrSocketBase() {}
 
   // Factory method; will create either an NrSocket, NrUdpSocketIpc, or
   // NrTcpSocketIpc as appropriate.
-  static int CreateSocket(nr_transport_addr *addr, RefPtr<NrSocketBase> *sock);
+  static int CreateSocket(nr_transport_addr *addr,
+                          RefPtr<NrSocketBase> *sock,
+                          const std::shared_ptr<NrSocketProxyConfig>& config);
 
   // the nr_socket APIs
   virtual int create(nr_transport_addr *addr) = 0;
   virtual int sendto(const void *msg, size_t len,
                      int flags, nr_transport_addr *to) = 0;
   virtual int recvfrom(void * buf, size_t maxlen,
                        size_t *len, int flags,
                        nr_transport_addr *from) = 0;
--- a/media/mtransport/nricectx.cpp
+++ b/media/mtransport/nricectx.cpp
@@ -39,16 +39,17 @@ DATA, OR PROFITS; OR BUSINESS INTERRUPTI
 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 #include <string>
 #include <vector>
 
+#include "nr_socket_proxy_config.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/UniquePtr.h"
 #include "mozilla/Unused.h"
 
 #include "logging.h"
 #include "nspr.h"
 #include "nss.h"
 #include "pk11pub.h"
@@ -74,17 +75,16 @@ extern "C" {
 #include "r_crc32.h"
 #include "r_memory.h"
 #include "ice_reg.h"
 #include "ice_util.h"
 #include "transport_addr.h"
 #include "nr_crypto.h"
 #include "nr_socket.h"
 #include "nr_socket_local.h"
-#include "nr_proxy_tunnel.h"
 #include "stun_client_ctx.h"
 #include "stun_reg.h"
 #include "stun_server_ctx.h"
 #include "stun_util.h"
 #include "ice_codeword.h"
 #include "ice_ctx.h"
 #include "ice_candidate.h"
 #include "ice_handler.h"
@@ -95,32 +95,43 @@ extern "C" {
 #include "nricemediastream.h"
 #include "nr_socket_prsock.h"
 #include "nrinterfaceprioritizer.h"
 #include "rlogconnector.h"
 #include "test_nr_socket.h"
 
 namespace mozilla {
 
+using std::shared_ptr;
+
 TimeStamp nr_socket_short_term_violation_time() {
   return NrSocketBase::short_term_violation_time();
 }
 
 TimeStamp nr_socket_long_term_violation_time() {
   return NrSocketBase::long_term_violation_time();
 }
 
 MOZ_MTLOG_MODULE("mtransport")
 
 const char kNrIceTransportUdp[] = "udp";
 const char kNrIceTransportTcp[] = "tcp";
 const char kNrIceTransportTls[] = "tls";
 
 static bool initialized = false;
 
+static int noop(void** obj) {
+  return 0;
+}
+
+static nr_socket_factory_vtbl ctx_socket_factory_vtbl = {
+  nr_socket_local_create,
+  noop
+};
+
 // Implement NSPR-based crypto algorithms
 static int nr_crypto_nss_random_bytes(UCHAR *buf, size_t len) {
   UniquePK11SlotInfo slot(PK11_GetInternalSlot());
   if (!slot)
     return R_INTERNAL;
 
   SECStatus rv = PK11_GenerateRandomOnSlot(slot.get(), buf, len);
   if (rv != SECSuccess)
@@ -283,17 +294,18 @@ NrIceCtx::NrIceCtx(const std::string& na
     ice_controlling_set_(false),
     streams_(),
     ctx_(nullptr),
     peer_(nullptr),
     ice_handler_vtbl_(nullptr),
     ice_handler_(nullptr),
     trickle_(true),
     policy_(policy),
-    nat_ (nullptr) {
+    nat_ (nullptr),
+    proxy_config_(nullptr) {
 }
 
 /* static */
 RefPtr<NrIceCtx>
 NrIceCtx::Create(const std::string& name,
                  bool allow_loopback,
                  bool tcp_enabled,
                  bool allow_link_local,
@@ -606,16 +618,29 @@ NrIceCtx::Initialize()
 
   r = nr_ice_ctx_create(const_cast<char *>(name_.c_str()), flags, &ctx_);
 
   if (r) {
     MOZ_MTLOG(ML_ERROR, "Couldn't create ICE ctx for '" << name_ << "'");
     return false;
   }
 
+  // override default factory to capture optional proxy config when creating
+  // sockets.
+  nr_socket_factory* factory;
+  r = nr_socket_factory_create_int(this,
+                                   &ctx_socket_factory_vtbl,
+                                   &factory);
+
+  if (r) {
+    MOZ_MTLOG(LogLevel::Error, "Couldn't create ctx socket factory.");
+    return false;
+  }
+  nr_ice_ctx_set_socket_factory(ctx_, factory);
+
   nr_interface_prioritizer *prioritizer = CreateInterfacePrioritizer();
   if (!prioritizer) {
     MOZ_MTLOG(LogLevel::Error, "Couldn't create interface prioritizer.");
     return false;
   }
 
   r = nr_ice_ctx_set_interface_prioritizer(ctx_, prioritizer);
   if (r) {
@@ -775,16 +800,17 @@ NrIceStats NrIceCtx::Destroy() {
     nr_ice_ctx_destroy(&ctx_);
   }
 
   delete ice_handler_vtbl_;
   delete ice_handler_;
 
   ice_handler_vtbl_ = nullptr;
   ice_handler_ = nullptr;
+  proxy_config_ = nullptr;
   streams_.clear();
 
   return stats;
 }
 
 NrIceCtx::~NrIceCtx() {
 }
 
@@ -870,53 +896,18 @@ nsresult NrIceCtx::SetResolver(nr_resolv
   if (r) {
     MOZ_MTLOG(ML_ERROR, "Couldn't set resolver for '" << name_ << "'");
     return NS_ERROR_FAILURE;
   }
 
   return NS_OK;
 }
 
-nsresult NrIceCtx::SetProxyServer(const NrIceProxyServer& proxy_server) {
-  int r,_status;
-  nr_proxy_tunnel_config *config = nullptr;
-  nr_socket_wrapper_factory *wrapper = nullptr;
-
-  if ((r = nr_proxy_tunnel_config_create(&config))) {
-    ABORT(r);
-  }
-
-  if ((r = nr_proxy_tunnel_config_set_proxy(config,
-                                            proxy_server.host().c_str(),
-                                            proxy_server.port()))) {
-    ABORT(r);
-  }
-
-  if ((r = nr_proxy_tunnel_config_set_resolver(config, ctx_->resolver))) {
-    ABORT(r);
-  }
-
-  if ((r = nr_socket_wrapper_factory_proxy_tunnel_create(config, &wrapper))) {
-    MOZ_MTLOG(LogLevel::Error, "Couldn't create proxy tunnel wrapper.");
-    ABORT(r);
-  }
-
-  // nr_ice_ctx will own the wrapper after this call
-  if ((r = nr_ice_ctx_set_turn_tcp_socket_wrapper(ctx_, wrapper))) {
-    MOZ_MTLOG(ML_ERROR, "Couldn't set proxy for '" << name_ << "': " << r);
-    ABORT(r);
-  }
-
-  _status = 0;
-abort:
-  nr_proxy_tunnel_config_destroy(&config);
-  if (_status) {
-    nr_socket_wrapper_factory_destroy(&wrapper);
-    return NS_ERROR_FAILURE;
-  }
+nsresult NrIceCtx::SetProxyServer(NrSocketProxyConfig&& config) {
+  proxy_config_.reset(new NrSocketProxyConfig(std::move(config)));
   return NS_OK;
 }
 
 void NrIceCtx::SetCtxFlags(bool default_route_only, bool proxy_only) {
   ASSERT_ON_THREAD(sts_target_);
 
   if (default_route_only) {
     nr_ice_ctx_add_flags(ctx_, NR_ICE_CTX_FLAGS_ONLY_DEFAULT_ADDRS);
@@ -1165,8 +1156,45 @@ void NrIceCtx::SetGatheringState(Gatheri
 void nr_ice_compute_codeword(char *buf, int len,char *codeword) {
     UINT4 c;
 
     r_crc32(buf,len,&c);
 
     PL_Base64Encode(reinterpret_cast<char*>(&c), 3, codeword);
     codeword[4] = 0;
 }
+
+int nr_socket_local_create(void *obj,
+                            nr_transport_addr *addr,
+                            nr_socket **sockp)
+{
+  using namespace mozilla;
+
+  RefPtr<NrSocketBase> sock;
+  int r, _status;
+  shared_ptr<NrSocketProxyConfig> config = nullptr;
+
+  if (obj) {
+    config = static_cast<NrIceCtx*>(obj)->GetProxyConfig();
+  }
+
+  r = NrSocketBase::CreateSocket(addr, &sock, config);
+  if (r) {
+    ABORT(r);
+  }
+
+  r = nr_socket_create_int(static_cast<void *>(sock),
+                           sock->vtbl(), sockp);
+  if (r)
+    ABORT(r);
+
+  _status = 0;
+
+  {
+    // We will release this reference in destroy(), not exactly the normal
+    // ownership model, but it is what it is.
+    NrSocketBase* dummy = sock.forget().take();
+    (void)dummy;
+  }
+
+abort:
+  return _status;
+}
--- a/media/mtransport/nricectx.h
+++ b/media/mtransport/nricectx.h
@@ -45,16 +45,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 // Original author: ekr@rtfm.com
 
 // This is a wrapper around the nICEr ICE stack
 #ifndef nricectx_h__
 #define nricectx_h__
 
+#include <memory>
 #include <string>
 #include <vector>
 #include <map>
 
 #include "sigslot.h"
 
 #include "prnetdb.h"
 
@@ -81,16 +82,18 @@ typedef struct nr_ice_stun_server_ nr_ic
 typedef struct nr_ice_turn_server_ nr_ice_turn_server;
 typedef struct nr_resolver_ nr_resolver;
 typedef struct nr_proxy_tunnel_config_ nr_proxy_tunnel_config;
 
 typedef void* NR_SOCKET;
 
 namespace mozilla {
 
+class NrSocketProxyConfig;
+
 // Timestamps set whenever a packet is dropped due to global rate limiting
 // (see nr_socket_prsock.cpp)
 TimeStamp nr_socket_short_term_violation_time();
 TimeStamp nr_socket_long_term_violation_time();
 
 class NrIceMediaStream;
 
 extern const char kNrIceTransportUdp[];
@@ -170,35 +173,16 @@ class NrIceTurnServer : public NrIceStun
                   const std::vector<unsigned char>& password,
                   const char *transport) :
       NrIceStunServer(transport), username_(username), password_(password) {}
 
   std::string username_;
   std::vector<unsigned char> password_;
 };
 
-class NrIceProxyServer {
- public:
-  NrIceProxyServer(const std::string& host, uint16_t port,
-                   const std::string& alpn) :
-    host_(host), port_(port), alpn_(alpn) {
-  }
-
-  NrIceProxyServer() : NrIceProxyServer("", 0, "") {}
-
-  const std::string& host() const { return host_; }
-  uint16_t port() const { return port_; }
-  const std::string& alpn() const { return alpn_; }
-
- private:
-  std::string host_;
-  uint16_t port_;
-  std::string alpn_;
-};
-
 class TestNat;
 
 class NrIceStats {
  public:
   uint16_t stun_retransmits = 0;
   uint16_t turn_401s = 0;
   uint16_t turn_403s = 0;
   uint16_t turn_438s = 0;
@@ -326,17 +310,20 @@ class NrIceCtx {
   nsresult SetTurnServers(const std::vector<NrIceTurnServer>& turn_servers);
 
   // Provide the resolution provider. Must be called before
   // StartGathering.
   nsresult SetResolver(nr_resolver *resolver);
 
   // Provide the proxy address. Must be called before
   // StartGathering.
-  nsresult SetProxyServer(const NrIceProxyServer& proxy_server);
+  nsresult SetProxyServer(NrSocketProxyConfig&& config);
+
+  const std::shared_ptr<NrSocketProxyConfig>& GetProxyConfig()
+    { return proxy_config_; }
 
   void SetCtxFlags(bool default_route_only, bool proxy_only);
 
   // Start ICE gathering
   nsresult StartGathering(bool default_route_only, bool proxy_only);
 
   // Start checking
   nsresult StartChecks(bool offerer);
@@ -410,13 +397,14 @@ private:
   nr_ice_ctx *ctx_;
   nr_ice_peer_ctx *peer_;
   nr_ice_handler_vtbl* ice_handler_vtbl_;  // Must be pointer
   nr_ice_handler* ice_handler_;  // Must be pointer
   bool trickle_;
   nsCOMPtr<nsIEventTarget> sts_target_; // The thread to run on
   Policy policy_;
   RefPtr<TestNat> nat_;
+  std::shared_ptr<NrSocketProxyConfig> proxy_config_;
 };
 
 
 }  // close namespace
 #endif
--- a/media/mtransport/test/moz.build
+++ b/media/mtransport/test/moz.build
@@ -1,14 +1,16 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
+include("/ipc/chromium/chromium-config.mozbuild")
+
 if CONFIG['OS_TARGET'] != 'WINNT':
     SOURCES += [
         'buffered_stun_socket_unittest.cpp',
         'ice_unittest.cpp',
         'multi_tcp_socket_unittest.cpp',
         'nrappkit_unittest.cpp',
         'proxy_tunnel_socket_unittest.cpp',
         'rlogconnector_unittest.cpp',
@@ -16,16 +18,17 @@ if CONFIG['OS_TARGET'] != 'WINNT':
         'simpletokenbucket_unittest.cpp',
         'sockettransportservice_unittest.cpp',
         'stunserver.cpp',
         'test_nr_socket_ice_unittest.cpp',
         'test_nr_socket_unittest.cpp',
         'TestSyncRunnable.cpp',
         'transport_unittests.cpp',
         'turn_unittest.cpp',
+        'webrtcproxychannel_unittest.cpp',
     ]
 
     if CONFIG['MOZ_SCTP']:
         SOURCES += [
             'sctp_unittest.cpp',
         ]
 
 
--- a/media/mtransport/test/proxy_tunnel_socket_unittest.cpp
+++ b/media/mtransport/test/proxy_tunnel_socket_unittest.cpp
@@ -1,339 +1,304 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 // Original authors: ekr@rtfm.com; ryan@tokbox.com
 
-#include <iostream>
+#include <vector>
+#include <numeric>
 
-extern "C" {
-#include "nr_api.h"
-#include "nr_socket.h"
-#include "nr_proxy_tunnel.h"
-#include "transport_addr.h"
-#include "stun.h"
-}
+#include "mozilla/dom/PBrowserOrId.h"
 
-#include "dummysocket.h"
-
-#include "nr_socket_prsock.h"
-#include "nriceresolverfake.h"
+#include "nr_socket_proxy.h"
+#include "nr_socket_proxy_config.h"
+#include "WebrtcProxyChannelWrapper.h"
 
 #define GTEST_HAS_RTTI 0
 #include "gtest/gtest.h"
 #include "gtest_utils.h"
 
 using namespace mozilla;
 
-const std::string kRemoteAddr = "192.0.2.133";
-const uint16_t kRemotePort = 3333;
+// update TestReadMultipleSizes if you change this
+const std::string kHelloMessage = "HELLO IS IT ME YOU'RE LOOKING FOR?";
 
-const std::string kProxyHost = "example.com";
-const std::string kProxyAddr = "192.0.2.134";
-const uint16_t kProxyPort = 9999;
+typedef mozilla::dom::PBrowserOrId PBrowserOrId;
 
-const std::string kHelloMessage = "HELLO";
-const std::string kGarbageMessage = "xxxxxxxxxx";
+class NrSocketProxyTest : public MtransportTest {
+ public:
+  NrSocketProxyTest()
+    : mSProxy(nullptr)
+    , nr_socket_(nullptr)
+    , mEmptyArray(0)
+    , mReadChunkSize(0)
+    , mReadChunkSizeIncrement(1)
+    , mReadAllowance(-1)
+    , mConnected(false) {}
 
-std::string connect_message(const std::string &host, uint16_t port, const std::string &alpn, const std::string &tail) {
-  std::stringstream ss;
-  ss << "CONNECT " << host << ":" << port << " HTTP/1.0\r\n";
-  if (!alpn.empty()) {
-    ss << "ALPN: " << alpn << "\r\n";
+  void SetUp() override {
+    nsCString alpn = NS_LITERAL_CSTRING("webrtc");
+    std::shared_ptr<NrSocketProxyConfig> config;
+    config.reset(new NrSocketProxyConfig(PBrowserOrId(), alpn));
+    // config is never used but must be non-null
+    mSProxy = new NrSocketProxy(config);
+    int r = nr_socket_create_int((void*)mSProxy.get(),
+                                 mSProxy->vtbl(),
+                                 &nr_socket_);
+    ASSERT_EQ(0, r);
+
+    // fake calling AsyncOpen() due to IPC calls. must be non-null
+    mSProxy->AssignChannel_DoNotUse(new WebrtcProxyChannelWrapper(nullptr));
   }
-  ss << "\r\n" << tail;
-  return ss.str();
-}
 
-std::string connect_response(int code, const std::string &tail = "") {
-  std::stringstream ss;
-  ss << "HTTP/1.0 " << code << "\r\n\r\n" << tail;
-  return ss.str();
-}
-
-class DummyResolver {
- public:
-  DummyResolver() {
-    vtbl_ = new nr_resolver_vtbl;
-    vtbl_->destroy = &DummyResolver::destroy;
-    vtbl_->resolve = &DummyResolver::resolve;
-    vtbl_->cancel = &DummyResolver::cancel;
-    nr_resolver_create_int((void *)this, vtbl_, &resolver_);
+  void TearDown() override {
+    mSProxy->close();
   }
 
-  ~DummyResolver() {
-    nr_resolver_destroy(&resolver_);
-    delete vtbl_;
-  }
+  static void readable_cb(NR_SOCKET s, int how, void *cb_arg) {
+    NrSocketProxyTest* test = (NrSocketProxyTest*) cb_arg;
+    size_t capacity = std::min(test->mReadChunkSize, test->mReadAllowance);
+    nsTArray<uint8_t> array(capacity);
+    size_t read;
+
+    nr_socket_read(test->nr_socket_,
+                   (char*)array.Elements(),
+                   array.Capacity(),
+                   &read,
+                   0);
 
-  static int destroy(void **objp) {
-    return 0;
+    ASSERT_TRUE(read <= array.Capacity());
+    ASSERT_TRUE(test->mReadAllowance >= read);
+
+    array.SetLength(read);
+    test->mData.AppendElements(array);
+    test->mReadAllowance -= read;
+
+    // We may read more bytes each time we're called. This way we can ensure we
+    // consume buffers partially and across multiple buffers.
+    test->mReadChunkSize += test->mReadChunkSizeIncrement;
+
+    if (test->mReadAllowance > 0) {
+      NR_ASYNC_WAIT(s, how, &NrSocketProxyTest::readable_cb, cb_arg);
+    }
   }
 
-  static int resolve(void *obj,
-                     nr_resolver_resource *resource,
-                     int (*cb)(void *cb_arg, nr_transport_addr *addr),
-                     void *cb_arg,
-                     void **handle) {
-    nr_transport_addr addr;
+  static void writable_cb(NR_SOCKET s, int how, void *cb_arg) {
+    NrSocketProxyTest* test = (NrSocketProxyTest*) cb_arg;
+    test->mConnected = true;
+  }
 
-    nr_str_port_to_transport_addr(
-        (char *)kProxyAddr.c_str(), kProxyPort, IPPROTO_TCP, &addr);
-
-    cb(cb_arg, &addr);
-    return 0;
+  const std::string DataString() {
+    return std::string((char*)mData.Elements(), mData.Length());
   }
 
-  static int cancel(void *obj, void *handle) {
-    return 0;
-  }
+ protected:
+  RefPtr<NrSocketProxy> mSProxy;
+  nr_socket *nr_socket_;
 
-  nr_resolver *get_nr_resolver() {
-    return resolver_;
-  }
+  nsTArray<uint8_t> mData;
+  nsTArray<uint8_t> mEmptyArray;
 
- private:
-  nr_resolver_vtbl *vtbl_;
-  nr_resolver *resolver_;
+  uint32_t mReadChunkSize;
+  uint32_t mReadChunkSizeIncrement;
+  uint32_t mReadAllowance;
+
+  bool mConnected;
 };
 
-class ProxyTunnelSocketTest : public MtransportTest {
- public:
-  ProxyTunnelSocketTest()
-      : socket_impl_(nullptr),
-        nr_socket_(nullptr) {}
-
-  ~ProxyTunnelSocketTest() {
-    nr_socket_destroy(&nr_socket_);
-    nr_proxy_tunnel_config_destroy(&config_);
-  }
-
-  void SetUp() override {
-    MtransportTest::SetUp();
+TEST_F(NrSocketProxyTest, TestCreate) {
+}
 
-    nr_resolver_ = resolver_impl_.get_nr_resolver();
-
-    int r = nr_str_port_to_transport_addr(
-        (char *)kRemoteAddr.c_str(), kRemotePort, IPPROTO_TCP, &remote_addr_);
-    ASSERT_EQ(0, r);
-
-    r = nr_str_port_to_transport_addr(
-        (char *)kProxyAddr.c_str(), kProxyPort, IPPROTO_TCP, &proxy_addr_);
-    ASSERT_EQ(0, r);
-
-    nr_proxy_tunnel_config_create(&config_);
-    nr_proxy_tunnel_config_set_resolver(config_, nr_resolver_);
-    nr_proxy_tunnel_config_set_proxy(config_, kProxyAddr.c_str(), kProxyPort);
-
-    Configure();
-  }
+TEST_F(NrSocketProxyTest, TestConnected) {
+  ASSERT_TRUE(!mConnected);
 
-  // This reconfigures the socket with the updated information in config_.
-  void Configure() {
-    if (nr_socket_) {
-      EXPECT_EQ(0, nr_socket_destroy(&nr_socket_));
-      EXPECT_EQ(nullptr, nr_socket_);
-    }
-
-    RefPtr<DummySocket> dummy(new DummySocket());
-    int r = nr_socket_proxy_tunnel_create(
-        config_,
-        dummy->get_nr_socket(),
-        &nr_socket_);
-    ASSERT_EQ(0, r);
-
-    socket_impl_ = dummy.forget();  // Now owned by nr_socket_.
-  }
-
-  void Connect(int expectedReturn = 0) {
-    int r = nr_socket_connect(nr_socket_, &remote_addr_);
-    EXPECT_EQ(expectedReturn, r);
+  NR_ASYNC_WAIT(mSProxy,
+                NR_ASYNC_WAIT_WRITE,
+                &NrSocketProxyTest::writable_cb,
+                this);
 
-    size_t written = 0;
-    r = nr_socket_write(nr_socket_, kHelloMessage.c_str(), kHelloMessage.size(), &written, 0);
-    EXPECT_EQ(0, r);
-    EXPECT_EQ(kHelloMessage.size(), written);
-  }
-
-  nr_socket *socket() { return nr_socket_; }
+  // still not connected just registered for writes...
+  ASSERT_TRUE(!mConnected);
 
- protected:
-  RefPtr<DummySocket> socket_impl_;
-  DummyResolver resolver_impl_;
-  nr_socket *nr_socket_;
-  nr_resolver *nr_resolver_;
-  nr_proxy_tunnel_config *config_;
-  nr_transport_addr proxy_addr_;
-  nr_transport_addr remote_addr_;
-};
+  mSProxy->OnConnected();
 
-
-TEST_F(ProxyTunnelSocketTest, TestCreate) {
+  ASSERT_TRUE(mConnected);
 }
 
-TEST_F(ProxyTunnelSocketTest, TestConnectProxyAddress) {
-  int r = nr_socket_connect(nr_socket_, &remote_addr_);
-  ASSERT_EQ(0, r);
+TEST_F(NrSocketProxyTest, TestRead) {
+  nsTArray<uint8_t> array;
+  array.AppendElements(kHelloMessage.c_str(), kHelloMessage.length());
 
-  ASSERT_EQ(0, nr_transport_addr_cmp(socket_impl_->get_connect_addr(), &proxy_addr_,
-        NR_TRANSPORT_ADDR_CMP_MODE_ALL));
+  NR_ASYNC_WAIT(mSProxy,
+                NR_ASYNC_WAIT_READ,
+                &NrSocketProxyTest::readable_cb,
+                this);
+  // this will read 0 bytes here
+  mSProxy->OnRead(std::move(array));
+
+  ASSERT_EQ(kHelloMessage.length(), mSProxy->CountUnreadBytes());
+
+  // callback is still set but terminated due to 0 byte read
+  // start callbacks again (first read is 0 then 1,2,3,...)
+  mSProxy->OnRead(std::move(mEmptyArray));
+
+  ASSERT_EQ(kHelloMessage.length(), mData.Length());
+  ASSERT_EQ(kHelloMessage, DataString());
 }
 
-// TODO: Reenable once bug 1251212 is fixed
-TEST_F(ProxyTunnelSocketTest, DISABLED_TestConnectProxyRequest) {
-  Connect();
+TEST_F(NrSocketProxyTest, TestReadConstantConsumeSize) {
+  std::string data;
+
+  // triangle number
+  const int kCount = 32;
 
-  std::string msg = connect_message(kRemoteAddr, kRemotePort, "", kHelloMessage);
-  socket_impl_->CheckWriteBuffer(reinterpret_cast<const uint8_t *>(msg.c_str()), msg.size());
-}
+  //  ~17kb
+  // triangle number formula n*(n+1)/2
+  for(int i = 0; i < kCount * (kCount + 1) / 2; ++i) {
+    data += kHelloMessage;
+  }
 
-// TODO: Reenable once bug 1251212 is fixed
-TEST_F(ProxyTunnelSocketTest, DISABLED_TestAlpnConnect) {
-  const std::string alpn = "this,is,alpn";
-  int r = nr_proxy_tunnel_config_set_alpn(config_, alpn.c_str());
-  EXPECT_EQ(0, r);
+  // decreasing buffer sizes
+  for(int i = 0, start = 0; i < kCount; ++i) {
+    int length = (kCount - i) * kHelloMessage.length();
+
+    nsTArray<uint8_t> array;
+    array.AppendElements(data.c_str() + start, length);
+    start += length;
 
-  Configure();
-  Connect();
+    mSProxy->OnRead(std::move(array));
+  }
 
-  std::string msg = connect_message(kRemoteAddr, kRemotePort, alpn, kHelloMessage);
-  socket_impl_->CheckWriteBuffer(reinterpret_cast<const uint8_t *>(msg.c_str()), msg.size());
-}
+  ASSERT_EQ(data.length(), mSProxy->CountUnreadBytes());
 
-// TODO: Reenable once bug 1251212 is fixed
-TEST_F(ProxyTunnelSocketTest, DISABLED_TestNullAlpnConnect) {
-  int r = nr_proxy_tunnel_config_set_alpn(config_, nullptr);
-  EXPECT_EQ(0, r);
+  // read same amount each callback
+  mReadChunkSize = 128;
+  mReadChunkSizeIncrement = 0;
+  NR_ASYNC_WAIT(mSProxy,
+                NR_ASYNC_WAIT_READ,
+                &NrSocketProxyTest::readable_cb,
+                this);
 
-  Configure();
-  Connect();
+  ASSERT_EQ(data.length(), mSProxy->CountUnreadBytes());
 
-  std::string msg = connect_message(kRemoteAddr, kRemotePort, "", kHelloMessage);
-  socket_impl_->CheckWriteBuffer(reinterpret_cast<const uint8_t *>(msg.c_str()), msg.size());
+  // start callbacks
+  mSProxy->OnRead(std::move(mEmptyArray));
+
+  ASSERT_EQ(data.length(), mData.Length());
+  ASSERT_EQ(data, DataString());
 }
 
-// TODO: Reenable once bug 1251212 is fixed
-TEST_F(ProxyTunnelSocketTest, DISABLED_TestConnectProxyHostRequest) {
-  nr_proxy_tunnel_config_set_proxy(config_, kProxyHost.c_str(), kProxyPort);
-  Configure();
-  // Because kProxyHost is a domain name and not an IP address,
-  // nr_socket_connect will need to resolve an IP address before continuing.  It
-  // does that, and assumes that resolving the IP will take some time, so it
-  // returns R_WOULDBLOCK.
-  //
-  // However, In this test setup, the resolution happens inline immediately, so
-  // nr_socket_connect is called recursively on the inner socket in
-  // nr_socket_proxy_tunnel_resolved_cb.  That also completes.  Thus, the socket
-  // is actually successfully connected after this call, even though
-  // nr_socket_connect reports an error.
-  //
-  // Arguably nr_socket_proxy_tunnel_connect() is busted, because it shouldn't
-  // report an error when it doesn't need any further assistance from the
-  // calling code, but that's pretty minor.
-  Connect(R_WOULDBLOCK);
+TEST_F(NrSocketProxyTest, TestReadNone) {
+  char buf[4096];
+  size_t read = 0;
+  int r = nr_socket_read(nr_socket_, buf, sizeof(buf), &read, 0);
+
+  ASSERT_EQ(R_WOULDBLOCK, r);
 
-  std::string msg = connect_message(kRemoteAddr, kRemotePort, "", kHelloMessage);
-  socket_impl_->CheckWriteBuffer(reinterpret_cast<const uint8_t *>(msg.c_str()), msg.size());
-}
+  nsTArray<uint8_t> array;
+  array.AppendElements(kHelloMessage.c_str(), kHelloMessage.length());
+  mSProxy->OnRead(std::move(array));
 
-// TODO: Reenable once bug 1251212 is fixed
-TEST_F(ProxyTunnelSocketTest, DISABLED_TestConnectProxyWrite) {
-  Connect();
+  ASSERT_EQ(kHelloMessage.length(), mSProxy->CountUnreadBytes());
 
-  socket_impl_->ClearWriteBuffer();
+  r = nr_socket_read(nr_socket_, buf, sizeof(buf), &read, 0);
 
-  size_t written = 0;
-  int r = nr_socket_write(nr_socket_, kHelloMessage.c_str(), kHelloMessage.size(), &written, 0);
-  EXPECT_EQ(0, r);
-  EXPECT_EQ(kHelloMessage.size(), written);
-
-  socket_impl_->CheckWriteBuffer(reinterpret_cast<const uint8_t *>(kHelloMessage.c_str()),
-      kHelloMessage.size());
+  ASSERT_EQ(0, r);
+  ASSERT_EQ(kHelloMessage.length(), read);
+  ASSERT_EQ(kHelloMessage, std::string(buf, read));
 }
 
-TEST_F(ProxyTunnelSocketTest, TestConnectProxySuccessResponse) {
-  int r = nr_socket_connect(nr_socket_, &remote_addr_);
-  ASSERT_EQ(0, r);
-
-  std::string resp = connect_response(200, kHelloMessage);
-  socket_impl_->SetReadBuffer(reinterpret_cast<const uint8_t *>(resp.c_str()), resp.size());
+TEST_F(NrSocketProxyTest, TestReadMultipleSizes) {
+  using namespace std;
 
-  char buf[4096];
-  size_t read = 0;
-  r = nr_socket_read(nr_socket_, buf, sizeof(buf), &read, 0);
-  ASSERT_EQ(0, r);
+  string data;
+  // 515 * kHelloMessage.length() == 17510
+  const size_t kCount = 515;
+  // randomly generated numbers, sums to 17510, 20 numbers
+  vector<int> varyingSizes = { 404, 622, 1463, 1597, 1676, 389, 389, 1272, 781,
+    81, 1030, 1450, 256, 812, 1571, 29, 1045, 911, 643, 1089 };
 
-  ASSERT_EQ(kHelloMessage.size(), read);
-  ASSERT_EQ(0, memcmp(buf, kHelloMessage.c_str(), kHelloMessage.size()));
-}
+  // changing varyingSizes or the test message breaks this so check here
+  ASSERT_EQ(kCount, 17510 / kHelloMessage.length());
+  ASSERT_EQ(17510, accumulate(varyingSizes.begin(), varyingSizes.end(), 0));
+
+  // ~17kb
+  for(size_t i = 0; i < kCount; ++i) {
+    data += kHelloMessage;
+  }
 
-TEST_F(ProxyTunnelSocketTest, TestConnectProxyRead) {
-  int r = nr_socket_connect(nr_socket_, &remote_addr_);
-  ASSERT_EQ(0, r);
+  nsTArray<uint8_t> array;
+  array.AppendElements(data.c_str(), data.length());
 
-  std::string resp = connect_response(200, kHelloMessage);
-  socket_impl_->SetReadBuffer(reinterpret_cast<const uint8_t *>(resp.c_str()), resp.size());
+  for(int amountToRead : varyingSizes) {
+    nsTArray<uint8_t> buffer;
+    buffer.AppendElements(array.Elements(), amountToRead);
+    array.RemoveElementsAt(0, amountToRead);
+    mSProxy->OnRead(std::move(buffer));
+  }
+
+  ASSERT_EQ(data.length(), mSProxy->CountUnreadBytes());
 
-  char buf[4096];
-  size_t read = 0;
-  r = nr_socket_read(nr_socket_, buf, sizeof(buf), &read, 0);
-  ASSERT_EQ(0, r);
+  // don't need to read 0 on the first read, so start at 1 and keep going
+  mReadChunkSize = 1;
+  NR_ASYNC_WAIT(mSProxy,
+                NR_ASYNC_WAIT_READ,
+                &NrSocketProxyTest::readable_cb,
+                this);
+  // start callbacks
+  mSProxy->OnRead(std::move(mEmptyArray));
 
-  socket_impl_->ClearReadBuffer();
-  socket_impl_->SetReadBuffer(reinterpret_cast<const uint8_t *>(kHelloMessage.c_str()),
-      kHelloMessage.size());
-
-  r = nr_socket_read(nr_socket_, buf, sizeof(buf), &read, 0);
-  ASSERT_EQ(0, r);
-
-  ASSERT_EQ(kHelloMessage.size(), read);
-  ASSERT_EQ(0, memcmp(buf, kHelloMessage.c_str(), kHelloMessage.size()));
+  ASSERT_EQ(data.length(), mData.Length());
+  ASSERT_EQ(data, DataString());
 }
 
-TEST_F(ProxyTunnelSocketTest, TestConnectProxyReadNone) {
-  int r = nr_socket_connect(nr_socket_, &remote_addr_);
-  ASSERT_EQ(0, r);
+TEST_F(NrSocketProxyTest, TestReadConsumeReadDrain) {
+  std::string data;
+  // ~26kb total; should be even
+  const int kCount = 512;
 
-  std::string resp = connect_response(200);
-  socket_impl_->SetReadBuffer(reinterpret_cast<const uint8_t *>(resp.c_str()), resp.size());
+  // there's some division by 2 here so check that kCount is even
+  ASSERT_EQ(0, kCount % 2);
 
-  char buf[4096];
-  size_t read = 0;
-  r = nr_socket_read(nr_socket_, buf, sizeof(buf), &read, 0);
-  ASSERT_EQ(R_WOULDBLOCK, r);
+  for(int i = 0; i < kCount; ++i) {
+    data += kHelloMessage;
+    nsTArray<uint8_t> array;
+    array.AppendElements(kHelloMessage.c_str(), kHelloMessage.length());
+    mSProxy->OnRead(std::move(array));
+  }
 
-  socket_impl_->ClearReadBuffer();
-  socket_impl_->SetReadBuffer(reinterpret_cast<const uint8_t *>(kHelloMessage.c_str()),
-      kHelloMessage.size());
-
-  r = nr_socket_read(nr_socket_, buf, sizeof(buf), &read, 0);
-  ASSERT_EQ(0, r);
-}
+  // read half at first
+  mReadAllowance = kCount / 2 * kHelloMessage.length();
+  // start by reading 1 byte
+  mReadChunkSize = 1;
+  NR_ASYNC_WAIT(mSProxy,
+                NR_ASYNC_WAIT_READ,
+                &NrSocketProxyTest::readable_cb,
+                this);
+  mSProxy->OnRead(std::move(mEmptyArray));
 
-TEST_F(ProxyTunnelSocketTest, TestConnectProxyFailResponse) {
-  int r = nr_socket_connect(nr_socket_, &remote_addr_);
-  ASSERT_EQ(0, r);
+  ASSERT_EQ(data.length() / 2, mSProxy->CountUnreadBytes());
+  ASSERT_EQ(data.length() / 2, mData.Length());
 
-  std::string resp = connect_response(500, kHelloMessage);
-  socket_impl_->SetReadBuffer(reinterpret_cast<const uint8_t *>(resp.c_str()), resp.size());
-
-  char buf[4096];
-  size_t read = 0;
-  r = nr_socket_read(nr_socket_, buf, sizeof(buf), &read, 0);
-  ASSERT_NE(0, r);
-}
+  // fill read buffer back up
+  for(int i = 0; i < kCount / 2; ++i) {
+    data += kHelloMessage;
+    nsTArray<uint8_t> array;
+    array.AppendElements(kHelloMessage.c_str(), kHelloMessage.length());
+    mSProxy->OnRead(std::move(array));
+  }
 
-TEST_F(ProxyTunnelSocketTest, TestConnectProxyGarbageResponse) {
-  int r = nr_socket_connect(nr_socket_, &remote_addr_);
-  ASSERT_EQ(0, r);
+  // remove read limit
+  mReadAllowance = -1;
+  // used entire read allowance so we need to setup a new await
+  NR_ASYNC_WAIT(mSProxy,
+                NR_ASYNC_WAIT_READ,
+                &NrSocketProxyTest::readable_cb,
+                this);
+  // start callbacks
+  mSProxy->OnRead(std::move(mEmptyArray));
 
-  socket_impl_->SetReadBuffer(reinterpret_cast<const uint8_t *>(kGarbageMessage.c_str()),
-      kGarbageMessage.size());
-
-  char buf[4096];
-  size_t read = 0;
-  r = nr_socket_read(nr_socket_, buf, sizeof(buf), &read, 0);
-  ASSERT_EQ(0ul, read);
+  ASSERT_EQ(data.length(), mData.Length());
+  ASSERT_EQ(data, DataString());
 }
new file mode 100644
--- /dev/null
+++ b/media/mtransport/test/webrtcproxychannel_unittest.cpp
@@ -0,0 +1,707 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include <algorithm>
+#include <mutex>
+
+#include "mozilla/net/WebrtcProxyChannel.h"
+#include "mozilla/net/WebrtcProxyChannelCallback.h"
+
+#include "nsISocketTransport.h"
+
+#define GTEST_HAS_RTTI 0
+#include "gtest/gtest.h"
+#include "gtest/Helpers.h"
+#include "gtest_utils.h"
+
+static const uint32_t kDefaultTestTimeout = 2000;
+static const char kReadData[] = "Hello, World!";
+static const size_t kReadDataLength = sizeof(kReadData) - 1;
+static const std::string kReadDataString = std::string(kReadData,
+                                                       kReadDataLength);
+static int kDataLargeOuterLoopCount = 128;
+static int kDataLargeInnerLoopCount = 1024;
+
+namespace mozilla {
+
+using namespace net;
+using namespace testing;
+
+class WebrtcProxyChannelTestCallback;
+
+class FakeSocketTransportProvider : public nsISocketTransport
+{
+public:
+  NS_DECL_THREADSAFE_ISUPPORTS
+
+  // nsISocketTransport
+  NS_IMETHOD GetHost(nsACString & aHost) override { MOZ_ASSERT(false); return NS_OK; }
+  NS_IMETHOD GetPort(int32_t *aPort) override { MOZ_ASSERT(false); return NS_OK; }
+  NS_IMETHOD GetScriptableOriginAttributes(JSContext* cx, JS::MutableHandleValue aOriginAttributes) override { MOZ_ASSERT(false); return NS_OK; }
+  NS_IMETHOD SetScriptableOriginAttributes(JSContext* cx, JS::HandleValue aOriginAttributes) override { MOZ_ASSERT(false); return NS_OK; }
+  virtual nsresult GetOriginAttributes(mozilla::OriginAttributes *_retval) override { MOZ_ASSERT(false); return NS_OK; }
+  virtual nsresult SetOriginAttributes(const mozilla::OriginAttributes & aOriginAttrs) override { MOZ_ASSERT(false); return NS_OK; }
+  NS_IMETHOD GetPeerAddr(mozilla::net::NetAddr *_retval) override { MOZ_ASSERT(false); return NS_OK; }
+  NS_IMETHOD GetSelfAddr(mozilla::net::NetAddr *_retval) override { MOZ_ASSERT(false); return NS_OK; }
+  NS_IMETHOD Bind(mozilla::net::NetAddr *aLocalAddr) override { MOZ_ASSERT(false); return NS_OK; }
+  NS_IMETHOD GetScriptablePeerAddr(nsINetAddr * *_retval) override { MOZ_ASSERT(false); return NS_OK; }
+  NS_IMETHOD GetScriptableSelfAddr(nsINetAddr * *_retval) override { MOZ_ASSERT(false); return NS_OK; }
+  NS_IMETHOD GetSecurityInfo(nsISupports * *aSecurityInfo) override { MOZ_ASSERT(false); return NS_OK; }
+  NS_IMETHOD GetSecurityCallbacks(nsIInterfaceRequestor * *aSecurityCallbacks) override { MOZ_ASSERT(false); return NS_OK; }
+  NS_IMETHOD SetSecurityCallbacks(nsIInterfaceRequestor *aSecurityCallbacks) override { MOZ_ASSERT(false); return NS_OK; }
+  NS_IMETHOD IsAlive(bool *_retval) override { MOZ_ASSERT(false); return NS_OK; }
+  NS_IMETHOD GetTimeout(uint32_t aType, uint32_t *_retval) override { MOZ_ASSERT(false); return NS_OK; }
+  NS_IMETHOD SetTimeout(uint32_t aType, uint32_t aValue) override { MOZ_ASSERT(false); return NS_OK; }
+  NS_IMETHOD SetReuseAddrPort(bool reuseAddrPort) override { MOZ_ASSERT(false); return NS_OK; }
+  NS_IMETHOD GetConnectionFlags(uint32_t *aConnectionFlags) override { MOZ_ASSERT(false); return NS_OK; }
+  NS_IMETHOD SetConnectionFlags(uint32_t aConnectionFlags) override { MOZ_ASSERT(false); return NS_OK; }
+  NS_IMETHOD GetTlsFlags(uint32_t *aTlsFlags) override { MOZ_ASSERT(false); return NS_OK; }
+  NS_IMETHOD SetTlsFlags(uint32_t aTlsFlags) override { MOZ_ASSERT(false); return NS_OK; }
+  NS_IMETHOD GetQoSBits(uint8_t *aQoSBits) override { MOZ_ASSERT(false); return NS_OK; }
+  NS_IMETHOD SetQoSBits(uint8_t aQoSBits) override { MOZ_ASSERT(false); return NS_OK; }
+  NS_IMETHOD GetRecvBufferSize(uint32_t *aRecvBufferSize) override { MOZ_ASSERT(false); return NS_OK; }
+  NS_IMETHOD GetSendBufferSize(uint32_t *aSendBufferSize) override { MOZ_ASSERT(false); return NS_OK; }
+  NS_IMETHOD GetKeepaliveEnabled(bool *aKeepaliveEnabled) override { MOZ_ASSERT(false); return NS_OK; }
+  NS_IMETHOD SetKeepaliveEnabled(bool aKeepaliveEnabled) override { MOZ_ASSERT(false); return NS_OK; }
+  NS_IMETHOD SetKeepaliveVals(int32_t keepaliveIdleTime, int32_t keepaliveRetryInterval) override { MOZ_ASSERT(false); return NS_OK; }
+  NS_IMETHOD SetFastOpenCallback(mozilla::net::TCPFastOpen *aFastOpen) override { MOZ_ASSERT(false); return NS_OK; }
+  NS_IMETHOD GetFirstRetryError(nsresult *aFirstRetryError) override { MOZ_ASSERT(false); return NS_OK; }
+  NS_IMETHOD GetResetIPFamilyPreference(bool *aResetIPFamilyPreference) override { MOZ_ASSERT(false); return NS_OK; }
+  NS_IMETHOD GetEsniUsed(bool *aEsniUsed) override { MOZ_ASSERT(false); return NS_OK; }
+
+  // nsITransport
+  NS_IMETHOD OpenInputStream(uint32_t aFlags, uint32_t aSegmentSize, uint32_t aSegmentCount, nsIInputStream * *_retval) override { MOZ_ASSERT(false); return NS_OK; }
+  NS_IMETHOD OpenOutputStream(uint32_t aFlags, uint32_t aSegmentSize, uint32_t aSegmentCount, nsIOutputStream * *_retval) override { MOZ_ASSERT(false); return NS_OK; }
+  NS_IMETHOD SetEventSink(nsITransportEventSink *aSink, nsIEventTarget *aEventTarget) override { MOZ_ASSERT(false); return NS_OK; }
+
+  // fake except for these methods which are OK to call
+  // nsISocketTransport
+  NS_IMETHOD SetRecvBufferSize(uint32_t aRecvBufferSize) override
+    { return NS_OK; }
+  NS_IMETHOD SetSendBufferSize(uint32_t aSendBufferSize) override
+    { return NS_OK; }
+  // nsITransport
+  NS_IMETHOD Close(nsresult aReason) override { return NS_OK; }
+
+protected:
+  virtual ~FakeSocketTransportProvider() = default;
+};
+
+NS_IMPL_ISUPPORTS(FakeSocketTransportProvider,
+                  nsISocketTransport,
+                  nsITransport)
+
+// Implements some common elements to WebrtcProxyChannelTestOutputStream and
+// WebrtcProxyChannelTestInputStream.
+class WebrtcProxyChannelTestStream
+{
+public:
+  WebrtcProxyChannelTestStream();
+
+  void Fail() { mMustFail = true; }
+
+  size_t DataLength();
+  template <typename T> void AppendElements(const T* aBuffer, size_t aLength);
+
+protected:
+  virtual ~WebrtcProxyChannelTestStream() = default;
+
+  nsTArray<uint8_t> mData;
+  std::mutex mDataMutex;
+
+  bool mMustFail;
+};
+
+WebrtcProxyChannelTestStream::WebrtcProxyChannelTestStream()
+  : mMustFail(false) {}
+
+template <typename T>
+void
+WebrtcProxyChannelTestStream::AppendElements(const T* aBuffer, size_t aLength)
+{
+  std::lock_guard<std::mutex> guard(mDataMutex);
+  mData.AppendElements(aBuffer, aLength);
+}
+
+size_t
+WebrtcProxyChannelTestStream::DataLength()
+{
+  std::lock_guard<std::mutex> guard(mDataMutex);
+  return mData.Length();
+}
+
+class WebrtcProxyChannelTestInputStream : public nsIAsyncInputStream,
+                                          public WebrtcProxyChannelTestStream
+{
+public:
+  NS_DECL_THREADSAFE_ISUPPORTS
+  NS_DECL_NSIASYNCINPUTSTREAM
+  NS_DECL_NSIINPUTSTREAM
+
+  WebrtcProxyChannelTestInputStream()
+    : mMaxReadSize(1024 * 1024)
+    , mAllowCallbacks(false) {}
+
+  void DoCallback();
+  void CallCallback(const nsCOMPtr<nsIInputStreamCallback>& aCallback);
+  void AllowCallbacks() { mAllowCallbacks = true; }
+
+  size_t mMaxReadSize;
+
+protected:
+  virtual ~WebrtcProxyChannelTestInputStream() = default;
+
+private:
+  nsCOMPtr<nsIInputStreamCallback> mCallback;
+  nsCOMPtr<nsIEventTarget> mCallbackTarget;
+
+  bool mAllowCallbacks;
+};
+
+NS_IMPL_ISUPPORTS(WebrtcProxyChannelTestInputStream,
+                  nsIAsyncInputStream,
+                  nsIInputStream)
+
+nsresult
+WebrtcProxyChannelTestInputStream::AsyncWait(nsIInputStreamCallback *aCallback,
+                                             uint32_t aFlags,
+                                             uint32_t aRequestedCount,
+                                             nsIEventTarget *aEventTarget)
+{
+  MOZ_ASSERT(!aEventTarget, "no event target should be set");
+
+  mCallback = aCallback;
+  mCallbackTarget = NS_GetCurrentThread();
+
+  if (mAllowCallbacks && DataLength() > 0) {
+    DoCallback();
+  }
+
+  return NS_OK;
+}
+
+nsresult
+WebrtcProxyChannelTestInputStream::CloseWithStatus(nsresult aStatus)
+{
+  return Close();
+}
+
+nsresult
+WebrtcProxyChannelTestInputStream::Close()
+{
+  return NS_OK;
+}
+
+nsresult
+WebrtcProxyChannelTestInputStream::Available(uint64_t* aAvailable)
+{
+  *aAvailable = DataLength();
+  return NS_OK;
+}
+
+nsresult
+WebrtcProxyChannelTestInputStream::Read(char* aBuffer,
+                                        uint32_t aCount,
+                                        uint32_t* aRead)
+{
+  std::lock_guard<std::mutex> guard(mDataMutex);
+  if (mMustFail) {
+    return NS_ERROR_FAILURE;
+  }
+  *aRead = std::min({ (size_t)aCount, mData.Length(), mMaxReadSize });
+  memcpy(aBuffer, mData.Elements(), *aRead);
+  mData.RemoveElementsAt(0, *aRead);
+  return *aRead > 0 ? NS_OK : NS_BASE_STREAM_WOULD_BLOCK;
+}
+
+nsresult
+WebrtcProxyChannelTestInputStream::ReadSegments(nsWriteSegmentFun aWriter,
+                                                void *aClosure,
+                                                uint32_t aCount,
+                                                uint32_t *_retval)
+{
+  MOZ_ASSERT(false);
+  return NS_OK;
+}
+
+nsresult
+WebrtcProxyChannelTestInputStream::IsNonBlocking(bool* aIsNonBlocking)
+{
+  *aIsNonBlocking = true;
+  return NS_OK;
+}
+
+void
+WebrtcProxyChannelTestInputStream::CallCallback(
+  const nsCOMPtr<nsIInputStreamCallback>& aCallback)
+{
+  aCallback->OnInputStreamReady(this);
+}
+
+void
+WebrtcProxyChannelTestInputStream::DoCallback()
+{
+  if (mCallback) {
+    mCallbackTarget->Dispatch(
+      NewRunnableMethod<const nsCOMPtr<nsIInputStreamCallback>&>(
+        "WebrtcProxyChannelTestInputStream::DoCallback",
+        this,
+        &WebrtcProxyChannelTestInputStream::CallCallback,
+        std::move(mCallback)));
+
+    mCallbackTarget = nullptr;
+  }
+}
+
+class WebrtcProxyChannelTestOutputStream : public nsIAsyncOutputStream,
+                                           public WebrtcProxyChannelTestStream
+{
+public:
+  NS_DECL_THREADSAFE_ISUPPORTS
+  NS_DECL_NSIASYNCOUTPUTSTREAM
+  NS_DECL_NSIOUTPUTSTREAM
+
+  WebrtcProxyChannelTestOutputStream()
+    : mMaxWriteSize(1024 * 1024) {}
+
+  void DoCallback();
+  void CallCallback(const nsCOMPtr<nsIOutputStreamCallback>& aCallback);
+
+  const std::string DataString();
+
+  uint32_t mMaxWriteSize;
+
+protected:
+  virtual ~WebrtcProxyChannelTestOutputStream() = default;
+
+private:
+  nsCOMPtr<nsIOutputStreamCallback> mCallback;
+  nsCOMPtr<nsIEventTarget> mCallbackTarget;
+};
+
+NS_IMPL_ISUPPORTS(WebrtcProxyChannelTestOutputStream,
+                  nsIAsyncOutputStream,
+                  nsIOutputStream)
+
+nsresult
+WebrtcProxyChannelTestOutputStream::AsyncWait(
+  nsIOutputStreamCallback *aCallback,
+  uint32_t aFlags,
+  uint32_t aRequestedCount,
+  nsIEventTarget *aEventTarget)
+{
+  MOZ_ASSERT(!aEventTarget, "no event target should be set");
+
+  mCallback = aCallback;
+  mCallbackTarget = NS_GetCurrentThread();
+
+  return NS_OK;
+}
+
+nsresult
+WebrtcProxyChannelTestOutputStream::CloseWithStatus(nsresult aStatus)
+{
+  return Close();
+}
+
+nsresult
+WebrtcProxyChannelTestOutputStream::Close()
+{
+  return NS_OK;
+}
+
+nsresult
+WebrtcProxyChannelTestOutputStream::Flush()
+{
+  return NS_OK;
+}
+
+nsresult
+WebrtcProxyChannelTestOutputStream::Write(const char* aBuffer,
+                                          uint32_t aCount,
+                                          uint32_t* aWrote)
+{
+  if (mMustFail) {
+    return NS_ERROR_FAILURE;
+  }
+  *aWrote = std::min(aCount, mMaxWriteSize);
+  AppendElements(aBuffer, *aWrote);
+  return NS_OK;
+}
+
+nsresult
+WebrtcProxyChannelTestOutputStream::WriteSegments(nsReadSegmentFun aReader,
+                                                  void *aClosure,
+                                                  uint32_t aCount,
+                                                  uint32_t *_retval)
+{
+  MOZ_ASSERT(false);
+  return NS_OK;
+}
+
+nsresult
+WebrtcProxyChannelTestOutputStream::WriteFrom(
+  nsIInputStream *aFromStream,
+  uint32_t aCount,
+  uint32_t *_retval)
+{
+  MOZ_ASSERT(false);
+  return NS_OK;
+}
+
+nsresult
+WebrtcProxyChannelTestOutputStream::IsNonBlocking(bool* aIsNonBlocking)
+{
+  *aIsNonBlocking = true;
+  return NS_OK;
+}
+
+void
+WebrtcProxyChannelTestOutputStream::CallCallback(
+  const nsCOMPtr<nsIOutputStreamCallback>& aCallback)
+{
+  aCallback->OnOutputStreamReady(this);
+}
+
+void
+WebrtcProxyChannelTestOutputStream::DoCallback()
+{
+  if (mCallback) {
+    mCallbackTarget->Dispatch(
+      NewRunnableMethod<const nsCOMPtr<nsIOutputStreamCallback>&>(
+        "WebrtcProxyChannelTestOutputStream::CallCallback",
+        this,
+        &WebrtcProxyChannelTestOutputStream::CallCallback,
+        std::move(mCallback)));
+
+    mCallbackTarget = nullptr;
+  }
+}
+
+const std::string
+WebrtcProxyChannelTestOutputStream::DataString()
+{
+  std::lock_guard<std::mutex> guard(mDataMutex);
+  return std::string((char*)mData.Elements(), mData.Length());
+}
+
+// Fake as in not the real WebrtcProxyChannel but real enough
+class FakeWebrtcProxyChannel : public WebrtcProxyChannel
+{
+public:
+  explicit FakeWebrtcProxyChannel(WebrtcProxyChannelCallback* aCallback)
+    : WebrtcProxyChannel(nullptr, aCallback) {}
+
+protected:
+  virtual ~FakeWebrtcProxyChannel() = default;
+
+  void InvokeOnClose(nsresult aReason) override;
+  void InvokeOnConnected() override;
+  void InvokeOnRead(nsTArray<uint8_t>&& aReadData) override;
+};
+
+void
+FakeWebrtcProxyChannel::InvokeOnClose(nsresult aReason)
+{
+  mProxyCallbacks->OnClose(aReason);
+}
+
+void
+FakeWebrtcProxyChannel::InvokeOnConnected()
+{
+  mProxyCallbacks->OnConnected();
+}
+
+void
+FakeWebrtcProxyChannel::InvokeOnRead(nsTArray<uint8_t>&& aReadData)
+{
+  mProxyCallbacks->OnRead(std::move(aReadData));
+}
+
+class WebrtcProxyChannelTest : public MtransportTest
+{
+public:
+  WebrtcProxyChannelTest()
+    : MtransportTest()
+    , mSocketThread(nullptr)
+    , mSocketTransport(nullptr)
+    , mInputStream(nullptr)
+    , mOutputStream(nullptr)
+    , mChannel(nullptr)
+    , mCallback(nullptr)
+    , mOnCloseCalled(false)
+    , mOnConnectedCalled(false) {}
+
+  // WebrtcProxyChannelCallback forwards from mCallback
+  void OnClose(nsresult aReason);
+  void OnConnected();
+  void OnRead(nsTArray<uint8_t>&& aReadData);
+
+  void SetUp() override;
+  void TearDown() override;
+
+  void DoTransportAvailable();
+
+  const std::string ReadDataAsString();
+  const std::string GetDataLarge();
+
+  nsCOMPtr<nsIEventTarget> mSocketThread;
+
+  nsCOMPtr<nsISocketTransport>               mSocketTransport;
+  RefPtr<WebrtcProxyChannelTestInputStream>  mInputStream;
+  RefPtr<WebrtcProxyChannelTestOutputStream> mOutputStream;
+  RefPtr<FakeWebrtcProxyChannel>             mChannel;
+  RefPtr<WebrtcProxyChannelTestCallback>     mCallback;
+
+  bool mOnCloseCalled;
+  bool mOnConnectedCalled;
+
+  size_t ReadDataLength();
+  template<typename T> void AppendReadData(const T* aBuffer, size_t aLength);
+
+private:
+  nsTArray<uint8_t> mReadData;
+  std::mutex mReadDataMutex;
+};
+
+class WebrtcProxyChannelTestCallback : public WebrtcProxyChannelCallback
+{
+public:
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WebrtcProxyChannelTestCallback,
+                                        override)
+
+  explicit WebrtcProxyChannelTestCallback(WebrtcProxyChannelTest* aTest)
+    : mTest(aTest) {}
+
+  // WebrtcProxyChannelCallback
+  void OnClose(nsresult aReason) override;
+  void OnConnected() override;
+  void OnRead(nsTArray<uint8_t>&& aReadData) override;
+
+protected:
+  virtual ~WebrtcProxyChannelTestCallback() = default;
+
+private:
+  WebrtcProxyChannelTest* mTest;
+};
+
+void
+WebrtcProxyChannelTest::SetUp()
+{
+  nsresult rv;
+  // WebrtcProxyChannel's threading model is the same as mtransport
+  // all socket operations are done on the socket thread
+  // callbacks are invoked on the main thread
+  mSocketThread = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
+  ASSERT_TRUE(NS_SUCCEEDED(rv));
+
+  mSocketTransport = new FakeSocketTransportProvider();
+  mInputStream = new WebrtcProxyChannelTestInputStream();
+  mOutputStream = new WebrtcProxyChannelTestOutputStream();
+  mCallback = new WebrtcProxyChannelTestCallback(this);
+  mChannel = new FakeWebrtcProxyChannel(mCallback.get());
+}
+
+void
+WebrtcProxyChannelTest::TearDown()
+{
+}
+
+// WebrtcProxyChannelCallback
+void
+WebrtcProxyChannelTest::OnRead(nsTArray<uint8_t>&& aReadData)
+{
+  AppendReadData(aReadData.Elements(), aReadData.Length());
+}
+
+void
+WebrtcProxyChannelTest::OnConnected()
+{
+  mOnConnectedCalled = true;
+}
+
+void
+WebrtcProxyChannelTest::OnClose(nsresult aReason)
+{
+  mOnCloseCalled = true;
+}
+
+void
+WebrtcProxyChannelTest::DoTransportAvailable()
+{
+  if (!mSocketThread->IsOnCurrentThread()) {
+    mSocketThread->Dispatch(
+      NS_NewRunnableFunction(
+        "DoTransportAvailable",
+        [this]() -> void {
+          nsresult rv;
+          rv = mChannel->OnTransportAvailable(mSocketTransport,
+                                              mInputStream,
+                                              mOutputStream);
+          ASSERT_EQ(NS_OK, rv);
+        }));
+  } else {
+    // should always be called on the main thread
+    MOZ_ASSERT(0);
+  }
+}
+
+const std::string
+WebrtcProxyChannelTest::ReadDataAsString()
+{
+  std::lock_guard<std::mutex> guard(mReadDataMutex);
+  return std::string((char*)mReadData.Elements(), mReadData.Length());
+}
+
+const std::string
+WebrtcProxyChannelTest::GetDataLarge()
+{
+  std::string data;
+  for(int i = 0; i < kDataLargeOuterLoopCount * kDataLargeInnerLoopCount; ++i) {
+    data += kReadData;
+  }
+  return data;
+}
+
+template<typename T>
+void
+WebrtcProxyChannelTest::AppendReadData(const T* aBuffer, size_t aLength)
+{
+  std::lock_guard<std::mutex> guard(mReadDataMutex);
+  mReadData.AppendElements(aBuffer, aLength);
+}
+
+size_t
+WebrtcProxyChannelTest::ReadDataLength()
+{
+  std::lock_guard<std::mutex> guard(mReadDataMutex);
+  return mReadData.Length();
+}
+
+void
+WebrtcProxyChannelTestCallback::OnClose(nsresult aReason)
+{
+  mTest->OnClose(aReason);
+}
+
+void
+WebrtcProxyChannelTestCallback::OnConnected()
+{
+  mTest->OnConnected();
+}
+
+void
+WebrtcProxyChannelTestCallback::OnRead(nsTArray<uint8_t>&& aReadData)
+{
+  mTest->OnRead(std::move(aReadData));
+}
+
+} // namespace mozilla
+
+typedef mozilla::WebrtcProxyChannelTest WebrtcProxyChannelTest;
+
+TEST_F(WebrtcProxyChannelTest, SetUp) {}
+
+TEST_F(WebrtcProxyChannelTest, TransportAvailable) {
+  DoTransportAvailable();
+  ASSERT_TRUE_WAIT(mOnConnectedCalled, kDefaultTestTimeout);
+}
+
+TEST_F(WebrtcProxyChannelTest, Read) {
+  DoTransportAvailable();
+  ASSERT_TRUE_WAIT(mOnConnectedCalled, kDefaultTestTimeout);
+
+  mInputStream->AppendElements(kReadData, kReadDataLength);
+  mInputStream->DoCallback();
+
+  ASSERT_TRUE_WAIT(ReadDataAsString() == kReadDataString, kDefaultTestTimeout);
+}
+
+TEST_F(WebrtcProxyChannelTest, Write) {
+  DoTransportAvailable();
+  ASSERT_TRUE_WAIT(mOnConnectedCalled, kDefaultTestTimeout);
+
+  nsTArray<uint8_t> data;
+  data.AppendElements(kReadData, kReadDataLength);
+  mChannel->Write(std::move(data));
+
+  ASSERT_TRUE_WAIT(mChannel->CountUnwrittenBytes() == kReadDataLength,
+                   kDefaultTestTimeout);
+
+  mOutputStream->DoCallback();
+
+  ASSERT_TRUE_WAIT(mOutputStream->DataString() == kReadDataString,
+                   kDefaultTestTimeout);
+}
+
+TEST_F(WebrtcProxyChannelTest, ReadFail) {
+  DoTransportAvailable();
+  ASSERT_TRUE_WAIT(mOnConnectedCalled, kDefaultTestTimeout);
+
+  mInputStream->AppendElements(kReadData, kReadDataLength);
+  mInputStream->Fail();
+  mInputStream->DoCallback();
+
+  ASSERT_TRUE_WAIT(mOnCloseCalled, kDefaultTestTimeout);
+  ASSERT_EQ(0U, ReadDataLength());
+}
+
+TEST_F(WebrtcProxyChannelTest, WriteFail) {
+  DoTransportAvailable();
+  ASSERT_TRUE_WAIT(mOnConnectedCalled, kDefaultTestTimeout);
+
+  nsTArray<uint8_t> array;
+  array.AppendElements(kReadData, kReadDataLength);
+  mChannel->Write(std::move(array));
+
+  ASSERT_TRUE_WAIT(mChannel->CountUnwrittenBytes() == kReadDataLength,
+                   kDefaultTestTimeout);
+
+  mOutputStream->Fail();
+  mOutputStream->DoCallback();
+
+  ASSERT_TRUE_WAIT(mOnCloseCalled, kDefaultTestTimeout);
+  ASSERT_EQ(0U, mOutputStream->DataLength());
+}
+
+TEST_F(WebrtcProxyChannelTest, ReadLarge) {
+  DoTransportAvailable();
+  ASSERT_TRUE_WAIT(mOnConnectedCalled, kDefaultTestTimeout);
+
+  const std::string data = GetDataLarge();
+
+  mInputStream->AppendElements(data.c_str(), data.length());
+  // make sure reading loops more than once
+  mInputStream->mMaxReadSize = 3072;
+  mInputStream->AllowCallbacks();
+  mInputStream->DoCallback();
+
+  ASSERT_TRUE_WAIT(ReadDataAsString() == data, kDefaultTestTimeout);
+}
+
+TEST_F(WebrtcProxyChannelTest, WriteLarge) {
+  DoTransportAvailable();
+  ASSERT_TRUE_WAIT(mOnConnectedCalled, kDefaultTestTimeout);
+
+  const std::string data = GetDataLarge();
+
+  for(int i = 0; i < kDataLargeOuterLoopCount; ++i) {
+    nsTArray<uint8_t> array;
+    int chunkSize = kReadDataString.length() * kDataLargeInnerLoopCount;
+    int offset = i * chunkSize;
+    array.AppendElements(data.c_str() + offset, chunkSize);
+    mChannel->Write(std::move(array));
+  }
+
+  ASSERT_TRUE_WAIT(mChannel->CountUnwrittenBytes() == data.length(),
+                   kDefaultTestTimeout);
+
+  // make sure writing loops more than once per write request
+  mOutputStream->mMaxWriteSize = 1024;
+  mOutputStream->DoCallback();
+
+  ASSERT_TRUE_WAIT(mOutputStream->DataString() == data, kDefaultTestTimeout);
+}
--- a/media/mtransport/test_nr_socket.cpp
+++ b/media/mtransport/test_nr_socket.cpp
@@ -232,33 +232,33 @@ RefPtr<NrSocketBase> TestNrSocket::creat
 
   if ((r = nr_transport_addr_set_port(&nat_external_addr, 0))) {
     r_log(LOG_GENERIC,LOG_CRIT, "%s: Failure in nr_transport_addr_set_port: %d",
                                 __FUNCTION__, r);
     return nullptr;
   }
 
   RefPtr<NrSocketBase> external_socket;
-  r = NrSocketBase::CreateSocket(&nat_external_addr, &external_socket);
+  r = NrSocketBase::CreateSocket(&nat_external_addr, &external_socket, nullptr);
 
   if (r) {
     r_log(LOG_GENERIC,LOG_CRIT, "%s: Failure in NrSocket::create: %d",
                                 __FUNCTION__, r);
     return nullptr;
   }
 
   return external_socket;
 }
 
 int TestNrSocket::create(nr_transport_addr *addr) {
   if (addr->tls_host[0] != '\0') {
     tls_ = true;
   }
 
-  return NrSocketBase::CreateSocket(addr, &internal_socket_);
+  return NrSocketBase::CreateSocket(addr, &internal_socket_, nullptr);
 }
 
 int TestNrSocket::getaddr(nr_transport_addr *addrp) {
   return internal_socket_->getaddr(addrp);
 }
 
 void TestNrSocket::close() {
   if (timer_handle_) {
--- a/media/mtransport/third_party/nICEr/nicer.gyp
+++ b/media/mtransport/third_party/nICEr/nicer.gyp
@@ -62,18 +62,16 @@
                 "./src/ice/ice_socket.c",
                 "./src/ice/ice_socket.h",
 
                 # Net
                 "./src/net/nr_resolver.c",
                 "./src/net/nr_resolver.h",
                 "./src/net/nr_socket_wrapper.c",
                 "./src/net/nr_socket_wrapper.h",
-                "./src/net/nr_proxy_tunnel.c",
-                "./src/net/nr_proxy_tunnel.h",
                 "./src/net/nr_socket.c",
                 "./src/net/nr_socket.h",
                 #"./src/net/nr_socket_local.c",
                 "./src/net/nr_socket_local.h",
                 "./src/net/nr_socket_multi_tcp.c",
                 "./src/net/nr_socket_multi_tcp.h",
                 "./src/net/transport_addr.c",
                 "./src/net/transport_addr.h",
deleted file mode 100644
--- a/media/mtransport/third_party/nICEr/src/net/nr_proxy_tunnel.c
+++ /dev/null
@@ -1,686 +0,0 @@
-/*
-Copyright (c) 2007, Adobe Systems, Incorporated
-Copyright (c) 2013, Mozilla
-
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
-* Redistributions of source code must retain the above copyright
-  notice, this list of conditions and the following disclaimer.
-
-* Redistributions in binary form must reproduce the above copyright
-  notice, this list of conditions and the following disclaimer in the
-  documentation and/or other materials provided with the distribution.
-
-* Neither the name of Adobe Systems, Network Resonance, Mozilla nor
-  the names of its contributors may be used to endorse or promote
-  products derived from this software without specific prior written
-  permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#include <nr_api.h>
-
-#include <assert.h>
-
-#include "nr_proxy_tunnel.h"
-
-#define MAX_HTTP_CONNECT_ADDR_SIZE 256
-#define MAX_HTTP_CONNECT_BUFFER_SIZE 1024
-#define MAX_ALPN_LENGTH 64
-#ifndef CRLF
-#define CRLF "\r\n"
-#endif
-#define END_HEADERS CRLF CRLF
-
-typedef enum {
-  PROXY_TUNNEL_NONE=0,
-  PROXY_TUNNEL_REQUESTED,
-  PROXY_TUNNEL_CONNECTED,
-  PROXY_TUNNEL_CLOSED,
-  PROXY_TUNNEL_FAILED
-} nr_socket_proxy_tunnel_state;
-
-typedef struct nr_socket_proxy_tunnel_ {
-  nr_proxy_tunnel_config *config;
-  nr_socket *inner;
-  nr_transport_addr remote_addr;
-  nr_socket_proxy_tunnel_state state;
-  char buffer[MAX_HTTP_CONNECT_BUFFER_SIZE];
-  size_t buffered_bytes;
-  void *resolver_handle;
-} nr_socket_proxy_tunnel;
-
-typedef struct nr_socket_wrapper_factory_proxy_tunnel_ {
-  nr_proxy_tunnel_config *config;
-} nr_socket_wrapper_factory_proxy_tunnel;
-
-static int nr_socket_proxy_tunnel_destroy(void **objpp);
-static int nr_socket_proxy_tunnel_getfd(void *obj, NR_SOCKET *fd);
-static int nr_socket_proxy_tunnel_getaddr(void *obj, nr_transport_addr *addrp);
-static int nr_socket_proxy_tunnel_connect(void *sock, nr_transport_addr *addr);
-static int nr_socket_proxy_tunnel_write(void *obj, const void *msg, size_t len, size_t *written);
-static int nr_socket_proxy_tunnel_read(void *obj, void * restrict buf, size_t maxlen, size_t *len);
-static int nr_socket_proxy_tunnel_close(void *obj);
-
-int nr_proxy_tunnel_config_copy(nr_proxy_tunnel_config *config, nr_proxy_tunnel_config **copypp);
-
-int nr_socket_wrapper_factory_proxy_tunnel_wrap(void *obj,
-                                                nr_socket *inner,
-                                                nr_socket **socketpp);
-
-int nr_socket_wrapper_factory_proxy_tunnel_destroy(void **objpp);
-
-static nr_socket_vtbl nr_socket_proxy_tunnel_vtbl={
-  1,
-  nr_socket_proxy_tunnel_destroy,
-  0,
-  0,
-  nr_socket_proxy_tunnel_getfd,
-  nr_socket_proxy_tunnel_getaddr,
-  nr_socket_proxy_tunnel_connect,
-  nr_socket_proxy_tunnel_write,
-  nr_socket_proxy_tunnel_read,
-  nr_socket_proxy_tunnel_close
-};
-
-static int send_http_connect(nr_socket_proxy_tunnel *sock)
-{
-  int r, _status;
-  int port;
-  int printed;
-  char addr[MAX_HTTP_CONNECT_ADDR_SIZE];
-  char mesg[MAX_HTTP_CONNECT_ADDR_SIZE + MAX_ALPN_LENGTH + 128];
-  size_t offset = 0;
-  size_t bytes_sent;
-
-  r_log(LOG_GENERIC,LOG_DEBUG,"send_http_connect");
-
-  if ((r=nr_transport_addr_get_port(&sock->remote_addr, &port))) {
-    ABORT(r);
-  }
-
-  if ((r=nr_transport_addr_get_addrstring(&sock->remote_addr, addr, sizeof(addr)))) {
-    ABORT(r);
-  }
-
-  printed = snprintf(mesg + offset, sizeof(mesg) - offset,
-                     "CONNECT %s:%d HTTP/1.0", addr, port);
-  offset += printed;
-  if (printed < 0 || (offset >= sizeof(mesg))) {
-    ABORT(R_FAILED);
-  }
-
-  if (sock->config->alpn) {
-    printed = snprintf(mesg + offset, sizeof(mesg) - offset,
-                       CRLF "ALPN: %s", sock->config->alpn);
-    offset += printed;
-    if (printed < 0 || (offset >= sizeof(mesg))) {
-      ABORT(R_FAILED);
-    }
-  }
-  if (offset + sizeof(END_HEADERS) >= sizeof(mesg)) {
-    ABORT(R_FAILED);
-  }
-  memcpy(mesg + offset, END_HEADERS, strlen(END_HEADERS));
-  offset += strlen(END_HEADERS);
-
-  if ((r=nr_socket_write(sock->inner, mesg, offset, &bytes_sent, 0))) {
-    ABORT(r);
-  }
-
-  if (bytes_sent < offset) {
-    /* TODO(bug 1116583): buffering and wait for */
-    r_log(LOG_GENERIC,LOG_DEBUG,"send_http_connect should be buffering %lu", (unsigned long)bytes_sent);
-    ABORT(R_IO_ERROR);
-  }
-
-  sock->state = PROXY_TUNNEL_REQUESTED;
-
-  _status = 0;
-abort:
-  return(_status);
-}
-
-static char *find_http_terminator(char *response, size_t len)
-{
-  char *term = response;
-  char *end = response + len;
-  int N = strlen(END_HEADERS);
-
-  for (; term = memchr(term, '\r', end - term); ++term) {
-    if (end - term >= N && memcmp(term, END_HEADERS, N) == 0) {
-      return term;
-    }
-  }
-
-  return NULL;
-}
-
-static int parse_http_response(char *begin, char *end, unsigned int *status)
-{
-  size_t len = end - begin;
-  char response[MAX_HTTP_CONNECT_BUFFER_SIZE + 1];
-
-  // len should *never* be greater than nr_socket_proxy_tunnel::buffered_bytes.
-  // Which in turn should never be greater nr_socket_proxy_tunnel::buffer size.
-  assert(len <= MAX_HTTP_CONNECT_BUFFER_SIZE);
-  if (len > MAX_HTTP_CONNECT_BUFFER_SIZE) {
-    return R_BAD_DATA;
-  }
-
-  memcpy(response, begin, len);
-  response[len] = '\0';
-
-  // http://www.rfc-editor.org/rfc/rfc7230.txt
-  // status-line    = HTTP-version SP status-code SP reason-phrase CRLF
-  // HTTP-version   = HTTP-name "/" DIGIT "." DIGIT
-  // HTTP-name      = "HTTP" ; "HTTP", case-sensitive
-  // status-code    = 3DIGIT
-
-  if (sscanf(response, "HTTP/%*u.%*u %u", status) != 1) {
-    r_log(LOG_GENERIC,LOG_WARNING,"parse_http_response failed to find status (%s)", response);
-    return R_BAD_DATA;
-  }
-
-  return 0;
-}
-
-static int nr_socket_proxy_tunnel_destroy(void **objpp)
-{
-  nr_socket_proxy_tunnel *sock;
-
-  r_log(LOG_GENERIC,LOG_DEBUG,"nr_socket_proxy_tunnel_destroy");
-
-  if (!objpp || !*objpp)
-    return 0;
-
-  sock = (nr_socket_proxy_tunnel *)*objpp;
-  *objpp = 0;
-
-  if (sock->resolver_handle) {
-    nr_resolver_cancel(sock->config->resolver, sock->resolver_handle);
-  }
-
-  nr_proxy_tunnel_config_destroy(&sock->config);
-  nr_socket_destroy(&sock->inner);
-  RFREE(sock);
-
-  return 0;
-}
-
-static int nr_socket_proxy_tunnel_getfd(void *obj, NR_SOCKET *fd)
-{
-  nr_socket_proxy_tunnel *sock = (nr_socket_proxy_tunnel *)obj;
-
-  r_log(LOG_GENERIC,LOG_DEBUG,"nr_socket_proxy_tunnel_getfd");
-
-  return nr_socket_getfd(sock->inner, fd);
-}
-
-static int nr_socket_proxy_tunnel_getaddr(void *obj, nr_transport_addr *addrp)
-{
-  nr_socket_proxy_tunnel *sock = (nr_socket_proxy_tunnel *)obj;
-
-  r_log(LOG_GENERIC,LOG_DEBUG,"nr_socket_proxy_tunnel_getaddr");
-
-  return nr_socket_getaddr(sock->inner, addrp);
-}
-
-static int nr_socket_proxy_tunnel_resolved_cb(void *obj, nr_transport_addr *proxy_addr)
-{
-  int r, _status;
-  nr_socket_proxy_tunnel *sock = (nr_socket_proxy_tunnel*)obj;
-
-  r_log(LOG_GENERIC,LOG_DEBUG,"nr_socket_proxy_tunnel_resolved_cb");
-
-  /* Mark the socket resolver as completed */
-  sock->resolver_handle = 0;
-
-  if (proxy_addr) {
-    r_log(LOG_GENERIC,LOG_DEBUG,"Resolved proxy address %s -> %s",
-        sock->config->proxy_host, proxy_addr->as_string);
-  }
-  else {
-    r_log(LOG_GENERIC,LOG_WARNING,"Failed to resolve proxy %s",
-        sock->config->proxy_host);
-    /* TODO: Mozilla bug 1241758: because of the callback the return value goes
-     * nowhere, so we can't mark the candidate as failed, so everything depends
-     * on the overall timeouts in this case. */
-    sock->state = PROXY_TUNNEL_FAILED;
-    ABORT(R_NOT_FOUND);
-  }
-
-  if ((r=nr_socket_connect(sock->inner, proxy_addr))) {
-    ABORT(r);
-  }
-
-  _status = 0;
-abort:
-  return(_status);
-}
-
-int nr_socket_proxy_tunnel_connect(void *obj, nr_transport_addr *addr)
-{
-  int r, _status;
-  int has_addr;
-  nr_socket_proxy_tunnel *sock = (nr_socket_proxy_tunnel*)obj;
-  nr_proxy_tunnel_config *config = sock->config;
-  nr_transport_addr proxy_addr, local_addr;
-  nr_resolver_resource resource;
-
-  if ((r=nr_transport_addr_copy(&sock->remote_addr, addr))) {
-    ABORT(r);
-  }
-
-  assert(config->proxy_host);
-
-  /* Check if the proxy_host is already an IP address */
-  has_addr = !nr_str_port_to_transport_addr(config->proxy_host,
-      config->proxy_port, IPPROTO_TCP, &proxy_addr);
-
-  r_log(LOG_GENERIC,LOG_DEBUG,"nr_socket_proxy_tunnel_connect: %s", config->proxy_host);
-
-  if (!has_addr && !config->resolver) {
-    r_log(LOG_GENERIC,LOG_ERR,"nr_socket_proxy_tunnel_connect name resolver not configured");
-    ABORT(R_NOT_FOUND);
-  }
-
-  if (!has_addr) {
-    resource.domain_name=config->proxy_host;
-    resource.port=config->proxy_port;
-    resource.stun_turn=NR_RESOLVE_PROTOCOL_TURN;
-    resource.transport_protocol=IPPROTO_TCP;
-
-    if ((r=nr_socket_getaddr(sock->inner, &local_addr))) {
-      r_log(LOG_GENERIC,LOG_ERR,"nr_socket_proxy_tunnel_connect failed to get local address");
-      ABORT(r);
-    }
-
-    switch(local_addr.ip_version) {
-      case NR_IPV4:
-        resource.address_family=AF_INET;
-        break;
-      case NR_IPV6:
-        resource.address_family=AF_INET6;
-        break;
-      default:
-        ABORT(R_BAD_ARGS);
-    }
-
-    r_log(LOG_GENERIC,LOG_DEBUG,"nr_socket_proxy_tunnel_connect: nr_resolver_resolve");
-    if ((r=nr_resolver_resolve(config->resolver, &resource,
-            nr_socket_proxy_tunnel_resolved_cb, (void *)sock, &sock->resolver_handle))) {
-      r_log(LOG_GENERIC,LOG_ERR,"Could not invoke DNS resolver");
-      ABORT(r);
-    }
-
-    ABORT(R_WOULDBLOCK);
-  }
-
-  if ((r=nr_socket_connect(sock->inner, &proxy_addr))) {
-    ABORT(r);
-  }
-
-  _status=0;
-abort:
-  return(_status);
-}
-
-int nr_socket_proxy_tunnel_write(void *obj, const void *msg, size_t len,
-                                 size_t *written)
-{
-  int r, _status;
-  nr_socket_proxy_tunnel *sock = (nr_socket_proxy_tunnel*)obj;
-
-  r_log(LOG_GENERIC,LOG_DEBUG,"nr_socket_proxy_tunnel_write");
-
-  if (sock->state >= PROXY_TUNNEL_CLOSED) {
-    return R_FAILED;
-  }
-
-  if (sock->state == PROXY_TUNNEL_NONE) {
-    if ((r=send_http_connect(sock))) {
-      ABORT(r);
-    }
-  }
-
-  if (sock->state != PROXY_TUNNEL_CONNECTED) {
-    return R_WOULDBLOCK;
-  }
-
-  if ((r=nr_socket_write(sock->inner, msg, len, written, 0))) {
-    ABORT(r);
-  }
-
-  _status=0;
-abort:
-  return(_status);
-}
-
-int nr_socket_proxy_tunnel_read(void *obj, void * restrict buf, size_t maxlen,
-                                size_t *len)
-{
-  int r, _status;
-  char *ptr, *http_term;
-  size_t bytes_read, available_buffer_len, maxlen_int;
-  size_t pending;
-  nr_socket_proxy_tunnel *sock = (nr_socket_proxy_tunnel*)obj;
-  unsigned int http_status;
-
-  r_log(LOG_GENERIC,LOG_DEBUG,"nr_socket_proxy_tunnel_read");
-
-  *len = 0;
-
-  if (sock->state >= PROXY_TUNNEL_CLOSED) {
-    return R_FAILED;
-  }
-
-  if (sock->state == PROXY_TUNNEL_CONNECTED) {
-    return nr_socket_read(sock->inner, buf, maxlen, len, 0);
-  }
-
-  if (sock->buffered_bytes >= sizeof(sock->buffer)) {
-    r_log(LOG_GENERIC,LOG_ERR,"buffer filled waiting for CONNECT response");
-    assert(sock->buffered_bytes == sizeof(sock->buffer));
-    ABORT(R_INTERNAL);
-  }
-
-  /* Do not read more than maxlen bytes */
-  available_buffer_len = sizeof(sock->buffer) - sock->buffered_bytes;
-  maxlen_int = maxlen < available_buffer_len ? maxlen : available_buffer_len;
-  if ((r=nr_socket_read(sock->inner, sock->buffer + sock->buffered_bytes,
-          maxlen_int, &bytes_read, 0))) {
-    ABORT(r);
-  }
-
-  sock->buffered_bytes += bytes_read;
-
-  if (http_term = find_http_terminator(sock->buffer, sock->buffered_bytes)) {
-    if ((r = parse_http_response(sock->buffer, http_term, &http_status))) {
-      ABORT(r);
-    }
-
-    /* TODO (bug 1115934): Handle authentication challenges. */
-    if (http_status < 200 || http_status >= 300) {
-      r_log(LOG_GENERIC,LOG_ERR,"nr_socket_proxy_tunnel_read unable to connect %u",
-            http_status);
-      ABORT(R_FAILED);
-    }
-
-    sock->state = PROXY_TUNNEL_CONNECTED;
-
-    ptr = http_term + strlen(END_HEADERS);
-    pending = sock->buffered_bytes - (ptr - sock->buffer);
-
-    if (pending == 0) {
-      ABORT(R_WOULDBLOCK);
-    }
-
-    assert(pending <= maxlen);
-    *len = pending;
-
-    memcpy(buf, ptr, *len);
-  }
-
-  _status=0;
-abort:
-  if (_status && _status != R_WOULDBLOCK) {
-      sock->state = PROXY_TUNNEL_FAILED;
-  }
-  return(_status);
-}
-
-int nr_socket_proxy_tunnel_close(void *obj)
-{
-  nr_socket_proxy_tunnel *sock = (nr_socket_proxy_tunnel*)obj;
-
-  r_log(LOG_GENERIC,LOG_DEBUG,"nr_socket_proxy_tunnel_close");
-
-  if (sock->resolver_handle) {
-    nr_resolver_cancel(sock->config->resolver, sock->resolver_handle);
-    sock->resolver_handle = 0;
-  }
-
-  sock->state = PROXY_TUNNEL_CLOSED;
-
-  return nr_socket_close(sock->inner);
-}
-
-int nr_proxy_tunnel_config_create(nr_proxy_tunnel_config **configpp)
-{
-  int _status;
-  nr_proxy_tunnel_config *configp=0;
-
-  r_log(LOG_GENERIC,LOG_DEBUG,"nr_proxy_tunnel_config_create");
-
-  if (!(configp=RCALLOC(sizeof(nr_proxy_tunnel_config))))
-    ABORT(R_NO_MEMORY);
-
-  *configpp=configp;
-  _status=0;
-abort:
-  return(_status);
-}
-
-int nr_proxy_tunnel_config_destroy(nr_proxy_tunnel_config **configpp)
-{
-  nr_proxy_tunnel_config *configp;
-
-  r_log(LOG_GENERIC,LOG_DEBUG,"nr_proxy_tunnel_config_destroy");
-
-  if (!configpp || !*configpp)
-    return 0;
-
-  configp = *configpp;
-  *configpp = 0;
-
-  RFREE(configp->proxy_host);
-  RFREE(configp->alpn);
-  RFREE(configp);
-
-  return 0;
-}
-
-int nr_proxy_tunnel_config_set_proxy(nr_proxy_tunnel_config *config,
-                                     const char *host, UINT2 port)
-{
-  char *hostdup;
-
-  r_log(LOG_GENERIC,LOG_DEBUG,"nr_proxy_tunnel_config_set_proxy %s %d", host, port);
-
-  if (!host) {
-    return R_BAD_ARGS;
-  }
-
-  if (!(hostdup = r_strdup(host))) {
-    return R_NO_MEMORY;
-  }
-
-  if (config->proxy_host) {
-    RFREE(config->proxy_host);
-  }
-
-  config->proxy_host = hostdup;
-  config->proxy_port = port;
-
-  return 0;
-}
-
-int nr_proxy_tunnel_config_set_resolver(nr_proxy_tunnel_config *config,
-                                        nr_resolver *resolver)
-{
-  r_log(LOG_GENERIC,LOG_DEBUG,"nr_proxy_tunnel_config_set_resolver");
-
-  config->resolver = resolver;
-
-  return 0;
-}
-
-int nr_proxy_tunnel_config_set_alpn(nr_proxy_tunnel_config *config,
-                                    const char *alpn)
-{
-  r_log(LOG_GENERIC,LOG_DEBUG,"nr_proxy_tunnel_config_set_alpn");
-
-  if (alpn && (strlen(alpn) > MAX_ALPN_LENGTH)) {
-    return R_BAD_ARGS;
-  }
-
-  if (config->alpn) {
-    RFREE(config->alpn);
-  }
-
-  config->alpn = NULL;
-
-  if (alpn) {
-    char *alpndup = r_strdup(alpn);
-
-    if (!alpndup) {
-      return R_NO_MEMORY;
-    }
-
-    config->alpn = alpndup;
-  }
-
-  return 0;
-}
-
-int nr_proxy_tunnel_config_copy(nr_proxy_tunnel_config *config, nr_proxy_tunnel_config **copypp)
-{
-  int r,_status;
-  nr_proxy_tunnel_config *copy = 0;
-
-  if ((r=nr_proxy_tunnel_config_create(&copy)))
-    ABORT(r);
-
-  if ((r=nr_proxy_tunnel_config_set_proxy(copy, config->proxy_host, config->proxy_port)))
-    ABORT(r);
-
-  if ((r=nr_proxy_tunnel_config_set_resolver(copy, config->resolver)))
-    ABORT(r);
-
-  if ((r=nr_proxy_tunnel_config_set_alpn(copy, config->alpn)))
-    ABORT(r);
-
-  *copypp = copy;
-
-  _status=0;
-abort:
-  if (_status) {
-    nr_proxy_tunnel_config_destroy(&copy);
-  }
-  return(_status);
-}
-
-
-int nr_socket_proxy_tunnel_create(nr_proxy_tunnel_config *config,
-                                  nr_socket *inner,
-                                  nr_socket **socketpp)
-{
-  int r, _status;
-  nr_socket_proxy_tunnel *sock=0;
-  void *sockv;
-
-  r_log(LOG_GENERIC,LOG_DEBUG,"nr_socket_proxy_tunnel_create");
-
-  if (!config) {
-    ABORT(R_BAD_ARGS);
-  }
-
-  if (!(sock=RCALLOC(sizeof(nr_socket_proxy_tunnel)))) {
-    ABORT(R_NO_MEMORY);
-  }
-
-  sock->inner = inner;
-
-  if ((r=nr_proxy_tunnel_config_copy(config, &sock->config)))
-    ABORT(r);
-
-  if ((r=nr_socket_create_int(sock, &nr_socket_proxy_tunnel_vtbl, socketpp))) {
-    ABORT(r);
-  }
-
-  r_log(LOG_GENERIC,LOG_DEBUG,"nr_socket_proxy_tunnel_created");
-
-  _status=0;
-abort:
-  if (_status) {
-    sockv = sock;
-    nr_socket_proxy_tunnel_destroy(&sockv);
-  }
-  return(_status);
-}
-
-int nr_socket_wrapper_factory_proxy_tunnel_wrap(void *obj,
-                                                nr_socket *inner,
-                                                nr_socket **socketpp)
-{
-  nr_socket_wrapper_factory_proxy_tunnel *wrapper = (nr_socket_wrapper_factory_proxy_tunnel *)obj;
-
-  r_log(LOG_GENERIC,LOG_DEBUG,"nr_socket_wrapper_factory_proxy_tunnel_wrap");
-
-  return nr_socket_proxy_tunnel_create(wrapper->config, inner, socketpp);
-}
-
-
-int nr_socket_wrapper_factory_proxy_tunnel_destroy(void **objpp) {
-  nr_socket_wrapper_factory_proxy_tunnel *wrapper;
-
-  r_log(LOG_GENERIC,LOG_DEBUG,"nr_socket_wrapper_factory_proxy_tunnel_destroy");
-
-  if (!objpp || !*objpp)
-    return 0;
-
-  wrapper = (nr_socket_wrapper_factory_proxy_tunnel *)*objpp;
-  *objpp = 0;
-
-  nr_proxy_tunnel_config_destroy(&wrapper->config);
-  RFREE(wrapper);
-
-  return 0;
-}
-
-static nr_socket_wrapper_factory_vtbl proxy_tunnel_wrapper_vtbl = {
-  nr_socket_wrapper_factory_proxy_tunnel_wrap,
-  nr_socket_wrapper_factory_proxy_tunnel_destroy
-};
-
-int nr_socket_wrapper_factory_proxy_tunnel_create(nr_proxy_tunnel_config *config,
-                                                  nr_socket_wrapper_factory **factory) {
-  int r,_status;
-  nr_socket_wrapper_factory_proxy_tunnel *wrapper=0;
-  void *wrapperv;
-
-  r_log(LOG_GENERIC,LOG_DEBUG,"nr_socket_wrapper_factory_proxy_tunnel_create");
-
-  if (!(wrapper=RCALLOC(sizeof(nr_socket_wrapper_factory_proxy_tunnel))))
-    ABORT(R_NO_MEMORY);
-
-  if ((r=nr_proxy_tunnel_config_copy(config, &wrapper->config)))
-    ABORT(r);
-
-  if ((r=nr_socket_wrapper_factory_create_int(wrapper, &proxy_tunnel_wrapper_vtbl, factory)))
-    ABORT(r);
-
-  _status=0;
-abort:
-  if (_status) {
-    wrapperv = wrapper;
-    nr_socket_wrapper_factory_proxy_tunnel_destroy(&wrapperv);
-  }
-  return(_status);
-}
deleted file mode 100644
--- a/media/mtransport/third_party/nICEr/src/net/nr_proxy_tunnel.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
-Copyright (c) 2007, Adobe Systems, Incorporated
-Copyright (c) 2013, Mozilla
-
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
-* Redistributions of source code must retain the above copyright
-  notice, this list of conditions and the following disclaimer.
-
-* Redistributions in binary form must reproduce the above copyright
-  notice, this list of conditions and the following disclaimer in the
-  documentation and/or other materials provided with the distribution.
-
-* Neither the name of Adobe Systems, Network Resonance, Mozilla nor
-  the names of its contributors may be used to endorse or promote
-  products derived from this software without specific prior written
-  permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#ifndef _nr_proxy_tunnel_h
-#define _nr_proxy_tunnel_h
-
-#include "nr_socket.h"
-#include "nr_resolver.h"
-#include "nr_socket_wrapper.h"
-
-typedef struct nr_proxy_tunnel_config_ {
-  nr_resolver *resolver;
-  char *proxy_host;
-  UINT2 proxy_port;
-  char *alpn;
-} nr_proxy_tunnel_config;
-
-int nr_proxy_tunnel_config_create(nr_proxy_tunnel_config **config);
-
-int nr_proxy_tunnel_config_destroy(nr_proxy_tunnel_config **config);
-
-int nr_proxy_tunnel_config_set_proxy(nr_proxy_tunnel_config *config,
-                                     const char* host, UINT2 port);
-
-int nr_proxy_tunnel_config_set_resolver(nr_proxy_tunnel_config *config,
-                                        nr_resolver *resolver);
-
-int nr_proxy_tunnel_config_set_alpn(nr_proxy_tunnel_config *config,
-                                    const char *alpn);
-
-int nr_socket_proxy_tunnel_create(nr_proxy_tunnel_config *config,
-                                  nr_socket *inner,
-                                  nr_socket **socketpp);
-
-int nr_socket_wrapper_factory_proxy_tunnel_create(nr_proxy_tunnel_config *config,
-                                                  nr_socket_wrapper_factory **factory);
-
-#endif
new file mode 100644
--- /dev/null
+++ b/media/webrtc/gn-configs/arm64_False_arm64_linux.json
@@ -0,0 +1,16270 @@
+{
+    "gn_gen_args": {
+        "host_cpu": "arm64",
+        "is_debug": false,
+        "target_cpu": "arm64",
+        "target_os": "linux"
+    },
+    "mozbuild_args": {
+        "CPU_ARCH": "aarch64",
+        "HOST_CPU_ARCH": "aarch64",
+        "MOZ_DEBUG": null,
+        "OS_TARGET": "Linux"
+    },
+    "sandbox_vars": {
+        "COMPILE_FLAGS": {
+            "WARNINGS_AS_ERRORS": []
+        },
+        "FINAL_LIBRARY": "webrtc"
+    },
+    "targets": {
+        "//:webrtc": {
+            "cflags": [
+                "-fno-strict-aliasing",
+                "--param=ssp-buffer-size=4",
+                "-fstack-protector",
+                "-Wno-builtin-macro-redefined",
+                "-D__DATE__=",
+                "-D__TIME__=",
+                "-D__TIMESTAMP__=",
+                "-funwind-tables",
+                "-fPIC",
+                "-pipe",
+                "-fcolor-diagnostics",
+                "--target=aarch64-linux-gnu",
+                "-pthread",
+                "-Wall",
+                "-Werror",
+                "-Wextra",
+                "-Wno-missing-field-initializers",
+                "-Wno-unused-parameter",
+                "-Wno-c++11-narrowing",
+                "-Wno-covered-switch-default",
+                "-Wno-unneeded-internal-declaration",
+                "-Wno-inconsistent-missing-override",
+                "-Wno-undefined-var-template",
+                "-Wno-nonportable-include-path",
+                "-Wno-address-of-packed-member",
+                "-Wno-unused-lambda-capture",
+                "-Wno-user-defined-warnings",
+                "-O2",
+                "-fno-ident",
+                "-fdata-sections",
+                "-ffunction-sections",
+                "-fno-omit-frame-pointer",
+                "-g0",
+                "-fvisibility=hidden",
+                "-Xclang",
+                "-load",
+                "-Xclang",
+                "../../../../../../media/webrtc/trunk/webrtc/third_party/llvm-build/Release+Asserts/lib/libFindBadConstructs.so",
+                "-Xclang",
+                "-add-plugin",
+                "-Xclang",
+                "find-bad-constructs",
+                "-Xclang",
+                "-plugin-arg-find-bad-constructs",
+                "-Xclang",
+                "check-auto-raw-pointer",
+                "-Xclang",
+                "-plugin-arg-find-bad-constructs",
+                "-Xclang",
+                "check-ipc",
+                "-Wheader-hygiene",
+                "-Wstring-conversion",
+                "-Wtautological-overlap-compare",
+                "-Wextra",
+                "-Wno-unused-parameter",
+                "-Wno-missing-field-initializers",
+                "-Wno-strict-overflow",
+                "-Wc++11-narrowing",
+                "-Wimplicit-fallthrough",
+                "-Wthread-safety",
+                "-Winconsistent-missing-override",
+                "-Wundef",
+                "-Wunused-lambda-capture"
+            ],
+            "defines": [
+                "V8_DEPRECATION_WARNINGS",
+                "USE_NSS_CERTS=1",
+                "USE_X11=1",
+                "NO_TCMALLOC",
+                "DISABLE_NACL",
+                "CHROMIUM_BUILD",
+                "_FILE_OFFSET_BITS=64",
+                "NDEBUG",
+                "NVALGRIND",
+                "DYNAMIC_ANNOTATIONS_ENABLED=0",
+                "WEBRTC_ENABLE_PROTOBUF=0",
+                "WEBRTC_RESTRICT_LOGGING",
+                "WEBRTC_ARCH_ARM64",
+                "WEBRTC_HAS_NEON",
+                "WEBRTC_MOZILLA_BUILD",
+                "WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS=0",
+                "WEBRTC_POSIX",
+                "WEBRTC_LINUX",
+                "HAVE_WEBRTC_VIDEO",
+                "HAVE_WEBRTC_VOICE"
+            ],
+            "deps": [
+                "//:webrtc_common",
+                "//api:base_peerconnection_api",
+                "//api:transport_api",
+                "//api:video_frame_api",
+                "//audio:audio",
+                "//call:call",
+                "//common_audio:common_audio",
+                "//common_video:common_video",
+                "//media:media",
+                "//modules:modules",
+                "//modules/video_capture:video_capture_internal_impl",
+                "//rtc_base:rtc_base",
+                "//system_wrappers:field_trial_default",
+                "//system_wrappers:metrics_default",
+                "//system_wrappers:system_wrappers_default",
+                "//video:video",
+                "//video_engine:video_engine",
+                "//voice_engine:voice_engine"
+            ],
+            "include_dirs": [
+                "//",
+                "/home/jenkins/workspace/Firefox-default/label/aarch64/firefox/obj-aarch64-unknown-linux-gnu/media/webrtc/trunk/webrtc/gn-output/gen/",
+                "//common_audio/resampler/include/",
+                "//common_audio/signal_processing/include/",
+                "//common_audio/vad/include/",
+                "//common_video/include/",
+                "/media/libyuv/libyuv/include/",
+                "//modules/audio_coding/include/",
+                "//modules/include/",
+                "//modules/include/",
+                "//modules/audio_device/include/",
+                "//modules/audio_device/dummy/"
+            ],
+            "libs": [
+                "rt",
+                "m",
+                "X11",
+                "X11-xcb",
+                "xcb",
+                "Xcomposite",
+                "Xcursor",
+                "Xdamage",
+                "Xext",
+                "Xfixes",
+                "Xi",
+                "Xrender"
+            ],
+            "sources": [],
+            "type": "static_library"
+        },
+        "//:webrtc_common": {
+            "cflags": [
+                "-fno-strict-aliasing",
+                "--param=ssp-buffer-size=4",
+                "-fstack-protector",
+                "-Wno-builtin-macro-redefined",
+                "-D__DATE__=",
+                "-D__TIME__=",
+                "-D__TIMESTAMP__=",
+                "-funwind-tables",
+                "-fPIC",
+                "-pipe",
+                "-fcolor-diagnostics",
+                "--target=aarch64-linux-gnu",
+                "-pthread",
+                "-Wall",
+                "-Werror",
+                "-Wextra",
+                "-Wno-missing-field-initializers",
+                "-Wno-unused-parameter",
+                "-Wno-c++11-narrowing",
+                "-Wno-covered-switch-default",
+                "-Wno-unneeded-internal-declaration",
+                "-Wno-inconsistent-missing-override",
+                "-Wno-undefined-var-template",
+                "-Wno-nonportable-include-path",
+                "-Wno-address-of-packed-member",
+                "-Wno-unused-lambda-capture",
+                "-Wno-user-defined-warnings",
+                "-O2",
+                "-fno-ident",
+                "-fdata-sections",
+                "-ffunction-sections",
+                "-fno-omit-frame-pointer",
+                "-g0",
+                "-fvisibility=hidden",
+                "-Wheader-hygiene",
+                "-Wstring-conversion",
+                "-Wtautological-overlap-compare",
+                "-Wextra",
+                "-Wno-unused-parameter",
+                "-Wno-missing-field-initializers",
+                "-Wno-strict-overflow",
+                "-Wc++11-narrowing",
+                "-Wimplicit-fallthrough",
+                "-Wthread-safety",
+                "-Winconsistent-missing-override",
+                "-Wundef",
+                "-Wunused-lambda-capture"
+            ],
+            "defines": [
+                "V8_DEPRECATION_WARNINGS",
+                "USE_NSS_CERTS=1",
+                "USE_X11=1",
+                "NO_TCMALLOC",
+                "DISABLE_NACL",
+                "CHROMIUM_BUILD",
+                "_FILE_OFFSET_BITS=64",
+                "NDEBUG",
+                "NVALGRIND",
+                "DYNAMIC_ANNOTATIONS_ENABLED=0",
+                "WEBRTC_ENABLE_PROTOBUF=0",
+                "WEBRTC_RESTRICT_LOGGING",
+                "WEBRTC_ARCH_ARM64",
+                "WEBRTC_HAS_NEON",
+                "WEBRTC_MOZILLA_BUILD",
+                "WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS=0",
+                "WEBRTC_POSIX",
+                "WEBRTC_LINUX"
+            ],
+            "deps": [],
+            "include_dirs": [
+                "//",
+                "/home/jenkins/workspace/Firefox-default/label/aarch64/firefox/obj-aarch64-unknown-linux-gnu/media/webrtc/trunk/webrtc/gn-output/gen/"
+            ],
+            "libs": [],
+            "sources": [
+                "//common_types.cc",
+                "//common_types.h",
+                "//typedefs.h"
+            ],
+            "type": "static_library"
+        },
+        "//api/audio_codecs/L16:audio_decoder_L16": {
+            "cflags": [
+                "-fno-strict-aliasing",
+                "--param=ssp-buffer-size=4",
+                "-fstack-protector",
+                "-Wno-builtin-macro-redefined",
+                "-D__DATE__=",
+                "-D__TIME__=",
+                "-D__TIMESTAMP__=",
+                "-funwind-tables",
+                "-fPIC",
+                "-pipe",
+                "-fcolor-diagnostics",
+                "--target=aarch64-linux-gnu",
+                "-pthread",
+                "-Wall",
+                "-Werror",
+                "-Wextra",
+                "-Wno-missing-field-initializers",
+                "-Wno-unused-parameter",
+                "-Wno-c++11-narrowing",
+                "-Wno-covered-switch-default",
+                "-Wno-unneeded-internal-declaration",
+                "-Wno-inconsistent-missing-override",
+                "-Wno-undefined-var-template",
+                "-Wno-nonportable-include-path",
+                "-Wno-address-of-packed-member",
+                "-Wno-unused-lambda-capture",
+                "-Wno-user-defined-warnings",
+                "-O2",
+                "-fno-ident",
+                "-fdata-sections",
+                "-ffunction-sections",
+                "-fno-omit-frame-pointer",
+                "-g0",
+                "-fvisibility=hidden",
+                "-Xclang",
+                "-load",
+                "-Xclang",
+                "../../../../../../media/webrtc/trunk/webrtc/third_party/llvm-build/Release+Asserts/lib/libFindBadConstructs.so",
+                "-Xclang",
+                "-add-plugin",
+                "-Xclang",
+                "find-bad-constructs",
+                "-Xclang",
+                "-plugin-arg-find-bad-constructs",
+                "-Xclang",
+                "check-auto-raw-pointer",
+                "-Xclang",
+                "-plugin-arg-find-bad-constructs",
+                "-Xclang",
+                "check-ipc",
+                "-Wheader-hygiene",
+                "-Wstring-conversion",
+                "-Wtautological-overlap-compare",
+                "-Wextra",
+                "-Wno-unused-parameter",
+                "-Wno-missing-field-initializers",
+                "-Wno-strict-overflow",
+                "-Wc++11-narrowing",
+                "-Wimplicit-fallthrough",
+                "-Wthread-safety",
+                "-Winconsistent-missing-override",
+                "-Wundef",
+                "-Wunused-lambda-capture"
+            ],
+            "defines": [
+                "V8_DEPRECATION_WARNINGS",
+                "USE_NSS_CERTS=1",
+                "USE_X11=1",
+                "NO_TCMALLOC",
+                "DISABLE_NACL",
+                "CHROMIUM_BUILD",
+                "_FILE_OFFSET_BITS=64",
+                "NDEBUG",
+                "NVALGRIND",
+                "DYNAMIC_ANNOTATIONS_ENABLED=0",
+                "WEBRTC_ENABLE_PROTOBUF=0",
+                "WEBRTC_RESTRICT_LOGGING",
+                "WEBRTC_ARCH_ARM64",
+                "WEBRTC_HAS_NEON",
+                "WEBRTC_MOZILLA_BUILD",
+                "WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS=0",
+                "WEBRTC_POSIX",
+                "WEBRTC_LINUX"
+            ],
+            "deps": [
+                "//:webrtc_common",
+                "//api:optional",
+                "//api/audio_codecs:audio_codecs_api",
+                "//modules/audio_coding:pcm16b",
+                "//rtc_base:rtc_base_approved"
+            ],
+            "include_dirs": [
+                "//",
+                "/home/jenkins/workspace/Firefox-default/label/aarch64/firefox/obj-aarch64-unknown-linux-gnu/media/webrtc/trunk/webrtc/gn-output/gen/",
+                "//modules/audio_coding/codecs/pcm16b/include/"
+            ],
+            "libs": [],
+            "sources": [
+                "//api/audio_codecs/L16/audio_decoder_L16.cc",
+                "//api/audio_codecs/L16/audio_decoder_L16.h"
+            ],
+            "type": "static_library"
+        },
+        "//api/audio_codecs/L16:audio_encoder_L16": {
+            "cflags": [
+                "-fno-strict-aliasing",
+                "--param=ssp-buffer-size=4",
+                "-fstack-protector",
+                "-Wno-builtin-macro-redefined",
+                "-D__DATE__=",
+                "-D__TIME__=",
+                "-D__TIMESTAMP__=",
+                "-funwind-tables",
+                "-fPIC",
+                "-pipe",
+                "-fcolor-diagnostics",
+                "--target=aarch64-linux-gnu",
+                "-pthread",
+                "-Wall",
+                "-Werror",
+                "-Wextra",
+                "-Wno-missing-field-initializers",
+                "-Wno-unused-parameter",
+                "-Wno-c++11-narrowing",
+                "-Wno-covered-switch-default",
+                "-Wno-unneeded-internal-declaration",
+                "-Wno-inconsistent-missing-override",
+                "-Wno-undefined-var-template",
+                "-Wno-nonportable-include-path",
+                "-Wno-address-of-packed-member",
+                "-Wno-unused-lambda-capture",
+                "-Wno-user-defined-warnings",
+                "-O2",
+                "-fno-ident",
+                "-fdata-sections",
+                "-ffunction-sections",
+                "-fno-omit-frame-pointer",
+                "-g0",
+                "-fvisibility=hidden",
+                "-Xclang",
+                "-load",
+                "-Xclang",
+                "../../../../../../media/webrtc/trunk/webrtc/third_party/llvm-build/Release+Asserts/lib/libFindBadConstructs.so",
+                "-Xclang",
+                "-add-plugin",
+                "-Xclang",
+                "find-bad-constructs",
+                "-Xclang",
+                "-plugin-arg-find-bad-constructs",
+                "-Xclang",
+                "check-auto-raw-pointer",
+                "-Xclang",
+                "-plugin-arg-find-bad-constructs",
+                "-Xclang",
+                "check-ipc",
+                "-Wheader-hygiene",
+                "-Wstring-conversion",
+                "-Wtautological-overlap-compare",
+                "-Wextra",
+                "-Wno-unused-parameter",
+                "-Wno-missing-field-initializers",
+                "-Wno-strict-overflow",
+                "-Wc++11-narrowing",
+                "-Wimplicit-fallthrough",
+                "-Wthread-safety",
+                "-Winconsistent-missing-override",
+                "-Wundef",
+                "-Wunused-lambda-capture"
+            ],
+            "defines": [
+                "V8_DEPRECATION_WARNINGS",
+                "USE_NSS_CERTS=1",
+                "USE_X11=1",
+                "NO_TCMALLOC",
+                "DISABLE_NACL",
+                "CHROMIUM_BUILD",
+                "_FILE_OFFSET_BITS=64",
+                "NDEBUG",
+                "NVALGRIND",
+                "DYNAMIC_ANNOTATIONS_ENABLED=0",
+                "WEBRTC_ENABLE_PROTOBUF=0",
+                "WEBRTC_RESTRICT_LOGGING",
+                "WEBRTC_ARCH_ARM64",
+                "WEBRTC_HAS_NEON",
+                "WEBRTC_MOZILLA_BUILD",
+                "WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS=0",
+                "WEBRTC_POSIX",
+                "WEBRTC_LINUX"
+            ],
+            "deps": [
+                "//:webrtc_common",
+                "//api:optional",
+                "//api/audio_codecs:audio_codecs_api",
+                "//modules/audio_coding:pcm16b",
+                "//rtc_base:rtc_base_approved"
+            ],
+            "include_dirs": [
+                "//",
+                "/home/jenkins/workspace/Firefox-default/label/aarch64/firefox/obj-aarch64-unknown-linux-gnu/media/webrtc/trunk/webrtc/gn-output/gen/",
+                "//modules/audio_coding/codecs/pcm16b/include/"
+            ],
+            "libs": [],
+            "sources": [
+                "//api/audio_codecs/L16/audio_encoder_L16.cc",
+                "//api/audio_codecs/L16/audio_encoder_L16.h"
+            ],
+            "type": "static_library"
+        },
+        "//api/audio_codecs/g711:audio_decoder_g711": {
+            "cflags": [
+                "-fno-strict-aliasing",
+                "--param=ssp-buffer-size=4",
+                "-fstack-protector",
+                "-Wno-builtin-macro-redefined",
+                "-D__DATE__=",
+                "-D__TIME__=",
+                "-D__TIMESTAMP__=",
+                "-funwind-tables",
+                "-fPIC",
+                "-pipe",
+                "-fcolor-diagnostics",
+                "--target=aarch64-linux-gnu",
+                "-pthread",
+                "-Wall",
+                "-Werror",
+                "-Wextra",
+                "-Wno-missing-field-initializers",
+                "-Wno-unused-parameter",
+                "-Wno-c++11-narrowing",
+                "-Wno-covered-switch-default",
+                "-Wno-unneeded-internal-declaration",
+                "-Wno-inconsistent-missing-override",
+                "-Wno-undefined-var-template",
+                "-Wno-nonportable-include-path",
+                "-Wno-address-of-packed-member",
+                "-Wno-unused-lambda-capture",
+                "-Wno-user-defined-warnings",
+                "-O2",
+                "-fno-ident",
+                "-fdata-sections",
+                "-ffunction-sections",
+                "-fno-omit-frame-pointer",
+                "-g0",
+                "-fvisibility=hidden",
+                "-Xclang",
+                "-load",
+                "-Xclang",
+                "../../../../../../media/webrtc/trunk/webrtc/third_party/llvm-build/Release+Asserts/lib/libFindBadConstructs.so",
+                "-Xclang",
+                "-add-plugin",
+                "-Xclang",
+                "find-bad-constructs",
+                "-Xclang",
+                "-plugin-arg-find-bad-constructs",
+                "-Xclang",
+                "check-auto-raw-pointer",
+                "-Xclang",
+                "-plugin-arg-find-bad-constructs",
+                "-Xclang",
+                "check-ipc",
+                "-Wheader-hygiene",
+                "-Wstring-conversion",
+                "-Wtautological-overlap-compare",
+                "-Wextra",
+                "-Wno-unused-parameter",
+                "-Wno-missing-field-initializers",
+                "-Wno-strict-overflow",
+                "-Wc++11-narrowing",
+                "-Wimplicit-fallthrough",
+                "-Wthread-safety",
+                "-Winconsistent-missing-override",
+                "-Wundef",
+                "-Wunused-lambda-capture"
+            ],
+            "defines": [
+                "V8_DEPRECATION_WARNINGS",
+                "USE_NSS_CERTS=1",
+                "USE_X11=1",
+                "NO_TCMALLOC",
+                "DISABLE_NACL",
+                "CHROMIUM_BUILD",
+                "_FILE_OFFSET_BITS=64",
+                "NDEBUG",
+                "NVALGRIND",
+                "DYNAMIC_ANNOTATIONS_ENABLED=0",
+                "WEBRTC_ENABLE_PROTOBUF=0",
+                "WEBRTC_RESTRICT_LOGGING",
+                "WEBRTC_ARCH_ARM64",
+                "WEBRTC_HAS_NEON",
+                "WEBRTC_MOZILLA_BUILD",
+                "WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS=0",
+                "WEBRTC_POSIX",
+                "WEBRTC_LINUX"
+            ],
+            "deps": [
+                "//:webrtc_common",
+                "//api:optional",
+                "//api/audio_codecs:audio_codecs_api",
+                "//modules/audio_coding:g711",
+                "//rtc_base:rtc_base_approved"
+            ],
+            "include_dirs": [
+                "//",
+                "/home/jenkins/workspace/Firefox-default/label/aarch64/firefox/obj-aarch64-unknown-linux-gnu/media/webrtc/trunk/webrtc/gn-output/gen/",
+                "//modules/audio_coding/codecs/g711/include/"
+            ],
+            "libs": [],
+            "sources": [
+                "//api/audio_codecs/g711/audio_decoder_g711.cc",
+                "//api/audio_codecs/g711/audio_decoder_g711.h"
+            ],
+            "type": "static_library"
+        },
+        "//api/audio_codecs/g711:audio_encoder_g711": {
+            "cflags": [
+                "-fno-strict-aliasing",
+                "--param=ssp-buffer-size=4",
+                "-fstack-protector",
+                "-Wno-builtin-macro-redefined",
+                "-D__DATE__=",
+                "-D__TIME__=",
+                "-D__TIMESTAMP__=",
+                "-funwind-tables",
+                "-fPIC",
+                "-pipe",
+                "-fcolor-diagnostics",
+                "--target=aarch64-linux-gnu",
+                "-pthread",
+                "-Wall",
+                "-Werror",
+                "-Wextra",
+                "-Wno-missing-field-initializers",
+                "-Wno-unused-parameter",
+                "-Wno-c++11-narrowing",
+                "-Wno-covered-switch-default",
+                "-Wno-unneeded-internal-declaration",
+                "-Wno-inconsistent-missing-override",
+                "-Wno-undefined-var-template",
+                "-Wno-nonportable-include-path",
+                "-Wno-address-of-packed-member",
+                "-Wno-unused-lambda-capture",
+                "-Wno-user-defined-warnings",
+                "-O2",
+                "-fno-ident",
+                "-fdata-sections",
+                "-ffunction-sections",
+                "-fno-omit-frame-pointer",
+                "-g0",
+                "-fvisibility=hidden",
+                "-Xclang",
+                "-load",
+                "-Xclang",
+                "../../../../../../media/webrtc/trunk/webrtc/third_party/llvm-build/Release+Asserts/lib/libFindBadConstructs.so",
+                "-Xclang",
+                "-add-plugin",
+                "-Xclang",
+                "find-bad-constructs",
+                "-Xclang",
+                "-plugin-arg-find-bad-constructs",
+                "-Xclang",
+                "check-auto-raw-pointer",
+                "-Xclang",
+                "-plugin-arg-find-bad-constructs",
+                "-Xclang",
+                "check-ipc",
+                "-Wheader-hygiene",
+                "-Wstring-conversion",
+                "-Wtautological-overlap-compare",
+                "-Wextra",
+                "-Wno-unused-parameter",
+                "-Wno-missing-field-initializers",
+                "-Wno-strict-overflow",
+                "-Wc++11-narrowing",
+                "-Wimplicit-fallthrough",
+                "-Wthread-safety",
+                "-Winconsistent-missing-override",
+                "-Wundef",
+                "-Wunused-lambda-capture"
+            ],
+            "defines": [
+                "V8_DEPRECATION_WARNINGS",
+                "USE_NSS_CERTS=1",
+                "USE_X11=1",
+                "NO_TCMALLOC",
+                "DISABLE_NACL",
+                "CHROMIUM_BUILD",
+                "_FILE_OFFSET_BITS=64",
+                "NDEBUG",
+                "NVALGRIND",
+                "DYNAMIC_ANNOTATIONS_ENABLED=0",
+                "WEBRTC_ENABLE_PROTOBUF=0",
+                "WEBRTC_RESTRICT_LOGGING",
+                "WEBRTC_ARCH_ARM64",
+                "WEBRTC_HAS_NEON",
+                "WEBRTC_MOZILLA_BUILD",
+                "WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS=0",
+                "WEBRTC_POSIX",
+                "WEBRTC_LINUX"
+            ],
+            "deps": [
+                "//:webrtc_common",
+                "//api:optional",
+                "//api/audio_codecs:audio_codecs_api",
+                "//modules/audio_coding:g711",
+                "//rtc_base:rtc_base_approved"
+            ],
+            "include_dirs": [
+                "//",
+                "/home/jenkins/workspace/Firefox-default/label/aarch64/firefox/obj-aarch64-unknown-linux-gnu/media/webrtc/trunk/webrtc/gn-output/gen/",
+                "//modules/audio_coding/codecs/g711/include/"
+            ],
+            "libs": [],
+            "sources": [
+                "//api/audio_codecs/g711/audio_encoder_g711.cc",
+                "//api/audio_codecs/g711/audio_encoder_g711.h"
+            ],
+            "type": "static_library"
+        },
+        "//api/audio_codecs/g722:audio_decoder_g722": {
+            "cflags": [
+                "-fno-strict-aliasing",
+                "--param=ssp-buffer-size=4",
+                "-fstack-protector",
+                "-Wno-builtin-macro-redefined",
+                "-D__DATE__=",
+                "-D__TIME__=",
+                "-D__TIMESTAMP__=",
+                "-funwind-tables",
+                "-fPIC",
+                "-pipe",
+                "-fcolor-diagnostics",
+                "--target=aarch64-linux-gnu",
+                "-pthread",
+                "-Wall",
+                "-Werror",
+                "-Wextra",
+                "-Wno-missing-field-initializers",
+                "-Wno-unused-parameter",
+                "-Wno-c++11-narrowing",
+                "-Wno-covered-switch-default",
+                "-Wno-unneeded-internal-declaration",
+                "-Wno-inconsistent-missing-override",
+                "-Wno-undefined-var-template",
+                "-Wno-nonportable-include-path",
+                "-Wno-address-of-packed-member",
+                "-Wno-unused-lambda-capture",
+                "-Wno-user-defined-warnings",
+                "-O2",
+                "-fno-ident",
+                "-fdata-sections",
+                "-ffunction-sections",
+                "-fno-omit-frame-pointer",
+                "-g0",
+                "-fvisibility=hidden",
+                "-Xclang",
+                "-load",
+                "-Xclang",
+                "../../../../../../media/webrtc/trunk/webrtc/third_party/llvm-build/Release+Asserts/lib/libFindBadConstructs.so",
+                "-Xclang",
+                "-add-plugin",
+                "-Xclang",
+                "find-bad-constructs",
+                "-Xclang",
+                "-plugin-arg-find-bad-constructs",
+                "-Xclang",
+                "check-auto-raw-pointer",
+                "-Xclang",
+                "-plugin-arg-find-bad-constructs",
+                "-Xclang",
+                "check-ipc",
+                "-Wheader-hygiene",
+                "-Wstring-conversion",
+                "-Wtautological-overlap-compare",
+                "-Wextra",
+                "-Wno-unused-parameter",
+                "-Wno-missing-field-initializers",
+                "-Wno-strict-overflow",
+                "-Wc++11-narrowing",
+                "-Wimplicit-fallthrough",
+                "-Wthread-safety",
+                "-Winconsistent-missing-override",
+                "-Wundef",
+                "-Wunused-lambda-capture"
+            ],
+            "defines": [
+                "V8_DEPRECATION_WARNINGS",
+                "USE_NSS_CERTS=1",
+                "USE_X11=1",
+                "NO_TCMALLOC",
+                "DISABLE_NACL",
+                "CHROMIUM_BUILD",
+                "_FILE_OFFSET_BITS=64",
+                "NDEBUG",
+                "NVALGRIND",
+                "DYNAMIC_ANNOTATIONS_ENABLED=0",
+                "WEBRTC_ENABLE_PROTOBUF=0",
+                "WEBRTC_RESTRICT_LOGGING",
+                "WEBRTC_ARCH_ARM64",
+                "WEBRTC_HAS_NEON",
+                "WEBRTC_MOZILLA_BUILD",
+                "WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS=0",
+                "WEBRTC_POSIX",
+                "WEBRTC_LINUX"
+            ],
+            "deps": [
+                "//:webrtc_common",
+                "//api:optional",
+                "//api/audio_codecs:audio_codecs_api",
+                "//modules/audio_coding:g722",
+                "//rtc_base:rtc_base_approved"
+            ],
+            "include_dirs": [
+                "//",
+                "/home/jenkins/workspace/Firefox-default/label/aarch64/firefox/obj-aarch64-unknown-linux-gnu/media/webrtc/trunk/webrtc/gn-output/gen/",
+                "//modules/audio_coding/codecs/g722/include/"
+            ],
+            "libs": [],
+            "sources": [
+                "//api/audio_codecs/g722/audio_decoder_g722.cc",
+                "//api/audio_codecs/g722/audio_decoder_g722.h"
+            ],
+            "type": "static_library"
+        },
+        "//api/audio_codecs/g722:audio_encoder_g722": {
+            "cflags": [
+                "-fno-strict-aliasing",
+                "--param=ssp-buffer-size=4",
+                "-fstack-protector",
+                "-Wno-builtin-macro-redefined",
+                "-D__DATE__=",
+                "-D__TIME__=",
+                "-D__TIMESTAMP__=",
+                "-funwind-tables",
+                "-fPIC",
+                "-pipe",
+                "-fcolor-diagnostics",
+                "--target=aarch64-linux-gnu",
+                "-pthread",
+                "-Wall",
+                "-Werror",
+                "-Wextra",
+                "-Wno-missing-field-initializers",
+                "-Wno-unused-parameter",
+                "-Wno-c++11-narrowing",
+                "-Wno-covered-switch-default",
+                "-Wno-unneeded-internal-declaration",
+                "-Wno-inconsistent-missing-override",
+                "-Wno-undefined-var-template",
+                "-Wno-nonportable-include-path",
+                "-Wno-address-of-packed-member",
+                "-Wno-unused-lambda-capture",
+                "-Wno-user-defined-warnings",
+                "-O2",
+                "-fno-ident",
+                "-fdata-sections",
+                "-ffunction-sections",
+                "-fno-omit-frame-pointer",
+                "-g0",
+                "-fvisibility=hidden",
+                "-Xclang",
+                "-load",
+                "-Xclang",
+                "../../../../../../media/webrtc/trunk/webrtc/third_party/llvm-build/Release+Asserts/lib/libFindBadConstructs.so",
+                "-Xclang",
+                "-add-plugin",
+                "-Xclang",
+                "find-bad-constructs",
+                "-Xclang",
+                "-plugin-arg-find-bad-constructs",
+                "-Xclang",
+                "check-auto-raw-pointer",
+                "-Xclang",
+                "-plugin-arg-find-bad-constructs",
+                "-Xclang",
+                "check-ipc",
+                "-Wheader-hygiene",
+                "-Wstring-conversion",
+                "-Wtautological-overlap-compare",
+                "-Wextra",
+                "-Wno-unused-parameter",
+                "-Wno-missing-field-initializers",
+                "-Wno-strict-overflow",
+                "-Wc++11-narrowing",
+                "-Wimplicit-fallthrough",
+                "-Wthread-safety",
+                "-Winconsistent-missing-override",
+                "-Wundef",
+                "-Wunused-lambda-capture"
+            ],
+            "defines": [
+                "V8_DEPRECATION_WARNINGS",
+                "USE_NSS_CERTS=1",
+                "USE_X11=1",
+                "NO_TCMALLOC",
+                "DISABLE_NACL",
+                "CHROMIUM_BUILD",
+                "_FILE_OFFSET_BITS=64",
+                "NDEBUG",
+                "NVALGRIND",
+                "DYNAMIC_ANNOTATIONS_ENABLED=0",
+                "WEBRTC_ENABLE_PROTOBUF=0",
+                "WEBRTC_RESTRICT_LOGGING",
+                "WEBRTC_ARCH_ARM64",
+                "WEBRTC_HAS_NEON",
+                "WEBRTC_MOZILLA_BUILD",
+                "WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS=0",
+                "WEBRTC_POSIX",
+                "WEBRTC_LINUX"
+            ],
+            "deps": [
+                "//:webrtc_common",
+                "//api:optional",
+                "//api/audio_codecs:audio_codecs_api",
+                "//api/audio_codecs/g722:audio_encoder_g722_config",
+                "//modules/audio_coding:g722",
+                "//rtc_base:rtc_base_approved"
+            ],
+            "include_dirs": [
+                "//",
+                "/home/jenkins/workspace/Firefox-default/label/aarch64/firefox/obj-aarch64-unknown-linux-gnu/media/webrtc/trunk/webrtc/gn-output/gen/",
+                "//modules/audio_coding/codecs/g722/include/"
+            ],
+            "libs": [],
+            "sources": [
+                "//api/audio_codecs/g722/audio_encoder_g722.cc",
+                "//api/audio_codecs/g722/audio_encoder_g722.h"
+            ],
+            "type": "static_library"
+        },
+        "//api/audio_codecs/g722:audio_encoder_g722_config": {
+            "cflags": [
+                "-fno-strict-aliasing",
+                "--param=ssp-buffer-size=4",
+                "-fstack-protector",
+                "-Wno-builtin-macro-redefined",
+                "-D__DATE__=",
+                "-D__TIME__=",
+                "-D__TIMESTAMP__=",
+                "-funwind-tables",
+                "-fPIC",
+                "-pipe",
+                "-fcolor-diagnostics",
+                "--target=aarch64-linux-gnu",
+                "-pthread",
+                "-Wall",
+                "-Werror",
+                "-Wextra",
+                "-Wno-missing-field-initializers",
+                "-Wno-unused-parameter",
+                "-Wno-c++11-narrowing",
+                "-Wno-covered-switch-default",
+                "-Wno-unneeded-internal-declaration",
+                "-Wno-inconsistent-missing-override",
+                "-Wno-undefined-var-template",
+                "-Wno-nonportable-include-path",
+                "-Wno-address-of-packed-member",
+                "-Wno-unused-lambda-capture",
+                "-Wno-user-defined-warnings",
+                "-O2",
+                "-fno-ident",
+                "-fdata-sections",
+                "-ffunction-sections",
+                "-fno-omit-frame-pointer",
+                "-g0",
+                "-fvisibility=hidden",
+                "-Xclang",
+                "-load",
+                "-Xclang",
+                "../../../../../../media/webrtc/trunk/webrtc/third_party/llvm-build/Release+Asserts/lib/libFindBadConstructs.so",
+                "-Xclang",
+                "-add-plugin",
+                "-Xclang",
+                "find-bad-constructs",
+                "-Xclang",
+                "-plugin-arg-find-bad-constructs",
+                "-Xclang",
+                "check-auto-raw-pointer",
+                "-Xclang",
+                "-plugin-arg-find-bad-constructs",
+                "-Xclang",
+                "check-ipc",
+                "-Wheader-hygiene",
+                "-Wstring-conversion",
+                "-Wtautological-overlap-compare",
+                "-Wextra",
+                "-Wno-unused-parameter",
+                "-Wno-missing-field-initializers",
+                "-Wno-strict-overflow",
+                "-Wc++11-narrowing",
+                "-Wimplicit-fallthrough",
+                "-Wthread-safety",
+                "-Winconsistent-missing-override",
+                "-Wundef",
+                "-Wunused-lambda-capture"
+            ],
+            "defines": [
+                "V8_DEPRECATION_WARNINGS",
+                "USE_NSS_CERTS=1",
+                "USE_X11=1",
+                "NO_TCMALLOC",
+                "DISABLE_NACL",
+                "CHROMIUM_BUILD",
+                "_FILE_OFFSET_BITS=64",
+                "NDEBUG",
+                "NVALGRIND",
+                "DYNAMIC_ANNOTATIONS_ENABLED=0",
+                "WEBRTC_ENABLE_PROTOBUF=0",
+                "WEBRTC_RESTRICT_LOGGING",
+                "WEBRTC_ARCH_ARM64",
+                "WEBRTC_HAS_NEON",
+                "WEBRTC_MOZILLA_BUILD",
+                "WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS=0",
+                "WEBRTC_POSIX",
+                "WEBRTC_LINUX"
+            ],
+            "deps": [],
+            "include_dirs": [
+                "//",
+                "/home/jenkins/workspace/Firefox-default/label/aarch64/firefox/obj-aarch64-unknown-linux-gnu/media/webrtc/trunk/webrtc/gn-output/gen/"
+            ],
+            "libs": [],
+            "sources": [
+                "//api/audio_codecs/g722/audio_encoder_g722_config.h"
+            ],
+            "type": "source_set"
+        },
+        "//api/audio_codecs/ilbc:audio_decoder_ilbc": {
+            "cflags": [
+                "-fno-strict-aliasing",
+                "--param=ssp-buffer-size=4",
+                "-fstack-protector",
+                "-Wno-builtin-macro-redefined",
+                "-D__DATE__=",
+                "-D__TIME__=",
+                "-D__TIMESTAMP__=",
+                "-funwind-tables",
+                "-fPIC",
+                "-pipe",
+                "-fcolor-diagnostics",
+                "--target=aarch64-linux-gnu",
+                "-pthread",
+                "-Wall",
+                "-Werror",
+                "-Wextra",
+                "-Wno-missing-field-initializers",
+                "-Wno-unused-parameter",
+                "-Wno-c++11-narrowing",
+                "-Wno-covered-switch-default",
+                "-Wno-unneeded-internal-declaration",
+                "-Wno-inconsistent-missing-override",
+                "-Wno-undefined-var-template",
+                "-Wno-nonportable-include-path",
+                "-Wno-address-of-packed-member",
+                "-Wno-unused-lambda-capture",
+                "-Wno-user-defined-warnings",
+                "-O2",
+                "-fno-ident",
+                "-fdata-sections",
+                "-ffunction-sections",
+                "-fno-omit-frame-pointer",
+                "-g0",
+                "-fvisibility=hidden",
+                "-Xclang",
+                "-load",
+                "-Xclang",
+                "../../../../../../media/webrtc/trunk/webrtc/third_party/llvm-build/Release+Asserts/lib/libFindBadConstructs.so",
+                "-Xclang",
+                "-add-plugin",
+                "-Xclang",
+                "find-bad-constructs",
+                "-Xclang",
+                "-plugin-arg-find-bad-constructs",
+                "-Xclang",
+                "check-auto-raw-pointer",
+                "-Xclang",
+                "-plugin-arg-find-bad-constructs",
+                "-Xclang",
+                "check-ipc",
+                "-Wheader-hygiene",
+                "-Wstring-conversion",
+                "-Wtautological-overlap-compare",
+                "-Wextra",
+                "-Wno-unused-parameter",
+                "-Wno-missing-field-initializers",
+                "-Wno-strict-overflow",
+                "-Wc++11-narrowing",
+                "-Wimplicit-fallthrough",
+                "-Wthread-safety",
+                "-Winconsistent-missing-override",
+                "-Wundef",
+                "-Wunused-lambda-capture"
+            ],
+            "defines": [
+                "V8_DEPRECATION_WARNINGS",
+                "USE_NSS_CERTS=1",
+                "USE_X11=1",
+                "NO_TCMALLOC",
+                "DISABLE_NACL",
+                "CHROMIUM_BUILD",
+                "_FILE_OFFSET_BITS=64",
+                "NDEBUG",
+                "NVALGRIND",
+                "DYNAMIC_ANNOTATIONS_ENABLED=0",
+                "WEBRTC_ENABLE_PROTOBUF=0",
+                "WEBRTC_RESTRICT_LOGGING",
+                "WEBRTC_ARCH_ARM64",
+                "WEBRTC_HAS_NEON",
+                "WEBRTC_MOZILLA_BUILD",
+                "WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS=0",
+                "WEBRTC_POSIX",
+                "WEBRTC_LINUX"
+            ],
+            "deps": [
+                "//:webrtc_common",
+                "//api:optional",
+                "//api/audio_codecs:audio_codecs_api",
+                "//modules/audio_coding:ilbc",
+                "//rtc_base:rtc_base_approved"
+            ],
+            "include_dirs": [
+                "//",
+                "/home/jenkins/workspace/Firefox-default/label/aarch64/firefox/obj-aarch64-unknown-linux-gnu/media/webrtc/trunk/webrtc/gn-output/gen/",
+                "//modules/audio_coding/codecs/ilbc/include/"
+            ],
+            "libs": [
+                "rt"
+            ],
+            "sources": [
+                "//api/audio_codecs/ilbc/audio_decoder_ilbc.cc",
+                "//api/audio_codecs/ilbc/audio_decoder_ilbc.h"
+            ],
+            "type": "static_library"
+        },
+        "//api/audio_codecs/ilbc:audio_encoder_ilbc": {
+            "cflags": [
+                "-fno-strict-aliasing",
+                "--param=ssp-buffer-size=4",
+                "-fstack-protector",
+                "-Wno-builtin-macro-redefined",
+                "-D__DATE__=",
+                "-D__TIME__=",
+                "-D__TIMESTAMP__=",
+                "-funwind-tables",
+                "-fPIC",
+                "-pipe",
+                "-fcolor-diagnostics",
+                "--target=aarch64-linux-gnu",
+                "-pthread",
+                "-Wall",
+                "-Werror",
+                "-Wextra",
+                "-Wno-missing-field-initializers",
+                "-Wno-unused-parameter",
+                "-Wno-c++11-narrowing",
+                "-Wno-covered-switch-default",
+                "-Wno-unneeded-internal-declaration",
+                "-Wno-inconsistent-missing-override",
+                "-Wno-undefined-var-template",
+                "-Wno-nonportable-include-path",
+                "-Wno-address-of-packed-member",
+                "-Wno-unused-lambda-capture",
+                "-Wno-user-defined-warnings",
+                "-O2",
+                "-fno-ident",
+                "-fdata-sections",
+                "-ffunction-sections",
+                "-fno-omit-frame-pointer",
+                "-g0",
+                "-fvisibility=hidden",
+                "-Xclang",
+                "-load",
+                "-Xclang",
+                "../../../../../../media/webrtc/trunk/webrtc/third_party/llvm-build/Release+Asserts/lib/libFindBadConstructs.so",
+                "-Xclang",
+                "-add-plugin",
+                "-Xclang",
+                "find-bad-constructs",
+                "-Xclang",
+                "-plugin-arg-find-bad-constructs",
+                "-Xclang",
+                "check-auto-raw-pointer",
+                "-Xclang",
+                "-plugin-arg-find-bad-constructs",
+                "-Xclang",
+                "check-ipc",
+                "-Wheader-hygiene",
+                "-Wstring-conversion",
+                "-Wtautological-overlap-compare",
+                "-Wextra",
+                "-Wno-unused-parameter",
+                "-Wno-missing-field-initializers",
+                "-Wno-strict-overflow",
+                "-Wc++11-narrowing",
+                "-Wimplicit-fallthrough",
+                "-Wthread-safety",
+                "-Winconsistent-missing-override",
+                "-Wundef",
+                "-Wunused-lambda-capture"
+            ],
+            "defines": [
+                "V8_DEPRECATION_WARNINGS",
+                "USE_NSS_CERTS=1",
+                "USE_X11=1",
+                "NO_TCMALLOC",
+                "DISABLE_NACL",
+                "CHROMIUM_BUILD",
+                "_FILE_OFFSET_BITS=64",
+                "NDEBUG",
+                "NVALGRIND",
+                "DYNAMIC_ANNOTATIONS_ENABLED=0",
+                "WEBRTC_ENABLE_PROTOBUF=0",
+                "WEBRTC_RESTRICT_LOGGING",
+                "WEBRTC_ARCH_ARM64",
+                "WEBRTC_HAS_NEON",
+                "WEBRTC_MOZILLA_BUILD",
+                "WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS=0",
+                "WEBRTC_POSIX",
+                "WEBRTC_LINUX"
+            ],
+            "deps": [
+                "//:webrtc_common",
+                "//api:optional",
+                "//api/audio_codecs:audio_codecs_api",
+                "//api/audio_codecs/ilbc:audio_encoder_ilbc_config",
+                "//modules/audio_coding:ilbc",
+                "//rtc_base:rtc_base_approved"
+            ],
+            "include_dirs": [
+                "//",
+                "/home/jenkins/workspace/Firefox-default/label/aarch64/firefox/obj-aarch64-unknown-linux-gnu/media/webrtc/trunk/webrtc/gn-output/gen/",
+                "//modules/audio_coding/codecs/ilbc/include/"
+            ],
+            "libs": [
+                "rt"
+            ],
+            "sources": [
+                "//api/audio_codecs/ilbc/audio_encoder_ilbc.cc",
+                "//api/audio_codecs/ilbc/audio_encoder_ilbc.h"
+            ],
+            "type": "static_library"
+        },
+        "//api/audio_codecs/ilbc:audio_encoder_ilbc_config": {
+            "cflags": [
+                "-fno-strict-aliasing",
+                "--param=ssp-buffer-size=4",
+                "-fstack-protector",
+                "-Wno-builtin-macro-redefined",
+                "-D__DATE__=",
+                "-D__TIME__=",
+                "-D__TIMESTAMP__=",
+                "-funwind-tables",
+                "-fPIC",
+                "-pipe",
+                "-fcolor-diagnostics",
+                "--target=aarch64-linux-gnu",
+                "-pthread",
+                "-Wall",
+                "-Werror",
+                "-Wextra",
+                "-Wno-missing-field-initializers",
+                "-Wno-unused-parameter",
+                "-Wno-c++11-narrowing",
+                "-Wno-covered-switch-default",
+                "-Wno-unneeded-internal-declaration",
+                "-Wno-inconsistent-missing-override",
+                "-Wno-undefined-var-template",
+                "-Wno-nonportable-include-path",
+                "-Wno-address-of-packed-member",
+                "-Wno-unused-lambda-capture",
+                "-Wno-user-defined-warnings",
+                "-O2",
+                "-fno-ident",
+                "-fdata-sections",
+                "-ffunction-sections",
+                "-fno-omit-frame-pointer",
+                "-g0",
+                "-fvisibility=hidden",
+                "-Xclang",
+                "-load",
+                "-Xclang",
+                "../../../../../../media/webrtc/trunk/webrtc/third_party/llvm-build/Release+Asserts/lib/libFindBadConstructs.so",
+                "-Xclang",
+                "-add-plugin",
+                "-Xclang",
+                "find-bad-constructs",
+                "-Xclang",
+                "-plugin-arg-find-bad-constructs",
+                "-Xclang",
+                "check-auto-raw-pointer",
+                "-Xclang",
+                "-plugin-arg-find-bad-constructs",
+                "-Xclang",
+                "check-ipc",
+                "-Wheader-hygiene",
+                "-Wstring-conversion",
+                "-Wtautological-overlap-compare",
+                "-Wextra",
+                "-Wno-unused-parameter",
+                "-Wno-missing-field-initializers",
+                "-Wno-strict-overflow",
+                "-Wc++11-narrowing",
+                "-Wimplicit-fallthrough",
+                "-Wthread-safety",
+                "-Winconsistent-missing-override",
+                "-Wundef",
+                "-Wunused-lambda-capture"
+            ],
+            "defines": [
+                "V8_DEPRECATION_WARNINGS",
+                "USE_NSS_CERTS=1",
+                "USE_X11=1",
+                "NO_TCMALLOC",
+                "DISABLE_NACL",
+                "CHROMIUM_BUILD",
+                "_FILE_OFFSET_BITS=64",
+                "NDEBUG",
+                "NVALGRIND",
+                "DYNAMIC_ANNOTATIONS_ENABLED=0",
+                "WEBRTC_ENABLE_PROTOBUF=0",
+                "WEBRTC_RESTRICT_LOGGING",
+                "WEBRTC_ARCH_ARM64",
+                "WEBRTC_HAS_NEON",
+                "WEBRTC_MOZILLA_BUILD",
+                "WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS=0",
+                "WEBRTC_POSIX",
+                "WEBRTC_LINUX"
+            ],
+            "deps": [],
+            "include_dirs": [
+                "//",
+                "/home/jenkins/workspace/Firefox-default/label/aarch64/firefox/obj-aarch64-unknown-linux-gnu/media/webrtc/trunk/webrtc/gn-output/gen/"
+            ],
+            "libs": [],
+            "sources": [
+                "//api/audio_codecs/ilbc/audio_encoder_ilbc_config.h"
+            ],
+            "type": "source_set"
+        },
+        "//api/audio_codecs/isac:audio_decoder_isac": {
+            "cflags": [
+                "-fno-strict-aliasing",
+                "--param=ssp-buffer-size=4",
+                "-fstack-protector",
+                "-Wno-builtin-macro-redefined",
+                "-D__DATE__=",
+                "-D__TIME__=",
+                "-D__TIMESTAMP__=",
+                "-funwind-tables",
+                "-fPIC",
+                "-pipe",
+                "-fcolor-diagnostics",
+                "--target=aarch64-linux-gnu",
+                "-pthread",
+                "-Wall",
+                "-Werror",
+                "-Wextra",
+                "-Wno-missing-field-initializers",
+                "-Wno-unused-parameter",
+                "-Wno-c++11-narrowing",
+                "-Wno-covered-switch-default",
+                "-Wno-unneeded-internal-declaration",
+                "-Wno-inconsistent-missing-override",
+                "-Wno-undefined-var-template",
+                "-Wno-nonportable-include-path",
+                "-Wno-address-of-packed-member",
+                "-Wno-unused-lambda-capture",
+                "-Wno-user-defined-warnings",
+                "-O2",
+                "-fno-ident",
+                "-fdata-sections",
+                "-ffunction-sections",
+                "-fno-omit-frame-pointer",
+                "-g0",
+                "-fvisibility=hidden",
+                "-Xclang",
+                "-load",
+                "-Xclang",
+                "../../../../../../media/webrtc/trunk/webrtc/third_party/llvm-build/Release+Asserts/lib/libFindBadConstructs.so",
+                "-Xclang",
+                "-add-plugin",
+                "-Xclang",
+                "find-bad-constructs",
+                "-Xclang",
+                "-plugin-arg-find-bad-constructs",
+                "-Xclang",
+                "check-auto-raw-pointer",
+                "-Xclang",
+                "-plugin-arg-find-bad-constructs",
+                "-Xclang",
+                "check-ipc",
+                "-Wheader-hygiene",
+                "-Wstring-conversion",
+                "-Wtautological-overlap-compare",
+                "-Wextra",
+                "-Wno-unused-parameter",
+                "-Wno-missing-field-initializers",
+                "-Wno-strict-overflow",
+                "-Wc++11-narrowing",
+                "-Wimplicit-fallthrough",
+                "-Wthread-safety",
+                "-Winconsistent-missing-override",
+                "-Wundef",
+                "-Wunused-lambda-capture"
+            ],
+            "defines": [
+                "V8_DEPRECATION_WARNINGS",
+                "USE_NSS_CERTS=1",
+                "USE_X11=1",
+                "NO_TCMALLOC",
+                "DISABLE_NACL",
+                "CHROMIUM_BUILD",
+                "_FILE_OFFSET_BITS=64",
+                "NDEBUG",
+                "NVALGRIND",
+                "DYNAMIC_ANNOTATIONS_ENABLED=0",
+                "WEBRTC_ENABLE_PROTOBUF=0",
+                "WEBRTC_RESTRICT_LOGGING",
+                "WEBRTC_ARCH_ARM64",
+                "WEBRTC_HAS_NEON",
+                "WEBRTC_MOZILLA_BUILD",
+                "WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS=0",
+                "WEBRTC_POSIX",
+                "WEBRTC_LINUX",
+                "WEBRTC_USE_BUILTIN_ISAC_FIX=0",
+                "WEBRTC_USE_BUILTIN_ISAC_FLOAT=1"
+            ],
+            "deps": [
+                "//api/audio_codecs/isac:audio_decoder_isac_float"
+            ],
+            "include_dirs": [
+                "//",
+                "/home/jenkins/workspace/Firefox-default/label/aarch64/firefox/obj-aarch64-unknown-linux-gnu/media/webrtc/trunk/webrtc/gn-output/gen/"
+            ],
+            "libs": [
+                "m",
+                "rt"
+            ],
+            "sources": [],
+            "type": "source_set"
+        },
+        "//api/audio_codecs/isac:audio_decoder_isac_float": {
+            "cflags": [
+                "-fno-strict-aliasing",
+                "--param=ssp-buffer-size=4",
+                "-fstack-protector",
+                "-Wno-builtin-macro-redefined",
+                "-D__DATE__=",
+                "-D__TIME__=",
+                "-D__TIMESTAMP__=",
+                "-funwind-tables",
+                "-fPIC",
+                "-pipe",
+                "-fcolor-diagnostics",
+                "--target=aarch64-linux-gnu",
+                "-pthread",
+                "-Wall",
+                "-Werror",
+                "-Wextra",
+                "-Wno-missing-field-initializers",
+                "-Wno-unused-parameter",
+                "-Wno-c++11-narrowing",
+                "-Wno-covered-switch-default",
+                "-Wno-unneeded-internal-declaration",
+                "-Wno-inconsistent-missing-override",
+                "-Wno-undefined-var-template",
+                "-Wno-nonportable-include-path",
+                "-Wno-address-of-packed-member",
+                "-Wno-unused-lambda-capture",
+                "-Wno-user-defined-warnings",
+                "-O2",
+                "-fno-ident",
+                "-fdata-sections",
+                "-ffunction-sections",
+                "-fno-omit-frame-pointer",
+                "-g0",
+                "-fvisibility=hidden",
+                "-Xclang",
+                "-load",
+                "-Xclang",
+                "../../../../../../media/webrtc/trunk/webrtc/third_party/llvm-build/Release+Asserts/lib/libFindBadConstructs.so",
+                "-Xclang",
+                "-add-plugin",
+                "-Xclang",
+                "find-bad-constructs",
+                "-Xclang",
+                "-plugin-arg-find-bad-constructs",
+                "-Xclang",
+                "check-auto-raw-pointer",
+                "-Xclang",
+                "-plugin-arg-find-bad-constructs",
+                "-Xclang",
+                "check-ipc",
+                "-Wheader-hygiene",
+                "-Wstring-conversion",
+                "-Wtautological-overlap-compare",
+                "-Wextra",
+                "-Wno-unused-parameter",
+                "-Wno-missing-field-initializers",
+                "-Wno-strict-overflow",
+                "-Wc++11-narrowing",
+                "-Wimplicit-fallthrough",
+                "-Wthread-safety",
+                "-Winconsistent-missing-override",
+                "-Wundef",
+                "-Wunused-lambda-capture"
+            ],
+            "defines": [
+                "V8_DEPRECATION_WARNINGS",
+                "USE_NSS_CERTS=1",
+                "USE_X11=1",
+                "NO_TCMALLOC",
+                "DISABLE_NACL",
+                "CHROMIUM_BUILD",
+                "_FILE_OFFSET_BITS=64",
+                "NDEBUG",
+                "NVALGRIND",
+                "DYNAMIC_ANNOTATIONS_ENABLED=0",
+                "WEBRTC_ENABLE_PROTOBUF=0",
+                "WEBRTC_RESTRICT_LOGGING",
+                "WEBRTC_ARCH_ARM64",
+                "WEBRTC_HAS_NEON",
+                "WEBRTC_MOZILLA_BUILD",
+                "WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS=0",
+                "WEBRTC_POSIX",
+                "WEBRTC_LINUX"
+            ],
+            "deps": [
+                "//:webrtc_common",
+                "//api:optional",
+                "//api/audio_codecs:audio_codecs_api",
+                "//modules/audio_coding:isac",
+                "//rtc_base:rtc_base_approved"
+            ],
+            "include_dirs": [
+                "//",
+                "/home/jenkins/workspace/Firefox-default/label/aarch64/firefox/obj-aarch64-unknown-linux-gnu/media/webrtc/trunk/webrtc/gn-output/gen/",
+                "//modules/audio_coding/codecs/isac/main/include/"
+            ],
+            "libs": [
+                "m",
+                "rt"
+            ],
+            "sources": [
+                "//api/audio_codecs/isac/audio_decoder_isac_float.cc",
+                "//api/audio_codecs/isac/audio_decoder_isac_float.h"
+            ],
+            "type": "static_library"
+        },
+        "//api/audio_codecs/isac:audio_encoder_isac": {
+            "cflags": [
+                "-fno-strict-aliasing",
+                "--param=ssp-buffer-size=4",
+                "-fstack-protector",
+                "-Wno-builtin-macro-redefined",
+                "-D__DATE__=",
+                "-D__TIME__=",
+                "-D__TIMESTAMP__=",
+                "-funwind-tables",
+                "-fPIC",
+                "-pipe",
+                "-fcolor-diagnostics",
+                "--target=aarch64-linux-gnu",
+                "-pthread",
+                "-Wall",
+                "-Werror",
+                "-Wextra",
+                "-Wno-missing-field-initializers",
+                "-Wno-unused-parameter",
+                "-Wno-c++11-narrowing",
+                "-Wno-covered-switch-default",
+                "-Wno-unneeded-internal-declaration",
+                "-Wno-inconsistent-missing-override",
+                "-Wno-undefined-var-template",
+                "-Wno-nonportable-include-path",
+                "-Wno-address-of-packed-member",
+                "-Wno-unused-lambda-capture",
+                "-Wno-user-defined-warnings",
+                "-O2",
+                "-fno-ident",
+                "-fdata-sections",
+                "-ffunction-sections",
+                "-fno-omit-frame-pointer",
+                "-g0",
+                "-fvisibility=hidden",
+                "-Xclang",
+                "-load",
+                "-Xclang",
+                "../../../../../../media/webrtc/trunk/webrtc/third_party/llvm-build/Release+Asserts/lib/libFindBadConstructs.so",
+                "-Xclang",
+                "-add-plugin",
+                "-Xclang",
+                "find-bad-constructs",
+                "-Xclang",
+                "-plugin-arg-find-bad-constructs",
+                "-Xclang",
+                "check-auto-raw-pointer",
+                "-Xclang",
+                "-plugin-arg-find-bad-constructs",
+                "-Xclang",
+                "check-ipc",
+                "-Wheader-hygiene",
+                "-Wstring-conversion",
+                "-Wtautological-overlap-compare",
+                "-Wextra",
+                "-Wno-unused-parameter",
+                "-Wno-missing-field-initializers",
+                "-Wno-strict-overflow",
+                "-Wc++11-narrowing",
+                "-Wimplicit-fallthrough",
+                "-Wthread-safety",
+                "-Winconsistent-missing-override",
+                "-Wundef",
+                "-Wunused-lambda-capture"
+            ],
+            "defines": [
+                "V8_DEPRECATION_WARNINGS",
+                "USE_NSS_CERTS=1",
+                "USE_X11=1",
+                "NO_TCMALLOC",
+                "DISABLE_NACL",
+                "CHROMIUM_BUILD",
+                "_FILE_OFFSET_BITS=64",
+                "NDEBUG",
+                "NVALGRIND",
+                "DYNAMIC_ANNOTATIONS_ENABLED=0",
+                "WEBRTC_ENABLE_PROTOBUF=0",
+                "WEBRTC_RESTRICT_LOGGING",
+                "WEBRTC_ARCH_ARM64",
+                "WEBRTC_HAS_NEON",
+                "WEBRTC_MOZILLA_BUILD",
+                "WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS=0",
+                "WEBRTC_POSIX",
+                "WEBRTC_LINUX",
+                "WEBRTC_USE_BUILTIN_ISAC_FIX=0",
+                "WEBRTC_USE_BUILTIN_ISAC_FLOAT=1"
+            ],
+            "deps": [
+                "//api/audio_codecs/isac:audio_encoder_isac_float"
+            ],
+            "include_dirs": [
+                "//",
+                "/home/jenkins/workspace/Firefox-default/label/aarch64/firefox/obj-aarch64-unknown-linux-gnu/media/webrtc/trunk/webrtc/gn-output/gen/"
+            ],
+            "libs": [
+                "m",
+                "rt"
+            ],
+            "sources": [],
+            "type": "source_set"
+        },
+        "//api/audio_codecs/isac:audio_encoder_isac_float": {
+            "cflags": [
+                "-fno-strict-aliasing",
+                "--param=ssp-buffer-size=4",
+                "-fstack-protector",
+                "-Wno-builtin-macro-redefined",
+                "-D__DATE__=",
+                "-D__TIME__=",
+                "-D__TIMESTAMP__=",
+                "-funwind-tables",
+                "-fPIC",
+                "-pipe",
+                "-fcolor-diagnostics",
+                "--target=aarch64-linux-gnu",
+                "-pthread",
+                "-Wall",
+                "-Werror",
+                "-Wextra",
+                "-Wno-missing-field-initializers",
+                "-Wno-unused-parameter",
+                "-Wno-c++11-narrowing",
+                "-Wno-covered-switch-default",
+                "-Wno-unneeded-internal-declaration",
+                "-Wno-inconsistent-missing-override",
+                "-Wno-undefined-var-template",
+                "-Wno-nonportable-include-path",
+                "-Wno-address-of-packed-member",
+                "-Wno-unused-lambda-capture",
+                "-Wno-user-defined-warnings",
+                "-O2",
+                "-fno-ident",
+                "-fdata-sections",
+                "-ffunction-sections",
+                "-fno-omit-frame-pointer",
+                "-g0",
+                "-fvisibility=hidden",
+                "-Xclang",
+                "-load",
+                "-Xclang",
+                "../../../../../../media/webrtc/trunk/webrtc/third_party/llvm-build/Release+Asserts/lib/libFindBadConstructs.so",
+                "-Xclang",
+                "-add-plugin",
+                "-Xclang",
+                "find-bad-constructs",
+                "-Xclang",
+                "-plugin-arg-find-bad-constructs",
+                "-Xclang",
+                "check-auto-raw-pointer",
+                "-Xclang",
+                "-plugin-arg-find-bad-constructs",
+                "-Xclang",
+                "check-ipc",
+                "-Wheader-hygiene",
+                "-Wstring-conversion",
+                "-Wtautological-overlap-compare",
+                "-Wextra",
+                "-Wno-unused-parameter",
+                "-Wno-missing-field-initializers",
+                "-Wno-strict-overflow",
+                "-Wc++11-narrowing",
+                "-Wimplicit-fallthrough",
+                "-Wthread-safety",
+                "-Winconsistent-missing-override",
+                "-Wundef",
+                "-Wunused-lambda-capture"
+            ],
+            "defines": [
+                "V8_DEPRECATION_WARNINGS",
+                "USE_NSS_CERTS=1",
+                "USE_X11=1",
+                "NO_TCMALLOC",
+                "DISABLE_NACL",
+                "CHROMIUM_BUILD",
+                "_FILE_OFFSET_BITS=64",
+                "NDEBUG",
+                "NVALGRIND",
+                "DYNAMIC_ANNOTATIONS_ENABLED=0",
+                "WEBRTC_ENABLE_PROTOBUF=0",
+                "WEBRTC_RESTRICT_LOGGING",
+                "WEBRTC_ARCH_ARM64",
+                "WEBRTC_HAS_NEON",
+                "WEBRTC_MOZILLA_BUILD",
+                "WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS=0",
+                "WEBRTC_POSIX",
+                "WEBRTC_LINUX"
+            ],
+            "deps": [
+                "//:webrtc_common",
+                "//api:optional",
+                "//api/audio_codecs:audio_codecs_api",
+                "//modules/audio_coding:isac",
+                "//rtc_base:rtc_base_approved"
+            ],
+            "include_dirs": [
+                "//",
+                "/home/jenkins/workspace/Firefox-default/label/aarch64/firefox/obj-aarch64-unknown-linux-gnu/media/webrtc/trunk/webrtc/gn-output/gen/",
+                "//modules/audio_coding/codecs/isac/main/include/"
+            ],
+            "libs": [
+                "m",
+                "rt"
+            ],
+            "sources": [
+                "//api/audio_codecs/isac/audio_encoder_isac_float.cc",
+                "//api/audio_codecs/isac/audio_encoder_isac_float.h"
+            ],
+            "type": "static_library"
+        },
+        "//api/audio_codecs/opus:audio_decoder_opus": {
+            "cflags": [
+                "-fno-strict-aliasing",
+                "--param=ssp-buffer-size=4",
+                "-fstack-protector",
+                "-Wno-builtin-macro-redefined",
+                "-D__DATE__=",
+                "-D__TIME__=",
+                "-D__TIMESTAMP__=",
+                "-funwind-tables",
+                "-fPIC",
+                "-pipe",
+                "-fcolor-diagnostics",
+                "--target=aarch64-linux-gnu",
+                "-pthread",
+                "-Wall",
+                "-Werror",
+                "-Wextra",
+                "-Wno-missing-field-initializers",
+                "-Wno-unused-parameter",
+                "-Wno-c++11-narrowing",
+                "-Wno-covered-switch-default",
+                "-Wno-unneeded-internal-declaration",
+                "-Wno-inconsistent-missing-override",
+                "-Wno-undefined-var-template",
+                "-Wno-nonportable-include-path",
+                "-Wno-address-of-packed-member",
+                "-Wno-unused-lambda-capture",
+                "-Wno-user-defined-warnings",
+                "-O2",
+                "-fno-ident",
+                "-fdata-sections",
+                "-ffunction-sections",
+                "-fno-omit-frame-pointer",
+                "-g0",
+                "-fvisibility=hidden",
+                "-Xclang",
+                "-load",
+                "-Xclang",
+                "../../../../../../media/webrtc/trunk/webrtc/third_party/llvm-build/Release+Asserts/lib/libFindBadConstructs.so",
+                "-Xclang",
+                "-add-plugin",
+                "-Xclang",
+                "find-bad-constructs",
+                "-Xclang",
+                "-plugin-arg-find-bad-constructs",
+                "-Xclang",
+                "check-auto-raw-pointer",
+                "-Xclang",
+                "-plugin-arg-find-bad-constructs",
+                "-Xclang",
+                "check-ipc",
+                "-Wheader-hygiene",
+                "-Wstring-conversion",
+                "-Wtautological-overlap-compare",
+                "-Wextra",
+                "-Wno-unused-parameter",
+                "-Wno-missing-field-initializers",
+                "-Wno-strict-overflow",
+                "-Wc++11-narrowing",
+                "-Wimplicit-fallthrough",
+                "-Wthread-safety",
+                "-Winconsistent-missing-override",
+                "-Wundef",
+                "-Wunused-lambda-capture"
+            ],
+            "defines": [
+                "V8_DEPRECATION_WARNINGS",
+                "USE_NSS_CERTS=1",
+                "USE_X11=1",
+                "NO_TCMALLOC",
+                "DISABLE_NACL",
+                "CHROMIUM_BUILD",
+                "_FILE_OFFSET_BITS=64",
+                "NDEBUG",
+                "NVALGRIND",
+                "DYNAMIC_ANNOTATIONS_ENABLED=0",
+                "WEBRTC_ENABLE_PROTOBUF=0",
+                "WEBRTC_RESTRICT_LOGGING",
+                "WEBRTC_ARCH_ARM64",
+                "WEBRTC_HAS_NEON",
+                "WEBRTC_MOZILLA_BUILD",
+                "WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS=0",
+                "WEBRTC_POSIX",
+                "WEBRTC_LINUX"
+            ],
+            "deps": [
+                "//:webrtc_common",
+                "//api:optional",
+                "//api/audio_codecs:audio_codecs_api",
+                "//modules/audio_coding:webrtc_opus",
+                "//rtc_base:rtc_base_approved"
+            ],
+            "include_dirs": [
+                "/media/libopus/include/",
+                "//",
+                "/home/jenkins/workspace/Firefox-default/label/aarch64/firefox/obj-aarch64-unknown-linux-gnu/media/webrtc/trunk/webrtc/gn-output/gen/"
+            ],
+            "libs": [
+                "rt"
+            ],
+            "sources": [
+                "//api/audio_codecs/opus/audio_decoder_opus.cc",
+                "//api/audio_codecs/opus/audio_decoder_opus.h"
+            ],
+            "type": "static_library"
+        },
+        "//api/audio_codecs/opus:audio_encoder_opus": {
+            "cflags": [
+                "-fno-strict-aliasing",
+                "--param=ssp-buffer-size=4",
+                "-fstack-protector",
+                "-Wno-builtin-macro-redefined",
+                "-D__DATE__=",
+                "-D__TIME__=",
+                "-D__TIMESTAMP__=",
+                "-funwind-tables",
+                "-fPIC",
+                "-pipe",
+                "-fcolor-diagnostics",
+                "--target=aarch64-linux-gnu",
+                "-pthread",
+                "-Wall",
+                "-Werror",
+                "-Wextra",
+                "-Wno-missing-field-initializers",
+                "-Wno-unused-parameter",
+                "-Wno-c++11-narrowing",
+                "-Wno-covered-switch-default",
+                "-Wno-unneeded-internal-declaration",
+                "-Wno-inconsistent-missing-override",
+                "-Wno-undefined-var-template",
+                "-Wno-nonportable-include-path",
+                "-Wno-address-of-packed-member",
+                "-Wno-unused-lambda-capture",
+                "-Wno-user-defined-warnings",
+                "-O2",
+                "-fno-ident",
+                "-fdata-sections",
+                "-ffunction-sections",
+                "-fno-omit-frame-pointer",
+                "-g0",
+                "-fvisibility=hidden",
+                "-Xclang",
+                "-load",
+                "-Xclang",
+                "../../../../../../media/webrtc/trunk/webrtc/third_party/llvm-build/Release+Asserts/lib/libFindBadConstructs.so",
+                "-Xclang",
+                "-add-plugin",
+                "-Xclang",
+                "find-bad-constructs",
+                "-Xclang",
+                "-plugin-arg-find-bad-constructs",
+                "-Xclang",
+                "check-auto-raw-pointer",
+                "-Xclang",
+                "-plugin-arg-find-bad-constructs",
+                "-Xclang",
+                "check-ipc",
+                "-Wheader-hygiene",
+                "-Wstring-conversion",
+                "-Wtautological-overlap-compare",
+                "-Wextra",
+                "-Wno-unused-parameter",
+                "-Wno-missing-field-initializers",
+                "-Wno-strict-overflow",
+                "-Wc++11-narrowing",
+                "-Wimplicit-fallthrough",
+                "-Wthread-safety",
+                "-Winconsistent-missing-override",
+                "-Wundef",
+                "-Wunused-lambda-capture"
+            ],
+            "defines": [
+                "V8_DEPRECATION_WARNINGS",
+                "USE_NSS_CERTS=1",
+                "USE_X11=1",
+                "NO_TCMALLOC",
+                "DISABLE_NACL",
+                "CHROMIUM_BUILD",
+                "_FILE_OFFSET_BITS=64",
+                "NDEBUG",
+                "NVALGRIND",
+                "DYNAMIC_ANNOTATIONS_ENABLED=0",
+                "WEBRTC_ENABLE_PROTOBUF=0",
+                "WEBRTC_RESTRICT_LOGGING",
+                "WEBRTC_ARCH_ARM64",
+                "WEBRTC_HAS_NEON",
+                "WEBRTC_MOZILLA_BUILD",
+                "WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS=0",
+                "WEBRTC_POSIX",
+                "WEBRTC_LINUX"
+            ],
+            "deps": [
+                "//api:optional",
+                "//api/audio_codecs:audio_codecs_api",
+                "//api/audio_codecs/opus:audio_encoder_opus_config",
+                "//modules/audio_coding:webrtc_opus",
+                "//rtc_base:protobuf_utils",
+                "//rtc_base:rtc_base_approved"
+            ],
+            "include_dirs": [
+                "/media/libopus/include/",
+                "//",
+                "/home/jenkins/workspace/Firefox-default/label/aarch64/firefox/obj-aarch64-unknown-linux-gnu/media/webrtc/trunk/webrtc/gn-output/gen/"
+            ],
+            "libs": [
+                "rt"
+            ],
+            "sources": [
+                "//api/audio_codecs/opus/audio_encoder_opus.cc"
+            ],
+            "type": "source_set"
+        },
+        "//api/audio_codecs/opus:audio_encoder_opus_config": {
+            "cflags": [
+                "-fno-strict-aliasing",
+                "--param=ssp-buffer-size=4",
+                "-fstack-protector",
+                "-Wno-builtin-macro-redefined",
+                "-D__DATE__=",
+                "-D__TIME__=",
+                "-D__TIMESTAMP__=",
+                "-funwind-tables",
+                "-fPIC",
+                "-pipe",
+                "-fcolor-diagnostics",
+                "--target=aarch64-linux-gnu",
+                "-pthread",
+                "-Wall",
+                "-Werror",
+                "-Wextra",
+                "-Wno-missing-field-initializers",
+                "-Wno-unused-parameter",
+                "-Wno-c++11-narrowing",
+                "-Wno-covered-switch-default",
+                "-Wno-unneeded-internal-declaration",
+                "-Wno-inconsistent-missing-override",
+                "-Wno-undefined-var-template",
+                "-Wno-nonportable-include-path",
+                "-Wno-address-of-packed-member",
+                "-Wno-unused-lambda-capture",
+                "-Wno-user-defined-warnings",
+                "-O2",
+                "-fno-ident",
+                "-fdata-sections",
+                "-ffunction-sections",
+                "-fno-omit-frame-pointer",
+                "-g0",
+                "-fvisibility=hidden",
+                "-Xclang",
+                "-load",
+                "-Xclang",
+                "../../../../../../media/webrtc/trunk/webrtc/third_party/llvm-build/Release+Asserts/lib/libFindBadConstructs.so",
+                "-Xclang",
+                "-add-plugin",
+                "-Xclang",
+                "find-bad-constructs",
+                "-Xclang",
+                "-plugin-arg-find-bad-constructs",
+                "-Xclang",
+                "check-auto-raw-pointer",
+                "-Xclang",
+                "-plugin-arg-find-bad-constructs",
+                "-Xclang",
+                "check-ipc",
+                "-Wheader-hygiene",
+                "-Wstring-conversion",
+                "-Wtautological-overlap-compare",
+                "-Wextra",
+                "-Wno-unused-parameter",
+                "-Wno-missing-field-initializers",
+                "-Wno-strict-overflow",
+                "-Wc++11-narrowing",
+                "-Wimplicit-fallthrough",
+                "-Wthread-safety",
+                "-Winconsistent-missing-override",
+                "-Wundef",
+                "-Wunused-lambda-capture"
+            ],
+            "defines": [
+                "WEBRTC_OPUS_VARIABLE_COMPLEXITY=0",
+                "V8_DEPRECATION_WARNINGS",
+                "USE_NSS_CERTS=1",
+                "USE_X11=1",
+                "NO_TCMALLOC",
+                "DISABLE_NACL",
+                "CHROMIUM_BUILD",
+                "_FILE_OFFSET_BITS=64",
+                "NDEBUG",
+                "NVALGRIND",
+                "DYNAMIC_ANNOTATIONS_ENABLED=0",
+                "WEBRTC_ENABLE_PROTOBUF=0",
+                "WEBRTC_RESTRICT_LOGGING",
+                "WEBRTC_ARCH_ARM64",
+                "WEBRTC_HAS_NEON",
+                "WEBRTC_MOZILLA_BUILD",
+                "WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS=0",
+                "WEBRTC_POSIX",
+                "WEBRTC_LINUX"
+            ],
+            "deps": [
+                "//api:optional",
+                "//rtc_base:rtc_base_approved"
+            ],
+            "include_dirs": [
+                "/media/libopus/include/",
+                "//",
+                "/home/jenkins/workspace/Firefox-default/label/aarch64/firefox/obj-aarch64-unknown-linux-gnu/media/webrtc/trunk/webrtc/gn-output/gen/"
+            ],
+            "libs": [],
+            "sources": [
+                "//api/audio_codecs/opus/audio_encoder_opus_config.cc",
+                "//api/audio_codecs/opus/audio_encoder_opus_config.h"
+            ],
+            "type": "static_library"
+        },
+        "//api/audio_codecs:audio_codecs_api": {
+            "cflags": [
+                "-fno-strict-aliasing",
+                "--param=ssp-buffer-size=4",
+                "-fstack-protector",
+                "-Wno-builtin-macro-redefined",
+                "-D__DATE__=",
+                "-D__TIME__=",
+                "-D__TIMESTAMP__=",
+                "-funwind-tables",
+                "-fPIC",
+                "-pipe",
+                "-fcolor-diagnostics",
+                "--target=aarch64-linux-gnu",
+                "-pthread",
+                "-Wall",
+                "-Werror",
+                "-Wextra",
+                "-Wno-missing-field-initializers",
+                "-Wno-unused-parameter",
+                "-Wno-c++11-narrowing",
+                "-Wno-covered-switch-default",
+                "-Wno-unneeded-internal-declaration",
+                "-Wno-inconsistent-missing-override",
+                "-Wno-undefined-var-template",
+                "-Wno-nonportable-include-path",
+                "-Wno-address-of-packed-member",
+                "-Wno-unused-lambda-capture",
+                "-Wno-user-defined-warnings",
+                "-O2",
+                "-fno-ident",
+                "-fdata-sections",
+                "-ffunction-sections",
+                "-fno-omit-frame-pointer",
+                "-g0",
+                "-fvisibility=hidden",
+                "-Xclang",
+                "-load",
+                "-Xclang",
+                "../../../../../../media/webrtc/trunk/webrtc/third_party/llvm-build/Release+Asserts/lib/libFindBadConstructs.so",
+                "-Xclang",
+                "-add-plugin",
+                "-Xclang",
+                "find-bad-constructs",
+                "-Xclang",
+                "-plugin-arg-find-bad-constructs",
+                "-Xclang",
+                "check-auto-raw-pointer",
+                "-Xclang",
+                "-plugin-arg-find-bad-constructs",
+                "-Xclang",
+                "check-ipc",
+                "-Wheader-hygiene",
+                "-Wstring-conversion",
+                "-Wtautological-overlap-compare",
+                "-Wextra",
+                "-Wno-unused-parameter",
+                "-Wno-missing-field-initializers",
+                "-Wno-strict-overflow",
+                "-Wc++11-narrowing",
+                "-Wimplicit-fallthrough",
+                "-Wthread-safety",
+                "-Winconsistent-missing-override",
+                "-Wundef",
+                "-Wunused-lambda-capture"
+            ],
+            "defines": [
+                "V8_DEPRECATION_WARNINGS",
+                "USE_NSS_CERTS=1",
+                "USE_X11=1",
+                "NO_TCMALLOC",
+                "DISABLE_NACL",
+                "CHROMIUM_BUILD",
+                "_FILE_OFFSET_BITS=64",
+                "NDEBUG",
+                "NVALGRIND",
+                "DYNAMIC_ANNOTATIONS_ENABLED=0",
+                "WEBRTC_ENABLE_PROTOBUF=0",
+                "WEBRTC_RESTRICT_LOGGING",
+                "WEBRTC_ARCH_ARM64",
+                "WEBRTC_HAS_NEON",
+                "WEBRTC_MOZILLA_BUILD",
+                "WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS=0",
+                "WEBRTC_POSIX",
+                "WEBRTC_LINUX"
+            ],
+            "deps": [
+                "//:webrtc_common",
+                "//api:array_view",
+                "//api:optional",
+                "//rtc_base:rtc_base_approved"
+            ],
+            "include_dirs": [
+                "//",
+                "/home/jenkins/workspace/Firefox-default/label/aarch64/firefox/obj-aarch64-unknown-linux-gnu/media/webrtc/trunk/webrtc/gn-output/gen/"
+            ],
+            "libs": [],
+            "sources": [
+                "//api/audio_codecs/audio_decoder.cc",
+                "//api/audio_codecs/audio_decoder.h",
+                "//api/audio_codecs/audio_decoder_factory.h",
+                "//api/audio_codecs/audio_decoder_factory_template.h",
+                "//api/audio_codecs/audio_encoder.cc",
+                "//api/audio_codecs/audio_encoder.h",
+                "//api/audio_codecs/audio_encoder_factory.h",
+                "//api/audio_codecs/audio_encoder_factory_template.h",
+                "//api/audio_codecs/audio_format.cc",
+                "//api/audio_codecs/audio_format.h"
+            ],
+            "type": "source_set"
+        },
+        "//api/audio_codecs:builtin_audio_decoder_factory": {
+            "cflags": [
+                "-fno-strict-aliasing",
+                "--param=ssp-buffer-size=4",
+                "-fstack-protector",
+                "-Wno-builtin-macro-redefined",
+                "-D__DATE__=",
+                "-D__TIME__=",
+                "-D__TIMESTAMP__=",
+                "-funwind-tables",
+                "-fPIC",
+                "-pipe",
+                "-fcolor-diagnostics",
+                "--target=aarch64-linux-gnu",
+                "-pthread",
+                "-Wall",
+                "-Werror",
+                "-Wextra",
+                "-Wno-missing-field-initializers",
+                "-Wno-unused-parameter",
+                "-Wno-c++11-narrowing",
+                "-Wno-covered-switch-default",
+                "-Wno-unneeded-internal-declaration",
+                "-Wno-inconsistent-missing-override",
+                "-Wno-undefined-var-template",
+                "-Wno-nonportable-include-path",
+                "-Wno-address-of-packed-member",
+                "-Wno-unused-lambda-capture",
+                "-Wno-user-defined-warnings",
+                "-O2",
+                "-fno-ident",
+                "-fdata-sections",
+                "-ffunction-sections",
+                "-fno-omit-frame-pointer",
+                "-g0",
+                "-fvisibility=hidden",
+                "-Xclang",
+                "-load",
+                "-Xclang",
+                "../../../../../../media/webrtc/trunk/webrtc/third_party/llvm-build/Release+Asserts/lib/libFindBadConstructs.so",
+                "-Xclang",
+                "-add-plugin",
+                "-Xclang",
+                "find-bad-constructs",
+                "-Xclang",
+                "-plugin-arg-find-bad-constructs",
+                "-Xclang",
+                "check-auto-raw-pointer",
+                "-Xclang",
+                "-plugin-arg-find-bad-constructs",
+                "-Xclang",
+                "check-ipc",
+                "-Wheader-hygiene",
+                "-Wstring-conversion",
+                "-Wtautological-overlap-compare",
+                "-Wextra",
+                "-Wno-unused-parameter",
+                "-Wno-missing-field-initializers",
+                "-Wno-strict-overflow",
+                "-Wc++11-narrowing",
+                "-Wimplicit-fallthrough",
+                "-Wthread-safety",
+                "-Winconsistent-missing-override",
+                "-Wundef",
+                "-Wunused-lambda-capture"
+            ],
+            "defines": [
+                "WEBRTC_USE_BUILTIN_ILBC=1",
+                "WEBRTC_USE_BUILTIN_OPUS=1",
+                "V8_DEPRECATION_WARNINGS",
+                "USE_NSS_CERTS=1",
+                "USE_X11=1",
+                "NO_TCMALLOC",
+                "DISABLE_NACL",
+                "CHROMIUM_BUILD",
+                "_FILE_OFFSET_BITS=64",
+                "NDEBUG",
+                "NVALGRIND",
+                "DYNAMIC_ANNOTATIONS_ENABLED=0",
+                "WEBRTC_ENABLE_PROTOBUF=0",
+                "WEBRTC_RESTRICT_LOGGING",
+                "WEBRTC_ARCH_ARM64",
+                "WEBRTC_HAS_NEON",
+                "WEBRTC_MOZILLA_BUILD",
+                "WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS=0",
+                "WEBRTC_POSIX",
+                "WEBRTC_LINUX",
+                "WEBRTC_USE_BUILTIN_ISAC_FIX=0",
+                "WEBRTC_USE_BUILTIN_ISAC_FLOAT=1"
+            ],
+            "deps": [
+                "//api/audio_codecs:audio_codecs_api",
+                "//api/audio_codecs/L16:audio_decoder_L16",
+                "//api/audio_codecs/g711:audio_decoder_g711",
+                "//api/audio_codecs/g722:audio_decoder_g722",
+                "//api/audio_codecs/ilbc:audio_decoder_ilbc",
+                "//api/audio_codecs/isac:audio_decoder_isac",
+                "//api/audio_codecs/opus:audio_decoder_opus",
+                "//rtc_base:rtc_base_approved"
+            ],
+            "include_dirs": [
+                "//",
+                "/home/jenkins/workspace/Firefox-default/label/aarch64/firefox/obj-aarch64-unknown-linux-gnu/media/webrtc/trunk/webrtc/gn-output/gen/"
+            ],
+            "libs": [
+                "m",
+                "rt"
+            ],
+            "sources": [
+                "//api/audio_codecs/builtin_audio_decoder_factory.cc",
+                "//api/audio_codecs/builtin_audio_decoder_factory.h"
+            ],
+            "type": "static_library"
+        },
+        "//api/audio_codecs:builtin_audio_encoder_factory": {
+            "cflags": [
+                "-fno-strict-aliasing",
+                "--param=ssp-buffer-size=4",
+                "-fstack-protector",
+                "-Wno-builtin-macro-redefined",
+                "-D__DATE__=",
+                "-D__TIME__=",
+                "-D__TIMESTAMP__=",
+                "-funwind-tables",
+                "-fPIC",
+                "-pipe",
+                "-fcolor-diagnostics",
+                "--target=aarch64-linux-gnu",
+                "-pthread",
+                "-Wall",
+                "-Werror",
+                "-Wextra",
+                "-Wno-missing-field-initializers",
+                "-Wno-unused-parameter",
+                "-Wno-c++11-narrowing",
+                "-Wno-covered-switch-default",
+                "-Wno-unneeded-internal-declaration",
+                "-Wno-inconsistent-missing-override",
+                "-Wno-undefined-var-template",
+                "-Wno-nonportable-include-path",
+                "-Wno-address-of-packed-member",
+                "-Wno-unused-lambda-capture",
+                "-Wno-user-defined-warnings",
+                "-O2",
+                "-fno-ident",
+                "-fdata-sections",
+                "-ffunction-sections",
+                "-fno-omit-frame-pointer",
+                "-g0",
+                "-fvisibility=hidden",
+                "-Xclang",
+                "-load",
+                "-Xclang",
+                "../../../../../../media/webrtc/trunk/webrtc/third_party/llvm-build/Release+Asserts/lib/libFindBadConstructs.so",
+                "-Xclang",
+                "-add-plugin",
+                "-Xclang",
+                "find-bad-constructs",
+                "-Xclang",
+                "-plugin-arg-find-bad-constructs",
+                "-Xclang",
+                "check-auto-raw-pointer",
+                "-Xclang",
+                "-plugin-arg-find-bad-constructs",
+                "-Xclang",
+                "check-ipc",
+                "-Wheader-hygiene",
+                "-Wstring-conversion",
+                "-Wtautological-overlap-compare",
+                "-Wextra",
+                "-Wno-unused-parameter",
+                "-Wno-missing-field-initializers",
+                "-Wno-strict-overflow",
+                "-Wc++11-narrowing",
+                "-Wimplicit-fallthrough",
+                "-Wthread-safety",
+                "-Winconsistent-missing-override",
+                "-Wundef",
+                "-Wunused-lambda-capture"
+            ],
+            "defines": [
+                "WEBRTC_USE_BUILTIN_ILBC=1",
+                "WEBRTC_USE_BUILTIN_OPUS=1",
+                "V8_DEPRECATION_WARNINGS",
+                "USE_NSS_CERTS=1",
+                "USE_X11=1",
+                "NO_TCMALLOC",
+                "DISABLE_NACL",
+                "CHROMIUM_BUILD",
+                "_FILE_OFFSET_BITS=64",
+                "NDEBUG",
+                "NVALGRIND",
+                "DYNAMIC_ANNOTATIONS_ENABLED=0",
+                "WEBRTC_ENABLE_PROTOBUF=0",
+                "WEBRTC_RESTRICT_LOGGING",
+                "WEBRTC_ARCH_ARM64",
+                "WEBRTC_HAS_NEON",
+                "WEBRTC_MOZILLA_BUILD",
+                "WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS=0",
+                "WEBRTC_POSIX",
+                "WEBRTC_LINUX",
+                "WEBRTC_USE_BUILTIN_ISAC_FIX=0",
+                "WEBRTC_USE_BUILTIN_ISAC_FLOAT=1"
+            ],
+            "deps": [
+                "//api/audio_codecs:audio_codecs_api",
+                "//api/audio_codecs/L16:audio_encoder_L16",
+                "//api/audio_codecs/g711:audio_encoder_g711",
+                "//api/audio_codecs/g722:audio_encoder_g722",
+                "//api/audio_codecs/ilbc:audio_encoder_ilbc",
+                "//api/audio_codecs/isac:audio_encoder_isac",
+                "//api/audio_codecs/opus:audio_encoder_opus",
+                "//rtc_base:rtc_base_approved"
+            ],
+            "include_dirs": [
+                "//",
+                "/home/jenkins/workspace/Firefox-default/label/aarch64/firefox/obj-aarch64-unknown-linux-gnu/media/webrtc/trunk/webrtc/gn-output/gen/"
+            ],
+            "libs": [
+                "m",
+                "rt"
+            ],
+            "sources": [
+                "//api/audio_codecs/builtin_audio_encoder_factory.cc",
+                "//api/audio_codecs/builtin_audio_encoder_factory.h"
+            ],
+            "type": "static_library"
+        },
+        "//api/video_codecs:video_codecs_api": {
+            "cflags": [
+                "-fno-strict-aliasing",
+                "--param=ssp-buffer-size=4",
+                "-fstack-protector",
+                "-Wno-builtin-macro-redefined",
+                "-D__DATE__=",
+                "-D__TIME__=",
+                "-D__TIMESTAMP__=",
+                "-funwind-tables",
+                "-fPIC",
+                "-pipe",
+                "-fcolor-diagnostics",
+                "--target=aarch64-linux-gnu",
+                "-pthread",
+                "-Wall",
+                "-Werror",
+                "-Wextra",
+                "-Wno-missing-field-initializers",
+                "-Wno-unused-parameter",
+                "-Wno-c++11-narrowing",
+                "-Wno-covered-switch-default",
+                "-Wno-unneeded-internal-declaration",
+                "-Wno-inconsistent-missing-override",
+                "-Wno-undefined-var-template",
+                "-Wno-nonportable-include-path",
+                "-Wno-address-of-packed-member",
+                "-Wno-unused-lambda-capture",
+                "-Wno-user-defined-warnings",
+                "-O2",
+                "-fno-ident",
+                "-fdata-sections",
+                "-ffunction-sections",
+                "-fno-omit-frame-pointer",
+                "-g0",
+                "-fvisibility=hidden",
+                "-Xclang",
+                "-load",
+                "-Xclang",
+                "../../../../../../media/webrtc/trunk/webrtc/third_party/llvm-build/Release+Asserts/lib/libFindBadConstructs.so",
+                "-Xclang",
+                "-add-plugin",
+                "-Xclang",
+                "find-bad-constructs",
+                "-Xclang",
+                "-plugin-arg-find-bad-constructs",
+                "-Xclang",
+                "check-auto-raw-pointer",
+                "-Xclang",
+                "-plugin-arg-find-bad-constructs",
+                "-Xclang",
+                "check-ipc",
+                "-Wheader-hygiene",
+                "-Wstring-conversion",
+                "-Wtautological-overlap-compare",
+                "-Wextra",
+                "-Wno-unused-parameter",
+                "-Wno-missing-field-initializers",
+                "-Wno-strict-overflow",
+                "-Wc++11-narrowing",
+                "-Wimplicit-fallthrough",
+                "-Wthread-safety",
+                "-Winconsistent-missing-override",
+                "-Wundef",
+                "-Wunused-lambda-capture"
+            ],
+            "defines": [
+                "V8_DEPRECATION_WARNINGS",
+                "USE_NSS_CERTS=1",
+                "USE_X11=1",
+                "NO_TCMALLOC",
+                "DISABLE_NACL",
+                "CHROMIUM_BUILD",
+                "_FILE_OFFSET_BITS=64",
+                "NDEBUG",
+                "NVALGRIND",
+                "DYNAMIC_ANNOTATIONS_ENABLED=0",
+                "WEBRTC_ENABLE_PROTOBUF=0",
+                "WEBRTC_RESTRICT_LOGGING",
+                "WEBRTC_ARCH_ARM64",
+                "WEBRTC_HAS_NEON",
+                "WEBRTC_MOZILLA_BUILD",
+                "WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS=0",
+                "WEBRTC_POSIX",
+                "WEBRTC_LINUX"
+            ],
+            "deps": [
+                "//:webrtc_common",
+                "//api:optional",
+                "//api:video_frame_api",
+                "//common_video:common_video",
+                "//rtc_base:rtc_base_approved"
+            ],
+            "include_dirs": [
+                "//",
+                "/home/jenkins/workspace/Firefox-default/label/aarch64/firefox/obj-aarch64-unknown-linux-gnu/media/webrtc/trunk/webrtc/gn-output/gen/",
+                "//common_video/include/",
+                "/media/libyuv/libyuv/include/"
+            ],
+            "libs": [
+                "rt"
+            ],
+            "sources": [
+                "//api/video_codecs/sdp_video_format.h",
+                "//api/video_codecs/video_decoder.h",
+                "//api/video_codecs/video_decoder_factory.h",
+                "//api/video_codecs/video_encoder.cc",
+                "//api/video_codecs/video_encoder.h",
+                "//api/video_codecs/video_encoder_factory.h"
+            ],
+            "type": "source_set"
+        },
+        "//api:array_view": {
+            "cflags": [
+                "-fno-strict-aliasing",
+                "--param=ssp-buffer-size=4",
+                "-fstack-protector",
+                "-Wno-builtin-macro-redefined",
+                "-D__DATE__=",
+                "-D__TIME__=",
+                "-D__TIMESTAMP__=",
+                "-funwind-tables",
+                "-fPIC",
+                "-pipe",
+                "-fcolor-diagnostics",
+                "--target=aarch64-linux-gnu",
+                "-pthread",
+                "-Wall",
+                "-Werror",
+                "-Wextra",
+                "-Wno-missing-field-initializers",
+                "-Wno-unused-parameter",
+                "-Wno-c++11-narrowing",
+                "-Wno-covered-switch-default",
+                "-Wno-unneeded-internal-declaration",
+                "-Wno-inconsistent-missing-override",
+                "-Wno-undefined-var-template",
+                "-Wno-nonportable-include-path",
+                "-Wno-address-of-packed-member",
+                "-Wno-unused-lambda-capture",
+                "-Wno-user-defined-warnings",
+                "-O2",
+                "-fno-ident",
+                "-fdata-sections",
+                "-ffunction-sections",
+                "-fno-omit-frame-pointer",
+                "-g0",
+                "-fvisibility=hidden",
+                "-Xclang",
+                "-load",
+                "-Xclang",
+                "../../../../../../media/webrtc/trunk/webrtc/third_party/llvm-build/Release+Asserts/lib/libFindBadConstructs.so",
+                "-Xclang",
+                "-add-plugin",
+                "-Xclang",
+                "find-bad-constructs",
+                "-Xclang",
+                "-plugin-arg-find-bad-constructs",
+                "-Xclang",
+                "check-auto-raw-pointer",
+                "-Xclang",
+                "-plugin-arg-find-bad-constructs",
+                "-Xclang",
+                "check-ipc",
+                "-Wheader-hygiene",
+                "-Wstring-conversion",
+                "-Wtautological-overlap-compare",
+                "-Wextra",
+                "-Wno-unused-parameter",
+                "-Wno-missing-field-initializers",
+                "-Wno-strict-overflow",
+                "-Wc++11-narrowing",
+                "-Wimplicit-fallthrough",
+                "-Wthread-safety",
+                "-Winconsistent-missing-override",
+                "-Wundef",
+                "-Wunused-lambda-capture"
+            ],
+            "defines": [
+                "V8_DEPRECATION_WARNINGS",
+                "USE_NSS_CERTS=1",
+                "USE_X11=1",
+                "NO_TCMALLOC",
+                "DISABLE_NACL",
+                "CHROMIUM_BUILD",
+                "_FILE_OFFSET_BITS=64",
+                "NDEBUG",
+                "NVALGRIND",
+                "DYNAMIC_ANNOTATIONS_ENABLED=0",
+                "WEBRTC_ENABLE_PROTOBUF=0",
+                "WEBRTC_RESTRICT_LOGGING",
+                "WEBRTC_ARCH_ARM64",
+                "WEBRTC_HAS_NEON",
+                "WEBRTC_MOZILLA_BUILD",
+                "WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS=0",
+                "WEBRTC_POSIX",
+                "WEBRTC_LINUX"
+            ],
+            "deps": [
+                "//rtc_base:rtc_base_approved"
+            ],
+            "include_dirs": [
+                "//",
+                "/home/jenkins/workspace/Firefox-default/label/aarch64/firefox/obj-aarch64-unknown-linux-gnu/media/webrtc/trunk/webrtc/gn-output/gen/"
+            ],
+            "libs": [],
+            "sources": [
+                "//api/array_view.h"
+            ],
+            "type": "source_set"
+        },
+        "//api:audio_mixer_api": {
+            "cflags": [
+                "-fno-strict-aliasing",
+                "--param=ssp-buffer-size=4",
+                "-fstack-protector",
+                "-Wno-builtin-macro-redefined",
+                "-D__DATE__=",
+                "-D__TIME__=",
+                "-D__TIMESTAMP__=",
+                "-funwind-tables",
+                "-fPIC",
+                "-pipe",
+                "-fcolor-diagnostics",
+                "--target=aarch64-linux-gnu",
+                "-pthread",
+                "-Wall",
+                "-Werror",
+                "-Wextra",
+                "-Wno-missing-field-initializers",
+                "-Wno-unused-parameter",
+                "-Wno-c++11-narrowing",
+                "-Wno-covered-switch-default",
+                "-Wno-unneeded-internal-declaration",
+                "-Wno-inconsistent-missing-override",
+                "-Wno-undefined-var-template",
+                "-Wno-nonportable-include-path",
+                "-Wno-address-of-packed-member",
+                "-Wno-unused-lambda-capture",
+                "-Wno-user-defined-warnings",
+                "-O2",
+                "-fno-ident",
+                "-fdata-sections",
+                "-ffunction-sections",
+                "-fno-omit-frame-pointer",
+                "-g0",
+                "-fvisibility=hidden",
+                "-Xclang",
+                "-load",
+                "-Xclang",
+                "../../../../../../media/webrtc/trunk/webrtc/third_party/llvm-build/Release+Asserts/lib/libFindBadConstructs.so",
+                "-Xclang",
+                "-add-plugin",
+                "-Xclang",
+                "find-bad-constructs",
+                "-Xclang",
+                "-plugin-arg-find-bad-constructs",
+                "-Xclang",
+                "check-auto-raw-pointer",
+                "-Xclang",
+                "-plugin-arg-find-bad-constructs",
+                "-Xclang",
+                "check-ipc",
+                "-Wheader-hygiene",
+                "-Wstring-conversion",
+                "-Wtautological-overlap-compare",
+                "-Wextra",
+                "-Wno-unused-parameter",
+                "-Wno-missing-field-initializers",
+                "-Wno-strict-overflow",
+                "-Wc++11-narrowing",
+                "-Wimplicit-fallthrough",
+                "-Wthread-safety",
+                "-Winconsistent-missing-override",
+                "-Wundef",
+                "-Wunused-lambda-capture"
+            ],
+            "defines": [
+                "V8_DEPRECATION_WARNINGS",
+                "USE_NSS_CERTS=1",
+                "USE_X11=1",
+                "NO_TCMALLOC",
+                "DISABLE_NACL",
+                "CHROMIUM_BUILD",
+                "_FILE_OFFSET_BITS=64",
+                "NDEBUG",
+                "NVALGRIND",
+                "DYNAMIC_ANNOTATIONS_ENABLED=0",
+                "WEBRTC_ENABLE_PROTOBUF=0",
+                "WEBRTC_RESTRICT_LOGGING",
+                "WEBRTC_ARCH_ARM64",
+                "WEBRTC_HAS_NEON",
+                "WEBRTC_MOZILLA_BUILD",
+                "WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS=0",
+                "WEBRTC_POSIX",
+                "WEBRTC_LINUX"
+            ],
+            "deps": [
+                "//modules:module_api",
+                "//rtc_base:rtc_base_approved"
+            ],
+            "include_dirs": [
+                "//",
+                "/home/jenkins/workspace/Firefox-default/label/aarch64/firefox/obj-aarch64-unknown-linux-gnu/media/webrtc/trunk/webrtc/gn-output/gen/"
+            ],
+            "libs": [
+                "rt"
+            ],
+            "sources": [
+                "//api/audio/audio_mixer.h"
+            ],
+            "type": "source_set"
+        },
+        "//api:base_peerconnection_api": {
+            "cflags": [
+                "-fno-strict-aliasing",
+                "--param=ssp-buffer-size=4",
+                "-fstack-protector",
+                "-Wno-builtin-macro-redefined",
+                "-D__DATE__=",
+                "-D__TIME__=",
+                "-D__TIMESTAMP__=",
+                "-funwind-tables",
+                "-fPIC",
+                "-pipe",
+                "-fcolor-diagnostics",
+                "--target=aarch64-linux-gnu",
+                "-pthread",
+                "-Wall",
+                "-Werror",
+                "-Wextra",
+                "-Wno-missing-field-initializers",
+                "-Wno-unused-parameter",
+                "-Wno-c++11-narrowing",
+                "-Wno-covered-switch-default",
+                "-Wno-unneeded-internal-declaration",
+                "-Wno-inconsistent-missing-override",
+                "-Wno-undefined-var-template",
+                "-Wno-nonportable-include-path",
+                "-Wno-address-of-packed-member",
+                "-Wno-unused-lambda-capture",
+                "-Wno-user-defined-warnings",
+                "-O2",
+                "-fno-ident",
+                "-fdata-sections",
+                "-ffunction-sections",
+                "-fno-omit-frame-pointer",
+                "-g0",
+                "-fvisibility=hidden",
+                "-Xclang",
+                "-load",
+                "-Xclang",
+                "../../../../../../media/webrtc/trunk/webrtc/third_party/llvm-build/Release+Asserts/lib/libFindBadConstructs.so",
+                "-Xclang",
+                "-add-plugin",
+                "-Xclang",
+                "find-bad-constructs",
+                "-Xclang",
+                "-plugin-arg-find-bad-constructs",
+                "-Xclang",
+                "check-auto-raw-pointer",
+                "-Xclang",
+                "-plugin-arg-find-bad-constructs",
+                "-Xclang",
+                "check-ipc",
+                "-Wheader-hygiene",
+                "-Wstring-conversion",
+                "-Wtautological-overlap-compare",
+                "-Wextra",
+                "-Wno-unused-parameter",
+                "-Wno-missing-field-initializers",
+                "-Wno-strict-overflow",
+                "-Wc++11-narrowing",
+                "-Wimplicit-fallthrough",
+                "-Wthread-safety",
+                "-Winconsistent-missing-override",
+                "-Wundef",
+                "-Wunused-lambda-capture"
+            ],
+            "defines": [
+                "V8_DEPRECATION_WARNINGS",
+                "USE_NSS_CERTS=1",
+                "USE_X11=1",
+                "NO_TCMALLOC",
+                "DISABLE_NACL",
+                "CHROMIUM_BUILD",
+                "_FILE_OFFSET_BITS=64",
+                "NDEBUG",
+                "NVALGRIND",
+                "DYNAMIC_ANNOTATIONS_ENABLED=0",
+                "WEBRTC_ENABLE_PROTOBUF=0",
+                "WEBRTC_RESTRICT_LOGGING",
+                "WEBRTC_ARCH_ARM64",
+                "WEBRTC_HAS_NEON",
+                "WEBRTC_MOZILLA_BUILD",
+                "WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS=0",
+                "WEBRTC_POSIX",
+                "WEBRTC_LINUX"
+            ],
+            "deps": [],
+            "include_dirs": [
+                "//",
+                "/home/jenkins/workspace/Firefox-default/label/aarch64/firefox/obj-aarch64-unknown-linux-gnu/media/webrtc/trunk/webrtc/gn-output/gen/"
+            ],
+            "libs": [],
+            "sources": [
+                "//api/rtpparameters.cc",
+                "//api/rtpparameters.h"
+            ],
+            "type": "static_library"
+        },
+        "//api:call_api": {
+            "cflags": [
+                "-fno-strict-aliasing",
+                "--param=ssp-buffer-size=4",
+                "-fstack-protector",
+                "-Wno-builtin-macro-redefined",
+                "-D__DATE__=",
+                "-D__TIME__=",
+                "-D__TIMESTAMP__=",
+                "-funwind-tables",
+                "-fPIC",
+                "-pipe",
+                "-fcolor-diagnostics",
+                "--target=aarch64-linux-gnu",
+                "-pthread",
+                "-Wall",
+                "-Werror",
+                "-Wextra",
+                "-Wno-missing-field-initializers",
+                "-Wno-unused-parameter",
+                "-Wno-c++11-narrowing",
+                "-Wno-covered-switch-default",
+                "-Wno-unneeded-internal-declaration",
+                "-Wno-inconsistent-missing-override",
+                "-Wno-undefined-var-template",
+                "-Wno-nonportable-include-path",
+                "-Wno-address-of-packed-member",
+                "-Wno-unused-lambda-capture",
+                "-Wno-user-defined-warnings",
+                "-O2",
+                "-fno-ident",
+                "-fdata-sections",
+                "-ffunction-sections",
+                "-fno-omit-frame-pointer",
+                "-g0",
+                "-fvisibility=hidden",
+                "-Xclang",
+                "-load",
+                "-Xclang",
+                "../../../../../../media/webrtc/trunk/webrtc/third_party/llvm-build/Release+Asserts/lib/libFindBadConstructs.so",
+                "-Xclang",
+                "-add-plugin",
+                "-Xclang",
+                "find-bad-constructs",
+                "-Xclang",
+                "-plugin-arg-find-bad-constructs",
+                "-Xclang",
+                "check-auto-raw-pointer",
+                "-Xclang",
+                "-plugin-arg-find-bad-constructs",
+                "-Xclang",
+                "check-ipc",
+                "-Wheader-hygiene",
+                "-Wstring-conversion",
+                "-Wtautological-overlap-compare",
+                "-Wextra",
+                "-Wno-unused-parameter",
+                "-Wno-missing-field-initializers",
+                "-Wno-strict-overflow",
+                "-Wc++11-narrowing",
+                "-Wimplicit-fallthrough",
+                "-Wthread-safety",
+                "-Winconsistent-missing-override",
+                "-Wundef",
+                "-Wunused-lambda-capture"
+            ],
+            "defines": [
+                "V8_DEPRECATION_WARNINGS",
+                "USE_NSS_CERTS=1",
+                "USE_X11=1",
+                "NO_TCMALLOC",
+                "DISABLE_NACL",
+                "CHROMIUM_BUILD",
+                "_FILE_OFFSET_BITS=64",
+                "NDEBUG",
+                "NVALGRIND",
+                "DYNAMIC_ANNOTATIONS_ENABLED=0",
+                "WEBRTC_ENABLE_PROTOBUF=0",
+                "WEBRTC_RESTRICT_LOGGING",
+                "WEBRTC_ARCH_ARM64",
+                "WEBRTC_HAS_NEON",
+                "WEBRTC_MOZILLA_BUILD",
+                "WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS=0",
+                "WEBRTC_POSIX",
+                "WEBRTC_LINUX"
+            ],
+            "deps": [
+                "//:webrtc_common",
+                "//api:audio_mixer_api",
+                "//api:transport_api",
+                "//api/audio_codecs:audio_codecs_api",
+