Merge m-c to fx-team. a=merge
authorRyan VanderMeulen <ryanvm@gmail.com>
Tue, 04 Aug 2015 15:55:24 -0400
changeset 287787 cf4a7df98beba52fcd26f4b129eb00a3e822efb9
parent 287786 f52bfe71d212377a9bd48708e3e8467727a4f791 (current diff)
parent 287764 a41bc7b8a24bd3f1cafe6af25629a72e73ad0d2e (diff)
child 287788 59ea22a660a5be6f8786b83b3334bcdddfcf5372
push id5067
push userraliiev@mozilla.com
push dateMon, 21 Sep 2015 14:04:52 +0000
treeherdermozilla-beta@14221ffe5b2f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone42.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 m-c to fx-team. a=merge CLOSED TREE
--- a/b2g/config/aries/sources.xml
+++ b/b2g/config/aries/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="67c38af8347f93ddc005a53f427d651b744b55c1"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="c5425d9f1f5184731a59ed4bc99295acbde30390"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4d9fbc08e87731447c19e96e13d8c7444baafcca"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="657894b4a1dc0a926117f4812e0940229f9f676f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="6ddfd98cdafefaa1b60273d5568b8dbd13730dae"/>
--- a/b2g/config/dolphin/sources.xml
+++ b/b2g/config/dolphin/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="67c38af8347f93ddc005a53f427d651b744b55c1"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="c5425d9f1f5184731a59ed4bc99295acbde30390"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4d9fbc08e87731447c19e96e13d8c7444baafcca"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="657894b4a1dc0a926117f4812e0940229f9f676f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="6ddfd98cdafefaa1b60273d5568b8dbd13730dae"/>
--- a/b2g/config/emulator-ics/sources.xml
+++ b/b2g/config/emulator-ics/sources.xml
@@ -14,17 +14,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="1b0db93fb6b870b03467aff50d6419771ba0d88c">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="67c38af8347f93ddc005a53f427d651b744b55c1"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="c5425d9f1f5184731a59ed4bc99295acbde30390"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4d9fbc08e87731447c19e96e13d8c7444baafcca"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="8bc59310552179f9a8bc6cdd0188e2475df52fb7"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="9d0e5057ee5404a31ec1bf76131cb11336a7c3b6"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="657894b4a1dc0a926117f4812e0940229f9f676f"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="34ea6163f9f0e0122fb0bb03607eccdca31ced7a"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/emulator-jb/sources.xml
+++ b/b2g/config/emulator-jb/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="660169a3d7e034a892359e39135e8c2785a6ad6f">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="67c38af8347f93ddc005a53f427d651b744b55c1"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="c5425d9f1f5184731a59ed4bc99295acbde30390"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4d9fbc08e87731447c19e96e13d8c7444baafcca"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="657894b4a1dc0a926117f4812e0940229f9f676f"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="6ddfd98cdafefaa1b60273d5568b8dbd13730dae"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
--- a/b2g/config/emulator-kk/sources.xml
+++ b/b2g/config/emulator-kk/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="67c38af8347f93ddc005a53f427d651b744b55c1"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="c5425d9f1f5184731a59ed4bc99295acbde30390"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4d9fbc08e87731447c19e96e13d8c7444baafcca"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="657894b4a1dc0a926117f4812e0940229f9f676f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="6ddfd98cdafefaa1b60273d5568b8dbd13730dae"/>
--- a/b2g/config/emulator-l/sources.xml
+++ b/b2g/config/emulator-l/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="07c383a786f188904311a37f6062c2cb84c9b61d">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="67c38af8347f93ddc005a53f427d651b744b55c1"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="c5425d9f1f5184731a59ed4bc99295acbde30390"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4d9fbc08e87731447c19e96e13d8c7444baafcca"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="657894b4a1dc0a926117f4812e0940229f9f676f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="6ddfd98cdafefaa1b60273d5568b8dbd13730dae"/>
--- a/b2g/config/emulator/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -14,17 +14,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="1b0db93fb6b870b03467aff50d6419771ba0d88c">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="67c38af8347f93ddc005a53f427d651b744b55c1"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="c5425d9f1f5184731a59ed4bc99295acbde30390"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4d9fbc08e87731447c19e96e13d8c7444baafcca"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="8bc59310552179f9a8bc6cdd0188e2475df52fb7"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="9d0e5057ee5404a31ec1bf76131cb11336a7c3b6"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="657894b4a1dc0a926117f4812e0940229f9f676f"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="34ea6163f9f0e0122fb0bb03607eccdca31ced7a"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/flame-kk/sources.xml
+++ b/b2g/config/flame-kk/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="67c38af8347f93ddc005a53f427d651b744b55c1"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="c5425d9f1f5184731a59ed4bc99295acbde30390"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4d9fbc08e87731447c19e96e13d8c7444baafcca"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="657894b4a1dc0a926117f4812e0940229f9f676f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="6ddfd98cdafefaa1b60273d5568b8dbd13730dae"/>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,9 +1,9 @@
 {
     "git": {
-        "git_revision": "67c38af8347f93ddc005a53f427d651b744b55c1", 
+        "git_revision": "c5425d9f1f5184731a59ed4bc99295acbde30390", 
         "remote": "https://git.mozilla.org/releases/gaia.git", 
         "branch": ""
     }, 
-    "revision": "72807eee01421a4ddf6180b2e5a66757a42a7984", 
+    "revision": "68ce99a4e1761c06e5f31f6674ee46fef1bbf44b", 
     "repo_path": "integration/gaia-central"
 }
--- a/b2g/config/nexus-4/sources.xml
+++ b/b2g/config/nexus-4/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="660169a3d7e034a892359e39135e8c2785a6ad6f">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="67c38af8347f93ddc005a53f427d651b744b55c1"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="c5425d9f1f5184731a59ed4bc99295acbde30390"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4d9fbc08e87731447c19e96e13d8c7444baafcca"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="657894b4a1dc0a926117f4812e0940229f9f676f"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="6ddfd98cdafefaa1b60273d5568b8dbd13730dae"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
--- a/b2g/config/nexus-5-l/sources.xml
+++ b/b2g/config/nexus-5-l/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="07c383a786f188904311a37f6062c2cb84c9b61d">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="67c38af8347f93ddc005a53f427d651b744b55c1"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="c5425d9f1f5184731a59ed4bc99295acbde30390"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4d9fbc08e87731447c19e96e13d8c7444baafcca"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="657894b4a1dc0a926117f4812e0940229f9f676f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="6ddfd98cdafefaa1b60273d5568b8dbd13730dae"/>
--- a/browser/config/tooltool-manifests/linux32/releng.manifest
+++ b/browser/config/tooltool-manifests/linux32/releng.manifest
@@ -2,21 +2,20 @@
 {
 "size": 80458572,
 "digest": "e5101f9dee1e462f6cbd3897ea57eede41d23981825c7b20d91d23ab461875d54d3dfc24999aa58a31e8b01f49fb3140e05ffe5af2957ef1d1afb89fd0dfe1ad",
 "algorithm": "sha512", 
 "filename": "gcc.tar.xz",
 "unpack": true
 },
 {
-"size": 11179576,
-"digest": "91567ce8e2bb8ab0ebc60c31e90731d88a1ea889fb71bcf55c735746a60fa7610b7e040ea3d8f727b6f692ae3ee703d6f3b30cdbd76fdf5617f77d9c38aa20ed",
+"size": 4079256,
+"digest": "bb5238558bcf6db2ca395513c8dccaa15dd61b3c375598eb6a685356b0c1a2d9840e3bf81bc00242b872fd798541f53d723777c754412abf0e772b7cc284937c",
 "algorithm": "sha512",
 "filename": "gtk3.tar.xz",
-"setup": "setup.sh",
 "unpack": true
 },
 {
 "size": 167175,
 "digest": "0b71a936edf5bd70cf274aaa5d7abc8f77fe8e7b5593a208f805cc9436fac646b9c4f0b43c2b10de63ff3da671497d35536077ecbc72dba7f8159a38b580f831",
 "algorithm": "sha512",
 "filename": "sccache.tar.bz2",
 "unpack": true
--- a/browser/config/tooltool-manifests/linux64/clang.manifest
+++ b/browser/config/tooltool-manifests/linux64/clang.manifest
@@ -5,16 +5,15 @@
 {
 "size": 100307285, 
 "digest": "4d147d0072a928945fc1e938f39a5d0a9d3c676399c09e092c8750b2f973cdbbebda8d94d4d05805fae74a5c49c54263dc22b8b443c23c9a0ae830a261d3cf30", 
 "algorithm": "sha512", 
 "filename": "clang.tar.bz2",
 "unpack": true
 },
 {
-"size": 12057960,
-"digest": "6105d6432943141cffb40020dc5ba3a793650bdeb3af9bd5e56d3796c5f03df9962a73e521646cd71fbfb5e266c1e74716ad722fb6055589dfb7d35175bca89e",
+"size": 4431740,
+"digest": "68fc56b0fb0cdba629b95683d6649ff76b00dccf97af90960c3d7716f6108b2162ffd5ffcd5c3a60a21b28674df688fe4dabc67345e2da35ec5abeae3d48c8e3",
 "algorithm": "sha512",
 "filename": "gtk3.tar.xz",
-"setup": "setup.sh",
 "unpack": true
 }
 ]
--- a/browser/config/tooltool-manifests/linux64/releng.manifest
+++ b/browser/config/tooltool-manifests/linux64/releng.manifest
@@ -2,21 +2,20 @@
 {
 "size": 80458572,
 "digest": "e5101f9dee1e462f6cbd3897ea57eede41d23981825c7b20d91d23ab461875d54d3dfc24999aa58a31e8b01f49fb3140e05ffe5af2957ef1d1afb89fd0dfe1ad",
 "algorithm": "sha512", 
 "filename": "gcc.tar.xz",
 "unpack": true
 },
 {
-"size": 12057960,
-"digest": "6105d6432943141cffb40020dc5ba3a793650bdeb3af9bd5e56d3796c5f03df9962a73e521646cd71fbfb5e266c1e74716ad722fb6055589dfb7d35175bca89e",
+"size": 4431740,
+"digest": "68fc56b0fb0cdba629b95683d6649ff76b00dccf97af90960c3d7716f6108b2162ffd5ffcd5c3a60a21b28674df688fe4dabc67345e2da35ec5abeae3d48c8e3",
 "algorithm": "sha512",
 "filename": "gtk3.tar.xz",
-"setup": "setup.sh",
 "unpack": true
 },
 {
 "size": 167175,
 "digest": "0b71a936edf5bd70cf274aaa5d7abc8f77fe8e7b5593a208f805cc9436fac646b9c4f0b43c2b10de63ff3da671497d35536077ecbc72dba7f8159a38b580f831",
 "algorithm": "sha512",
 "filename": "sccache.tar.bz2",
 "unpack": true
--- a/browser/config/tooltool-manifests/linux64/tsan.manifest
+++ b/browser/config/tooltool-manifests/linux64/tsan.manifest
@@ -5,16 +5,15 @@
 {
 "size": 89690541, 
 "digest": "470d258d9785a120fcba65eee90daa632a42affa0f97f57d70fc8285bd76bcc27d4d0d70b6c37577ab271a04c843b6269425391a8d6df1967718dba26dd3a73d", 
 "algorithm": "sha512", 
 "filename": "clang.tar.bz2",
 "unpack": true
 },
 {
-"size": 12057960,
-"digest": "6105d6432943141cffb40020dc5ba3a793650bdeb3af9bd5e56d3796c5f03df9962a73e521646cd71fbfb5e266c1e74716ad722fb6055589dfb7d35175bca89e",
+"size": 4431740,
+"digest": "68fc56b0fb0cdba629b95683d6649ff76b00dccf97af90960c3d7716f6108b2162ffd5ffcd5c3a60a21b28674df688fe4dabc67345e2da35ec5abeae3d48c8e3",
 "algorithm": "sha512",
 "filename": "gtk3.tar.xz",
-"setup": "setup.sh",
 "unpack": true
 }
 ]
--- a/browser/locales/en-US/chrome/browser/browser.properties
+++ b/browser/locales/en-US/chrome/browser/browser.properties
@@ -635,17 +635,21 @@ getUserMedia.sharingMenu.accesskey = d
 #                    getUserMedia.sharingMenuCameraAudioCaptureBrowser,
 #                    getUserMedia.sharingMenuCameraApplication,
 #                    getUserMedia.sharingMenuCameraScreen,
 #                    getUserMedia.sharingMenuCameraWindow,
 #                    getUserMedia.sharingMenuCameraBrowser,
 #                    getUserMedia.sharingMenuMicrophoneApplication,
 #                    getUserMedia.sharingMenuMicrophoneScreen,
 #                    getUserMedia.sharingMenuMicrophoneWindow,
-#                    getUserMedia.sharingMenuMicrophoneBrowser):
+#                    getUserMedia.sharingMenuMicrophoneBrowser,
+#                    getUserMedia.sharingMenuAudioCaptureApplication,
+#                    getUserMedia.sharingMenuAudioCaptureScreen,
+#                    getUserMedia.sharingMenuAudioCaptureWindow,
+#                    getUserMedia.sharingMenuAudioCaptureBrowser):
 # %S is the website origin (e.g. www.mozilla.org)
 getUserMedia.sharingMenuCamera = %S (camera)
 getUserMedia.sharingMenuMicrophone = %S (microphone)
 getUserMedia.sharingMenuAudioCapture = %S (tab audio)
 getUserMedia.sharingMenuApplication = %S (application)
 getUserMedia.sharingMenuScreen = %S (screen)
 getUserMedia.sharingMenuWindow = %S (window)
 getUserMedia.sharingMenuBrowser = %S (tab)
@@ -662,20 +666,20 @@ getUserMedia.sharingMenuCameraAudioCaptu
 getUserMedia.sharingMenuCameraApplication = %S (camera and application)
 getUserMedia.sharingMenuCameraScreen = %S (camera and screen)
 getUserMedia.sharingMenuCameraWindow = %S (camera and window)
 getUserMedia.sharingMenuCameraBrowser = %S (camera and tab)
 getUserMedia.sharingMenuMicrophoneApplication = %S (microphone and application)
 getUserMedia.sharingMenuMicrophoneScreen = %S (microphone and screen)
 getUserMedia.sharingMenuMicrophoneWindow = %S (microphone and window)
 getUserMedia.sharingMenuMicrophoneBrowser = %S (microphone and tab)
-getUserMedia.sharingMenuMicrophoneApplication = %S (tab audio and application)
-getUserMedia.sharingMenuMicrophoneScreen = %S (tab audio and screen)
-getUserMedia.sharingMenuMicrophoneWindow = %S (tab audio and window)
-getUserMedia.sharingMenuMicrophoneBrowser = %S (tab audio and tab)
+getUserMedia.sharingMenuAudioCaptureApplication = %S (tab audio and application)
+getUserMedia.sharingMenuAudioCaptureScreen = %S (tab audio and screen)
+getUserMedia.sharingMenuAudioCaptureWindow = %S (tab audio and window)
+getUserMedia.sharingMenuAudioCaptureBrowser = %S (tab audio and tab)
 # LOCALIZATION NOTE(getUserMedia.sharingMenuUnknownHost): this is used for the website
 # origin for the sharing menu if no readable origin could be deduced from the URL.
 getUserMedia.sharingMenuUnknownHost = Unknown origin
 
 # LOCALIZATION NOTE(emeNotifications.drmContentPlaying.message2): %S is brandShortName.
 emeNotifications.drmContentPlaying.message2 = Some audio or video on this site uses DRM software, which may limit what %S can let you do with it.
 emeNotifications.drmContentPlaying.button.label = Configureā€¦
 emeNotifications.drmContentPlaying.button.accesskey = C
--- a/build/unix/build-gtk3/build-gtk3.sh
+++ b/build/unix/build-gtk3/build-gtk3.sh
@@ -52,17 +52,17 @@ build() {
 	version=$(eval echo \$${pkg}_version)
 	url=$(eval echo \$${pkg}_url)
 	wget -c -P $TMPDIR $url
 	tar -axf $TMPDIR/$name-$version.tar.*
 	mkdir -p build/$name
 	cd build/$name
 	eval ../../$name-$version/configure --disable-static $* $configure_args
 	make $make_flags
-	make install DESTDIR=$root_dir/gtk3
+	make install-strip DESTDIR=$root_dir/gtk3
 	find $root_dir/gtk3 -name \*.la -delete
 	cd ../..
 }
 
 case "$1" in
 32)
 	configure_args='--host=i686-pc-linux --build=i686-pc-linux CC="gcc -m32" CXX="g++ -m32"'
         lib=lib
@@ -98,49 +98,10 @@ build cairo --enable-tee
 build pango
 build atk
 make_flags="$make_flags GLIB_COMPILE_SCHEMAS=glib-compile-schemas"
 build gtk+
 
 rm -rf $root_dir/gtk3/usr/local/share/gtk-doc
 rm -rf $root_dir/gtk3/usr/local/share/locale
 
-# mock build environment doesn't have fonts in /usr/share/fonts, but
-# has some in /usr/share/X11/fonts. Add this directory to the
-# fontconfig configuration without changing the gtk3 tooltool package.
-cat << EOF > $root_dir/gtk3/usr/local/etc/fonts/local.conf
-<?xml version="1.0"?>
-<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
-<fontconfig>
-  <dir>/usr/share/X11/fonts</dir>
-</fontconfig>
-EOF
-
-cat <<EOF > $root_dir/gtk3/setup.sh
-#!/bin/sh
-
-cd \$(dirname \$0)
-
-# pango expects absolute paths in pango.modules, and TOOLTOOL_DIR may vary...
-LD_LIBRARY_PATH=./usr/local/lib \
-PANGO_SYSCONFDIR=./usr/local/etc \
-PANGO_LIBDIR=./usr/local/lib \
-./usr/local/bin/pango-querymodules > ./usr/local/etc/pango/pango.modules
-
-# same with gdb-pixbuf and loaders.cache
-LD_LIBRARY_PATH=./usr/local/lib \
-GDK_PIXBUF_MODULE_FILE=./usr/local/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache \
-GDK_PIXBUF_MODULEDIR=./usr/local/lib/gdk-pixbuf-2.0/2.10.0/loaders \
-./usr/local/bin/gdk-pixbuf-query-loaders > ./usr/local/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache
-
-# The fontconfig version in the tooltool package has known uses of
-# uninitialized memory when creating its cache, and while most users
-# will already have an existing cache, running Firefox on automation
-# will create it. Combined with valgrind, this generates irrelevant
-# errors.
-# So create the fontconfig cache beforehand.
-./usr/local/bin/fc-cache
-EOF
-
-chmod +x $root_dir/gtk3/setup.sh
-
 cd $cwd
 tar -C $root_dir -Jcf gtk3.tar.xz gtk3
--- a/build/unix/mozconfig.gtk
+++ b/build/unix/mozconfig.gtk
@@ -6,23 +6,53 @@ if [ -d "$TOOLTOOL_DIR/gtk3" ]; then
     echo PKG_CONFIG_LIBDIR must be set >&2
     exit 1
   fi
   export PKG_CONFIG_SYSROOT_DIR="$TOOLTOOL_DIR/gtk3"
   export PKG_CONFIG_PATH="$TOOLTOOL_DIR/gtk3/usr/local/lib/pkgconfig"
   export PATH="$TOOLTOOL_DIR/gtk3/usr/local/bin:${PATH}"
   # Ensure cairo, gdk-pixbuf, etc. are not taken from the system installed packages.
   LDFLAGS="-L$TOOLTOOL_DIR/gtk3/usr/local/lib ${LDFLAGS}"
+  mk_add_options "export LD_LIBRARY_PATH=$TOOLTOOL_DIR/gtk3/usr/local/lib"
   ac_add_options --enable-default-toolkit=cairo-gtk3
 
   # Set things up to use Gtk+3 from the tooltool package
   mk_add_options "export FONTCONFIG_PATH=$TOOLTOOL_DIR/gtk3/usr/local/etc/fonts"
   mk_add_options "export PANGO_SYSCONFDIR=$TOOLTOOL_DIR/gtk3/usr/local/etc"
   mk_add_options "export PANGO_LIBDIR=$TOOLTOOL_DIR/gtk3/usr/local/lib"
   mk_add_options "export GDK_PIXBUF_MODULE_FILE=$TOOLTOOL_DIR/gtk3/usr/local/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache"
   mk_add_options "export GDK_PIXBUF_MODULEDIR=$TOOLTOOL_DIR/gtk3/usr/local/lib/gdk-pixbuf-2.0/2.10.0/loaders"
   mk_add_options "export LD_LIBRARY_PATH=$TOOLTOOL_DIR/gtk3/usr/local/lib"
 
-  # Until a tooltool with bug 1188571 landed is available everywhere
-  $TOOLTOOL_DIR/gtk3/setup.sh
+  # pango expects absolute paths in pango.modules, and TOOLTOOL_DIR may vary...
+  LD_LIBRARY_PATH=$TOOLTOOL_DIR/gtk3/usr/local/lib \
+  PANGO_SYSCONFDIR=$TOOLTOOL_DIR/gtk3/usr/local/etc \
+  PANGO_LIBDIR=$TOOLTOOL_DIR/gtk3/usr/local/lib \
+  $TOOLTOOL_DIR/gtk3/usr/local/bin/pango-querymodules > $TOOLTOOL_DIR/gtk3/usr/local/etc/pango/pango.modules
+
+  # same with gdb-pixbuf and loaders.cache
+  LD_LIBRARY_PATH=$TOOLTOOL_DIR/gtk3/usr/local/lib \
+  GDK_PIXBUF_MODULE_FILE=$TOOLTOOL_DIR/gtk3/usr/local/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache \
+  GDK_PIXBUF_MODULEDIR=$TOOLTOOL_DIR/gtk3/usr/local/lib/gdk-pixbuf-2.0/2.10.0/loaders \
+  $TOOLTOOL_DIR/gtk3/usr/local/bin/gdk-pixbuf-query-loaders > $TOOLTOOL_DIR/gtk3/usr/local/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache
+
+  # The fontconfig version in the tooltool package has known uses of
+  # uninitialized memory when creating its cache, and while most users
+  # will already have an existing cache, running Firefox on automation
+  # will create it. Combined with valgrind, this generates irrelevant
+  # errors.
+  # So create the fontconfig cache beforehand.
+  $TOOLTOOL_DIR/gtk3/usr/local/bin/fc-cache
+
+  # mock build environment doesn't have fonts in /usr/share/fonts, but
+  # has some in /usr/share/X11/fonts. Add this directory to the
+  # fontconfig configuration without changing the gtk3 tooltool package.
+  cat << EOF > $TOOLTOOL_DIR/gtk3/usr/local/etc/fonts/local.conf
+<?xml version="1.0"?>
+<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
+<fontconfig>
+  <dir>/usr/share/X11/fonts</dir>
+</fontconfig>
+EOF
+
 else
   ac_add_options --enable-default-toolkit=cairo-gtk2
 fi
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -3723,22 +3723,24 @@ void HTMLMediaElement::ChangeNetworkStat
   // Changing mNetworkState affects AddRemoveSelfReference().
   AddRemoveSelfReference();
 }
 
 bool HTMLMediaElement::CanActivateAutoplay()
 {
   // For stream inputs, we activate autoplay on HAVE_NOTHING because
   // this element itself might be blocking the stream from making progress by
-  // being paused.
+  // being paused. We also activate autopaly when playing a media source since
+  // the data download is controlled by the script and there is no way to
+  // evaluate MediaDecoder::CanPlayThrough().
   return !mPausedForInactiveDocumentOrChannel &&
          mAutoplaying &&
          mPaused &&
          ((mDecoder && mReadyState >= nsIDOMHTMLMediaElement::HAVE_ENOUGH_DATA) ||
-          mSrcStream) &&
+          mSrcStream || mMediaSource) &&
          HasAttr(kNameSpaceID_None, nsGkAtoms::autoplay) &&
          mAutoplayEnabled &&
          !IsEditable();
 }
 
 void HTMLMediaElement::CheckAutoplayDataReady()
 {
   if (!CanActivateAutoplay()) {
--- a/dom/icc/gonk/IccService.js
+++ b/dom/icc/gonk/IccService.js
@@ -91,17 +91,17 @@ function IccContact(aContact) {
   }
 
   if (aContact.number) {
     this._numbers.push(aContact.number);
   }
 
   let anrLen = aContact.anr ? aContact.anr.length : 0;
   for (let i = 0; i < anrLen; i++) {
-    this._numbers.push(anr[i]);
+    this._numbers.push(aContact.anr[i]);
   }
 
   if (aContact.email) {
     this._emails.push(aContact.email);
   }
 }
 IccContact.prototype = {
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIIccContact]),
@@ -712,17 +712,17 @@ Icc.prototype = {
     if (count.value > 0) {
       iccContact.number = numbers[0];
 
       let anrArray = numbers.slice(1);
       let length = anrArray.length;
       if (length > 0) {
         iccContact.anr = [];
         for (let i = 0; i < length; i++) {
-          iccContact.anr.push(anrArray[i].value);
+          iccContact.anr.push(anrArray[i]);
         }
       }
     }
 
     let emails = aContact.getEmails(count);
     if (count.value > 0) {
       iccContact.email = emails[0];
     }
--- a/dom/media/GraphDriver.cpp
+++ b/dom/media/GraphDriver.cpp
@@ -275,76 +275,73 @@ SystemClockDriver::~SystemClockDriver()
 
 void
 ThreadedDriver::RunThread()
 {
   AutoProfilerUnregisterThread autoUnregister;
 
   bool stillProcessing = true;
   while (stillProcessing) {
-    GraphTime prevCurrentTime, nextCurrentTime;
-    GetIntervalForIteration(prevCurrentTime, nextCurrentTime);
+    mIterationStart = IterationEnd();
+    mIterationEnd += GetIntervalForIteration();
+
+    if (mStateComputedTime < mIterationEnd) {
+      STREAM_LOG(LogLevel::Warning, ("Media graph global underrun detected"));
+      mIterationEnd = mStateComputedTime;
+    }
 
-    mStateComputedTime = mNextStateComputedTime;
+    if (mIterationStart >= mIterationEnd) {
+      NS_ASSERTION(mIterationStart == mIterationEnd ,
+                   "Time can't go backwards!");
+      // This could happen due to low clock resolution, maybe?
+      STREAM_LOG(LogLevel::Debug, ("Time did not advance"));
+    }
+
+    MOZ_ASSERT(mStateComputedTime == mNextStateComputedTime);
     mNextStateComputedTime =
       mGraphImpl->RoundUpToNextAudioBlock(
-        nextCurrentTime + mGraphImpl->MillisecondsToMediaTime(AUDIO_TARGET_MS));
+        mIterationEnd + mGraphImpl->MillisecondsToMediaTime(AUDIO_TARGET_MS));
     STREAM_LOG(LogLevel::Debug,
                ("interval[%ld; %ld] state[%ld; %ld]",
                (long)mIterationStart, (long)mIterationEnd,
                (long)mStateComputedTime, (long)mNextStateComputedTime));
 
     mGraphImpl->mFlushSourcesNow = mGraphImpl->mFlushSourcesOnNextIteration;
     mGraphImpl->mFlushSourcesOnNextIteration = false;
-    stillProcessing = mGraphImpl->OneIteration(prevCurrentTime,
-                                               nextCurrentTime,
+    stillProcessing = mGraphImpl->OneIteration(mIterationStart,
+                                               mIterationEnd,
                                                StateComputedTime(),
                                                mNextStateComputedTime);
 
     if (mNextDriver && stillProcessing) {
       STREAM_LOG(LogLevel::Debug, ("Switching to AudioCallbackDriver"));
       mNextDriver->SetGraphTime(this, mIterationStart, mIterationEnd,
                                  mStateComputedTime, mNextStateComputedTime);
       mGraphImpl->SetCurrentDriver(mNextDriver);
       mNextDriver->Start();
       return;
     }
   }
 }
 
-void
-SystemClockDriver::GetIntervalForIteration(GraphTime& aFrom, GraphTime& aTo)
+MediaTime
+SystemClockDriver::GetIntervalForIteration()
 {
   TimeStamp now = TimeStamp::Now();
-  aFrom = mIterationStart = IterationEnd();
-  aTo = mIterationEnd = mGraphImpl->SecondsToMediaTime((now - mCurrentTimeStamp).ToSeconds()) + IterationEnd();
-
+  MediaTime interval =
+    mGraphImpl->SecondsToMediaTime((now - mCurrentTimeStamp).ToSeconds());
   mCurrentTimeStamp = now;
 
-  MOZ_LOG(gMediaStreamGraphLog, LogLevel::Verbose, ("Updating current time to %f (real %f, mStateComputedTime %f)",
-         mGraphImpl->MediaTimeToSeconds(aTo),
-         (now - mInitialTimeStamp).ToSeconds(),
-         mGraphImpl->MediaTimeToSeconds(StateComputedTime())));
-
-  if (mStateComputedTime < aTo) {
-    STREAM_LOG(LogLevel::Warning, ("Media graph global underrun detected"));
-    aTo = mIterationEnd = mStateComputedTime;
-  }
+  MOZ_LOG(gMediaStreamGraphLog, LogLevel::Verbose,
+          ("Updating current time to %f (real %f, mStateComputedTime %f)",
+           mGraphImpl->MediaTimeToSeconds(IterationEnd() + interval),
+           (now - mInitialTimeStamp).ToSeconds(),
+           mGraphImpl->MediaTimeToSeconds(StateComputedTime())));
 
-  if (aFrom >= aTo) {
-    NS_ASSERTION(aFrom == aTo , "Time can't go backwards!");
-    // This could happen due to low clock resolution, maybe?
-    STREAM_LOG(LogLevel::Debug, ("Time did not advance"));
-  }
-}
-
-GraphTime
-SystemClockDriver::GetCurrentTime()
-{
-  return IterationEnd();
+  return interval;
 }
 
 TimeStamp
 OfflineClockDriver::GetCurrentTimeStamp()
 {
   MOZ_CRASH("This driver does not support getting the current timestamp.");
   return TimeStamp();
 }
@@ -427,41 +424,22 @@ OfflineClockDriver::~OfflineClockDriver(
   // XXX should use .forget()/etc
   if (mThread) {
     nsCOMPtr<nsIRunnable> event = new MediaStreamGraphShutdownThreadRunnable2(mThread);
     mThread = nullptr;
     NS_DispatchToMainThread(event);
   }
 }
 
-void
-OfflineClockDriver::GetIntervalForIteration(GraphTime& aFrom, GraphTime& aTo)
+MediaTime
+OfflineClockDriver::GetIntervalForIteration()
 {
-  aFrom = mIterationStart = IterationEnd();
-  aTo = mIterationEnd = IterationEnd() + mGraphImpl->MillisecondsToMediaTime(mSlice);
-
-  if (mStateComputedTime < aTo) {
-    STREAM_LOG(LogLevel::Warning, ("Media graph global underrun detected"));
-    aTo = mIterationEnd = mStateComputedTime;
-  }
-
-  if (aFrom >= aTo) {
-    NS_ASSERTION(aFrom == aTo , "Time can't go backwards!");
-    // This could happen due to low clock resolution, maybe?
-    STREAM_LOG(LogLevel::Debug, ("Time did not advance"));
-  }
+  return mGraphImpl->MillisecondsToMediaTime(mSlice);
 }
 
-GraphTime
-OfflineClockDriver::GetCurrentTime()
-{
-  return mIterationEnd;
-}
-
-
 void
 OfflineClockDriver::WaitForNextIteration()
 {
   // No op: we want to go as fast as possible when we are offline
 }
 
 void
 OfflineClockDriver::WakeUp()
@@ -700,34 +678,16 @@ AudioCallbackDriver::Revive()
   } else {
     STREAM_LOG(LogLevel::Debug, ("Starting audio threads for MediaStreamGraph %p from a new thread.", mGraphImpl));
     nsRefPtr<AsyncCubebTask> initEvent =
       new AsyncCubebTask(this, AsyncCubebOperation::INIT);
     initEvent->Dispatch();
   }
 }
 
-void
-AudioCallbackDriver::GetIntervalForIteration(GraphTime& aFrom,
-                                             GraphTime& aTo)
-{
-}
-
-GraphTime
-AudioCallbackDriver::GetCurrentTime()
-{
-  uint64_t position = 0;
-
-  if (cubeb_stream_get_position(mAudioStream, &position) != CUBEB_OK) {
-    NS_WARNING("Could not get current time from cubeb.");
-  }
-
-  return mSampleRate * position;
-}
-
 void AudioCallbackDriver::WaitForNextIteration()
 {
 }
 
 void
 AudioCallbackDriver::WakeUp()
 {
   mGraphImpl->GetMonitor().AssertCurrentThreadOwns();
@@ -857,17 +817,17 @@ AudioCallbackDriver::DataCallback(AudioD
   mBuffer.SetBuffer(aBuffer, aFrames);
   // fill part or all with leftover data from last iteration (since we
   // align to Audio blocks)
   mScratchBuffer.Empty(mBuffer);
   // if we totally filled the buffer (and mScratchBuffer isn't empty),
   // we don't need to run an iteration and if we do so we may overflow.
   if (mBuffer.Available()) {
 
-    mStateComputedTime = mNextStateComputedTime;
+    MOZ_ASSERT(mStateComputedTime == mNextStateComputedTime);
 
     // State computed time is decided by the audio callback's buffer length. We
     // compute the iteration start and end from there, trying to keep the amount
     // of buffering in the graph constant.
     mNextStateComputedTime =
       mGraphImpl->RoundUpToNextAudioBlock(mStateComputedTime + mBuffer.Available());
 
     mIterationStart = mIterationEnd;
--- a/dom/media/GraphDriver.h
+++ b/dom/media/GraphDriver.h
@@ -45,33 +45,18 @@ static const int SCHEDULE_SAFETY_MARGIN_
  * is 2*MEDIA_GRAPH_TARGET_PERIOD_MS + SCHEDULE_SAFETY_MARGIN_MS.
  * There is no point in buffering more audio than this in a stream at any
  * given time (until we add processing).
  * This is not optimal yet.
  */
 static const int AUDIO_TARGET_MS = 2*MEDIA_GRAPH_TARGET_PERIOD_MS +
     SCHEDULE_SAFETY_MARGIN_MS;
 
-/**
- * Try have this much video buffered. Video frames are set
- * near the end of the iteration of the control loop. The maximum delay
- * to the setting of the next video frame is 2*MEDIA_GRAPH_TARGET_PERIOD_MS +
- * SCHEDULE_SAFETY_MARGIN_MS. This is not optimal yet.
- */
-static const int VIDEO_TARGET_MS = 2*MEDIA_GRAPH_TARGET_PERIOD_MS +
-    SCHEDULE_SAFETY_MARGIN_MS;
-
 class MediaStreamGraphImpl;
 
-/**
- * Microseconds relative to the start of the graph timeline.
- */
-typedef int64_t GraphTime;
-const GraphTime GRAPH_TIME_MAX = MEDIA_TIME_MAX;
-
 class AudioCallbackDriver;
 class OfflineClockDriver;
 
 /**
  * A driver is responsible for the scheduling of the processing, the thread
  * management, and give the different clocks to a MediaStreamGraph. This is an
  * abstract base class. A MediaStreamGraph can be driven by an
  * OfflineClockDriver, if the graph is offline, or a SystemClockDriver, if the
@@ -79,23 +64,16 @@ class OfflineClockDriver;
  * A MediaStreamGraph holds an owning reference to its driver.
  */
 class GraphDriver
 {
 public:
   explicit GraphDriver(MediaStreamGraphImpl* aGraphImpl);
 
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GraphDriver);
-  /* When the graph wakes up to do an iteration, this returns the range of time
-   * that will be processed. */
-  virtual void GetIntervalForIteration(GraphTime& aFrom,
-                                       GraphTime& aTo) = 0;
-  /* Returns the current time for this graph. This is the end of the current
-   * iteration. */
-  virtual GraphTime GetCurrentTime() = 0;
   /* For real-time graphs, this waits until it's time to process more data. For
    * offline graphs, this is a no-op. */
   virtual void WaitForNextIteration() = 0;
   /* Wakes up the graph if it is waiting. */
   virtual void WakeUp() = 0;
   virtual void Destroy() {}
   /* Start the graph, init the driver, start the thread. */
   virtual void Start() = 0;
@@ -272,32 +250,35 @@ public:
   void RunThread();
   friend class MediaStreamGraphInitThreadRunnable;
   virtual uint32_t IterationDuration() override {
     return MEDIA_GRAPH_TARGET_PERIOD_MS;
   }
 
   virtual bool OnThread() override { return !mThread || NS_GetCurrentThread() == mThread; }
 
+  /* When the graph wakes up to do an iteration, implementations return the
+   * range of time that will be processed.  This is called only once per
+   * iteration; it may determine the interval from state in a previous
+   * call. */
+  virtual MediaTime GetIntervalForIteration() = 0;
 protected:
   nsCOMPtr<nsIThread> mThread;
 };
 
 /**
  * A SystemClockDriver drives a MediaStreamGraph using a system clock, and waits
  * using a monitor, between each iteration.
  */
 class SystemClockDriver : public ThreadedDriver
 {
 public:
   explicit SystemClockDriver(MediaStreamGraphImpl* aGraphImpl);
   virtual ~SystemClockDriver();
-  virtual void GetIntervalForIteration(GraphTime& aFrom,
-                                       GraphTime& aTo) override;
-  virtual GraphTime GetCurrentTime() override;
+  virtual MediaTime GetIntervalForIteration() override;
   virtual void WaitForNextIteration() override;
   virtual void WakeUp() override;
 
 
 private:
   TimeStamp mInitialTimeStamp;
   TimeStamp mLastTimeStamp;
 };
@@ -306,19 +287,17 @@ private:
  * An OfflineClockDriver runs the graph as fast as possible, without waiting
  * between iteration.
  */
 class OfflineClockDriver : public ThreadedDriver
 {
 public:
   OfflineClockDriver(MediaStreamGraphImpl* aGraphImpl, GraphTime aSlice);
   virtual ~OfflineClockDriver();
-  virtual void GetIntervalForIteration(GraphTime& aFrom,
-                                       GraphTime& aTo) override;
-  virtual GraphTime GetCurrentTime() override;
+  virtual MediaTime GetIntervalForIteration() override;
   virtual void WaitForNextIteration() override;
   virtual void WakeUp() override;
   virtual TimeStamp GetCurrentTimeStamp() override;
   virtual OfflineClockDriver* AsOfflineClockDriver() override {
     return this;
   }
 
 private:
@@ -369,19 +348,16 @@ public:
                                dom::AudioChannel aChannel = dom::AudioChannel::Normal);
   virtual ~AudioCallbackDriver();
 
   virtual void Destroy() override;
   virtual void Start() override;
   virtual void Stop() override;
   virtual void Resume() override;
   virtual void Revive() override;
-  virtual void GetIntervalForIteration(GraphTime& aFrom,
-                                       GraphTime& aTo) override;
-  virtual GraphTime GetCurrentTime() override;
   virtual void WaitForNextIteration() override;
   virtual void WakeUp() override;
 
   /* Static wrapper function cubeb calls back. */
   static long DataCallback_s(cubeb_stream * aStream,
                              void * aUser, void * aBuffer,
                              long aFrames);
   static void StateCallback_s(cubeb_stream* aStream, void * aUser,
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -409,19 +409,18 @@ bool MediaDecoderStateMachine::HaveEnoug
   MOZ_ASSERT(OnTaskQueue());
   AssertCurrentThreadInMonitor();
 
   if (AudioQueue().GetSize() == 0 ||
       GetDecodedAudioDuration() < aAmpleAudioUSecs) {
     return false;
   }
 
-  // We don't have to check SourceMediaStream::HaveEnoughBuffered() in the
-  // case of stream-capture for MDSM will ensure buffering level is high enough
-  // for playback speed at 1x at which the DecodedStream is playing.
+  // MDSM will ensure buffering level is high enough for playback speed at 1x
+  // at which the DecodedStream is playing.
   return true;
 }
 
 bool MediaDecoderStateMachine::HaveEnoughDecodedVideo()
 {
   MOZ_ASSERT(OnTaskQueue());
   AssertCurrentThreadInMonitor();
 
@@ -1270,17 +1269,16 @@ void MediaDecoderStateMachine::SetDorman
     // on that in other places (i.e. seeking), so it seems reasonable to rely on
     // it here as well.
     nsCOMPtr<nsIRunnable> r = NS_NewRunnableMethod(mReader, &MediaDecoderReader::ReleaseMediaResources);
     DecodeTaskQueue()->Dispatch(r.forget());
     mDecoder->GetReentrantMonitor().NotifyAll();
   } else if ((aDormant != true) && (mState == DECODER_STATE_DORMANT)) {
     mDecodingFrozenAtStateDecoding = true;
     ScheduleStateMachine();
-    mCurrentPosition = 0;
     mDecodingFirstFrame = true;
     SetState(DECODER_STATE_DECODING_NONE);
     mDecoder->GetReentrantMonitor().NotifyAll();
   }
 }
 
 void MediaDecoderStateMachine::Shutdown()
 {
--- a/dom/media/MediaSegment.h
+++ b/dom/media/MediaSegment.h
@@ -44,16 +44,22 @@ const int64_t MEDIA_TIME_MAX = TRACK_TIC
 
 /**
  * Media time relative to the start of a StreamBuffer.
  */
 typedef MediaTime StreamTime;
 const StreamTime STREAM_TIME_MAX = MEDIA_TIME_MAX;
 
 /**
+ * Media time relative to the start of the graph timeline.
+ */
+typedef MediaTime GraphTime;
+const GraphTime GRAPH_TIME_MAX = MEDIA_TIME_MAX;
+
+/**
  * A MediaSegment is a chunk of media data sequential in time. Different
  * types of data have different subclasses of MediaSegment, all inheriting
  * from MediaSegmentBase.
  * All MediaSegment data is timed using StreamTime. The actual tick rate
  * is defined on a per-track basis. For some track types, this can be
  * a fixed constant for all tracks of that type (e.g. 1MHz for video).
  *
  * Each media segment defines a concept of "null media data" (e.g. silence
--- a/dom/media/MediaStreamGraph.cpp
+++ b/dom/media/MediaStreamGraph.cpp
@@ -66,27 +66,16 @@ static nsDataHashtable<nsUint32HashKey, 
 MediaStreamGraphImpl::~MediaStreamGraphImpl()
 {
   NS_ASSERTION(IsEmpty(),
                "All streams should have been destroyed by messages from the main thread");
   STREAM_LOG(LogLevel::Debug, ("MediaStreamGraph %p destroyed", this));
   LIFECYCLE_LOG("MediaStreamGraphImpl::~MediaStreamGraphImpl\n");
 }
 
-
-StreamTime
-MediaStreamGraphImpl::GetDesiredBufferEnd(MediaStream* aStream)
-{
-  StreamTime current = IterationEnd() - aStream->mBufferStartTime;
-  // When waking up media decoders, we need a longer safety margin, as it can
-  // take more time to get new samples. A factor of two seem to work.
-  return current +
-      2 * MillisecondsToMediaTime(std::max(AUDIO_TARGET_MS, VIDEO_TARGET_MS));
-}
-
 void
 MediaStreamGraphImpl::FinishStream(MediaStream* aStream)
 {
   if (aStream->mFinished)
     return;
   STREAM_LOG(LogLevel::Debug, ("MediaStream %p will finish", aStream));
   aStream->mFinished = true;
   aStream->mBuffer.AdvanceKnownTracksTime(STREAM_TIME_MAX);
@@ -256,58 +245,16 @@ MediaStreamGraphImpl::ExtractPendingInpu
   if (aStream->mBuffer.GetEnd() > 0) {
     aStream->mHasCurrentData = true;
   }
   if (finished) {
     FinishStream(aStream);
   }
 }
 
-void
-MediaStreamGraphImpl::UpdateBufferSufficiencyState(SourceMediaStream* aStream)
-{
-  StreamTime desiredEnd = GetDesiredBufferEnd(aStream);
-  nsTArray<SourceMediaStream::ThreadAndRunnable> runnables;
-
-  {
-    MutexAutoLock lock(aStream->mMutex);
-    for (uint32_t i = 0; i < aStream->mUpdateTracks.Length(); ++i) {
-      SourceMediaStream::TrackData* data = &aStream->mUpdateTracks[i];
-      if (data->mCommands & SourceMediaStream::TRACK_CREATE) {
-        // This track hasn't been created yet, so we have no sufficiency
-        // data. The track will be created in the next iteration of the
-        // control loop and then we'll fire insufficiency notifications
-        // if necessary.
-        continue;
-      }
-      if (data->mCommands & SourceMediaStream::TRACK_END) {
-        // This track will end, so no point in firing not-enough-data
-        // callbacks.
-        continue;
-      }
-      StreamBuffer::Track* track = aStream->mBuffer.FindTrack(data->mID);
-      // Note that track->IsEnded() must be false, otherwise we would have
-      // removed the track from mUpdateTracks already.
-      NS_ASSERTION(!track->IsEnded(), "What is this track doing here?");
-      data->mHaveEnough = track->GetEnd() >= desiredEnd;
-      if (!data->mHaveEnough) {
-        runnables.MoveElementsFrom(data->mDispatchWhenNotEnough);
-      }
-    }
-  }
-
-  for (uint32_t i = 0; i < runnables.Length(); ++i) {
-    // This dispatch was observed to fail in test_video_dimensions.html on
-    // win8 64 debug when invoked from noop_resampler::fill on the cubeb audio
-    // thread.
-    nsCOMPtr<nsIRunnable> r = runnables[i].mRunnable;
-    runnables[i].mTarget->Dispatch(r.forget(), AbstractThread::DontAssertDispatchSuccess);
-  }
-}
-
 StreamTime
 MediaStreamGraphImpl::GraphTimeToStreamTime(MediaStream* aStream,
                                             GraphTime aTime)
 {
   MOZ_ASSERT(aTime <= CurrentDriver()->StateComputedTime(),
                "Don't ask about times where we haven't made blocking decisions yet");
   if (aTime <= IterationEnd()) {
     return std::max<StreamTime>(0, aTime - aStream->mBufferStartTime);
@@ -1447,20 +1394,16 @@ MediaStreamGraphImpl::Process(GraphTime 
           ticksPlayed = ticksPlayedForThisStream;
         } else {
           MOZ_ASSERT(!ticksPlayedForThisStream || ticksPlayedForThisStream == ticksPlayed,
               "Each stream should have the same number of frame.");
         }
       }
       PlayVideo(stream);
     }
-    SourceMediaStream* is = stream->AsSourceStream();
-    if (is) {
-      UpdateBufferSufficiencyState(is);
-    }
     GraphTime end;
     if (!stream->mBlocked.GetAt(aTo, &end) || end < GRAPH_TIME_MAX) {
       allBlockedForever = false;
     }
   }
 
   if (CurrentDriver()->AsAudioCallbackDriver() && ticksPlayed) {
     mMixer.FinishMixing();
@@ -2480,17 +2423,16 @@ SourceMediaStream::AddTrackInternal(Trac
                                     &mPendingTracks : &mUpdateTracks;
   TrackData* data = track_data->AppendElement();
   data->mID = aID;
   data->mInputRate = aRate;
   data->mStart = aStart;
   data->mEndOfFlushedData = aStart;
   data->mCommands = TRACK_CREATE;
   data->mData = aSegment;
-  data->mHaveEnough = false;
   if (!(aFlags & ADDTRACK_QUEUED) && GraphImpl()) {
     GraphImpl()->EnsureNextIteration();
   }
 }
 
 void
 SourceMediaStream::FinishAddTracks()
 {
@@ -2641,62 +2583,29 @@ SourceMediaStream::RemoveDirectListener(
   }
 
   if (isEmpty) {
     // Async
     NotifyListenersEvent(MediaStreamListener::EVENT_HAS_NO_DIRECT_LISTENERS);
   }
 }
 
-bool
-SourceMediaStream::HaveEnoughBuffered(TrackID aID)
-{
-  MutexAutoLock lock(mMutex);
-  TrackData *track = FindDataForTrack(aID);
-  if (track) {
-    return track->mHaveEnough;
-  }
-  return false;
-}
-
 StreamTime
 SourceMediaStream::GetEndOfAppendedData(TrackID aID)
 {
   MutexAutoLock lock(mMutex);
   TrackData *track = FindDataForTrack(aID);
   if (track) {
     return track->mEndOfFlushedData + track->mData->GetDuration();
   }
   NS_ERROR("Track not found");
   return 0;
 }
 
 void
-SourceMediaStream::DispatchWhenNotEnoughBuffered(TrackID aID,
-    TaskQueue* aSignalQueue, nsIRunnable* aSignalRunnable)
-{
-  MutexAutoLock lock(mMutex);
-  TrackData* data = FindDataForTrack(aID);
-  if (!data) {
-    nsCOMPtr<nsIRunnable> r = aSignalRunnable;
-    aSignalQueue->Dispatch(r.forget());
-    return;
-  }
-
-  if (data->mHaveEnough) {
-    if (data->mDispatchWhenNotEnough.IsEmpty()) {
-      data->mDispatchWhenNotEnough.AppendElement()->Init(aSignalQueue, aSignalRunnable);
-    }
-  } else {
-    nsCOMPtr<nsIRunnable> r = aSignalRunnable;
-    aSignalQueue->Dispatch(r.forget());
-  }
-}
-
-void
 SourceMediaStream::EndTrack(TrackID aID)
 {
   MutexAutoLock lock(mMutex);
   TrackData *track = FindDataForTrack(aID);
   if (track) {
     track->mCommands |= TRACK_END;
   }
   if (auto graph = GraphImpl()) {
--- a/dom/media/MediaStreamGraph.h
+++ b/dom/media/MediaStreamGraph.h
@@ -7,26 +7,26 @@
 #define MOZILLA_MEDIASTREAMGRAPH_H_
 
 #include "mozilla/LinkedList.h"
 #include "mozilla/Mutex.h"
 #include "mozilla/TaskQueue.h"
 
 #include "mozilla/dom/AudioChannelBinding.h"
 
+#include "AudioSegment.h"
 #include "AudioStream.h"
 #include "nsTArray.h"
 #include "nsIRunnable.h"
 #include "StreamBuffer.h"
 #include "TimeVarying.h"
 #include "VideoFrameContainer.h"
 #include "VideoSegment.h"
 #include "MainThreadUtils.h"
 #include "nsAutoRef.h"
-#include "GraphDriver.h"
 #include <speex/speex_resampler.h>
 #include "DOMMediaStream.h"
 #include "AudioContext.h"
 
 class nsIRunnable;
 
 template <>
 class nsAutoRefTraits<SpeexResamplerState> : public nsPointerRefTraits<SpeexResamplerState>
@@ -811,36 +811,23 @@ public:
   /**
    * Append media data to a track. Ownership of aSegment remains with the caller,
    * but aSegment is emptied.
    * Returns false if the data was not appended because no such track exists
    * or the stream was already finished.
    */
   bool AppendToTrack(TrackID aID, MediaSegment* aSegment, MediaSegment *aRawSegment = nullptr);
   /**
-   * Returns true if the buffer currently has enough data.
-   * Returns false if there isn't enough data or if no such track exists.
-   */
-  bool HaveEnoughBuffered(TrackID aID);
-  /**
    * Get the stream time of the end of the data that has been appended so far.
    * Can be called from any thread but won't be useful if it can race with
    * an AppendToTrack call, so should probably just be called from the thread
    * that also calls AppendToTrack.
    */
   StreamTime GetEndOfAppendedData(TrackID aID);
   /**
-   * Ensures that aSignalRunnable will be dispatched to aSignalThread
-   * when we don't have enough buffered data in the track (which could be
-   * immediately). Will dispatch the runnable immediately if the track
-   * does not exist. No op if a runnable is already present for this track.
-   */
-  void DispatchWhenNotEnoughBuffered(TrackID aID,
-      TaskQueue* aSignalQueue, nsIRunnable* aSignalRunnable);
-  /**
    * Indicate that a track has ended. Do not do any more API calls
    * affecting this track.
    * Ignored if the track does not exist.
    */
   void EndTrack(TrackID aID);
   /**
    * Indicate that no tracks will be added starting before time aKnownTime.
    * aKnownTime must be >= its value at the last call to AdvanceKnownTracksTime.
@@ -925,21 +912,19 @@ protected:
     int mResamplerChannelCount;
 #endif
     StreamTime mStart;
     // End-time of data already flushed to the track (excluding mData)
     StreamTime mEndOfFlushedData;
     // Each time the track updates are flushed to the media graph thread,
     // the segment buffer is emptied.
     nsAutoPtr<MediaSegment> mData;
-    nsTArray<ThreadAndRunnable> mDispatchWhenNotEnough;
     // Each time the track updates are flushed to the media graph thread,
     // this is cleared.
     uint32_t mCommands;
-    bool mHaveEnough;
   };
 
   bool NeedsMixing();
 
   void ResampleAudioToGraphSampleRate(TrackData* aTrackData, MediaSegment* aSegment);
 
   void AddTrackInternal(TrackID aID, TrackRate aRate,
                         StreamTime aStart, MediaSegment* aSegment,
--- a/dom/media/mediasource/SourceBuffer.cpp
+++ b/dom/media/mediasource/SourceBuffer.cpp
@@ -71,17 +71,17 @@ SourceBuffer::SetMode(SourceBufferAppend
   if (!IsAttached() || mUpdating) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
   if (!mIsUsingFormatReader && aMode == SourceBufferAppendMode::Sequence) {
     aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
     return;
   }
-  if (mIsUsingFormatReader && mGenerateTimestamps &&
+  if (mIsUsingFormatReader && mAttributes->mGenerateTimestamps &&
       aMode == SourceBufferAppendMode::Segments) {
     aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
     return;
   }
   MOZ_ASSERT(mMediaSource->ReadyState() != MediaSourceReadyState::Closed);
   if (mMediaSource->ReadyState() == MediaSourceReadyState::Ended) {
     mMediaSource->SetReadyState(MediaSourceReadyState::Open);
   }
@@ -91,17 +91,17 @@ SourceBuffer::SetMode(SourceBufferAppend
     return;
   }
 
   if (mIsUsingFormatReader && aMode == SourceBufferAppendMode::Sequence) {
     // Will set GroupStartTimestamp to GroupEndTimestamp.
     mContentManager->RestartGroupStartTimestamp();
   }
 
-  mAppendMode = aMode;
+  mAttributes->SetAppendMode(aMode);
 }
 
 void
 SourceBuffer::SetTimestampOffset(double aTimestampOffset, ErrorResult& aRv)
 {
   typedef mozilla::SourceBufferContentManager::AppendState AppendState;
 
   MOZ_ASSERT(NS_IsMainThread());
@@ -114,32 +114,23 @@ SourceBuffer::SetTimestampOffset(double 
   if (mMediaSource->ReadyState() == MediaSourceReadyState::Ended) {
     mMediaSource->SetReadyState(MediaSourceReadyState::Open);
   }
   if (mIsUsingFormatReader &&
       mContentManager->GetAppendState() == AppendState::PARSING_MEDIA_SEGMENT){
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
-  mApparentTimestampOffset = aTimestampOffset;
-  mTimestampOffset = TimeUnit::FromSeconds(aTimestampOffset);
-  if (mIsUsingFormatReader && mAppendMode == SourceBufferAppendMode::Sequence) {
-    mContentManager->SetGroupStartTimestamp(mTimestampOffset);
+  mAttributes->SetApparentTimestampOffset(aTimestampOffset);
+  if (mIsUsingFormatReader &&
+      mAttributes->GetAppendMode() == SourceBufferAppendMode::Sequence) {
+    mContentManager->SetGroupStartTimestamp(mAttributes->GetTimestampOffset());
   }
 }
 
-void
-SourceBuffer::SetTimestampOffset(const TimeUnit& aTimestampOffset)
-{
-  MOZ_ASSERT(NS_IsMainThread());
-
-  mTimestampOffset = aTimestampOffset;
-  mApparentTimestampOffset = aTimestampOffset.ToSeconds();
-}
-
 already_AddRefed<TimeRanges>
 SourceBuffer::GetBuffered(ErrorResult& aRv)
 {
   MOZ_ASSERT(NS_IsMainThread());
   if (!IsAttached()) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return nullptr;
   }
@@ -160,37 +151,39 @@ void
 SourceBuffer::SetAppendWindowStart(double aAppendWindowStart, ErrorResult& aRv)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MSE_API("SetAppendWindowStart(aAppendWindowStart=%f)", aAppendWindowStart);
   if (!IsAttached() || mUpdating) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
-  if (aAppendWindowStart < 0 || aAppendWindowStart >= mAppendWindowEnd) {
+  if (aAppendWindowStart < 0 ||
+      aAppendWindowStart >= mAttributes->GetAppendWindowEnd()) {
     aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
     return;
   }
-  mAppendWindowStart = aAppendWindowStart;
+  mAttributes->SetAppendWindowStart(aAppendWindowStart);
 }
 
 void
 SourceBuffer::SetAppendWindowEnd(double aAppendWindowEnd, ErrorResult& aRv)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MSE_API("SetAppendWindowEnd(aAppendWindowEnd=%f)", aAppendWindowEnd);
   if (!IsAttached() || mUpdating) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
-  if (IsNaN(aAppendWindowEnd) || aAppendWindowEnd <= mAppendWindowStart) {
+  if (IsNaN(aAppendWindowEnd) ||
+      aAppendWindowEnd <= mAttributes->GetAppendWindowStart()) {
     aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
     return;
   }
-  mAppendWindowEnd = aAppendWindowEnd;
+  mAttributes->SetAppendWindowEnd(aAppendWindowEnd);
 }
 
 void
 SourceBuffer::AppendBuffer(const ArrayBuffer& aData, ErrorResult& aRv)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MSE_API("AppendBuffer(ArrayBuffer)");
   aData.ComputeLengthAndData();
@@ -216,18 +209,18 @@ SourceBuffer::Abort(ErrorResult& aRv)
     return;
   }
   if (mMediaSource->ReadyState() != MediaSourceReadyState::Open) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
   AbortBufferAppend();
   mContentManager->ResetParserState();
-  mAppendWindowStart = 0;
-  mAppendWindowEnd = PositiveInfinity<double>();
+  mAttributes->SetAppendWindowStart(0);
+  mAttributes->SetAppendWindowEnd(PositiveInfinity<double>());
 }
 
 void
 SourceBuffer::AbortBufferAppend()
 {
   if (mUpdating) {
     mPendingAppend.DisconnectIfExists();
     // TODO: Abort stream append loop algorithms.
@@ -307,46 +300,44 @@ SourceBuffer::Ended()
   // We want the MediaSourceReader to refresh its buffered range as it may
   // have been modified (end lined up).
   mMediaSource->GetDecoder()->NotifyDataArrived(1, mReportedOffset++, /* aThrottleUpdates = */ false);
 }
 
 SourceBuffer::SourceBuffer(MediaSource* aMediaSource, const nsACString& aType)
   : DOMEventTargetHelper(aMediaSource->GetParentObject())
   , mMediaSource(aMediaSource)
-  , mAppendWindowStart(0)
-  , mAppendWindowEnd(PositiveInfinity<double>())
-  , mApparentTimestampOffset(0)
-  , mAppendMode(SourceBufferAppendMode::Segments)
   , mUpdating(false)
   , mActive(false)
   , mUpdateID(0)
   , mReportedOffset(0)
   , mType(aType)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(aMediaSource);
   mEvictionThreshold = Preferences::GetUint("media.mediasource.eviction_threshold",
                                             100 * (1 << 20));
+  bool generateTimestamps = false;
+  if (aType.LowerCaseEqualsLiteral("audio/mpeg") ||
+      aType.LowerCaseEqualsLiteral("audio/aac")) {
+    generateTimestamps = true;
+  }
+  mAttributes = new SourceBufferAttributes(generateTimestamps);
+
   mContentManager =
-    SourceBufferContentManager::CreateManager(this,
+    SourceBufferContentManager::CreateManager(mAttributes,
                                               aMediaSource->GetDecoder(),
                                               aType);
   MSE_DEBUG("Create mContentManager=%p",
             mContentManager.get());
-  if (aType.LowerCaseEqualsLiteral("audio/mpeg") ||
-      aType.LowerCaseEqualsLiteral("audio/aac")) {
-    mGenerateTimestamps = true;
-  } else {
-    mGenerateTimestamps = false;
-  }
+
   mIsUsingFormatReader =
     Preferences::GetBool("media.mediasource.format-reader", false);
   ErrorResult dummy;
-  if (mGenerateTimestamps) {
+  if (mAttributes->mGenerateTimestamps) {
     SetMode(SourceBufferAppendMode::Sequence, dummy);
   } else {
     SetMode(SourceBufferAppendMode::Segments, dummy);
   }
   if (mIsUsingFormatReader) {
     mMediaSource->GetDecoder()->GetDemuxer()->AttachSourceBuffer(
       static_cast<mozilla::TrackBuffersManager*>(mContentManager.get()));
   }
@@ -441,21 +432,22 @@ void
 SourceBuffer::AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aRv)
 {
   MSE_DEBUG("AppendData(aLength=%u)", aLength);
 
   nsRefPtr<MediaByteBuffer> data = PrepareAppend(aData, aLength, aRv);
   if (!data) {
     return;
   }
-  mContentManager->AppendData(data, mTimestampOffset);
+  mContentManager->AppendData(data, mAttributes->GetTimestampOffset());
 
   StartUpdating();
 
-  MOZ_ASSERT(mIsUsingFormatReader || mAppendMode == SourceBufferAppendMode::Segments,
+  MOZ_ASSERT(mIsUsingFormatReader ||
+             mAttributes->GetAppendMode() == SourceBufferAppendMode::Segments,
              "We don't handle timestampOffset for sequence mode yet");
   nsCOMPtr<nsIRunnable> task = new BufferAppendRunnable(this, mUpdateID);
   NS_DispatchToMainThread(task);
 }
 
 void
 SourceBuffer::BufferAppend(uint32_t aUpdateID)
 {
--- a/dom/media/mediasource/SourceBuffer.h
+++ b/dom/media/mediasource/SourceBuffer.h
@@ -20,67 +20,158 @@
 #include "nsAutoPtr.h"
 #include "nsCOMPtr.h"
 #include "nsCycleCollectionNoteChild.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsISupports.h"
 #include "nsString.h"
 #include "nscore.h"
 #include "SourceBufferContentManager.h"
+#include "mozilla/Monitor.h"
 
 class JSObject;
 struct JSContext;
 
 namespace mozilla {
 
 class ErrorResult;
 class MediaByteBuffer;
 template <typename T> class AsyncEventRunner;
 class TrackBuffersManager;
 
 namespace dom {
 
 class TimeRanges;
 
+class SourceBufferAttributes {
+public:
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SourceBufferAttributes);
+  explicit SourceBufferAttributes(bool aGenerateTimestamp)
+    : mGenerateTimestamps(aGenerateTimestamp)
+    , mMonitor("SourceBufferAttributes")
+    , mAppendWindowStart(0)
+    , mAppendWindowEnd(PositiveInfinity<double>())
+    , mAppendMode(SourceBufferAppendMode::Segments)
+    , mApparentTimestampOffset(0)
+  {}
+
+  double GetAppendWindowStart()
+  {
+    MonitorAutoLock mon(mMonitor);
+    return mAppendWindowStart;
+  }
+
+  double GetAppendWindowEnd()
+  {
+    MonitorAutoLock mon(mMonitor);
+    return mAppendWindowEnd;
+  }
+
+  void SetAppendWindowStart(double aWindowStart)
+  {
+    MonitorAutoLock mon(mMonitor);
+    mAppendWindowStart = aWindowStart;
+  }
+
+  void SetAppendWindowEnd(double aWindowEnd)
+  {
+    MonitorAutoLock mon(mMonitor);
+    mAppendWindowEnd = aWindowEnd;
+  }
+
+  double GetApparentTimestampOffset()
+  {
+    MonitorAutoLock mon(mMonitor);
+    return mApparentTimestampOffset;
+  }
+
+  void SetApparentTimestampOffset(double aTimestampOffset)
+  {
+    MonitorAutoLock mon(mMonitor);
+    mApparentTimestampOffset = aTimestampOffset;
+    mTimestampOffset = media::TimeUnit::FromSeconds(aTimestampOffset);
+  }
+
+  media::TimeUnit GetTimestampOffset()
+  {
+    MonitorAutoLock mon(mMonitor);
+    return mTimestampOffset;
+  }
+
+  void SetTimestampOffset(media::TimeUnit& aTimestampOffset)
+  {
+    MonitorAutoLock mon(mMonitor);
+    mTimestampOffset = aTimestampOffset;
+    mApparentTimestampOffset = aTimestampOffset.ToSeconds();
+  }
+
+  SourceBufferAppendMode GetAppendMode()
+  {
+    MonitorAutoLock mon(mMonitor);
+    return mAppendMode;
+  }
+
+  void SetAppendMode(SourceBufferAppendMode aAppendMode)
+  {
+    MonitorAutoLock mon(mMonitor);
+    mAppendMode = aAppendMode;
+  }
+
+  // mGenerateTimestamp isn't mutable once the source buffer has been constructed
+  // We don't need a monitor to protect it across threads.
+  const bool mGenerateTimestamps;
+
+private:
+  ~SourceBufferAttributes() {};
+
+  // Monitor protecting all members below.
+  Monitor mMonitor;
+  double mAppendWindowStart;
+  double mAppendWindowEnd;
+  SourceBufferAppendMode mAppendMode;
+  double mApparentTimestampOffset;
+  media::TimeUnit mTimestampOffset;
+};
+
 class SourceBuffer final : public DOMEventTargetHelper
 {
 public:
   /** WebIDL Methods. */
   SourceBufferAppendMode Mode() const
   {
-    return mAppendMode;
+    return mAttributes->GetAppendMode();
   }
 
   void SetMode(SourceBufferAppendMode aMode, ErrorResult& aRv);
 
   bool Updating() const
   {
     return mUpdating;
   }
 
   already_AddRefed<TimeRanges> GetBuffered(ErrorResult& aRv);
   media::TimeIntervals GetTimeIntervals();
 
   double TimestampOffset() const
   {
-    return mApparentTimestampOffset;
+    return mAttributes->GetApparentTimestampOffset();
   }
 
   void SetTimestampOffset(double aTimestampOffset, ErrorResult& aRv);
 
   double AppendWindowStart() const
   {
-    return mAppendWindowStart;
+    return mAttributes->GetAppendWindowStart();
   }
 
   void SetAppendWindowStart(double aAppendWindowStart, ErrorResult& aRv);
 
   double AppendWindowEnd() const
   {
-    return mAppendWindowEnd;
+    return mAttributes->GetAppendWindowEnd();
   }
 
   void SetAppendWindowEnd(double aAppendWindowEnd, ErrorResult& aRv);
 
   void AppendBuffer(const ArrayBuffer& aData, ErrorResult& aRv);
   void AppendBuffer(const ArrayBufferView& aData, ErrorResult& aRv);
 
   void Abort(ErrorResult& aRv);
@@ -159,34 +250,24 @@ private:
   // on success or nullptr (with aRv set) on error.
   already_AddRefed<MediaByteBuffer> PrepareAppend(const uint8_t* aData,
                                                   uint32_t aLength,
                                                   ErrorResult& aRv);
 
   void AppendDataCompletedWithSuccess(bool aHasActiveTracks);
   void AppendDataErrored(nsresult aError);
 
-  // Set timestampOffset, must be called on the main thread.
-  void SetTimestampOffset(const media::TimeUnit& aTimestampOffset);
-
   nsRefPtr<MediaSource> mMediaSource;
 
   uint32_t mEvictionThreshold;
 
   nsRefPtr<SourceBufferContentManager> mContentManager;
-
-  double mAppendWindowStart;
-  double mAppendWindowEnd;
+  nsRefPtr<SourceBufferAttributes> mAttributes;
 
-  double mApparentTimestampOffset;
-  media::TimeUnit mTimestampOffset;
-
-  SourceBufferAppendMode mAppendMode;
   bool mUpdating;
-  bool mGenerateTimestamps;
   bool mIsUsingFormatReader;
 
   mozilla::Atomic<bool> mActive;
 
   // Each time mUpdating is set to true, mUpdateID will be incremented.
   // This allows for a queued AppendData task to identify if it was earlier
   // aborted and another AppendData queued.
   uint32_t mUpdateID;
--- a/dom/media/mediasource/SourceBufferContentManager.cpp
+++ b/dom/media/mediasource/SourceBufferContentManager.cpp
@@ -13,25 +13,25 @@ namespace mozilla {
 
 #if defined(MOZ_GONK_MEDIACODEC) || defined(XP_WIN) || defined(MOZ_APPLEMEDIA) || defined(MOZ_FFMPEG)
 #define MP4_READER_DORMANT_HEURISTIC
 #else
 #undef MP4_READER_DORMANT_HEURISTIC
 #endif
 
 already_AddRefed<SourceBufferContentManager>
-SourceBufferContentManager::CreateManager(dom::SourceBuffer* aParent,
+SourceBufferContentManager::CreateManager(dom::SourceBufferAttributes* aAttributes,
                                           MediaSourceDecoder* aParentDecoder,
                                           const nsACString &aType)
 {
   nsRefPtr<SourceBufferContentManager> manager;
   bool useFormatReader =
     Preferences::GetBool("media.mediasource.format-reader", false);
   if (useFormatReader) {
-    manager = new TrackBuffersManager(aParent, aParentDecoder, aType);
+    manager = new TrackBuffersManager(aAttributes, aParentDecoder, aType);
   } else {
     manager = new TrackBuffer(aParentDecoder, aType);
   }
 
   // Now that we know what type we're dealing with, enable dormant as needed.
 #if defined(MP4_READER_DORMANT_HEURISTIC)
   if (aType.LowerCaseEqualsLiteral("video/mp4") ||
       aType.LowerCaseEqualsLiteral("audio/mp4") ||
--- a/dom/media/mediasource/SourceBufferContentManager.h
+++ b/dom/media/mediasource/SourceBufferContentManager.h
@@ -13,27 +13,29 @@
 #include "MediaSourceDecoder.h"
 #include "TimeUnits.h"
 #include "nsString.h"
 
 namespace mozilla {
 
 namespace dom {
 class SourceBuffer;
+class SourceBufferAttributes;
 }
 
 class SourceBufferContentManager {
 public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SourceBufferContentManager);
 
   typedef MozPromise<bool, nsresult, /* IsExclusive = */ true> AppendPromise;
   typedef AppendPromise RangeRemovalPromise;
 
   static already_AddRefed<SourceBufferContentManager>
-  CreateManager(dom::SourceBuffer* aParent, MediaSourceDecoder* aParentDecoder,
+  CreateManager(dom::SourceBufferAttributes* aAttributes,
+                MediaSourceDecoder* aParentDecoder,
                 const nsACString& aType);
 
   // Add data to the end of the input buffer.
   // Returns false if the append failed.
   virtual bool
   AppendData(MediaByteBuffer* aData, media::TimeUnit aTimestampOffset) = 0;
 
   // Run MSE Buffer Append Algorithm
--- a/dom/media/mediasource/TrackBuffersManager.cpp
+++ b/dom/media/mediasource/TrackBuffersManager.cpp
@@ -85,30 +85,31 @@ public:
   }
 private:
   nsRefPtr<AbstractMediaDecoder> mDecoder;
   nsTArray<uint8_t> mInitData;
   nsString mInitDataType;
 };
 #endif // MOZ_EME
 
-TrackBuffersManager::TrackBuffersManager(dom::SourceBuffer* aParent, MediaSourceDecoder* aParentDecoder, const nsACString& aType)
+TrackBuffersManager::TrackBuffersManager(dom::SourceBufferAttributes* aAttributes,
+                                         MediaSourceDecoder* aParentDecoder,
+                                         const nsACString& aType)
   : mInputBuffer(new MediaByteBuffer)
   , mAppendState(AppendState::WAITING_FOR_SEGMENT)
   , mBufferFull(false)
   , mFirstInitializationSegmentReceived(false)
   , mActiveTrack(false)
   , mType(aType)
   , mParser(ContainerParser::CreateForMIMEType(aType))
   , mProcessedInput(0)
   , mAppendRunning(false)
   , mTaskQueue(aParentDecoder->GetDemuxer()->GetTaskQueue())
-  , mParent(new nsMainThreadPtrHolder<dom::SourceBuffer>(aParent, false /* strict */))
+  , mSourceBufferAttributes(aAttributes)
   , mParentDecoder(new nsMainThreadPtrHolder<MediaSourceDecoder>(aParentDecoder, false /* strict */))
-  , mMediaSourceDemuxer(mParentDecoder->GetDemuxer())
   , mMediaSourceDuration(mTaskQueue, Maybe<double>(), "TrackBuffersManager::mMediaSourceDuration (Mirror)")
   , mAbort(false)
   , mEvictionThreshold(Preferences::GetUint("media.mediasource.eviction_threshold",
                                             100 * (1 << 20)))
   , mEvictionOccurred(false)
   , mMonitor("TrackBuffersManager")
 {
   MOZ_ASSERT(NS_IsMainThread(), "Must be instanciated on the main thread");
@@ -615,18 +616,18 @@ TrackBuffersManager::AppendIncomingBuffe
       RejectAppend(NS_ERROR_OUT_OF_MEMORY, __func__);
     }
     mTimestampOffset = incomingBuffer.second();
     mLastTimestampOffset = mTimestampOffset;
   }
   mIncomingBuffers.Clear();
 
   mAppendWindow =
-    TimeInterval(TimeUnit::FromSeconds(mParent->AppendWindowStart()),
-                 TimeUnit::FromSeconds(mParent->AppendWindowEnd()));
+    TimeInterval(TimeUnit::FromSeconds(mSourceBufferAttributes->GetAppendWindowStart()),
+                 TimeUnit::FromSeconds(mSourceBufferAttributes->GetAppendWindowEnd()));
 }
 
 void
 TrackBuffersManager::SegmentParserLoop()
 {
   MOZ_ASSERT(OnTaskQueue());
   while (true) {
     // 1. If the input buffer is empty, then jump to the need more data step below.
@@ -1234,17 +1235,17 @@ TrackBuffersManager::ResolveProcessing(b
     mAppendRunning = false;
   }
   mProcessingPromise.ResolveIfExists(aResolveValue, __func__);
 }
 
 void
 TrackBuffersManager::CheckSequenceDiscontinuity()
 {
-  if (mParent->mAppendMode == SourceBufferAppendMode::Sequence &&
+  if (mSourceBufferAttributes->GetAppendMode() == SourceBufferAppendMode::Sequence &&
       mGroupStartTimestamp.isSome()) {
     mTimestampOffset = mGroupStartTimestamp.ref();
     mGroupEndTimestamp = mGroupStartTimestamp.ref();
     mVideoTracks.mNeedRandomAccessPoint = true;
     mAudioTracks.mNeedRandomAccessPoint = true;
     mGroupStartTimestamp.reset();
   }
 }
@@ -1309,41 +1310,43 @@ TrackBuffersManager::ProcessFrames(Track
     //   Let presentation timestamp be a double precision floating point representation of the coded frame's presentation timestamp in seconds.
     //   Let decode timestamp be a double precision floating point representation of the coded frame's decode timestamp in seconds.
 
     // 2. Let frame duration be a double precision floating point representation of the coded frame's duration in seconds.
     // Step 3 is performed earlier or when a discontinuity has been detected.
     // 4. If timestampOffset is not 0, then run the following steps:
 
     TimeInterval sampleInterval =
-      mParent->mGenerateTimestamps
+      mSourceBufferAttributes->mGenerateTimestamps
         ? TimeInterval(mTimestampOffset,
                        mTimestampOffset + TimeUnit::FromMicroseconds(sample->mDuration))
         : TimeInterval(TimeUnit::FromMicroseconds(sample->mTime) + mTimestampOffset,
                        TimeUnit::FromMicroseconds(sample->GetEndTime()) + mTimestampOffset);
     TimeUnit decodeTimestamp =
-      mParent->mGenerateTimestamps
+      mSourceBufferAttributes->mGenerateTimestamps
         ? mTimestampOffset
         : TimeUnit::FromMicroseconds(sample->mTimecode) + mTimestampOffset;
 
     // 6. If last decode timestamp for track buffer is set and decode timestamp is less than last decode timestamp:
     // OR
     // If last decode timestamp for track buffer is set and the difference between decode timestamp and last decode timestamp is greater than 2 times last frame duration:
 
     if (needDiscontinuityCheck && trackBuffer.mLastDecodeTimestamp.isSome() &&
         (decodeTimestamp < trackBuffer.mLastDecodeTimestamp.ref() ||
          decodeTimestamp - trackBuffer.mLastDecodeTimestamp.ref() > 2*trackBuffer.mLongestFrameDuration.ref())) {
       MSE_DEBUG("Discontinuity detected.");
+      SourceBufferAppendMode appendMode = mSourceBufferAttributes->GetAppendMode();
+
       // 1a. If mode equals "segments":
-      if (mParent->mAppendMode == SourceBufferAppendMode::Segments) {
+      if (appendMode == SourceBufferAppendMode::Segments) {
         // Set group end timestamp to presentation timestamp.
         mGroupEndTimestamp = sampleInterval.mStart;
       }
       // 1b. If mode equals "sequence":
-      if (mParent->mAppendMode == SourceBufferAppendMode::Sequence) {
+      if (appendMode == SourceBufferAppendMode::Sequence) {
         // Set group start timestamp equal to the group end timestamp.
         mGroupStartTimestamp = Some(mGroupEndTimestamp);
       }
       for (auto& track : GetTracksList()) {
         // 2. Unset the last decode timestamp on all track buffers.
         // 3. Unset the last frame duration on all track buffers.
         // 4. Unset the highest end timestamp on all track buffers.
         // 5. Set the need random access point flag on all track buffers to true.
@@ -1353,27 +1356,27 @@ TrackBuffersManager::ProcessFrames(Track
       // Rather that restarting the process for the frame, we run the first
       // steps again instead.
       // 3. If mode equals "sequence" and group start timestamp is set, then run the following steps:
       CheckSequenceDiscontinuity();
 
       if (!sample->mKeyframe) {
         continue;
       }
-      if (mParent->mAppendMode == SourceBufferAppendMode::Sequence) {
+      if (appendMode == SourceBufferAppendMode::Sequence) {
         // mTimestampOffset was modified during CheckSequenceDiscontinuity.
         // We need to update our variables.
         sampleInterval =
-          mParent->mGenerateTimestamps
+          mSourceBufferAttributes->mGenerateTimestamps
             ? TimeInterval(mTimestampOffset,
                            mTimestampOffset + TimeUnit::FromMicroseconds(sample->mDuration))
             : TimeInterval(TimeUnit::FromMicroseconds(sample->mTime) + mTimestampOffset,
                            TimeUnit::FromMicroseconds(sample->GetEndTime()) + mTimestampOffset);
         decodeTimestamp =
-          mParent->mGenerateTimestamps
+          mSourceBufferAttributes->mGenerateTimestamps
             ? mTimestampOffset
             : TimeUnit::FromMicroseconds(sample->mTimecode) + mTimestampOffset;
       }
       trackBuffer.mNeedRandomAccessPoint = false;
       needDiscontinuityCheck = false;
     }
 
     // 7. Let frame end timestamp equal the sum of presentation timestamp and frame duration.
@@ -1423,17 +1426,17 @@ TrackBuffersManager::ProcessFrames(Track
         sampleInterval.mEnd > trackBuffer.mHighestEndTimestamp.ref()) {
       trackBuffer.mHighestEndTimestamp = Some(sampleInterval.mEnd);
     }
     // 20. If frame end timestamp is greater than group end timestamp, then set group end timestamp equal to frame end timestamp.
     if (sampleInterval.mEnd > mGroupEndTimestamp) {
       mGroupEndTimestamp = sampleInterval.mEnd;
     }
     // 21. If generate timestamps flag equals true, then set timestampOffset equal to frame end timestamp.
-    if (mParent->mGenerateTimestamps) {
+    if (mSourceBufferAttributes->mGenerateTimestamps) {
       mTimestampOffset = sampleInterval.mEnd;
     }
   }
 
   if (samples.Length()) {
     InsertFrames(samples, samplesRange, trackBuffer);
     trackBuffer.mSizeBuffer += sizeNewSamples;
   }
@@ -1674,22 +1677,17 @@ TrackBuffersManager::GetTracksList()
   return tracks;
 }
 
 void
 TrackBuffersManager::RestoreCachedVariables()
 {
   MOZ_ASSERT(OnTaskQueue());
   if (mTimestampOffset != mLastTimestampOffset) {
-    nsRefPtr<TrackBuffersManager> self = this;
-    nsCOMPtr<nsIRunnable> task =
-      NS_NewRunnableFunction([self] {
-        self->mParent->SetTimestampOffset(self->mTimestampOffset);
-      });
-    AbstractThread::MainThread()->Dispatch(task.forget());
+    mSourceBufferAttributes->SetTimestampOffset(mTimestampOffset);
   }
 }
 
 void
 TrackBuffersManager::SetAppendState(TrackBuffersManager::AppendState aAppendState)
 {
   MSE_DEBUG("AppendState changed from %s to %s",
             AppendStateToStr(mAppendState), AppendStateToStr(aAppendState));
--- a/dom/media/mediasource/TrackBuffersManager.h
+++ b/dom/media/mediasource/TrackBuffersManager.h
@@ -20,27 +20,32 @@
 #include "nsTArray.h"
 
 namespace mozilla {
 
 class ContainerParser;
 class MediaByteBuffer;
 class MediaRawData;
 class MediaSourceDemuxer;
-class SourceBuffer;
 class SourceBufferResource;
 
+namespace dom {
+  class SourceBufferAttributes;
+}
+
 class TrackBuffersManager : public SourceBufferContentManager {
 public:
   typedef MozPromise<bool, nsresult, /* IsExclusive = */ true> CodedFrameProcessingPromise;
   typedef TrackInfo::TrackType TrackType;
   typedef MediaData::Type MediaType;
   typedef nsTArray<nsRefPtr<MediaRawData>> TrackBuffer;
 
-  TrackBuffersManager(dom::SourceBuffer* aParent, MediaSourceDecoder* aParentDecoder, const nsACString& aType);
+  TrackBuffersManager(dom::SourceBufferAttributes* aAttributes,
+                      MediaSourceDecoder* aParentDecoder,
+                      const nsACString& aType);
 
   bool AppendData(MediaByteBuffer* aData,
                   media::TimeUnit aTimestampOffset) override;
 
   nsRefPtr<AppendPromise> BufferAppend() override;
 
   void AbortAppendData() override;
 
@@ -310,19 +315,18 @@ private:
   RefPtr<TaskQueue> mTaskQueue;
 
   media::TimeInterval mAppendWindow;
   media::TimeUnit mTimestampOffset;
   media::TimeUnit mLastTimestampOffset;
   void RestoreCachedVariables();
 
   // Strong references to external objects.
-  nsMainThreadPtrHandle<dom::SourceBuffer> mParent;
+  nsRefPtr<dom::SourceBufferAttributes> mSourceBufferAttributes;
   nsMainThreadPtrHandle<MediaSourceDecoder> mParentDecoder;
-  nsRefPtr<MediaSourceDemuxer> mMediaSourceDemuxer;
 
   // MediaSource duration mirrored from MediaDecoder on the main thread..
   Mirror<Maybe<double>> mMediaSourceDuration;
 
   // Set to true if abort was called.
   Atomic<bool> mAbort;
   // Set to true if mediasource state changed to ended.
   Atomic<bool> mEnded;
--- a/dom/media/moz.build
+++ b/dom/media/moz.build
@@ -105,17 +105,16 @@ EXPORTS += [
     'AudioStream.h',
     'BufferMediaResource.h',
     'CubebUtils.h',
     'DecodedStream.h',
     'DecoderTraits.h',
     'DOMMediaStream.h',
     'EncodedBufferCache.h',
     'FileBlockCache.h',
-    'GraphDriver.h',
     'Intervals.h',
     'Latency.h',
     'MediaCache.h',
     'MediaData.h',
     'MediaDataDemuxer.h',
     'MediaDecoder.h',
     'MediaDecoderOwner.h',
     'MediaDecoderReader.h',
--- a/dom/media/platforms/wmf/WMFAudioMFTManager.cpp
+++ b/dom/media/platforms/wmf/WMFAudioMFTManager.cpp
@@ -63,17 +63,16 @@ AACAudioSpecificConfigToUserData(uint8_t
   aOutUserData.AppendElements(heeInfo, heeInfoLen);
   aOutUserData.AppendElements(aAudioSpecConfig, aConfigLength);
 }
 
 WMFAudioMFTManager::WMFAudioMFTManager(
   const AudioInfo& aConfig)
   : mAudioChannels(aConfig.mChannels)
   , mAudioRate(aConfig.mRate)
-  , mAudioFrameOffset(0)
   , mAudioFrameSum(0)
   , mMustRecaptureAudioPosition(true)
 {
   MOZ_COUNT_CTOR(WMFAudioMFTManager);
 
   if (aConfig.mMimeType.EqualsLiteral("audio/mpeg")) {
     mStreamType = MP3;
   } else if (aConfig.mMimeType.EqualsLiteral("audio/mp4a-latm")) {
@@ -262,18 +261,17 @@ WMFAudioMFTManager::Output(int64_t aStre
     // don't get a MF_E_TRANSFORM_STREAM_CHANGE when the rate changes.
     hr = UpdateOutputType();
     NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
 
     mAudioFrameSum = 0;
     LONGLONG timestampHns = 0;
     hr = sample->GetSampleTime(&timestampHns);
     NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
-    hr = HNsToFrames(timestampHns, mAudioRate, &mAudioFrameOffset);
-    NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
+    mAudioTimeOffset = media::TimeUnit::FromMicroseconds(timestampHns / 10);
     mMustRecaptureAudioPosition = false;
   }
   // We can assume PCM 16 output.
   int32_t numSamples = currentLength / 2;
   int32_t numFrames = numSamples / mAudioChannels;
   MOZ_ASSERT(numFrames >= 0);
   MOZ_ASSERT(numSamples >= 0);
   if (numFrames == 0) {
@@ -287,17 +285,17 @@ WMFAudioMFTManager::Output(int64_t aStre
   int16_t* pcm = (int16_t*)data;
   for (int32_t i = 0; i < numSamples; ++i) {
     audioData[i] = AudioSampleToFloat(pcm[i]);
   }
 
   buffer->Unlock();
 
   media::TimeUnit timestamp =
-    FramesToTimeUnit(mAudioFrameOffset + mAudioFrameSum, mAudioRate);
+    mAudioTimeOffset + FramesToTimeUnit(mAudioFrameSum, mAudioRate);
   NS_ENSURE_TRUE(timestamp.IsValid(), E_FAIL);
 
   mAudioFrameSum += numFrames;
 
   media::TimeUnit duration = FramesToTimeUnit(numFrames, mAudioRate);
   NS_ENSURE_TRUE(duration.IsValid(), E_FAIL);
 
   aOutData = new AudioData(aStreamOffset,
--- a/dom/media/platforms/wmf/WMFAudioMFTManager.h
+++ b/dom/media/platforms/wmf/WMFAudioMFTManager.h
@@ -37,34 +37,34 @@ private:
 
   // IMFTransform wrapper that performs the decoding.
   RefPtr<MFTDecoder> mDecoder;
 
   uint32_t mAudioChannels;
   uint32_t mAudioRate;
   nsTArray<BYTE> mUserData;
 
-  // The offset, in audio frames, at which playback started since the
+  // The offset, at which playback started since the
   // last discontinuity.
-  int64_t mAudioFrameOffset;
+  media::TimeUnit mAudioTimeOffset;
   // The number of audio frames that we've played since the last
   // discontinuity.
   int64_t mAudioFrameSum;
 
   enum StreamType {
     Unknown,
     AAC,
     MP3
   };
   StreamType mStreamType;
 
   const GUID& GetMFTGUID();
   const GUID& GetMediaSubtypeGUID();
 
-  // True if we need to re-initialize mAudioFrameOffset and mAudioFrameSum
+  // True if we need to re-initialize mAudioTimeOffset and mAudioFrameSum
   // from the next audio packet we decode. This happens after a seek, since
   // WMF doesn't mark a stream as having a discontinuity after a seek(0).
   bool mMustRecaptureAudioPosition;
 };
 
 } // namespace mozilla
 
 #endif // WMFAudioOutputSource_h_
--- a/dom/media/platforms/wmf/WMFVideoMFTManager.cpp
+++ b/dom/media/platforms/wmf/WMFVideoMFTManager.cpp
@@ -25,31 +25,34 @@
 PRLogModuleInfo* GetDemuxerLog();
 #define LOG(...) MOZ_LOG(GetDemuxerLog(), mozilla::LogLevel::Debug, (__VA_ARGS__))
 
 using mozilla::layers::Image;
 using mozilla::layers::IMFYCbCrImage;
 using mozilla::layers::LayerManager;
 using mozilla::layers::LayersBackend;
 
+#if MOZ_WINSDK_MAXVER < 0x0A000000
+// Windows 10+ SDK has VP80 and VP90 defines
 const GUID MFVideoFormat_VP80 =
 {
   0x30385056,
   0x0000,
   0x0010,
   {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
 };
 
 const GUID MFVideoFormat_VP90 =
 {
   0x30395056,
   0x0000,
   0x0010,
   {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
 };
+#endif
 
 const CLSID CLSID_WebmMfVp8Dec =
 {
   0x451e3cb7,
   0x2622,
   0x4ba5,
   {0x8e, 0x1d, 0x44, 0xb3, 0xc4, 0x1d, 0x09, 0x24}
 };
--- a/dom/media/webaudio/AudioNodeEngine.h
+++ b/dom/media/webaudio/AudioNodeEngine.h
@@ -375,17 +375,17 @@ public:
   {
     return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
   }
 
   void SizeOfIncludingThis(MallocSizeOf aMallocSizeOf,
                            AudioNodeSizes& aUsage) const
   {
     aUsage.mEngine = SizeOfIncludingThis(aMallocSizeOf);
-    if (HasNode()) {
+    if (mNode) {
       aUsage.mDomNode = mNode->SizeOfIncludingThis(aMallocSizeOf);
       aUsage.mNodeType = mNode->NodeType();
     }
   }
 
 private:
   dom::AudioNode* mNode;
   const uint16_t mInputCount;
--- a/dom/media/webspeech/recognition/PocketSphinxSpeechRecognitionService.cpp
+++ b/dom/media/webspeech/recognition/PocketSphinxSpeechRecognitionService.cpp
@@ -49,18 +49,17 @@ public:
                                    // thread!
 
     // Declare javascript result events
     nsRefPtr<SpeechEvent> event = new SpeechEvent(
       mRecognition, SpeechRecognition::EVENT_RECOGNITIONSERVICE_FINAL_RESULT);
     SpeechRecognitionResultList* resultList =
       new SpeechRecognitionResultList(mRecognition);
     SpeechRecognitionResult* result = new SpeechRecognitionResult(mRecognition);
-    ErrorResult rv;
-    if (0 < mRecognition->GetMaxAlternatives(rv)) { // GetMaxAlternatives can't fail
+    if (0 < mRecognition->MaxAlternatives()) {
       SpeechRecognitionAlternative* alternative =
         new SpeechRecognitionAlternative(mRecognition);
 
       alternative->mTranscript = mResult;
       alternative->mConfidence = 100;
 
       result->mItems.AppendElement(alternative);
     }
@@ -326,18 +325,17 @@ PocketSphinxSpeechRecognitionService::Ob
 }
 
 SpeechRecognitionResultList*
 PocketSphinxSpeechRecognitionService::BuildMockResultList()
 {
   SpeechRecognitionResultList* resultList =
     new SpeechRecognitionResultList(mRecognition);
   SpeechRecognitionResult* result = new SpeechRecognitionResult(mRecognition);
-  ErrorResult rv;
-  if (0 < mRecognition->GetMaxAlternatives(rv)) { // GetMaxAlternatives can't fail
+  if (0 < mRecognition->MaxAlternatives()) {
     SpeechRecognitionAlternative* alternative =
       new SpeechRecognitionAlternative(mRecognition);
 
     alternative->mTranscript = NS_LITERAL_STRING("Mock final result");
     alternative->mConfidence = 0.0f;
 
     result->mItems.AppendElement(alternative);
   }
--- a/dom/media/webspeech/recognition/SpeechRecognition.cpp
+++ b/dom/media/webspeech/recognition/SpeechRecognition.cpp
@@ -679,23 +679,23 @@ SpeechRecognition::InterimResults() cons
 void
 SpeechRecognition::SetInterimResults(bool aArg)
 {
   mInterimResults = aArg;
   return;
 }
 
 uint32_t
-SpeechRecognition::GetMaxAlternatives(ErrorResult& aRv) const
+SpeechRecognition::MaxAlternatives() const
 {
   return mMaxAlternatives;
 }
 
 void
-SpeechRecognition::SetMaxAlternatives(uint32_t aArg, ErrorResult& aRv)
+SpeechRecognition::SetMaxAlternatives(uint32_t aArg)
 {
   mMaxAlternatives = aArg;
   return;
 }
 
 void
 SpeechRecognition::GetServiceURI(nsString& aRetVal, ErrorResult& aRv) const
 {
--- a/dom/media/webspeech/recognition/SpeechRecognition.h
+++ b/dom/media/webspeech/recognition/SpeechRecognition.h
@@ -82,19 +82,19 @@ public:
   bool GetContinuous(ErrorResult& aRv) const;
 
   void SetContinuous(bool aArg, ErrorResult& aRv);
 
   bool InterimResults() const;
 
   void SetInterimResults(bool aArg);
 
-  uint32_t GetMaxAlternatives(ErrorResult& aRv) const;
+  uint32_t MaxAlternatives() const;
 
-  void SetMaxAlternatives(uint32_t aArg, ErrorResult& aRv);
+  void SetMaxAlternatives(uint32_t aArg);
 
   void GetServiceURI(nsString& aRetVal, ErrorResult& aRv) const;
 
   void SetServiceURI(const nsAString& aArg, ErrorResult& aRv);
 
   void Start(const Optional<NonNull<DOMMediaStream>>& aStream, ErrorResult& aRv);
 
   void Stop();
--- a/dom/media/webspeech/recognition/test/FakeSpeechRecognitionService.cpp
+++ b/dom/media/webspeech/recognition/test/FakeSpeechRecognitionService.cpp
@@ -97,18 +97,17 @@ FakeSpeechRecognitionService::Observe(ns
   return NS_OK;
 }
 
 SpeechRecognitionResultList*
 FakeSpeechRecognitionService::BuildMockResultList()
 {
   SpeechRecognitionResultList* resultList = new SpeechRecognitionResultList(mRecognition);
   SpeechRecognitionResult* result = new SpeechRecognitionResult(mRecognition);
-  ErrorResult rv;
-  if (0 < mRecognition->GetMaxAlternatives(rv)) { // GetMaxAlternatives can't fail
+  if (0 < mRecognition->MaxAlternatives()) {
     SpeechRecognitionAlternative* alternative = new SpeechRecognitionAlternative(mRecognition);
 
     alternative->mTranscript = NS_LITERAL_STRING("Mock final result");
     alternative->mConfidence = 0.0f;
 
     result->mItems.AppendElement(alternative);
   }
   resultList->mItems.AppendElement(result);
--- a/dom/webidl/SpeechRecognition.webidl
+++ b/dom/webidl/SpeechRecognition.webidl
@@ -15,17 +15,16 @@
  Func="SpeechRecognition::IsAuthorized"]
 interface SpeechRecognition : EventTarget {
     // recognition parameters
     attribute SpeechGrammarList grammars;
     attribute DOMString lang;
     [Throws]
     attribute boolean continuous;
     attribute boolean interimResults;
-    [Throws]
     attribute unsigned long maxAlternatives;
     [Throws]
     attribute DOMString serviceURI;
 
     // methods to drive the speech interaction
     [Throws, UnsafeInPrerendering]
     void start(optional MediaStream stream);
     void stop();
--- a/gfx/layers/LayerScope.cpp
+++ b/gfx/layers/LayerScope.cpp
@@ -65,124 +65,157 @@ using namespace mozilla::gfx;
 using namespace mozilla::gl;
 using namespace mozilla;
 using namespace layerscope;
 
 class DebugDataSender;
 class DebugGLData;
 
 /*
- * This class handle websocket protocol which included
- * handshake and data frame's header
- */
-class LayerScopeWebSocketHandler : public nsIInputStreamCallback {
-public:
-    NS_DECL_THREADSAFE_ISUPPORTS
-
-    enum SocketStateType {
-        NoHandshake,
-        HandshakeSuccess,
-        HandshakeFailed
-    };
-
-    LayerScopeWebSocketHandler()
-        : mState(NoHandshake)
-        , mConnected(false)
-    { }
-
-    void OpenStream(nsISocketTransport* aTransport);
-
-    bool WriteToStream(void *aPtr, uint32_t aSize);
-
-    // nsIInputStreamCallback
-    NS_IMETHODIMP OnInputStreamReady(nsIAsyncInputStream *aStream) override;
-
-private:
-    virtual ~LayerScopeWebSocketHandler() { CloseConnection(); }
-
-    void ReadInputStreamData(nsTArray<nsCString>& aProtocolString);
-
-    bool WebSocketHandshake(nsTArray<nsCString>& aProtocolString);
-
-    nsresult HandleSocketMessage(nsIAsyncInputStream *aStream);
-
-    nsresult ProcessInput(uint8_t *aBuffer, uint32_t aCount);
-
-    // Copied from WebsocketChannel, helper function to decode data frame
-    void ApplyMask(uint32_t aMask, uint8_t *aData, uint64_t aLen);
-
-    bool HandleDataFrame(uint8_t *aData, uint32_t aSize);
-
-    void CloseConnection();
-
-private:
-    nsCOMPtr<nsIOutputStream> mOutputStream;
-    nsCOMPtr<nsIAsyncInputStream> mInputStream;
-    nsCOMPtr<nsISocketTransport> mTransport;
-    SocketStateType mState;
-    bool mConnected;
-};
-
-NS_IMPL_ISUPPORTS(LayerScopeWebSocketHandler, nsIInputStreamCallback);
-
-
-/*
  * Manage Websocket connections
  */
 class LayerScopeWebSocketManager {
 public:
     LayerScopeWebSocketManager();
     ~LayerScopeWebSocketManager();
 
-    void AddConnection(nsISocketTransport *aTransport)
-    {
-        MOZ_ASSERT(aTransport);
-        nsRefPtr<LayerScopeWebSocketHandler> temp = new LayerScopeWebSocketHandler();
-        temp->OpenStream(aTransport);
-        mHandlers.AppendElement(temp.get());
-    }
-
-    void RemoveConnection(uint32_t aIndex)
-    {
-        MOZ_ASSERT(aIndex < mHandlers.Length());
-        mHandlers.RemoveElementAt(aIndex);
-    }
-
     void RemoveAllConnections()
     {
+        MOZ_ASSERT(NS_IsMainThread());
+
+        MutexAutoLock lock(mHandlerMutex);
         mHandlers.Clear();
     }
 
     bool WriteAll(void *ptr, uint32_t size)
     {
+        MOZ_ASSERT(NS_IsMainThread());
+
         for (int32_t i = mHandlers.Length() - 1; i >= 0; --i) {
             if (!mHandlers[i]->WriteToStream(ptr, size)) {
                 // Send failed, remove this handler
                 RemoveConnection(i);
             }
         }
 
         return true;
     }
 
     bool IsConnected()
     {
+        // This funtion can be called in both main thread and compositor thread.
+        MutexAutoLock lock(mHandlerMutex);
         return (mHandlers.Length() != 0) ? true : false;
     }
 
     void AppendDebugData(DebugGLData *aDebugData);
     void CleanDebugData();
     void DispatchDebugData();
+
 private:
-    nsTArray<nsRefPtr<LayerScopeWebSocketHandler> > mHandlers;
-    nsCOMPtr<nsIThread> mDebugSenderThread;
-    nsRefPtr<DebugDataSender> mCurrentSender;
-    nsCOMPtr<nsIServerSocket> mServerSocket;
+    void AddConnection(nsISocketTransport *aTransport)
+    {
+        MOZ_ASSERT(NS_IsMainThread());
+        MOZ_ASSERT(aTransport);
+
+        MutexAutoLock lock(mHandlerMutex);
+
+        nsRefPtr<SocketHandler> temp = new SocketHandler();
+        temp->OpenStream(aTransport);
+        mHandlers.AppendElement(temp.get());
+    }
+
+    void RemoveConnection(uint32_t aIndex)
+    {
+        MOZ_ASSERT(NS_IsMainThread());
+        MOZ_ASSERT(aIndex < mHandlers.Length());
+
+        MutexAutoLock lock(mHandlerMutex);
+        mHandlers.RemoveElementAt(aIndex);
+    }
+
+    friend class SocketListener;
+    class SocketListener : public nsIServerSocketListener
+    {
+    public:
+       NS_DECL_THREADSAFE_ISUPPORTS
+
+       SocketListener() { }
+
+       /* nsIServerSocketListener */
+       NS_IMETHODIMP OnSocketAccepted(nsIServerSocket *aServ,
+                                      nsISocketTransport *aTransport) override;
+       NS_IMETHODIMP OnStopListening(nsIServerSocket *aServ,
+                                   nsresult aStatus) override
+       {
+           return NS_OK;
+       }
+    private:
+       virtual ~SocketListener() { }
+    };
+
+    /*
+     * This class handle websocket protocol which included
+     * handshake and data frame's header
+     */
+    class SocketHandler : public nsIInputStreamCallback {
+    public:
+        NS_DECL_THREADSAFE_ISUPPORTS
+
+        SocketHandler()
+            : mState(NoHandshake)
+            , mConnected(false)
+        { }
+
+        void OpenStream(nsISocketTransport* aTransport);
+        bool WriteToStream(void *aPtr, uint32_t aSize);
+
+        // nsIInputStreamCallback
+        NS_IMETHODIMP OnInputStreamReady(nsIAsyncInputStream *aStream) override;
+
+    private:
+        virtual ~SocketHandler() { CloseConnection(); }
+
+        void ReadInputStreamData(nsTArray<nsCString>& aProtocolString);
+        bool WebSocketHandshake(nsTArray<nsCString>& aProtocolString);
+        void ApplyMask(uint32_t aMask, uint8_t *aData, uint64_t aLen);
+        bool HandleDataFrame(uint8_t *aData, uint32_t aSize);
+        void CloseConnection();
+
+        nsresult HandleSocketMessage(nsIAsyncInputStream *aStream);
+        nsresult ProcessInput(uint8_t *aBuffer, uint32_t aCount);
+
+    private:
+        enum SocketStateType {
+            NoHandshake,
+            HandshakeSuccess,
+            HandshakeFailed
+        };
+        SocketStateType               mState;
+
+        nsCOMPtr<nsIOutputStream>     mOutputStream;
+        nsCOMPtr<nsIAsyncInputStream> mInputStream;
+        nsCOMPtr<nsISocketTransport>  mTransport;
+        bool                          mConnected;
+    };
+
+    nsTArray<nsRefPtr<SocketHandler> > mHandlers;
+    nsCOMPtr<nsIThread>                   mDebugSenderThread;
+    nsRefPtr<DebugDataSender>             mCurrentSender;
+    nsCOMPtr<nsIServerSocket>             mServerSocket;
+
+    // Keep mHandlers accessing thread safe.
+    Mutex mHandlerMutex;
 };
 
+NS_IMPL_ISUPPORTS(LayerScopeWebSocketManager::SocketListener,
+                  nsIServerSocketListener);
+NS_IMPL_ISUPPORTS(LayerScopeWebSocketManager::SocketHandler,
+                  nsIInputStreamCallback);
+
 class DrawSession {
 public:
     DrawSession()
       : mOffsetX(0.0)
       , mOffsetY(0.0)
       , mRects(0)
     { }
 
@@ -231,17 +264,19 @@ public:
         mSeenHosts.SetLength(0);
         mChangedHosts.SetLength(0);
     }
 private:
     THArray mSeenHosts;
     THArray mChangedHosts;
 };
 
-// Hold all singleton objects used by LayerScope
+/*
+ * Hold all singleton objects used by LayerScope.
+ */
 class LayerScopeManager
 {
 public:
     void CreateServerSocket()
     {
         //  WebSocketManager must be created on the main thread.
         if (NS_IsMainThread()) {
             mWebSocketManager = mozilla::MakeUnique<LayerScopeWebSocketManager>();
@@ -703,50 +738,16 @@ protected:
     gfx::Matrix4x4 mMVMatrix;
     size_t mRects;
     gfx::Rect mLayerRects[4];
     gfx::Rect mTextureRects[4];
     std::list<GLuint> mTexIDs;
     uint64_t mLayerRef;
 };
 
-class DebugListener : public nsIServerSocketListener
-{
-    virtual ~DebugListener() { }
-
-public:
-
-    NS_DECL_THREADSAFE_ISUPPORTS
-
-    DebugListener() { }
-
-    /* nsIServerSocketListener */
-
-    NS_IMETHODIMP OnSocketAccepted(nsIServerSocket *aServ,
-                                   nsISocketTransport *aTransport) override
-    {
-        if (!gLayerScopeManager.GetSocketManager())
-            return NS_OK;
-
-        printf_stderr("*** LayerScope: Accepted connection\n");
-        gLayerScopeManager.GetSocketManager()->AddConnection(aTransport);
-        gLayerScopeManager.GetContentMonitor()->Empty();
-        return NS_OK;
-    }
-
-    NS_IMETHODIMP OnStopListening(nsIServerSocket *aServ,
-                                  nsresult aStatus) override
-    {
-        return NS_OK;
-    }
-};
-
-NS_IMPL_ISUPPORTS(DebugListener, nsIServerSocketListener);
-
-
 class DebugDataSender : public nsIRunnable
 {
     virtual ~DebugDataSender() {
         Cleanup();
     }
 
 public:
 
@@ -1130,20 +1131,20 @@ LayerScope::ContentChanged(TextureHost *
     if (!CheckSendable()) {
       return;
     }
 
     gLayerScopeManager.GetContentMonitor()->SetChangedHost(host);
 }
 
 // ----------------------------------------------
-// LayerScopeWebSocketHandler implementation
+// SocketHandler implementation
 // ----------------------------------------------
 void
-LayerScopeWebSocketHandler::OpenStream(nsISocketTransport* aTransport)
+LayerScopeWebSocketManager::SocketHandler::OpenStream(nsISocketTransport* aTransport)
 {
     MOZ_ASSERT(aTransport);
 
     mTransport = aTransport;
     mTransport->OpenOutputStream(nsITransport::OPEN_BLOCKING,
                                  0,
                                  0,
                                  getter_AddRefs(mOutputStream));
@@ -1153,17 +1154,17 @@ LayerScopeWebSocketHandler::OpenStream(n
                                 0,
                                 0,
                                 getter_AddRefs(debugInputStream));
     mInputStream = do_QueryInterface(debugInputStream);
     mInputStream->AsyncWait(this, 0, 0, NS_GetCurrentThread());
 }
 
 bool
-LayerScopeWebSocketHandler::WriteToStream(void *aPtr,
+LayerScopeWebSocketManager::SocketHandler::WriteToStream(void *aPtr,
                                           uint32_t aSize)
 {
     if (mState == NoHandshake) {
         // Not yet handshake, just return true in case of
         // LayerScope remove this handle
         return true;
     } else if (mState == HandshakeFailed) {
         return false;
@@ -1209,17 +1210,17 @@ LayerScopeWebSocketHandler::WriteToStrea
 
         written += cnt;
     }
 
     return true;
 }
 
 NS_IMETHODIMP
-LayerScopeWebSocketHandler::OnInputStreamReady(nsIAsyncInputStream *aStream)
+LayerScopeWebSocketManager::SocketHandler::OnInputStreamReady(nsIAsyncInputStream *aStream)
 {
     MOZ_ASSERT(mInputStream);
 
     if (!mInputStream) {
         return NS_OK;
     }
 
     if (!mConnected) {
@@ -1235,32 +1236,32 @@ LayerScopeWebSocketHandler::OnInputStrea
         }
         return NS_OK;
     } else {
         return HandleSocketMessage(aStream);
     }
 }
 
 void
-LayerScopeWebSocketHandler::ReadInputStreamData(nsTArray<nsCString>& aProtocolString)
+LayerScopeWebSocketManager::SocketHandler::ReadInputStreamData(nsTArray<nsCString>& aProtocolString)
 {
     nsLineBuffer<char> lineBuffer;
     nsCString line;
     bool more = true;
     do {
         NS_ReadLine(mInputStream.get(), &lineBuffer, line, &more);
 
         if (line.Length() > 0) {
             aProtocolString.AppendElement(line);
         }
     } while (more && line.Length() > 0);
 }
 
 bool
-LayerScopeWebSocketHandler::WebSocketHandshake(nsTArray<nsCString>& aProtocolString)
+LayerScopeWebSocketManager::SocketHandler::WebSocketHandshake(nsTArray<nsCString>& aProtocolString)
 {
     nsresult rv;
     bool isWebSocket = false;
     nsCString version;
     nsCString wsKey;
     nsCString protocol;
 
     // Validate WebSocket client request.
@@ -1338,17 +1339,17 @@ LayerScopeWebSocketHandler::WebSocketHan
         written += cnt;
     }
     mOutputStream->Flush();
 
     return true;
 }
 
 nsresult
-LayerScopeWebSocketHandler::HandleSocketMessage(nsIAsyncInputStream *aStream)
+LayerScopeWebSocketManager::SocketHandler::HandleSocketMessage(nsIAsyncInputStream *aStream)
 {
     // The reading and parsing of this input stream is customized for layer viewer.
     const uint32_t cPacketSize = 1024;
     char buffer[cPacketSize];
     uint32_t count = 0;
     nsresult rv = NS_OK;
 
     do {
@@ -1372,17 +1373,17 @@ LayerScopeWebSocketHandler::HandleSocket
         }
 
         rv = ProcessInput(reinterpret_cast<uint8_t *>(buffer), count);
     } while (NS_SUCCEEDED(rv) && mInputStream);
     return rv;
 }
 
 nsresult
-LayerScopeWebSocketHandler::ProcessInput(uint8_t *aBuffer,
+LayerScopeWebSocketManager::SocketHandler::ProcessInput(uint8_t *aBuffer,
                                          uint32_t aCount)
 {
     uint32_t avail = aCount;
 
     // Decode Websocket data frame
     if (avail <= 2) {
         NS_WARNING("Packet size is less than 2 bytes");
         return NS_OK;
@@ -1460,17 +1461,17 @@ LayerScopeWebSocketHandler::ProcessInput
     if (!HandleDataFrame(payload, payloadLength)) {
         NS_WARNING("Cannot decode payload data by the protocol buffer");
     }
 
     return NS_OK;
 }
 
 void
-LayerScopeWebSocketHandler::ApplyMask(uint32_t aMask,
+LayerScopeWebSocketManager::SocketHandler::ApplyMask(uint32_t aMask,
                                       uint8_t *aData,
                                       uint64_t aLen)
 {
     if (!aData || aLen == 0) {
         return;
     }
 
     // Optimally we want to apply the mask 32 bits at a time,
@@ -1500,17 +1501,17 @@ LayerScopeWebSocketHandler::ApplyMask(ui
         *aData ^= aMask >> 24;
         aMask = RotateLeft(aMask, 8);
         aData++;
         aLen--;
     }
 }
 
 bool
-LayerScopeWebSocketHandler::HandleDataFrame(uint8_t *aData,
+LayerScopeWebSocketManager::SocketHandler::HandleDataFrame(uint8_t *aData,
                                             uint32_t aSize)
 {
     // Handle payload data by protocol buffer
     auto p = MakeUnique<CommandPacket>();
     p->ParseFromArray(static_cast<void*>(aData), aSize);
 
     if (!p->has_type()) {
         MOZ_ASSERT(false, "Protocol buffer decoding failed or cannot recongize it");
@@ -1534,45 +1535,45 @@ LayerScopeWebSocketHandler::HandleDataFr
         default:
             NS_WARNING("Invalid message type");
             break;
     }
     return true;
 }
 
 void
-LayerScopeWebSocketHandler::CloseConnection()
+LayerScopeWebSocketManager::SocketHandler::CloseConnection()
 {
     gLayerScopeManager.GetSocketManager()->CleanDebugData();
     if (mInputStream) {
         mInputStream->AsyncWait(nullptr, 0, 0, nullptr);
         mInputStream = nullptr;
     }
     if (mOutputStream) {
         mOutputStream = nullptr;
     }
     if (mTransport) {
         mTransport->Close(NS_BASE_STREAM_CLOSED);
         mTransport = nullptr;
     }
     mConnected = false;
 }
 
-
 // ----------------------------------------------
 // LayerScopeWebSocketManager implementation
 // ----------------------------------------------
 LayerScopeWebSocketManager::LayerScopeWebSocketManager()
+    : mHandlerMutex("LayerScopeWebSocketManager::mHandlerMutex")
 {
     NS_NewThread(getter_AddRefs(mDebugSenderThread));
 
     mServerSocket = do_CreateInstance(NS_SERVERSOCKET_CONTRACTID);
     int port = gfxPrefs::LayerScopePort();
     mServerSocket->Init(port, false, -1);
-    mServerSocket->AsyncListen(new DebugListener);
+    mServerSocket->AsyncListen(new SocketListener);
 }
 
 LayerScopeWebSocketManager::~LayerScopeWebSocketManager()
 {
     mServerSocket->Close();
 }
 
 void
@@ -1595,61 +1596,78 @@ LayerScopeWebSocketManager::CleanDebugDa
 
 void
 LayerScopeWebSocketManager::DispatchDebugData()
 {
     mDebugSenderThread->Dispatch(mCurrentSender, NS_DISPATCH_NORMAL);
     mCurrentSender = nullptr;
 }
 
+NS_IMETHODIMP LayerScopeWebSocketManager::SocketListener::OnSocketAccepted(
+                                     nsIServerSocket *aServ,
+                                     nsISocketTransport *aTransport)
+{
+    if (!gLayerScopeManager.GetSocketManager())
+        return NS_OK;
+
+    printf_stderr("*** LayerScope: Accepted connection\n");
+    gLayerScopeManager.GetSocketManager()->AddConnection(aTransport);
+    gLayerScopeManager.GetContentMonitor()->Empty();
+    return NS_OK;
+}
 
 // ----------------------------------------------
 // LayerScope implementation
 // ----------------------------------------------
+/*static*/
 void
 LayerScope::Init()
 {
     if (!gfxPrefs::LayerScopeEnabled()) {
         return;
     }
 
     gLayerScopeManager.CreateServerSocket();
 }
 
+/*static*/
 void
 LayerScope::DrawBegin()
 {
     if (!CheckSendable()) {
         return;
     }
 
     gLayerScopeManager.NewDrawSession();
 }
 
+/*static*/
 void
 LayerScope::SetRenderOffset(float aX, float aY)
 {
     if (!CheckSendable()) {
         return;
     }
 
     gLayerScopeManager.CurrentSession().mOffsetX = aX;
     gLayerScopeManager.CurrentSession().mOffsetY = aY;
 }
 
+/*static*/
 void
 LayerScope::SetLayerTransform(const gfx::Matrix4x4& aMatrix)
 {
     if (!CheckSendable()) {
         return;
     }
 
     gLayerScopeManager.CurrentSession().mMVMatrix = aMatrix;
 }
 
+/*static*/
 void
 LayerScope::SetDrawRects(size_t aRects,
                          const gfx::Rect* aLayerRects,
                          const gfx::Rect* aTextureRects)
 {
     if (!CheckSendable()) {
         return;
     }
@@ -1660,16 +1678,17 @@ LayerScope::SetDrawRects(size_t aRects,
     gLayerScopeManager.CurrentSession().mRects = aRects;
 
     for (size_t i = 0; i < aRects; i++){
         gLayerScopeManager.CurrentSession().mLayerRects[i] = aLayerRects[i];
         gLayerScopeManager.CurrentSession().mTextureRects[i] = aTextureRects[i];
     }
 }
 
+/*static*/
 void
 LayerScope::DrawEnd(gl::GLContext* aGLContext,
                     const EffectChain& aEffectChain,
                     int aWidth,
                     int aHeight)
 {
     // Protect this public function
     if (!CheckSendable()) {
@@ -1687,39 +1706,42 @@ LayerScope::DrawEnd(gl::GLContext* aGLCo
                             draws.mMVMatrix, draws.mRects,
                             draws.mLayerRects,
                             draws.mTextureRects,
                             draws.mTexIDs,
                             aEffectChain.mLayerRef));
 
 }
 
+/*static*/
 void
 LayerScope::SendLayer(LayerComposite* aLayer,
                       int aWidth,
                       int aHeight)
 {
     // Protect this public function
     if (!CheckSendable()) {
         return;
     }
     SenderHelper::SendLayer(aLayer, aWidth, aHeight);
 }
 
+/*static*/
 void
 LayerScope::SendLayerDump(UniquePtr<Packet> aPacket)
 {
     // Protect this public function
     if (!CheckSendable() || !SenderHelper::GetLayersTreeSendable()) {
         return;
     }
     gLayerScopeManager.GetSocketManager()->AppendDebugData(
         new DebugGLLayersData(Move(aPacket)));
 }
 
+/*static*/
 bool
 LayerScope::CheckSendable()
 {
     // Only compositor threads check LayerScope status
     MOZ_ASSERT(CompositorParent::IsInCompositorThread() || gIsGtest);
 
     if (!gfxPrefs::LayerScopeEnabled()) {
         return false;
@@ -1729,38 +1751,42 @@ LayerScope::CheckSendable()
         return false;
     }
     if (!gLayerScopeManager.GetSocketManager()->IsConnected()) {
         return false;
     }
     return true;
 }
 
+/*static*/
 void
 LayerScope::CleanLayer()
 {
     if (CheckSendable()) {
         gLayerScopeManager.GetSocketManager()->CleanDebugData();
     }
 }
 
+/*static*/
 void
 LayerScope::SetHWComposed()
 {
     if (CheckSendable()) {
         gLayerScopeManager.GetSocketManager()->AppendDebugData(
             new DebugGLMetaData(Packet::META, true));
     }
 }
 
+/*static*/
 void
 LayerScope::SetPixelScale(double devPixelsPerCSSPixel)
 {
     gLayerScopeManager.SetPixelScale(devPixelsPerCSSPixel);
 }
+
 // ----------------------------------------------
 // LayerScopeAutoFrame implementation
 // ----------------------------------------------
 LayerScopeAutoFrame::LayerScopeAutoFrame(int64_t aFrameStamp)
 {
     // Do Begin Frame
     BeginFrame(aFrameStamp);
 }
--- a/js/src/builtin/Map.js
+++ b/js/src/builtin/Map.js
@@ -42,21 +42,18 @@ function MapIteratorNext() {
     // Steps 2-3.
     if (!IsObject(O) || !IsMapIterator(O))
         return callFunction(CallMapIteratorMethodIfWrapped, O, "MapIteratorNext");
 
     // Steps 4-5 (implemented in _GetNextMapEntryForIterator).
     // Steps 8-9 (omitted).
 
     var mapIterationResultPair = iteratorTemp.mapIterationResultPair;
-    if (!mapIterationResultPair) {
-        mapIterationResultPair = iteratorTemp.mapIterationResultPair = NewDenseArray(2);
-        mapIterationResultPair[0] = null;
-        mapIterationResultPair[1] = null;
-    }
+    if (!mapIterationResultPair)
+        mapIterationResultPair = iteratorTemp.mapIterationResultPair = [null, null];
 
     var retVal = {value: undefined, done: true};
 
     // Step 10.a, 11.
     var done = _GetNextMapEntryForIterator(O, mapIterationResultPair);
     if (!done) {
         // Steps 10.b-c (omitted).
 
--- a/js/src/devtools/rootAnalysis/build/gcc.manifest
+++ b/js/src/devtools/rootAnalysis/build/gcc.manifest
@@ -5,16 +5,15 @@
 {
 "size": 79831648,
 "digest": "958d0dfb531ac6911187cf57907317144a547b884c79dcb483668f0e468ab9f031492ab49177edebf6a6437680b69f54a346a37b4316da78c0ff87aa39c5f2c3",
 "algorithm": "sha512",
 "filename": "gcc.tar.xz",
 "unpack": true
 },
 {
-"size": 12057960,
-"digest": "6105d6432943141cffb40020dc5ba3a793650bdeb3af9bd5e56d3796c5f03df9962a73e521646cd71fbfb5e266c1e74716ad722fb6055589dfb7d35175bca89e",
+"size": 4431740,
+"digest": "68fc56b0fb0cdba629b95683d6649ff76b00dccf97af90960c3d7716f6108b2162ffd5ffcd5c3a60a21b28674df688fe4dabc67345e2da35ec5abeae3d48c8e3",
 "algorithm": "sha512",
 "filename": "gtk3.tar.xz",
-"setup": "setup.sh",
 "unpack": true
 }
 ]
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -1319,17 +1319,17 @@ static inline ScriptCountsMap::Ptr GetSc
 {
     MOZ_ASSERT(script->hasScriptCounts());
     ScriptCountsMap* map = script->compartment()->scriptCountsMap;
     ScriptCountsMap::Ptr p = map->lookup(script);
     MOZ_ASSERT(p);
     return p;
 }
 
-js::PCCounts
+js::PCCounts&
 JSScript::getPCCounts(jsbytecode* pc) {
     MOZ_ASSERT(containsPC(pc));
     ScriptCountsMap::Ptr p = GetScriptCountsMapEntry(this);
     return p->value().pcCountsVector[pcToOffset(pc)];
 }
 
 void
 JSScript::addIonCounts(jit::IonScriptCounts* ionCounts)
--- a/js/src/jsscript.h
+++ b/js/src/jsscript.h
@@ -1624,17 +1624,17 @@ class JSScript : public js::gc::TenuredC
     void resetWarmUpCounter() { incWarmUpResetCounter(); warmUpCount = 0; }
 
     uint16_t getWarmUpResetCount() const { return warmUpResetCount; }
     uint16_t incWarmUpResetCounter(uint16_t amount = 1) { return warmUpResetCount += amount; }
     void resetWarmUpResetCounter() { warmUpResetCount = 0; }
 
   public:
     bool initScriptCounts(JSContext* cx);
-    js::PCCounts getPCCounts(jsbytecode* pc);
+    js::PCCounts& getPCCounts(jsbytecode* pc);
     void addIonCounts(js::jit::IonScriptCounts* ionCounts);
     js::jit::IonScriptCounts* getIonCounts();
     js::ScriptCounts releaseScriptCounts();
     void destroyScriptCounts(js::FreeOp* fop);
 
     jsbytecode* main() {
         return code() + mainOffset();
     }
--- a/js/xpconnect/src/XPCConvert.cpp
+++ b/js/xpconnect/src/XPCConvert.cpp
@@ -1276,17 +1276,17 @@ XPCConvert::NativeArray2JS(MutableHandle
     uint32_t i;
     RootedValue current(cx, JS::NullValue());
 
 #define POPULATE(_t)                                                                    \
     PR_BEGIN_MACRO                                                                      \
         for (i = 0; i < count; i++) {                                                   \
             if (!NativeData2JS(&current, ((_t*)*s)+i, type, iid, pErr) ||               \
                 !JS_DefineElement(cx, array, i, current, JSPROP_ENUMERATE))             \
-                goto failure;                                                           \
+                return false;                                                           \
         }                                                                               \
     PR_END_MACRO
 
     // XXX check IsPtr - esp. to handle array of nsID (as opposed to nsID*)
 
     switch (type.TagPart()) {
     case nsXPTType::T_I8            : POPULATE(int8_t);         break;
     case nsXPTType::T_I16           : POPULATE(int16_t);        break;
@@ -1296,37 +1296,34 @@ XPCConvert::NativeArray2JS(MutableHandle
     case nsXPTType::T_U16           : POPULATE(uint16_t);       break;
     case nsXPTType::T_U32           : POPULATE(uint32_t);       break;
     case nsXPTType::T_U64           : POPULATE(uint64_t);       break;
     case nsXPTType::T_FLOAT         : POPULATE(float);          break;
     case nsXPTType::T_DOUBLE        : POPULATE(double);         break;
     case nsXPTType::T_BOOL          : POPULATE(bool);           break;
     case nsXPTType::T_CHAR          : POPULATE(char);           break;
     case nsXPTType::T_WCHAR         : POPULATE(char16_t);       break;
-    case nsXPTType::T_VOID          : NS_ERROR("bad type");     goto failure;
+    case nsXPTType::T_VOID          : NS_ERROR("bad type");     return false;
     case nsXPTType::T_IID           : POPULATE(nsID*);          break;
-    case nsXPTType::T_DOMSTRING     : NS_ERROR("bad type");     goto failure;
+    case nsXPTType::T_DOMSTRING     : NS_ERROR("bad type");     return false;
     case nsXPTType::T_CHAR_STR      : POPULATE(char*);          break;
     case nsXPTType::T_WCHAR_STR     : POPULATE(char16_t*);      break;
     case nsXPTType::T_INTERFACE     : POPULATE(nsISupports*);   break;
     case nsXPTType::T_INTERFACE_IS  : POPULATE(nsISupports*);   break;
-    case nsXPTType::T_UTF8STRING    : NS_ERROR("bad type");     goto failure;
-    case nsXPTType::T_CSTRING       : NS_ERROR("bad type");     goto failure;
-    case nsXPTType::T_ASTRING       : NS_ERROR("bad type");     goto failure;
-    default                         : NS_ERROR("bad type");     goto failure;
+    case nsXPTType::T_UTF8STRING    : NS_ERROR("bad type");     return false;
+    case nsXPTType::T_CSTRING       : NS_ERROR("bad type");     return false;
+    case nsXPTType::T_ASTRING       : NS_ERROR("bad type");     return false;
+    default                         : NS_ERROR("bad type");     return false;
     }
 
     if (pErr)
         *pErr = NS_OK;
     d.setObject(*array);
     return true;
 
-failure:
-    return false;
-
 #undef POPULATE
 }
 
 
 
 // Check that the tag part of the type matches the type
 // of the array. If the check succeeds, check that the size
 // of the output does not exceed UINT32_MAX bytes. Allocate
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/1190635-1-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML>
+<body style="width:500px; border:2px solid black;">
+<div style="width:300px; height:300px; background:yellow; float:left;"></div>
+<div style="width:300px; height:400px;">
+  <span style="display:inline-block; outline:3px solid cyan">
+    <span style="display:inline-block; width:300px; height:100px; outline:5px solid red" id="d"></span>
+  </span>
+</div>
+</body>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/1190635-1.html
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML>
+<html class="reftest-wait">
+<body style="width:500px; border:2px solid black;">
+<div style="width:300px; height:300px; background:yellow; float:left;"></div>
+<div style="width:300px; height:400px;">
+  <span style="display:inline-block; outline:3px solid cyan">
+    <span style="display:inline-block; width:0; height:0; outline:5px solid red" id="d"></span>
+  </span>
+</div>
+<script>
+window.addEventListener("MozReftestInvalidate", function() {
+  d.style.width = "300px";
+  d.style.height = "100px";
+  document.documentElement.removeAttribute("class");
+});
+</script>
+</body>
--- a/layout/reftests/bugs/reftest.list
+++ b/layout/reftests/bugs/reftest.list
@@ -1926,8 +1926,9 @@ skip-if(B2G||Mulet) == 1150021-1.xul 115
 == 1151145-1.html 1151145-1-ref.html
 == 1151306-1.html 1151306-1-ref.html
 == 1153845-1.html 1153845-1-ref.html
 == 1155828-1.html 1155828-1-ref.html
 == 1156129-1.html 1156129-1-ref.html
 == 1169331-1.html 1169331-1-ref.html
 == 1179078-1.html 1179078-1-ref.html
 fuzzy(1,74) fuzzy-if(gtkWidget,6,79) == 1174332-1.html 1174332-1-ref.html
+== 1190635-1.html 1190635-1-ref.html
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -1595,47 +1595,44 @@ nsChangeHint nsStylePosition::CalcDiffer
 
   if (mHeight != aOther.mHeight ||
       mMinHeight != aOther.mMinHeight ||
       mMaxHeight != aOther.mMaxHeight) {
     // Height changes can affect descendant intrinsic sizes due to replaced
     // elements with percentage heights in descendants which also have
     // percentage heights. This is handled via nsChangeHint_UpdateComputedBSize
     // which clears intrinsic sizes for frames that have such replaced elements.
-    return NS_CombineHint(hint, nsChangeHint_NeedReflow |
+    NS_UpdateHint(hint, nsChangeHint_NeedReflow |
         nsChangeHint_UpdateComputedBSize |
         nsChangeHint_ReflowChangesSizeOrPosition);
   }
 
   if (mWidth != aOther.mWidth ||
       mMinWidth != aOther.mMinWidth ||
       mMaxWidth != aOther.mMaxWidth) {
     // None of our width differences can affect descendant intrinsic
     // sizes and none of them need to force children to reflow.
-    return
-      NS_CombineHint(hint,
-                     NS_SubtractHint(nsChangeHint_AllReflowHints,
-                                     NS_CombineHint(nsChangeHint_ClearDescendantIntrinsics,
-                                                    nsChangeHint_NeedDirtyReflow)));
+    NS_UpdateHint(hint, NS_SubtractHint(nsChangeHint_AllReflowHints,
+                                        NS_CombineHint(nsChangeHint_ClearDescendantIntrinsics,
+                                                       nsChangeHint_NeedDirtyReflow)));
   }
 
-  // If width and height have not changed, but any of the offsets have changed,
-  // then return the respective hints so that we would hopefully be able to
-  // avoid reflowing.
+  // If any of the offsets have changed, then return the respective hints
+  // so that we would hopefully be able to avoid reflowing.
   // Note that it is possible that we'll need to reflow when processing
   // restyles, but we don't have enough information to make a good decision
   // right now.
   // Don't try to handle changes between "auto" and non-auto efficiently;
   // that's tricky to do and will hardly ever be able to avoid a reflow.
   if (mOffset != aOther.mOffset) {
     if (IsAutonessEqual(mOffset, aOther.mOffset)) {
       NS_UpdateHint(hint, nsChangeHint(nsChangeHint_RecomputePosition |
                                        nsChangeHint_UpdateParentOverflow));
     } else {
-      return NS_CombineHint(hint, nsChangeHint_AllReflowHints);
+      NS_UpdateHint(hint, nsChangeHint_AllReflowHints);
     }
   }
   return hint;
 }
 
 /* static */ bool
 nsStylePosition::WidthCoordDependsOnContainer(const nsStyleCoord &aCoord)
 {
--- a/media/libstagefright/frameworks/av/media/libstagefright/SampleTable.cpp
+++ b/media/libstagefright/frameworks/av/media/libstagefright/SampleTable.cpp
@@ -575,17 +575,19 @@ SampleTable::setSampleAuxiliaryInformati
 
     uint32_t cencOffsetCount;
     if (!mDataSource->getUInt32(data_offset, &cencOffsetCount)) {
         ALOGE("error reading cenc aux info offset count");
         return ERROR_IO;
     }
     data_offset += 4;
 
-    mCencOffsets.setCapacity(cencOffsetCount);
+    if (mCencOffsets.setCapacity(cencOffsetCount) < 0) {
+        return ERROR_MALFORMED;
+    }
     if (!version) {
         for (uint32_t i = 0; i < cencOffsetCount; i++) {
             uint32_t tmp;
             if (!mDataSource->getUInt32(data_offset, &tmp)) {
                 ALOGE("error reading cenc aux info offsets");
                 return ERROR_IO;
             }
             mCencOffsets.push(tmp);
@@ -1099,18 +1101,22 @@ SampleTable::getSampleCencInfo(
     CHECK(clear_sizes.isEmpty() && cipher_sizes.isEmpty());
 
     if (sample_index >= mCencInfoCount) {
         ALOGE("cenc info requested for out of range sample index");
         return ERROR_MALFORMED;
     }
 
     auto& info = mCencInfo[sample_index];
-    clear_sizes.setCapacity(info.mSubsampleCount);
-    cipher_sizes.setCapacity(info.mSubsampleCount);
+    if (clear_sizes.setCapacity(info.mSubsampleCount) < 0) {
+        return ERROR_MALFORMED;
+    }
+    if (cipher_sizes.setCapacity(info.mSubsampleCount) < 0) {
+        return ERROR_MALFORMED;
+    }
 
     for (uint32_t i = 0; i < info.mSubsampleCount; i++) {
         clear_sizes.push(info.mSubsamples[i].mClearBytes);
         cipher_sizes.push(info.mSubsamples[i].mCipherBytes);
     }
 
     memcpy(iv, info.mIV, IV_BYTES);
 
--- a/media/libstagefright/system/core/include/utils/Vector.h
+++ b/media/libstagefright/system/core/include/utils/Vector.h
@@ -13,16 +13,17 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 #ifndef ANDROID_VECTOR_H
 #define ANDROID_VECTOR_H
 
 #include <new>
+#include <assert.h>
 #include <stdint.h>
 #include <sys/types.h>
 
 #include <cutils/log.h>
 
 #include <utils/VectorImpl.h>
 #include <utils/TypeHelpers.h>
 
@@ -186,17 +187,17 @@ public:
       */
      typedef TYPE* iterator;
      typedef TYPE const* const_iterator;
 
      inline iterator begin() { return editArray(); }
      inline iterator end()   { return editArray() + size(); }
      inline const_iterator begin() const { return array(); }
      inline const_iterator end() const   { return array() + size(); }
-     inline void reserve(size_t n) { setCapacity(n); }
+     inline void reserve(size_t n) { assert(setCapacity(n) >= 0); }
      inline bool empty() const{ return isEmpty(); }
      inline void push_back(const TYPE& item)  { insertAt(item, size(), 1); }
      inline void push_front(const TYPE& item) { insertAt(item, 0, 1); }
      inline iterator erase(iterator pos) {
          ssize_t index = removeItemsAt(pos-array());
          return begin() + index;
      }
 
--- a/media/libstagefright/system/core/libutils/VectorImpl.cpp
+++ b/media/libstagefright/system/core/libutils/VectorImpl.cpp
@@ -22,19 +22,18 @@
 #include <stdio.h>
 
 #include <cutils/log.h>
 
 #include <utils/Errors.h>
 #include <utils/SharedBuffer.h>
 #include <utils/VectorImpl.h>
 
-#if !defined(SSIZE_MAX)
-#define SSIZE_MAX ((ssize_t)(SIZE_MAX/2))
-#endif
+static const uint32_t kMAX_ALLOCATION =
+    ((SIZE_MAX > INT32_MAX ? INT32_MAX : SIZE_MAX) - 1);
 
 /*****************************************************************************/
 
 
 namespace stagefright {
 
 // ----------------------------------------------------------------------------
 
@@ -88,16 +87,17 @@ VectorImpl& VectorImpl::operator = (cons
 }
 
 void* VectorImpl::editArrayImpl()
 {
     if (mStorage) {
         SharedBuffer* sb = SharedBuffer::bufferFromData(mStorage)->attemptEdit();
         if (sb == 0) {
             sb = SharedBuffer::alloc(capacity() * mItemSize);
+            assert(sb);
             if (sb) {
                 _do_copy(sb->data(), mStorage, mCount);
                 release_storage();
                 mStorage = sb->data();
             }
         }
     }
     return mStorage;
@@ -329,17 +329,17 @@ const void* VectorImpl::itemLocation(siz
 }
 
 ssize_t VectorImpl::setCapacity(size_t new_capacity)
 {
     if (new_capacity <= size()) {
         // we can't reduce the capacity
         return capacity();
     }
-    if (new_capacity >= (SSIZE_MAX / mItemSize)) {
+    if (new_capacity >= (kMAX_ALLOCATION / mItemSize)) {
         return NO_MEMORY;
     }
     SharedBuffer* sb = SharedBuffer::alloc(new_capacity * mItemSize);
     if (sb) {
         void* array = sb->data();
         _do_copy(array, mStorage, size());
         release_storage();
         mStorage = const_cast<void*>(array);
@@ -375,29 +375,35 @@ void* VectorImpl::_grow(size_t where, si
 //    ALOGV("_grow(this=%p, where=%d, amount=%d) count=%d, capacity=%d",
 //        this, (int)where, (int)amount, (int)mCount, (int)capacity());
 
     ALOG_ASSERT(where <= mCount,
             "[%p] _grow: where=%d, amount=%d, count=%d",
             this, (int)where, (int)amount, (int)mCount); // caller already checked
 
     const size_t new_size = mCount + amount;
+    assert(amount < kMAX_ALLOCATION - mCount);
     if (capacity() < new_size) {
+        assert(new_size < (SIZE_MAX / 3 - 1));
         const size_t new_capacity = max(kMinVectorCapacity, ((new_size*3)+1)/2);
+        assert(new_capacity < (kMAX_ALLOCATION / mItemSize));
 //        ALOGV("grow vector %p, new_capacity=%d", this, (int)new_capacity);
         if ((mStorage) &&
             (mCount==where) &&
             (mFlags & HAS_TRIVIAL_COPY) &&
             (mFlags & HAS_TRIVIAL_DTOR))
         {
             const SharedBuffer* cur_sb = SharedBuffer::bufferFromData(mStorage);
+            assert(cur_sb);
             SharedBuffer* sb = cur_sb->editResize(new_capacity * mItemSize);
+            assert(sb);
             mStorage = sb->data();
         } else {
             SharedBuffer* sb = SharedBuffer::alloc(new_capacity * mItemSize);
+            assert(sb);
             if (sb) {
                 void* array = sb->data();
                 if (where != 0) {
                     _do_copy(array, mStorage, where);
                 }
                 if (where != mCount) {
                     const void* from = reinterpret_cast<const uint8_t *>(mStorage) + where*mItemSize;
                     void* dest = reinterpret_cast<uint8_t *>(array) + (where+amount)*mItemSize;
@@ -428,44 +434,50 @@ void VectorImpl::_shrink(size_t where, s
 //    ALOGV("_shrink(this=%p, where=%d, amount=%d) count=%d, capacity=%d",
 //        this, (int)where, (int)amount, (int)mCount, (int)capacity());
 
     ALOG_ASSERT(where + amount <= mCount,
             "[%p] _shrink: where=%d, amount=%d, count=%d",
             this, (int)where, (int)amount, (int)mCount); // caller already checked
 
     const size_t new_size = mCount - amount;
-    if (new_size*3 < capacity()) {
+    assert(new_size < (SIZE_MAX / 2));
+    if (new_size*2 < capacity()) {
         const size_t new_capacity = max(kMinVectorCapacity, new_size*2);
 //        ALOGV("shrink vector %p, new_capacity=%d", this, (int)new_capacity);
+        assert(new_capacity < (kMAX_ALLOCATION / mItemSize));
         if ((where == new_size) &&
             (mFlags & HAS_TRIVIAL_COPY) &&
             (mFlags & HAS_TRIVIAL_DTOR))
         {
             const SharedBuffer* cur_sb = SharedBuffer::bufferFromData(mStorage);
+            assert(cur_sb);
             SharedBuffer* sb = cur_sb->editResize(new_capacity * mItemSize);
+            assert(sb);
             mStorage = sb->data();
         } else {
             SharedBuffer* sb = SharedBuffer::alloc(new_capacity * mItemSize);
+            assert(sb);
             if (sb) {
                 void* array = sb->data();
                 if (where != 0) {
                     _do_copy(array, mStorage, where);
                 }
                 if (where != new_size) {
                     const void* from = reinterpret_cast<const uint8_t *>(mStorage) + (where+amount)*mItemSize;
                     void* dest = reinterpret_cast<uint8_t *>(array) + where*mItemSize;
                     _do_copy(dest, from, new_size - where);
                 }
                 release_storage();
                 mStorage = const_cast<void*>(array);
             }
         }
     } else {
         void* array = editArrayImpl();
+        assert(array);
         void* to = reinterpret_cast<uint8_t *>(array) + where*mItemSize;
         _do_destroy(to, amount);
         if (where != new_size) {
             const void* from = reinterpret_cast<uint8_t *>(array) + (where+amount)*mItemSize;
             _do_move_backward(to, from, new_size - where);
         }
     }
     mCount = new_size;
--- a/media/webrtc/signaling/src/jsep/JsepSessionImpl.cpp
+++ b/media/webrtc/signaling/src/jsep/JsepSessionImpl.cpp
@@ -284,55 +284,55 @@ JsepSessionImpl::GetRemoteTracksAdded() 
 
 std::vector<RefPtr<JsepTrack>>
 JsepSessionImpl::GetRemoteTracksRemoved() const
 {
   return GetTracks(mRemoteTracksRemoved);
 }
 
 nsresult
-JsepSessionImpl::AddOfferMSections(const JsepOfferOptions& options, Sdp* sdp)
+JsepSessionImpl::SetupOfferMSections(const JsepOfferOptions& options, Sdp* sdp)
 {
   // First audio, then video, then datachannel, for interop
   // TODO(bug 1121756): We need to group these by stream-id, _then_ by media
   // type, according to the spec. However, this is not going to interop with
   // older versions of Firefox if a video-only stream is added before an
   // audio-only stream.
   // We should probably wait until 38 is ESR before trying to do this.
-  nsresult rv = AddOfferMSectionsByType(
+  nsresult rv = SetupOfferMSectionsByType(
       SdpMediaSection::kAudio, options.mOfferToReceiveAudio, sdp);
 
   NS_ENSURE_SUCCESS(rv, rv);
 
-  rv = AddOfferMSectionsByType(
+  rv = SetupOfferMSectionsByType(
       SdpMediaSection::kVideo, options.mOfferToReceiveVideo, sdp);
 
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (!(options.mDontOfferDataChannel.isSome() &&
         *options.mDontOfferDataChannel)) {
-    rv = AddOfferMSectionsByType(
+    rv = SetupOfferMSectionsByType(
         SdpMediaSection::kApplication, Maybe<size_t>(), sdp);
 
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   if (!sdp->GetMediaSectionCount()) {
     JSEP_SET_ERROR("Cannot create an offer with no local tracks, "
                    "no offerToReceiveAudio/Video, and no DataChannel.");
     return NS_ERROR_INVALID_ARG;
   }
 
   return NS_OK;
 }
 
 nsresult
-JsepSessionImpl::AddOfferMSectionsByType(SdpMediaSection::MediaType mediatype,
-                                         Maybe<size_t> offerToReceiveMaybe,
-                                         Sdp* sdp)
+JsepSessionImpl::SetupOfferMSectionsByType(SdpMediaSection::MediaType mediatype,
+                                           Maybe<size_t> offerToReceiveMaybe,
+                                           Sdp* sdp)
 {
   // Convert the Maybe into a size_t*, since that is more readable, especially
   // when using it as an in/out param.
   size_t offerToReceiveCount;
   size_t* offerToReceiveCountPtr = nullptr;
 
   if (offerToReceiveMaybe) {
     offerToReceiveCount = *offerToReceiveMaybe;
@@ -462,17 +462,17 @@ JsepSessionImpl::SetRecvAsNeededOrDisabl
       }
     } else if (msection.IsSending()) {
       msection.SetReceiving(true);
       continue;
     }
 
     if (!msection.IsSending()) {
       // Unused m-section, and no reason to offer to recv on it
-      DisableMsection(sdp, &msection);
+      mSdpHelper.DisableMsection(sdp, &msection);
     }
   }
 
   return NS_OK;
 }
 
 nsresult
 JsepSessionImpl::AddRecvonlyMsections(SdpMediaSection::MediaType mediatype,
@@ -486,40 +486,38 @@ JsepSessionImpl::AddRecvonlyMsections(Sd
     NS_ENSURE_SUCCESS(rv, rv);
   }
   return NS_OK;
 }
 
 // This function creates a skeleton SDP based on the old descriptions
 // (ie; all m-sections are inactive).
 nsresult
-JsepSessionImpl::CreateReoffer(const Sdp& oldLocalSdp,
-                               const Sdp& oldAnswer,
-                               Sdp* newSdp)
+JsepSessionImpl::AddReofferMsections(const Sdp& oldLocalSdp,
+                                     const Sdp& oldAnswer,
+                                     Sdp* newSdp)
 {
   nsresult rv;
 
   for (size_t i = 0; i < oldLocalSdp.GetMediaSectionCount(); ++i) {
     // We do not set the direction in this function (or disable when previously
-    // disabled), that happens in |AddOfferMSectionsByType|
+    // disabled), that happens in |SetupOfferMSectionsByType|
     rv = CreateOfferMSection(oldLocalSdp.GetMediaSection(i).GetMediaType(),
                              SdpDirectionAttribute::kInactive,
                              newSdp);
     NS_ENSURE_SUCCESS(rv, rv);
 
     rv = mSdpHelper.CopyStickyParams(oldAnswer.GetMediaSection(i),
                                      &newSdp->GetMediaSection(i));
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   return NS_OK;
 }
 
-// TODO(1142105): Do we teach SdpHelper about BundlePolicy, or are
-// we getting too much JSEP in there at that point?
 void
 JsepSessionImpl::SetupBundle(Sdp* sdp) const
 {
   std::vector<std::string> mids;
   std::set<SdpMediaSection::MediaType> observedTypes;
 
   // This has the effect of changing the bundle level if the first m-section
   // goes from disabled to enabled. This is kinda inefficient.
@@ -603,51 +601,52 @@ JsepSessionImpl::CreateOffer(const JsepO
 {
   mLastError.clear();
 
   if (mState != kJsepStateStable) {
     JSEP_SET_ERROR("Cannot create offer in state " << GetStateStr(mState));
     return NS_ERROR_UNEXPECTED;
   }
 
+  // Undo track assignments from a previous call to CreateOffer
+  // (ie; if the track has not been negotiated yet, it doesn't necessarily need
+  // to stay in the same m-section that it was in)
+  for (auto i = mLocalTracks.begin(); i != mLocalTracks.end(); ++i) {
+    if (!i->mNegotiated) {
+      i->mAssignedMLine.reset();
+    }
+  }
+
   UniquePtr<Sdp> sdp;
 
   // Make the basic SDP that is common to offer/answer.
   nsresult rv = CreateGenericSDP(&sdp);
   NS_ENSURE_SUCCESS(rv, rv);
-  ++mSessionVersion;
 
   if (mCurrentLocalDescription) {
-    rv = CreateReoffer(*mCurrentLocalDescription, *GetAnswer(), sdp.get());
+    rv = AddReofferMsections(*mCurrentLocalDescription,
+                             *GetAnswer(),
+                             sdp.get());
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
-  // Get rid of all m-line assignments that have not been negotiated
-  if (NS_SUCCEEDED(rv)) {
-    for (auto i = mLocalTracks.begin(); i != mLocalTracks.end(); ++i) {
-      if (!i->mNegotiated) {
-        i->mAssignedMLine.reset();
-      }
-    }
-  }
-
-  // Now add all the m-lines that we are attempting to negotiate.
-  rv = AddOfferMSections(options, sdp.get());
+  // Ensure that we have all the m-sections we need, and disable extras
+  rv = SetupOfferMSections(options, sdp.get());
   NS_ENSURE_SUCCESS(rv, rv);
 
   SetupBundle(sdp.get());
 
-  if (GetAnswer()) {
-    // We have an old answer from a previous negotiation
-    rv = SetupTransportParams(*GetAnswer(), *sdp, sdp.get());
+  if (mCurrentLocalDescription) {
+    rv = CopyPreviousTransportParams(*GetAnswer(), *sdp, sdp.get());
     NS_ENSURE_SUCCESS(rv,rv);
   }
 
   *offer = sdp->ToString();
   mGeneratedLocalDescription = Move(sdp);
+  ++mSessionVersion;
 
   return NS_OK;
 }
 
 std::string
 JsepSessionImpl::GetLocalDescription() const
 {
   std::ostringstream os;
@@ -769,46 +768,20 @@ JsepSessionImpl::GetCommonCodecs(const S
 
   return matchingCodecs;
 }
 
 void
 JsepSessionImpl::AddCommonExtmaps(const SdpMediaSection& remoteMsection,
                                   SdpMediaSection* msection)
 {
-  if (!remoteMsection.GetAttributeList().HasAttribute(
-        SdpAttribute::kExtmapAttribute)) {
-    return;
-  }
-
   auto* ourExtensions = GetRtpExtensions(remoteMsection.GetMediaType());
 
-  if (!ourExtensions) {
-    return;
-  }
-
-  UniquePtr<SdpExtmapAttributeList> ourExtmap(new SdpExtmapAttributeList);
-  auto& theirExtmap = remoteMsection.GetAttributeList().GetExtmap().mExtmaps;
-  for (auto i = theirExtmap.begin(); i != theirExtmap.end(); ++i) {
-    for (auto j = ourExtensions->begin(); j != ourExtensions->end(); ++j) {
-      if (i->extensionname == j->extensionname) {
-        ourExtmap->mExtmaps.push_back(*i);
-
-        // RFC 5285 says that ids >= 4096 can be used by the offerer to
-        // force the answerer to pick, otherwise the value in the offer is
-        // used.
-        if (ourExtmap->mExtmaps.back().entry >= 4096) {
-          ourExtmap->mExtmaps.back().entry = j->entry;
-        }
-      }
-    }
-  }
-
-  if (!ourExtmap->mExtmaps.empty()) {
-    msection->GetAttributeList().SetAttribute(ourExtmap.release());
+  if (ourExtensions) {
+    mSdpHelper.AddCommonExtmaps(remoteMsection, *ourExtensions, msection);
   }
 }
 
 nsresult
 JsepSessionImpl::CreateAnswer(const JsepAnswerOptions& options,
                               std::string* answer)
 {
   mLastError.clear();
@@ -831,18 +804,16 @@ JsepSessionImpl::CreateAnswer(const Jsep
   UniquePtr<Sdp> sdp;
 
   // Make the basic SDP that is common to offer/answer.
   nsresult rv = CreateGenericSDP(&sdp);
   NS_ENSURE_SUCCESS(rv, rv);
 
   const Sdp& offer = *mPendingRemoteDescription;
 
-  std::vector<SdpGroupAttributeList::Group> bundleGroups;
-
   // Copy the bundle groups into our answer
   UniquePtr<SdpGroupAttributeList> groupAttr(new SdpGroupAttributeList);
   mSdpHelper.GetBundleGroups(offer, &groupAttr->mGroups);
   sdp->GetAttributeList().SetAttribute(groupAttr.release());
 
   // Disable send for local tracks if the offer no longer allows it
   // (i.e., the m-section is recvonly, inactive or disabled)
   for (auto i = mLocalTracks.begin(); i != mLocalTracks.end(); ++i) {
@@ -864,19 +835,18 @@ JsepSessionImpl::CreateAnswer(const Jsep
   size_t numMsections = offer.GetMediaSectionCount();
 
   for (size_t i = 0; i < numMsections; ++i) {
     const SdpMediaSection& remoteMsection = offer.GetMediaSection(i);
     rv = CreateAnswerMSection(options, i, remoteMsection, sdp.get());
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
-  if (GetAnswer()) {
-    // We have an old answer from a previous negotiation
-    rv = SetupTransportParams(*GetAnswer(), *sdp, sdp.get());
+  if (mCurrentLocalDescription) {
+    rv = CopyPreviousTransportParams(*GetAnswer(), *sdp, sdp.get());
     NS_ENSURE_SUCCESS(rv,rv);
   }
 
   *answer = sdp->ToString();
   mGeneratedLocalDescription = Move(sdp);
 
   return NS_OK;
 }
@@ -948,17 +918,17 @@ JsepSessionImpl::CreateAnswerMSection(co
                            remoteMsection.GetProtocol(),
                            sdp::kIPv4,
                            "0.0.0.0");
 
   nsresult rv = mSdpHelper.CopyStickyParams(remoteMsection, &msection);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (mSdpHelper.MsectionIsDisabled(remoteMsection)) {
-    DisableMsection(sdp, &msection);
+    mSdpHelper.DisableMsection(sdp, &msection);
     return NS_OK;
   }
 
   SdpSetupAttribute::Role role;
   rv = DetermineAnswererSetupRole(remoteMsection, &role);
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = AddTransportAttributes(&msection, role);
@@ -990,23 +960,23 @@ JsepSessionImpl::CreateAnswerMSection(co
       break;
     }
   }
 
   // Add extmap attributes.
   AddCommonExtmaps(remoteMsection, &msection);
 
   if (!msection.IsReceiving() && !msection.IsSending()) {
-    DisableMsection(sdp, &msection);
+    mSdpHelper.DisableMsection(sdp, &msection);
     return NS_OK;
   }
 
   if (msection.GetFormats().empty()) {
     // Could not negotiate anything. Disable m-section.
-    DisableMsection(sdp, &msection);
+    mSdpHelper.DisableMsection(sdp, &msection);
   }
 
   return NS_OK;
 }
 
 nsresult
 JsepSessionImpl::SetRecvonlySsrc(SdpMediaSection* msection)
 {
@@ -1153,17 +1123,17 @@ JsepSessionImpl::SetLocalDescription(Jse
   nsresult rv = ParseSdp(sdp, &parsed);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Check that content hasn't done anything unsupported with the SDP
   rv = ValidateLocalDescription(*parsed);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Create transport objects.
-  mOldTransports = mTransports;
+  mOldTransports = mTransports; // Save in case we need to rollback
   for (size_t t = 0; t < parsed->GetMediaSectionCount(); ++t) {
     if (t >= mTransports.size()) {
       mTransports.push_back(RefPtr<JsepTransport>(new JsepTransport));
     }
 
     UpdateTransport(parsed->GetMediaSection(t), mTransports[t].get());
   }
 
@@ -1380,21 +1350,19 @@ JsepSessionImpl::HandleNegotiatedSession
   rv = SetUniquePayloadTypes();
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Ouch, this probably needs some dirty bit instead of just clearing
   // stuff for renegotiation.
   mNegotiatedTrackPairs = trackPairs;
 
   // Mark all assigned local tracks as negotiated
-  if (NS_SUCCEEDED(rv)) {
-    for (auto i = mLocalTracks.begin(); i != mLocalTracks.end(); ++i) {
-      if (i->mAssignedMLine.isSome()) {
-        i->mNegotiated = true;
-      }
+  for (auto i = mLocalTracks.begin(); i != mLocalTracks.end(); ++i) {
+    if (i->mAssignedMLine.isSome()) {
+      i->mNegotiated = true;
     }
   }
 
   mGeneratedLocalDescription.reset();
   return NS_OK;
 }
 
 nsresult
@@ -1674,19 +1642,19 @@ JsepSessionImpl::AddTransportAttributes(
       new SdpStringAttribute(SdpAttribute::kIcePwdAttribute, mIcePwd));
 
   msection->GetAttributeList().SetAttribute(new SdpSetupAttribute(dtlsRole));
 
   return NS_OK;
 }
 
 nsresult
-JsepSessionImpl::SetupTransportParams(const Sdp& oldAnswer,
-                                      const Sdp& newOffer,
-                                      Sdp* newLocal)
+JsepSessionImpl::CopyPreviousTransportParams(const Sdp& oldAnswer,
+                                             const Sdp& newOffer,
+                                             Sdp* newLocal)
 {
   for (size_t i = 0; i < oldAnswer.GetMediaSectionCount(); ++i) {
     if (!mSdpHelper.MsectionIsDisabled(newLocal->GetMediaSection(i)) &&
         mSdpHelper.AreOldTransportParamsValid(oldAnswer, newOffer, i)) {
       // If newLocal is an offer, this will be the number of components we used
       // last time, and if it is an answer, this will be the number of
       // components we've decided we're using now.
       size_t numComponents = mTransports[i]->mComponents;
@@ -2363,110 +2331,59 @@ JsepSessionImpl::EndOfLocalCandidates(co
     JSEP_SET_ERROR("Cannot add ICE candidate in state " << GetStateStr(mState));
     return NS_ERROR_UNEXPECTED;
   }
 
   if (level >= sdp->GetMediaSectionCount()) {
     return NS_OK;
   }
 
-  SdpHelper::BundledMids bundledMids;
-  nsresult rv = GetNegotiatedBundledMids(&bundledMids);
-  if (NS_FAILED(rv)) {
-    MOZ_ASSERT(false);
-    mLastError += " (This should have been caught sooner!)";
-    return NS_ERROR_FAILURE;
-  }
-
   std::string defaultRtcpCandidateAddrCopy(defaultRtcpCandidateAddr);
   if (mState == kJsepStateStable && mTransports[level]->mComponents == 1) {
     // We know we're doing rtcp-mux by now. Don't create an rtcp attr.
     defaultRtcpCandidateAddrCopy = "";
     defaultRtcpCandidatePort = 0;
   }
 
-  SdpMediaSection& msection = sdp->GetMediaSection(level);
-
-  // TODO(bug 1142105): Factor some of this out into a helper class
+  // If offer/answer isn't done, it is too early to tell whether these defaults
+  // need to be applied to other m-sections.
+  SdpHelper::BundledMids bundledMids;
   if (mState == kJsepStateStable) {
-    // offer/answer is done. Do we actually incorporate these defaults?
-    if (msection.GetAttributeList().HasAttribute(SdpAttribute::kMidAttribute)) {
-      std::string mid(msection.GetAttributeList().GetMid());
-      if (bundledMids.count(mid)) {
-        const SdpMediaSection* masterBundleMsection(bundledMids[mid]);
-        if (msection.GetLevel() != masterBundleMsection->GetLevel()) {
-          // Slave bundle m-section. Skip.
-          return NS_OK;
-        }
-
-        // Master bundle m-section. Set defaultCandidateAddr and
-        // defaultCandidatePort on all bundled m-sections.
-        for (auto i = bundledMids.begin(); i != bundledMids.end(); ++i) {
-          if (i->second != masterBundleMsection) {
-            continue;
-          }
-          SdpMediaSection* bundledMsection =
-            mSdpHelper.FindMsectionByMid(*sdp, i->first);
-          if (!bundledMsection) {
-            MOZ_ASSERT(false);
-            continue;
-          }
-          mSdpHelper.SetDefaultAddresses(defaultCandidateAddr,
-                                         defaultCandidatePort,
-                                         defaultRtcpCandidateAddrCopy,
-                                         defaultRtcpCandidatePort,
-                                         bundledMsection);
-        }
-      }
+    nsresult rv = GetNegotiatedBundledMids(&bundledMids);
+    if (NS_FAILED(rv)) {
+      MOZ_ASSERT(false);
+      mLastError += " (This should have been caught sooner!)";
+      return NS_ERROR_FAILURE;
     }
   }
 
-  mSdpHelper.SetDefaultAddresses(defaultCandidateAddr,
-                                 defaultCandidatePort,
-                                 defaultRtcpCandidateAddrCopy,
-                                 defaultRtcpCandidatePort,
-                                 &msection);
-
-  // TODO(bug 1095793): Will this have an mid someday?
-
-  SdpAttributeList& attrs = msection.GetAttributeList();
-  attrs.SetAttribute(
-      new SdpFlagAttribute(SdpAttribute::kEndOfCandidatesAttribute));
-  if (!mIsOfferer) {
-    attrs.RemoveAttribute(SdpAttribute::kIceOptionsAttribute);
-  }
+  mSdpHelper.SetDefaultAddresses(
+      defaultCandidateAddr,
+      defaultCandidatePort,
+      defaultRtcpCandidateAddrCopy,
+      defaultRtcpCandidatePort,
+      sdp,
+      level,
+      bundledMids);
 
   return NS_OK;
 }
 
 nsresult
 JsepSessionImpl::GetNegotiatedBundledMids(SdpHelper::BundledMids* bundledMids)
 {
   const Sdp* answerSdp = GetAnswer();
 
   if (!answerSdp) {
     return NS_OK;
   }
 
   return mSdpHelper.GetBundledMids(*answerSdp, bundledMids);
 }
 
-void
-JsepSessionImpl::DisableMsection(Sdp* sdp, SdpMediaSection* msection) const
-{
-  mSdpHelper.DisableMsection(sdp, msection);
-  msection->ClearCodecs();
-
-  // We need to have something here to fit the grammar
-  // TODO(bcampen@mozilla.com): What's the accepted way of doing this? Just
-  // add the codecs we do support? Does it matter? Most endpoints just pick
-  // something that the other end supported.
-  msection->AddCodec("111", "NULL", 0, 0);
-}
-
 nsresult
 JsepSessionImpl::EnableOfferMsection(SdpMediaSection* msection)
 {
   // We assert here because adding rtcp-mux to a non-disabled m-section that
   // did not already have rtcp-mux can cause problems.
   MOZ_ASSERT(mSdpHelper.MsectionIsDisabled(*msection));
 
   msection->SetPort(9);
--- a/media/webrtc/signaling/src/jsep/JsepSessionImpl.h
+++ b/media/webrtc/signaling/src/jsep/JsepSessionImpl.h
@@ -212,40 +212,40 @@ private:
   nsresult CreateReceivingTrack(size_t mline,
                                 const Sdp& sdp,
                                 const SdpMediaSection& msection,
                                 RefPtr<JsepTrack>* track);
   nsresult HandleNegotiatedSession(const UniquePtr<Sdp>& local,
                                    const UniquePtr<Sdp>& remote);
   nsresult AddTransportAttributes(SdpMediaSection* msection,
                                   SdpSetupAttribute::Role dtlsRole);
-  nsresult SetupTransportParams(const Sdp& oldAnswer,
-                                const Sdp& newOffer,
-                                Sdp* newLocal);
-  nsresult AddOfferMSections(const JsepOfferOptions& options, Sdp* sdp);
+  nsresult CopyPreviousTransportParams(const Sdp& oldAnswer,
+                                       const Sdp& newOffer,
+                                       Sdp* newLocal);
+  nsresult SetupOfferMSections(const JsepOfferOptions& options, Sdp* sdp);
   // Non-const so it can assign m-line index to tracks
-  nsresult AddOfferMSectionsByType(SdpMediaSection::MediaType type,
-                                   Maybe<size_t> offerToReceive,
-                                   Sdp* sdp);
+  nsresult SetupOfferMSectionsByType(SdpMediaSection::MediaType type,
+                                     Maybe<size_t> offerToReceive,
+                                     Sdp* sdp);
   nsresult BindLocalTracks(SdpMediaSection::MediaType mediatype,
                            Sdp* sdp);
   nsresult BindTrackToMsection(JsepSendingTrack* track,
                                SdpMediaSection* msection);
   nsresult EnsureRecvForRemoteTracks(SdpMediaSection::MediaType mediatype,
                                      Sdp* sdp,
                                      size_t* offerToReceive);
   nsresult SetRecvAsNeededOrDisable(SdpMediaSection::MediaType mediatype,
                                     Sdp* sdp,
                                     size_t* offerToRecv);
   nsresult AddRecvonlyMsections(SdpMediaSection::MediaType mediatype,
                                 size_t count,
                                 Sdp* sdp);
-  nsresult CreateReoffer(const Sdp& oldLocalSdp,
-                         const Sdp& oldAnswer,
-                         Sdp* newSdp);
+  nsresult AddReofferMsections(const Sdp& oldLocalSdp,
+                               const Sdp& oldAnswer,
+                               Sdp* newSdp);
   void SetupBundle(Sdp* sdp) const;
   nsresult GetRemoteIds(const Sdp& sdp,
                         const SdpMediaSection& msection,
                         std::string* streamId,
                         std::string* trackId);
   nsresult CreateOfferMSection(SdpMediaSection::MediaType type,
                                SdpDirectionAttribute::Direction direction,
                                Sdp* sdp);
@@ -275,17 +275,16 @@ private:
                        JsepTransport* transport);
 
   nsresult FinalizeTransport(const SdpAttributeList& remote,
                              const SdpAttributeList& answer,
                              const RefPtr<JsepTransport>& transport);
 
   nsresult GetNegotiatedBundledMids(SdpHelper::BundledMids* bundledMids);
 
-  void DisableMsection(Sdp* sdp, SdpMediaSection* msection) const;
   nsresult EnableOfferMsection(SdpMediaSection* msection);
 
   nsresult SetUniquePayloadTypes();
   nsresult GetAllPayloadTypes(const JsepTrackNegotiatedDetails& trackDetails,
                               std::vector<uint8_t>* payloadTypesOut);
   const Sdp* GetAnswer() const;
 
   std::vector<JsepSendingTrack> mLocalTracks;
--- a/media/webrtc/signaling/src/sdp/SdpHelper.cpp
+++ b/media/webrtc/signaling/src/sdp/SdpHelper.cpp
@@ -133,16 +133,21 @@ SdpHelper::DisableMsection(Sdp* sdp, Sdp
 
   // Clear out attributes.
   msection->GetAttributeList().Clear();
 
   auto* direction =
     new SdpDirectionAttribute(SdpDirectionAttribute::kInactive);
   msection->GetAttributeList().SetAttribute(direction);
   msection->SetPort(0);
+
+  msection->ClearCodecs();
+
+  // We need to have something here to fit the grammar, this seems safe.
+  msection->AddCodec("0", "PCMU", 8000, 1);
 }
 
 void
 SdpHelper::GetBundleGroups(
     const Sdp& sdp,
     std::vector<SdpGroupAttributeList::Group>* bundleGroups) const
 {
   if (sdp.GetAttributeList().HasAttribute(SdpAttribute::kGroupAttribute)) {
@@ -266,16 +271,71 @@ SdpHelper::AddCandidateToSdp(Sdp* sdp,
   return NS_OK;
 }
 
 void
 SdpHelper::SetDefaultAddresses(const std::string& defaultCandidateAddr,
                                uint16_t defaultCandidatePort,
                                const std::string& defaultRtcpCandidateAddr,
                                uint16_t defaultRtcpCandidatePort,
+                               Sdp* sdp,
+                               uint16_t level,
+                               BundledMids bundledMids)
+{
+  SdpMediaSection& msection = sdp->GetMediaSection(level);
+
+  if (msection.GetAttributeList().HasAttribute(SdpAttribute::kMidAttribute)) {
+    std::string mid(msection.GetAttributeList().GetMid());
+    if (bundledMids.count(mid)) {
+      const SdpMediaSection* masterBundleMsection(bundledMids[mid]);
+      if (msection.GetLevel() != masterBundleMsection->GetLevel()) {
+        // Slave bundle m-section. Skip.
+        return;
+      }
+
+      // Master bundle m-section. Set defaultCandidateAddr and
+      // defaultCandidatePort on all bundled m-sections.
+      for (auto i = bundledMids.begin(); i != bundledMids.end(); ++i) {
+        if (i->second != masterBundleMsection) {
+          continue;
+        }
+        SdpMediaSection* bundledMsection = FindMsectionByMid(*sdp, i->first);
+        if (!bundledMsection) {
+          MOZ_ASSERT(false);
+          continue;
+        }
+        SetDefaultAddresses(defaultCandidateAddr,
+                            defaultCandidatePort,
+                            defaultRtcpCandidateAddr,
+                            defaultRtcpCandidatePort,
+                            bundledMsection);
+      }
+    }
+  }
+
+  SetDefaultAddresses(defaultCandidateAddr,
+                      defaultCandidatePort,
+                      defaultRtcpCandidateAddr,
+                      defaultRtcpCandidatePort,
+                      &msection);
+
+  // TODO(bug 1095793): Will this have an mid someday?
+
+  SdpAttributeList& attrs = msection.GetAttributeList();
+  attrs.SetAttribute(
+      new SdpFlagAttribute(SdpAttribute::kEndOfCandidatesAttribute));
+  // Remove trickle-ice option
+  attrs.RemoveAttribute(SdpAttribute::kIceOptionsAttribute);
+}
+
+void
+SdpHelper::SetDefaultAddresses(const std::string& defaultCandidateAddr,
+                               uint16_t defaultCandidatePort,
+                               const std::string& defaultRtcpCandidateAddr,
+                               uint16_t defaultRtcpCandidatePort,
                                SdpMediaSection* msection)
 {
   msection->GetConnection().SetAddress(defaultCandidateAddr);
   msection->SetPort(defaultCandidatePort);
 
   if (!defaultRtcpCandidateAddr.empty()) {
     sdp::AddrType ipVersion = sdp::kIPv4;
     if (defaultRtcpCandidateAddr.find(':') != std::string::npos) {
@@ -599,11 +659,44 @@ SdpHelper::GetPtAsInt(const std::string&
   size_t length = static_cast<size_t>(end - ptString.c_str());
   if ((pt > UINT16_MAX) || (length != ptString.size())) {
     return false;
   }
   *ptOutparam = pt;
   return true;
 }
 
+void
+SdpHelper::AddCommonExtmaps(
+    const SdpMediaSection& remoteMsection,
+    const std::vector<SdpExtmapAttributeList::Extmap>& localExtensions,
+    SdpMediaSection* localMsection)
+{
+  if (!remoteMsection.GetAttributeList().HasAttribute(
+        SdpAttribute::kExtmapAttribute)) {
+    return;
+  }
+
+  UniquePtr<SdpExtmapAttributeList> localExtmap(new SdpExtmapAttributeList);
+  auto& theirExtmap = remoteMsection.GetAttributeList().GetExtmap().mExtmaps;
+  for (auto i = theirExtmap.begin(); i != theirExtmap.end(); ++i) {
+    for (auto j = localExtensions.begin(); j != localExtensions.end(); ++j) {
+      if (i->extensionname == j->extensionname) {
+        localExtmap->mExtmaps.push_back(*i);
+
+        // RFC 5285 says that ids >= 4096 can be used by the offerer to
+        // force the answerer to pick, otherwise the value in the offer is
+        // used.
+        if (localExtmap->mExtmaps.back().entry >= 4096) {
+          localExtmap->mExtmaps.back().entry = j->entry;
+        }
+      }
+    }
+  }
+
+  if (!localExtmap->mExtmaps.empty()) {
+    localMsection->GetAttributeList().SetAttribute(localExtmap.release());
+  }
+}
+
 } // namespace mozilla
 
 
--- a/media/webrtc/signaling/src/sdp/SdpHelper.h
+++ b/media/webrtc/signaling/src/sdp/SdpHelper.h
@@ -61,16 +61,23 @@ class SdpHelper {
     nsresult AddCandidateToSdp(Sdp* sdp,
                                const std::string& candidate,
                                const std::string& mid,
                                uint16_t level);
     void SetDefaultAddresses(const std::string& defaultCandidateAddr,
                              uint16_t defaultCandidatePort,
                              const std::string& defaultRtcpCandidateAddr,
                              uint16_t defaultRtcpCandidatePort,
+                             Sdp* sdp,
+                             uint16_t level,
+                             BundledMids bundledMids);
+    void SetDefaultAddresses(const std::string& defaultCandidateAddr,
+                             uint16_t defaultCandidatePort,
+                             const std::string& defaultRtcpCandidateAddr,
+                             uint16_t defaultRtcpCandidatePort,
                              SdpMediaSection* msection);
     void SetupMsidSemantic(const std::vector<std::string>& msids,
                            Sdp* sdp) const;
 
     std::string GetCNAME(const SdpMediaSection& msection) const;
     void SetSsrcs(const std::vector<uint32_t>& ssrcs,
                   const std::string& cname,
                   SdpMediaSection* msection) const;
@@ -87,16 +94,21 @@ class SdpHelper {
     SdpMediaSection::Protocol GetProtocolForMediaType(
         SdpMediaSection::MediaType type);
     void appendSdpParseErrors(
           const std::vector<std::pair<size_t, std::string> >& aErrors,
           std::string* aErrorString);
 
     static bool GetPtAsInt(const std::string& ptString, uint16_t* ptOutparam);
 
+    void AddCommonExtmaps(
+        const SdpMediaSection& remoteMsection,
+        const std::vector<SdpExtmapAttributeList::Extmap>& localExtensions,
+        SdpMediaSection* localMsection);
+
   private:
     std::string& mLastError;
 
     DISALLOW_COPY_ASSIGN(SdpHelper);
 };
 } // namespace mozilla
 
 #endif // _SDPHELPER_H_
--- a/netwerk/protocol/http/SpdySession31.cpp
+++ b/netwerk/protocol/http/SpdySession31.cpp
@@ -793,30 +793,16 @@ SpdySession31::GenerateSettings()
   if (!gHttpHandler->AllowPush()) {
     // announcing that we accept 0 incoming streams is done to
     // disable server push
     packet[15 + 8 * numberOfEntries] = SETTINGS_TYPE_MAX_CONCURRENT;
     // The value portion of the setting pair is already initialized to 0
     numberOfEntries++;
   }
 
-  nsRefPtr<nsHttpConnectionInfo> ci;
-  uint32_t cwnd = 0;
-  GetConnectionInfo(getter_AddRefs(ci));
-  if (ci)
-    cwnd = gHttpHandler->ConnMgr()->GetSpdyCWNDSetting(ci);
-  if (cwnd) {
-    packet[12 + 8 * numberOfEntries] = PERSISTED_VALUE;
-    packet[15 + 8 * numberOfEntries] = SETTINGS_TYPE_CWND;
-    LOG(("SpdySession31::GenerateSettings %p sending CWND %u\n", this, cwnd));
-    cwnd = PR_htonl(cwnd);
-    memcpy(packet + 16 + 8 * numberOfEntries, &cwnd, 4);
-    numberOfEntries++;
-  }
-
   // Advertise the Push RWIN and on each client SYN_STREAM pipeline
   // a window update with it in order to use larger initial windows with pulled
   // streams.
   packet[15 + 8 * numberOfEntries] = SETTINGS_TYPE_INITIAL_WINDOW;
   uint32_t rwin = PR_htonl(mPushAllowance);
   memcpy(packet + 16 + 8 * numberOfEntries, &rwin, 4);
   numberOfEntries++;
 
@@ -1440,51 +1426,22 @@ SpdySession31::HandleSettings(SpdySessio
     uint32_t flags = setting[0];
     uint32_t id = PR_ntohl(reinterpret_cast<uint32_t *>(setting)[0]) & 0xffffff;
     uint32_t value =  PR_ntohl(reinterpret_cast<uint32_t *>(setting)[1]);
 
     LOG3(("Settings ID %d, Flags %X, Value %d", id, flags, value));
 
     switch (id)
     {
-    case SETTINGS_TYPE_UPLOAD_BW:
-      Telemetry::Accumulate(Telemetry::SPDY_SETTINGS_UL_BW, value);
-      break;
-
-    case SETTINGS_TYPE_DOWNLOAD_BW:
-      Telemetry::Accumulate(Telemetry::SPDY_SETTINGS_DL_BW, value);
-      break;
-
-    case SETTINGS_TYPE_RTT:
-      Telemetry::Accumulate(Telemetry::SPDY_SETTINGS_RTT, value);
-      break;
-
     case SETTINGS_TYPE_MAX_CONCURRENT:
       self->mMaxConcurrent = value;
-      Telemetry::Accumulate(Telemetry::SPDY_SETTINGS_MAX_STREAMS, value);
       self->ProcessPending();
       break;
 
-    case SETTINGS_TYPE_CWND:
-      if (flags & PERSIST_VALUE)
-      {
-        nsRefPtr<nsHttpConnectionInfo> ci;
-        self->GetConnectionInfo(getter_AddRefs(ci));
-        if (ci)
-          gHttpHandler->ConnMgr()->ReportSpdyCWNDSetting(ci, value);
-      }
-      Telemetry::Accumulate(Telemetry::SPDY_SETTINGS_CWND, value);
-      break;
-
-    case SETTINGS_TYPE_DOWNLOAD_RETRANS_RATE:
-      Telemetry::Accumulate(Telemetry::SPDY_SETTINGS_RETRANS, value);
-      break;
-
     case SETTINGS_TYPE_INITIAL_WINDOW:
-      Telemetry::Accumulate(Telemetry::SPDY_SETTINGS_IW, value >> 10);
       {
         int32_t delta = value - self->mServerInitialStreamWindow;
         self->mServerInitialStreamWindow = value;
 
         // do not use SETTINGS to adjust the session window.
 
         // we need to add the delta to all open streams (delta can be negative)
         self->mStreamTransactionHash.Enumerate(UpdateServerRwinEnumerator,
--- a/netwerk/protocol/http/nsHttpAtomList.h
+++ b/netwerk/protocol/http/nsHttpAtomList.h
@@ -20,16 +20,17 @@
 HTTP_ATOM(Accept,                    "Accept")
 HTTP_ATOM(Accept_Encoding,           "Accept-Encoding")
 HTTP_ATOM(Accept_Language,           "Accept-Language")
 HTTP_ATOM(Accept_Ranges,             "Accept-Ranges")
 HTTP_ATOM(Age,                       "Age")
 HTTP_ATOM(Allow,                     "Allow")
 HTTP_ATOM(Alternate_Service,         "Alt-Svc")
 HTTP_ATOM(Alternate_Service_Used,    "Alt-Used")
+HTTP_ATOM(Alternate_Protocol,        "Alternate-Protocol")
 HTTP_ATOM(Assoc_Req,                 "Assoc-Req")
 HTTP_ATOM(Authentication,            "Authentication")
 HTTP_ATOM(Authorization,             "Authorization")
 HTTP_ATOM(Cache_Control,             "Cache-Control")
 HTTP_ATOM(Connection,                "Connection")
 HTTP_ATOM(Content_Disposition,       "Content-Disposition")
 HTTP_ATOM(Content_Encoding,          "Content-Encoding")
 HTTP_ATOM(Content_Language,          "Content-Language")
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -1392,23 +1392,31 @@ nsHttpChannel::ProcessAltService()
 }
 
 nsresult
 nsHttpChannel::ProcessResponse()
 {
     nsresult rv;
     uint32_t httpStatus = mResponseHead->Status();
 
-    // Gather data on whether the transaction and page (if this is
-    // the initial page load) is being loaded with SSL.
-    Telemetry::Accumulate(Telemetry::HTTP_TRANSACTION_IS_SSL,
-                          mConnectionInfo->EndToEndSSL());
-    if (mLoadFlags & LOAD_INITIAL_DOCUMENT_URI) {
-        Telemetry::Accumulate(Telemetry::HTTP_PAGELOAD_IS_SSL,
+    // do some telemetry
+    if (gHttpHandler->IsTelemetryEnabled()) {
+        // Gather data on whether the transaction and page (if this is
+        // the initial page load) is being loaded with SSL.
+        Telemetry::Accumulate(Telemetry::HTTP_TRANSACTION_IS_SSL,
                               mConnectionInfo->EndToEndSSL());
+        if (mLoadFlags & LOAD_INITIAL_DOCUMENT_URI) {
+            Telemetry::Accumulate(Telemetry::HTTP_PAGELOAD_IS_SSL,
+                                  mConnectionInfo->EndToEndSSL());
+        }
+
+        // how often do we see something like Alternate-Protocol: "443:quic,p=1"
+        const char *alt_protocol = mResponseHead->PeekHeader(nsHttp::Alternate_Protocol);
+        bool saw_quic = (alt_protocol && PL_strstr(alt_protocol, "quic")) ? 1 : 0;
+        Telemetry::Accumulate(Telemetry::HTTP_SAW_QUIC_ALT_PROTOCOL, saw_quic);
     }
 
     LOG(("nsHttpChannel::ProcessResponse [this=%p httpStatus=%u]\n",
         this, httpStatus));
 
     if (mTransaction->ProxyConnectFailed()) {
         // Only allow 407 (authentication required) to continue
         if (httpStatus != 407)
--- a/netwerk/protocol/http/nsHttpConnectionMgr.cpp
+++ b/netwerk/protocol/http/nsHttpConnectionMgr.cpp
@@ -742,77 +742,16 @@ nsHttpConnectionMgr::ReportSpdyConnectio
               "may have insufficient cert. Leave mapping in place but do not "
               "abandon this connection yet."));
     }
 
     ProcessPendingQ(ent->mConnInfo);
     PostEvent(&nsHttpConnectionMgr::OnMsgProcessAllSpdyPendingQ);
 }
 
-void
-nsHttpConnectionMgr::ReportSpdyCWNDSetting(nsHttpConnectionInfo *ci,
-                                           uint32_t cwndValue)
-{
-    MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
-
-    if (!gHttpHandler->UseSpdyPersistentSettings())
-        return;
-
-    if (!ci)
-        return;
-
-    nsConnectionEntry *ent = mCT.Get(ci->HashKey());
-    if (!ent)
-        return;
-
-    ent = GetSpdyPreferredEnt(ent);
-    if (!ent) // just to be thorough - but that map should always exist
-        return;
-
-    cwndValue = std::max(2U, cwndValue);
-    cwndValue = std::min(128U, cwndValue);
-
-    ent->mSpdyCWND = cwndValue;
-    ent->mSpdyCWNDTimeStamp = TimeStamp::Now();
-    return;
-}
-
-// a value of 0 means no setting is available
-uint32_t
-nsHttpConnectionMgr::GetSpdyCWNDSetting(nsHttpConnectionInfo *ci)
-{
-    MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
-
-    if (!gHttpHandler->UseSpdyPersistentSettings())
-        return 0;
-
-    if (!ci)
-        return 0;
-
-    nsConnectionEntry *ent = mCT.Get(ci->HashKey());
-    if (!ent)
-        return 0;
-
-    ent = GetSpdyPreferredEnt(ent);
-    if (!ent) // just to be thorough - but that map should always exist
-        return 0;
-
-    if (ent->mSpdyCWNDTimeStamp.IsNull())
-        return 0;
-
-    // For privacy tracking reasons, and the fact that CWND is not
-    // meaningful after some time, we don't honor stored CWND after 8
-    // hours.
-    TimeDuration age = TimeStamp::Now() - ent->mSpdyCWNDTimeStamp;
-    if (age.ToMilliseconds() > (1000 * 60 * 60 * 8))
-        return 0;
-
-    return ent->mSpdyCWND;
-}
-
 nsHttpConnectionMgr::nsConnectionEntry *
 nsHttpConnectionMgr::GetSpdyPreferredEnt(nsConnectionEntry *aOriginalEntry)
 {
     if (!gHttpHandler->IsSpdyEnabled() ||
         !gHttpHandler->CoalesceSpdy() ||
         aOriginalEntry->mCoalescingKeys.IsEmpty()) {
         return nullptr;
     }
@@ -3664,17 +3603,16 @@ nsHttpConnectionMgr::
 nsConnectionEntry::nsConnectionEntry(nsHttpConnectionInfo *ci)
     : mConnInfo(ci)
     , mPipelineState(PS_YELLOW)
     , mYellowGoodEvents(0)
     , mYellowBadEvents(0)
     , mYellowConnection(nullptr)
     , mGreenDepth(kPipelineOpen)
     , mPipeliningPenalty(0)
-    , mSpdyCWND(0)
     , mUsingSpdy(false)
     , mTestedSpdy(false)
     , mInPreferredHash(false)
     , mPreferIPv4(false)
     , mPreferIPv6(false)
 {
     MOZ_COUNT_CTOR(nsConnectionEntry);
     if (gHttpHandler->GetPipelineAggressive()) {
--- a/netwerk/protocol/http/nsHttpConnectionMgr.h
+++ b/netwerk/protocol/http/nsHttpConnectionMgr.h
@@ -237,21 +237,16 @@ public:
     // that the network peer has closed the transport.
     nsresult CloseIdleConnection(nsHttpConnection *);
 
     // The connection manager needs to know when a normal HTTP connection has been
     // upgraded to SPDY because the dispatch and idle semantics are a little
     // bit different.
     void ReportSpdyConnection(nsHttpConnection *, bool usingSpdy);
 
-    // A spdy server can supply cwnd information for the session that is used
-    // in future sessions to speed up the opening portions of the connection.
-    void ReportSpdyCWNDSetting(nsHttpConnectionInfo *host, uint32_t cwndValue);
-    uint32_t GetSpdyCWNDSetting(nsHttpConnectionInfo *host);
-
     bool     SupportsPipelining(nsHttpConnectionInfo *);
 
     bool GetConnectionData(nsTArray<HttpRetParams> *);
 
     void ResetIPFamilyPreference(nsHttpConnectionInfo *);
 
     uint16_t MaxRequestDelay() { return mMaxRequestDelay; }
 
@@ -361,21 +356,16 @@ private:
         // to build the hash key for hosts in the same ip pool.
         //
         // When a set of hosts are coalesced together one of them is marked
         // mSpdyPreferred. The mapping is maintained in the connection mananger
         // mSpdyPreferred hash.
         //
         nsTArray<nsCString> mCoalescingKeys;
 
-        // The value of a recevied SPDY settings type 5 previously received
-        // for this connection entry and the time it was set.
-        uint32_t            mSpdyCWND;
-        TimeStamp  mSpdyCWNDTimeStamp;
-
         // To have the UsingSpdy flag means some host with the same connection
         // entry has done NPN=spdy/* at some point. It does not mean every
         // connection is currently using spdy.
         bool mUsingSpdy;
 
         // mTestedSpdy is set after NPN negotiation has occurred and we know
         // with confidence whether a host speaks spdy or not (which is reflected
         // in mUsingSpdy). Before mTestedSpdy is set, handshake parallelism is
--- a/testing/mozbase/docs/mozversion.rst
+++ b/testing/mozbase/docs/mozversion.rst
@@ -1,16 +1,25 @@
 :mod:`mozversion` --- Get application information
 =================================================
 
 `mozversion <https://github.com/mozilla/mozbase/tree/master/mozversion>`_
 provides version information such as the application name and the changesets
 that it has been built from. This is commonly used in reporting or for
 conditional logic based on the application under test.
 
+Note that mozversion can report the version of remote devices (e.g. Firefox OS)
+but it requires the :mod:`mozdevice` dependency in that case. You can require it
+along with mozversion by using the extra *device* dependency:
+
+.. code-block:: bash
+
+  pip install mozversion[device]
+
+
 API Usage
 ---------
 
 .. automodule:: mozversion
     :members: get_version
 
 Examples
 ````````
--- a/testing/mozbase/mozversion/mozversion/mozversion.py
+++ b/testing/mozbase/mozversion/mozversion/mozversion.py
@@ -7,17 +7,16 @@ import ConfigParser
 from StringIO import StringIO
 import os
 import re
 import sys
 import tempfile
 import xml.dom.minidom
 import zipfile
 
-import mozdevice
 import mozfile
 import mozlog
 
 import errors
 
 
 INI_DATA_MAPPING = (('application', 'App'), ('platform', 'Build'))
 
@@ -184,16 +183,23 @@ class LocalB2GVersion(B2GVersion):
 
 class RemoteB2GVersion(B2GVersion):
 
     def __init__(self, sources=None, dm_type='adb', host=None,
                  device_serial=None, adb_host=None, adb_port=None,
                  **kwargs):
         B2GVersion.__init__(self, sources, **kwargs)
 
+        try:
+            import mozdevice
+        except ImportError:
+            self._logger.critical("mozdevice is required to get the version"
+                                  " of a remote device")
+            raise
+
         if dm_type == 'adb':
             dm = mozdevice.DeviceManagerADB(deviceSerial=device_serial,
                                             serverHost=adb_host,
                                             serverPort=adb_port)
         elif dm_type == 'sut':
             if not host:
                 raise errors.RemoteAppNotFoundError(
                     'A host for SUT must be supplied.')
--- a/testing/mozbase/mozversion/setup.py
+++ b/testing/mozbase/mozversion/setup.py
@@ -1,31 +1,29 @@
 # 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/.
 
 from setuptools import setup
 
 PACKAGE_VERSION = '1.3'
 
-dependencies = ['mozdevice >= 0.44',
-                'mozfile >= 1.0',
-                'mozlog >= 3.0']
 
 setup(name='mozversion',
       version=PACKAGE_VERSION,
       description='Library to get version information for applications',
       long_description='See http://mozbase.readthedocs.org',
       classifiers=[],
       keywords='mozilla',
       author='Mozilla Automation and Testing Team',
       author_email='tools@lists.mozilla.org',
       url='https://wiki.mozilla.org/Auto-tools/Projects/Mozbase',
       license='MPL',
       packages=['mozversion'],
       include_package_data=True,
       zip_safe=False,
-      install_requires=dependencies,
+      install_requires=['mozfile >= 1.0', 'mozlog >= 3.0'],
+      extras_require={'device': ['mozdevice >= 0.44']},
       entry_points="""
       # -*- Entry points: -*-
       [console_scripts]
       mozversion = mozversion:cli
       """)
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -1451,70 +1451,70 @@
     "expires_in_version": "never",
     "kind": "exponential",
     "high": "3000",
     "n_buckets": 50,
     "extended_statistics_ok": true,
     "description": "SPDY: KB read per connection"
   },
   "SPDY_SETTINGS_UL_BW": {
-    "expires_in_version": "never",
+    "expires_in_version": "42",
     "kind": "exponential",
     "high": "10000",
     "n_buckets": 100,
     "extended_statistics_ok": true,
     "description": "SPDY: Settings Upload Bandwidth"
   },
   "SPDY_SETTINGS_DL_BW": {
-    "expires_in_version": "never",
+    "expires_in_version": "42",
     "kind": "exponential",
     "high": "10000",
     "n_buckets": 100,
     "extended_statistics_ok": true,
     "description": "SPDY: Settings Download Bandwidth"
   },
   "SPDY_SETTINGS_RTT": {
-    "expires_in_version": "never",
+    "expires_in_version": "42",
     "kind": "exponential",
     "high": "1000",
     "n_buckets": 100,
     "extended_statistics_ok": true,
     "description": "SPDY: Settings RTT"
   },
   "SPDY_SETTINGS_MAX_STREAMS": {
     "expires_in_version": "never",
     "kind": "exponential",
     "high": "5000",
     "n_buckets": 100,
     "extended_statistics_ok": true,
-    "description": "SPDY: Settings Max Streams parameter"
+    "description": "H2: Settings Max Streams parameter"
   },
   "SPDY_SETTINGS_CWND": {
-    "expires_in_version": "never",
+    "expires_in_version": "42",
     "kind": "exponential",
     "high": "500",
     "n_buckets": 50,
     "extended_statistics_ok": true,
     "description": "SPDY: Settings CWND (packets)"
   },
   "SPDY_SETTINGS_RETRANS": {
-    "expires_in_version": "never",
+    "expires_in_version": "42",
     "kind": "exponential",
     "high": "100",
     "n_buckets": 50,
     "extended_statistics_ok": true,
     "description": "SPDY: Retransmission Rate"
   },
   "SPDY_SETTINGS_IW": {
     "expires_in_version": "never",
     "kind": "exponential",
     "high": "1000",
     "n_buckets": 50,
     "extended_statistics_ok": true,
-    "description": "SPDY: Settings IW (rounded to KB)"
+    "description": "H2: Settings Initial Window (rounded to KB)"
   },
   "DISK_CACHE_CORRUPT_DETAILS": {
     "expires_in_version": "40",
     "kind": "enumerated",
     "n_values": 50,
     "description": "Why the HTTP disk cache was corrupted at startup"
   },
   "DISK_CACHE_REDUCTION_TRIAL": {
@@ -1652,17 +1652,22 @@
   "TRANSACTION_WAIT_TIME_SPDY": {
     "expires_in_version": "never",
     "kind": "exponential",
     "high": "5000",
     "n_buckets": 100,
     "extended_statistics_ok": true,
     "description": "Time from submission to dispatch of SPDY transaction (ms)"
   },
-  "HTTP_DISK_CACHE_OVERHEAD": {
+  "HTTP_SAW_QUIC_ALT_PROTOCOL": {
+    "expires_in_version": "never",
+    "kind": "boolean",
+    "description": "Fraction of responses with a quic alt-protocol advertisement."
+  },
+ "HTTP_DISK_CACHE_OVERHEAD": {
     "expires_in_version": "default",
     "kind": "exponential",
     "high": "32000000",
     "n_buckets": 100,
     "extended_statistics_ok": true,
     "description": "HTTP Disk cache memory overhead (bytes)"
   },
   "CACHE_LM_INCONSISTENT": {
--- a/toolkit/content/aboutTelemetry.js
+++ b/toolkit/content/aboutTelemetry.js
@@ -1058,17 +1058,17 @@ let Histogram = {
    */
   renderValues: function Histogram_renderValues(aDiv, aHgram, aOptions) {
     let text = "";
     // If the last label is not the longest string, alignment will break a little
     let labelPadTo = 0;
     if (aHgram.values.length) {
       labelPadTo = String(aHgram.values[aHgram.values.length - 1][0]).length;
     }
-    let maxBarValue = aOptions.exponential ? this.getLogValue(aHgram.max_value) : aHgram.max;
+    let maxBarValue = aOptions.exponential ? this.getLogValue(aHgram.max) : aHgram.max;
 
     for (let [label, value] of aHgram.values) {
       let barValue = aOptions.exponential ? this.getLogValue(value) : value;
 
       // Create a text representation: <right-aligned-label> |<bar-of-#><value>  <percentage>
       text += EOL
               + " ".repeat(Math.max(0, labelPadTo - String(label).length)) + label // Right-aligned label
               + " |" + "#".repeat(Math.round(MAX_BAR_CHARS * barValue / maxBarValue)) // Bar
--- a/widget/windows/IMMHandler.h
+++ b/widget/windows/IMMHandler.h
@@ -431,21 +431,39 @@ protected:
     }
     uint32_t Length() const { return mString.Length(); }
     bool Collapsed() const { return !Length(); }
 
     bool IsValid() const;
     bool Update(const IMENotification& aIMENotification);
     bool Init(nsWindow* aWindow);
     bool EnsureValidSelection(nsWindow* aWindow);
+  private:
+    Selection(const Selection& aOther) = delete;
+    void operator =(const Selection& aOther) = delete;
   };
+  // mSelection stores the latest selection data only when sHasFocus is true.
+  // Don't access mSelection directly.  You should use GetSelection() for
+  // getting proper state.
   Selection mSelection;
-  // mSelection stores the latest selection data only when sHasFocus it true.
-  // Therefore, if sHasFocus is false, temporary instance should be used.
-  Selection GetSelection() { return sHasFocus ? mSelection : Selection(); }
+
+  Selection& GetSelection()
+  {
+    // When IME has focus, mSelection is automatically updated by
+    // NOTIFY_IME_OF_SELECTION_CHANGE.
+    if (sHasFocus) {
+      return mSelection;
+    }
+    // Otherwise, i.e., While IME doesn't have focus, we cannot observe
+    // selection changes.  So, in such case, we need to query selection
+    // when it's necessary.
+    static Selection sTempSelection;
+    sTempSelection.Clear();
+    return sTempSelection;
+  }
 
   bool mIsComposing;
   bool mIsComposingOnPlugin;
   bool mNativeCaretIsCreated;
 
   static mozilla::WritingMode sWritingModeOfCompositionFont;
   static nsString sIMEName;
   static UINT sCodePage;