Merge m-c to fx-team
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Fri, 19 Sep 2014 14:37:43 +0200
changeset 206238 3243776bed0e1fbaea3a72fd839031356da08159
parent 206237 86a707d5ffdba458281e6dbfb833b57956c39b9a (current diff)
parent 206162 3475e6a1665a6339dcbdc220a06ebdcdd9a9293c (diff)
child 206239 c5247437d857469b0f280e125a95d2da73d40b13
push id27517
push userryanvm@gmail.com
push dateFri, 19 Sep 2014 18:13:39 +0000
treeherdermozilla-central@a084c4cfd8a1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone35.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/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="fe92ddd450e03b38edb2d465de7897971d68ac68">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="bc2da39ccd2b82b67773f10c8da8fc8eedc483ab"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="d170091ba1b5597b05f37fb259f6b8eb02568798"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f293787d4a86257c9e78a35bd3f73b31b706e2"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <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="f3e998242fb9a857cf50f5bf3a02304a530ea617"/>
--- 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="4d1e85908d792d9468c4da7040acd191fbb51b40">
     <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="bc2da39ccd2b82b67773f10c8da8fc8eedc483ab"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="d170091ba1b5597b05f37fb259f6b8eb02568798"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f293787d4a86257c9e78a35bd3f73b31b706e2"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="c058843242068d0df7c107e09da31b53d2e08fa6"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f3e998242fb9a857cf50f5bf3a02304a530ea617"/>
   <!-- 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="8986df0f82e15ac2798df0b6c2ee3435400677ac">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="bc2da39ccd2b82b67773f10c8da8fc8eedc483ab"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="d170091ba1b5597b05f37fb259f6b8eb02568798"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f293787d4a86257c9e78a35bd3f73b31b706e2"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f3e998242fb9a857cf50f5bf3a02304a530ea617"/>
   <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="fe92ddd450e03b38edb2d465de7897971d68ac68">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="bc2da39ccd2b82b67773f10c8da8fc8eedc483ab"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="d170091ba1b5597b05f37fb259f6b8eb02568798"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f293787d4a86257c9e78a35bd3f73b31b706e2"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <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="f3e998242fb9a857cf50f5bf3a02304a530ea617"/>
--- 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="4d1e85908d792d9468c4da7040acd191fbb51b40">
     <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="bc2da39ccd2b82b67773f10c8da8fc8eedc483ab"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="d170091ba1b5597b05f37fb259f6b8eb02568798"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f293787d4a86257c9e78a35bd3f73b31b706e2"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="c058843242068d0df7c107e09da31b53d2e08fa6"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f3e998242fb9a857cf50f5bf3a02304a530ea617"/>
   <!-- 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="fe92ddd450e03b38edb2d465de7897971d68ac68">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="bc2da39ccd2b82b67773f10c8da8fc8eedc483ab"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="d170091ba1b5597b05f37fb259f6b8eb02568798"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f293787d4a86257c9e78a35bd3f73b31b706e2"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <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="f3e998242fb9a857cf50f5bf3a02304a530ea617"/>
@@ -130,23 +130,23 @@
   <remote fetch="https://git.mozilla.org/external/t2m-foxfone" name="t2m"/>
   <default remote="caf" revision="LNX.LA.3.5.2.1.1" sync-j="4"/>
   <!-- Flame specific things -->
   <project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="1bb28abbc215f45220620af5cd60a8ac1be93722"/>
   <project name="device/qcom/common" path="device/qcom/common" revision="54c32c2ddef066fbdf611d29e4b7c47e0363599e"/>
   <project name="device-flame" path="device/t2m/flame" remote="b2g" revision="6f72b9d7a2322043fd0c4ba889ad689b084081c5"/>
   <project name="codeaurora_kernel_msm" path="kernel" remote="b2g" revision="893238eb1215f8fd4f3747169170cc5e1cc33969"/>
   <project name="kernel_lk" path="bootable/bootloader/lk" remote="b2g" revision="fda40423ffa573dc6cafd3780515010cb2a086be"/>
-  <project name="platform/external/bluetooth/bluedroid" path="external/bluetooth/bluedroid" revision="082a1f98422e6a6b56f61218d6fcf465e85d4c58"/>
+  <project name="platform/external/bluetooth/bluedroid" path="external/bluetooth/bluedroid" revision="b2af89ae378a119819a9c86d9a12e573c7130459"/>
   <project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="5b71e40213f650459e95d35b6f14af7e88d8ab62"/>
   <project name="platform_external_libnfc-nci" path="external/libnfc-nci" remote="t2m" revision="4186bdecb4dae911b39a8202252cc2310d91b0be"/>
   <project name="platform/frameworks/av" path="frameworks/av" revision="c1814713bd2d07c2af0c236007badc8732a34324"/>
   <project name="platform/frameworks/base" path="frameworks/base" revision="6b58ab45e3e56c1fc20708cc39fa2264c52558df"/>
   <project name="platform/frameworks/native" path="frameworks/native" revision="a46a9f1ac0ed5662d614c277cbb14eb3f332f365"/>
-  <project name="platform/hardware/libhardware" path="hardware/libhardware" revision="9982f697972cfab09379fd909307e993a6247ebf"/>
+  <project name="platform/hardware/libhardware" path="hardware/libhardware" revision="7196881a0e9dd7bfbbcf0af64c8064e70f0fa094"/>
   <project name="platform/hardware/qcom/audio" path="hardware/qcom/audio" revision="8d7676dfb68ee0cd069affedd5d1e97316a184ba"/>
   <project name="platform/hardware/qcom/camera" path="hardware/qcom/camera" revision="2a1ded216a91bf62a72b1640cf01ab4998f37028"/>
   <project name="platform/hardware/qcom/display" path="hardware/qcom/display" revision="e5a971282719907f73fb1da964ca40aad67a3be0"/>
   <project name="platform/hardware/qcom/gps" path="hardware/qcom/gps" revision="9883ea57b0668d8f60dba025d4522dfa69a1fbfa"/>
   <project name="platform/hardware/qcom/media" path="hardware/qcom/media" revision="a558dc844bf5144fc38603fd8f4df8d9557052a5"/>
   <project name="platform/hardware/qcom/wlan" path="hardware/qcom/wlan" revision="57ee1320ed7b4a1a1274d8f3f6c177cd6b9becb2"/>
   <project name="platform/hardware/ril" path="hardware/ril" revision="12b1977cc704b35f2e9db2bb423fa405348bc2f3"/>
   <project name="platform/system/bluetooth" path="system/bluetooth" revision="985bf15264d865fe7b9c5b45f61c451cbaafa43d"/>
--- a/b2g/config/flame/sources.xml
+++ b/b2g/config/flame/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="8986df0f82e15ac2798df0b6c2ee3435400677ac">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="bc2da39ccd2b82b67773f10c8da8fc8eedc483ab"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="d170091ba1b5597b05f37fb259f6b8eb02568798"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f293787d4a86257c9e78a35bd3f73b31b706e2"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f3e998242fb9a857cf50f5bf3a02304a530ea617"/>
   <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="e95b4ce22c825da44d14299e1190ea39a5260bde"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="471afab478649078ad7c75ec6b252481a59e19b8"/>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,9 +1,9 @@
 {
     "git": {
         "git_revision": "", 
         "remote": "", 
         "branch": ""
     }, 
-    "revision": "cc0cc3a29b940c3b2e7434540f0e7263458a925d", 
+    "revision": "98ad49da1fb006f0dcd8ed1af37382ab531ef016", 
     "repo_path": "/integration/gaia-central"
 }
--- a/b2g/config/hamachi/sources.xml
+++ b/b2g/config/hamachi/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="4d1e85908d792d9468c4da7040acd191fbb51b40">
     <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="bc2da39ccd2b82b67773f10c8da8fc8eedc483ab"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="d170091ba1b5597b05f37fb259f6b8eb02568798"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f293787d4a86257c9e78a35bd3f73b31b706e2"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f3e998242fb9a857cf50f5bf3a02304a530ea617"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
--- a/b2g/config/helix/sources.xml
+++ b/b2g/config/helix/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="4d1e85908d792d9468c4da7040acd191fbb51b40">
     <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="bc2da39ccd2b82b67773f10c8da8fc8eedc483ab"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="d170091ba1b5597b05f37fb259f6b8eb02568798"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f293787d4a86257c9e78a35bd3f73b31b706e2"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
--- 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="8986df0f82e15ac2798df0b6c2ee3435400677ac">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="bc2da39ccd2b82b67773f10c8da8fc8eedc483ab"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="d170091ba1b5597b05f37fb259f6b8eb02568798"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f293787d4a86257c9e78a35bd3f73b31b706e2"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f3e998242fb9a857cf50f5bf3a02304a530ea617"/>
   <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/wasabi/sources.xml
+++ b/b2g/config/wasabi/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="ics_chocolate_rb4.2" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="4d1e85908d792d9468c4da7040acd191fbb51b40">
     <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="bc2da39ccd2b82b67773f10c8da8fc8eedc483ab"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="d170091ba1b5597b05f37fb259f6b8eb02568798"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f293787d4a86257c9e78a35bd3f73b31b706e2"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f3e998242fb9a857cf50f5bf3a02304a530ea617"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
--- a/content/media/fmp4/wmf/WMFAudioMFTManager.cpp
+++ b/content/media/fmp4/wmf/WMFAudioMFTManager.cpp
@@ -303,9 +303,15 @@ WMFAudioMFTManager::Output(int64_t aStre
   #ifdef LOG_SAMPLE_DECODE
   LOG("Decoded audio sample! timestamp=%lld duration=%lld currentLength=%u",
       timestamp, duration, currentLength);
   #endif
 
   return S_OK;
 }
 
+void
+WMFAudioMFTManager::Shutdown()
+{
+  mDecoder = nullptr;
+}
+
 } // namespace mozilla
--- a/content/media/fmp4/wmf/WMFAudioMFTManager.h
+++ b/content/media/fmp4/wmf/WMFAudioMFTManager.h
@@ -24,16 +24,19 @@ public:
 
   virtual HRESULT Input(mp4_demuxer::MP4Sample* aSample) MOZ_OVERRIDE;
 
   // Note WMF's AAC decoder sometimes output negatively timestamped samples,
   // presumably they're the preroll samples, and we strip them. We may return
   // a null aOutput in this case.
   virtual HRESULT Output(int64_t aStreamOffset,
                          nsAutoPtr<MediaData>& aOutput) MOZ_OVERRIDE;
+
+  virtual void Shutdown() MOZ_OVERRIDE;
+
 private:
 
   HRESULT UpdateOutputType();
 
   // IMFTransform wrapper that performs the decoding.
   RefPtr<MFTDecoder> mDecoder;
 
   uint32_t mAudioChannels;
--- a/content/media/fmp4/wmf/WMFMediaDataDecoder.cpp
+++ b/content/media/fmp4/wmf/WMFMediaDataDecoder.cpp
@@ -43,18 +43,26 @@ WMFMediaDataDecoder::Init()
   NS_ENSURE_TRUE(mDecoder, NS_ERROR_FAILURE);
 
   return NS_OK;
 }
 
 nsresult
 WMFMediaDataDecoder::Shutdown()
 {
+  mTaskQueue->FlushAndDispatch(NS_NewRunnableMethod(this, &WMFMediaDataDecoder::ProcessShutdown));
+  return NS_OK;
+}
+
+void
+WMFMediaDataDecoder::ProcessShutdown()
+{
+  mMFTManager->Shutdown();
+  mMFTManager = nullptr;
   mDecoder = nullptr;
-  return NS_OK;
 }
 
 // Inserts data into the decoder's pipeline.
 nsresult
 WMFMediaDataDecoder::Input(mp4_demuxer::MP4Sample* aSample)
 {
   mTaskQueue->Dispatch(
     NS_NewRunnableMethodWithArg<nsAutoPtr<mp4_demuxer::MP4Sample>>(
--- a/content/media/fmp4/wmf/WMFMediaDataDecoder.h
+++ b/content/media/fmp4/wmf/WMFMediaDataDecoder.h
@@ -38,16 +38,19 @@ public:
   // Produces decoded output, if possible. Blocks until output can be produced,
   // or until no more is able to be produced.
   // Returns S_OK on success, or MF_E_TRANSFORM_NEED_MORE_INPUT if there's not
   // enough data to produce more output. If this returns a failure code other
   // than MF_E_TRANSFORM_NEED_MORE_INPUT, an error will be reported to the
   // MP4Reader.
   virtual HRESULT Output(int64_t aStreamOffset,
                          nsAutoPtr<MediaData>& aOutput) = 0;
+
+  // Destroys all resources.
+  virtual void Shutdown() = 0;
 };
 
 // Decodes audio and video using Windows Media Foundation. Samples are decoded
 // using the MFTDecoder created by the MFTManager. This class implements
 // the higher-level logic that drives mapping the MFT to the async
 // MediaDataDecoder interface. The specifics of decoding the exact stream
 // type are handled by MFTManager and the MFTDecoder it creates.
 class WMFMediaDataDecoder : public MediaDataDecoder {
@@ -76,16 +79,18 @@ private:
   // Called on the task queue. Extracts output if available, and delivers
   // it to the reader. Called after ProcessDecode() and ProcessDrain().
   void ProcessOutput();
 
   // Called on the task queue. Orders the MFT to drain, and then extracts
   // all available output.
   void ProcessDrain();
 
+  void ProcessShutdown();
+
   RefPtr<MediaTaskQueue> mTaskQueue;
   MediaDataDecoderCallback* mCallback;
 
   RefPtr<MFTDecoder> mDecoder;
   nsAutoPtr<MFTManager> mMFTManager;
 
   // The last offset into the media resource that was passed into Input().
   // This is used to approximate the decoder's position in the media resource.
--- a/content/media/fmp4/wmf/WMFVideoMFTManager.cpp
+++ b/content/media/fmp4/wmf/WMFVideoMFTManager.cpp
@@ -394,9 +394,15 @@ WMFVideoMFTManager::Output(int64_t aStre
   NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
   NS_ENSURE_TRUE(frame, E_FAIL);
 
   aOutData = frame;
 
   return S_OK;
 }
 
+void
+WMFVideoMFTManager::Shutdown()
+{
+  mDecoder = nullptr;
+}
+
 } // namespace mozilla
--- a/content/media/fmp4/wmf/WMFVideoMFTManager.h
+++ b/content/media/fmp4/wmf/WMFVideoMFTManager.h
@@ -28,16 +28,18 @@ public:
 
   virtual TemporaryRef<MFTDecoder> Init() MOZ_OVERRIDE;
 
   virtual HRESULT Input(mp4_demuxer::MP4Sample* aSample) MOZ_OVERRIDE;
 
   virtual HRESULT Output(int64_t aStreamOffset,
                          nsAutoPtr<MediaData>& aOutput) MOZ_OVERRIDE;
 
+  virtual void Shutdown() MOZ_OVERRIDE;
+
 private:
 
   bool InitializeDXVA();
 
   HRESULT ConfigureVideoFrameGeometry();
 
   HRESULT CreateBasicVideoFrame(IMFSample* aSample,
                                 int64_t aStreamOffset,
--- a/content/media/mediasource/MediaSource.cpp
+++ b/content/media/mediasource/MediaSource.cpp
@@ -333,17 +333,17 @@ MediaSource::Detach()
             this, mDecoder.get(), mDecoder ? mDecoder->GetOwner() : nullptr);
   if (!mDecoder) {
     MOZ_ASSERT(mReadyState == MediaSourceReadyState::Closed);
     MOZ_ASSERT(mActiveSourceBuffers->IsEmpty() && mSourceBuffers->IsEmpty());
     return;
   }
   mDecoder->DetachMediaSource();
   mDecoder = nullptr;
-  mFirstSourceBufferInitialization = false;
+  mFirstSourceBufferInitialized = false;
   SetReadyState(MediaSourceReadyState::Closed);
   mDuration = UnspecifiedNaN<double>();
   if (mActiveSourceBuffers) {
     mActiveSourceBuffers->Clear();
   }
   if (mSourceBuffers) {
     mSourceBuffers->Clear();
   }
@@ -390,17 +390,17 @@ MediaSource::GetBuffered(TimeRanges* aBu
   MSE_DEBUG("MediaSource(%p)::GetBuffered ranges=%s", this, DumpTimeRanges(intersectionRanges).get());
 }
 
 MediaSource::MediaSource(nsPIDOMWindow* aWindow)
   : DOMEventTargetHelper(aWindow)
   , mDuration(UnspecifiedNaN<double>())
   , mDecoder(nullptr)
   , mReadyState(MediaSourceReadyState::Closed)
-  , mFirstSourceBufferInitialization(false)
+  , mFirstSourceBufferInitialized(false)
 {
   MOZ_ASSERT(NS_IsMainThread());
   mSourceBuffers = new SourceBufferList(this);
   mActiveSourceBuffers = new SourceBufferList(this);
   MSE_API("MediaSource(%p)::MediaSource(aWindow=%p) mSourceBuffers=%p mActiveSourceBuffers=%p",
           this, aWindow, mSourceBuffers.get(), mActiveSourceBuffers.get());
 }
 
@@ -482,19 +482,20 @@ MediaSource::NotifyEvicted(double aStart
   // the given range.
   mSourceBuffers->Evict(aStart, aEnd);
 }
 
 void
 MediaSource::QueueInitializationEvent()
 {
   MOZ_ASSERT(NS_IsMainThread());
-  if (!mFirstSourceBufferInitialization) {
-    mFirstSourceBufferInitialization = true;
+  if (mFirstSourceBufferInitialized) {
+    return;
   }
+  mFirstSourceBufferInitialized = true;
   MSE_DEBUG("MediaSource(%p)::QueueInitializationEvent()", this);
   nsRefPtr<nsIRunnable> task =
     NS_NewRunnableMethod(this, &MediaSource::InitializationEvent);
   NS_DispatchToMainThread(task);
 }
 
 void
 MediaSource::InitializationEvent()
--- a/content/media/mediasource/MediaSource.h
+++ b/content/media/mediasource/MediaSource.h
@@ -87,17 +87,17 @@ public:
 
   // Called by SourceBuffers to notify this MediaSource that data has
   // been evicted from the buffered data. The start and end times
   // that were evicted are provided.
   void NotifyEvicted(double aStart, double aEnd);
 
   // Queue InitializationEvent to run on the main thread.  Called when a
   // SourceBuffer has an initialization segment appended, but only
-  // dispatched the first time (using mFirstSourceBufferInitialization).
+  // dispatched the first time (using mFirstSourceBufferInitialized).
   // Demarcates the point in time at which only currently registered
   // TrackBuffers are treated as essential by the MediaSourceReader for
   // initialization.
   void QueueInitializationEvent();
 
 #if defined(DEBUG)
   // Dump the contents of each SourceBuffer to a series of files under aPath.
   // aPath must exist.  Debug only, invoke from your favourite debugger.
@@ -125,17 +125,17 @@ private:
 
   nsRefPtr<SourceBufferList> mSourceBuffers;
   nsRefPtr<SourceBufferList> mActiveSourceBuffers;
 
   nsRefPtr<MediaSourceDecoder> mDecoder;
 
   MediaSourceReadyState mReadyState;
 
-  bool mFirstSourceBufferInitialization;
+  bool mFirstSourceBufferInitialized;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(MediaSource, MOZILLA_DOM_MEDIASOURCE_IMPLEMENTATION_IID)
 
 } // namespace dom
 
 } // namespace mozilla
 #endif /* mozilla_dom_MediaSource_h_ */
--- a/content/media/mediasource/MediaSourceReader.cpp
+++ b/content/media/mediasource/MediaSourceReader.cpp
@@ -468,17 +468,20 @@ MediaSourceReader::Seek(int64_t aTime, i
 
 nsresult
 MediaSourceReader::ReadMetadata(MediaInfo* aInfo, MetadataTags** aTags)
 {
   MSE_DEBUG("MediaSourceReader(%p)::ReadMetadata tracks=%u/%u audio=%p video=%p",
             this, mEssentialTrackBuffers.Length(), mTrackBuffers.Length(),
             mAudioTrack.get(), mVideoTrack.get());
 
-  mEssentialTrackBuffers.Clear();
+  {
+    ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
+    mEssentialTrackBuffers.Clear();
+  }
   if (!mAudioTrack && !mVideoTrack) {
     MSE_DEBUG("MediaSourceReader(%p)::ReadMetadata missing track: mAudioTrack=%p mVideoTrack=%p",
               this, mAudioTrack.get(), mVideoTrack.get());
     return NS_ERROR_FAILURE;
   }
 
   int64_t maxDuration = -1;
 
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..64a24ec898e75252663cd366ffd88f61b7c6f983
GIT binary patch
literal 18442
zc$@%XK%T!EMc<>JLWY3>Lid3ILh^wGLi2$LLV|>MWnyhYhk*n_g@FPXQ-Egy00000
z09}F+O`CMBO}mU!tArIvsb*8Gf)E2uyNpw-gcek;Yg4R(5R^^3j8m(G5>&%yQ>=np
z&J{_iW<ZN7*Rg_8U`>FdY-wU;Vr^_7b}=q9E-)Y~AZ%%3ZDDkBZ*yy5Aa*e>G%hh$
zLB?%sc5P*HXJsIEH!d(PFd!%=S7>E&Wgu5&AV+U$Zf7ScAT~5&X>=fBb!lvLAa8CU
zN_B1^F*qPHFflYBGBP?fIXW{lM2Uz%@Hc<}0000)VTc9+i)eRYKmZn0u4~Dz$Jc=Y
zbH#xIgMk8uhCyFXP*qb_yMzS9v;bqGlTUDUb4X=jWB~#=0f4&z00000BDI`@b#7!<
zs)J)Lpy7$NghxAo0H1*ZA49fvV8Q2s0Hak1fdBx82SY_)Qec%|oPb}sod1LUBieba
z6!vD+YRpg~;>;Xt><U62u=S5OpkTNM9O=z8(WUaQYN+oI7A3_2r@nL7rvW~MocHta
z9)aoh3|c4D{2S)4KU<=ek((}k?C~)m0tKa;?$wbHU~R~B#A`x4@!&u}Ks~u*F#GXL
z`d|iGz&+XehQWc_vSqqQnAiALp{J6g#tpuA*+D@g)>lqyT6vXDYHTtJ9<1MwN*y>A
zUM%1M0000000000006Nx2knK_J`PxctJyw!(-UiHiM72pz8{s7vUHG>gpkMxD#`v9
zZDj16O@Ytpg1@v*x88=bbVW!14b*oO{Wd?ntxNq@8;PiR`;Q&>*Gd8W#9*K;Iq$?C
z`LZf(0aPJulIvwIC}1i1xW=}JCVy>9IldU3a-plD+DxwLx>nydr3<mpE$a^-hQ=fl
zO2F?`#ryWUUh15I9HpIr@d{g8_9xriCd?o7cn{3*PAX0Qi2JS*67VAJ2z1Mzl8N>O
z-hFi%|AHm(|K4;a9Z~LSwDA{cv`NO@_WHR(0+rHp7r}8_%Lvf{3{zZe_+#%-ez6hk
z(qVz~nC`6S`8CV>EC^k(e5bf#+tddEO#h5|h7Kc#Fz{NKf3h<c;daElg^x(;6&A!I
zC<|dXND8bFs(h;~2BMH~<L<L@5S2_s;3Zh)koP$0Hwor%%-kohLRryw)Ue2tb07Wc
zR<ZIbR;AE_5Z8`hp!bPfi+u||V`~`>POopythrrQz8;j>)W3k6D;5#AGBAcll3!t}
z!@b~4!HPema-gFZCecZ96Q1B<Awh;Nc9D&xk!}|cI!71Su|dy7ruW4(6Om&@7VN*h
ziTR0pGmj^)v4F{neTZJ<u&R}jOTbK65^L;%dMYfjlcvZ0q4`;y#l(r3FQAnsyb5P;
zMxHb*#IGd_zjz!Wi!8==LDtBaJNt&T6z}3Pn3s`)t1zG{<s`P8-l|o~O$)72^BSnM
zwRwg}82L1Zv?Vl?6y9wnJ`Yqg3Ya^07H|>rw39tyl!9nTnMAvHAdeD{%H>`+lUQEW
z^f%#bXO>Y!tK|@!fkIVaQbkLG9z+TzxF{~jeel)0fe`1resf04J&*W-pw0&Xk8l5j
z+}%NLugjx*?}qL3@xnlVA|+`Fbd`>QfHPXk+@K@s?5*&tE^=FVFup$roR!4i2R;#h
ztUW*6I!6Y;`PW`^mTkNdQqFNFd#Q2HP3mw6t%I5Wd=UFz^|r$Z44Q2d7sjI`ZDCgV
zsgX<uIj9(hiAz-X9HK;uS{l5H!Fs`ZypMN#F)cKjX`U<ot#~?q8e4DmCac#npj|uo
zk_fS-z~UzazjIF!W<Bh@et|EoT|1gR8$Pnh^RuG|3ZZ;lqtgJOJbNpnI=3Ipqois7
z-|fN%5EKbv&tNK()C@uJCL&P8>X)f!Hz4J!(if$vI_LekdR!BWiBUdaiJ4OP+RFCm
zHY}<WmW>$4(dkX9w#e4p96&_@Z>y?G;YpLEwzC8v?equF@q^2DQTbrPv~4K94)a0r
z-CS;QcFIJ#9tsc*Nn01!`x@Gku;;J#HMixit~SQ8*_5;u-LPt0MtIGM32zy+IWL{-
zxmq90do4!VAuT+cq(=pg6(`<_i<1x5GFS&2EyTzyyG)nZj}r#TRbh-dWOb-_t0*=v
z(n>){VZ&KD$S3HNR~?T+OHQH(N&ZQXtlIb$^`}@Vw_Ci>qFy<BS@Hox;I^~uG4hJp
zc0J6tHX0xnW))<1>$xYKFs6@?eIQ>1T}zCnwElyg!2a!u55d=B4ahfv*klcsLp@-u
zpDb;u@JG%D_CZoajY*YduB{Yu0o8hE1i4vvu$F0)9xne85WT8d9d<-6whTKzl69=v
z?2vB0IUkunvZ=GZ>Pw$;bi^A^ys7grV+C+lN|4%)BGyt7Wil$paWqi0K5RRt^?9Df
za5vC%=o4=Qn<g5L@om|bsl%eH!ZrvcvJOGjHYd*V-9@wfZVCT`+uK2A6EpSZqWHkD
z<IN47+0d!~8q8hLPjLZ-_FUYr>g&%(hN4&wO=a=>X-r){I(EvE1T1pS)?rd1B$N<C
z^j!-Ogz{$pwMc@J<>ii!q002jIdvzo5Ct|iyt;hVabpk;7}Qmcb?YY)zC{uQBU$=s
zik4z}dhz@vEN8?xpZX}1j&hU`x+ca2ZSG<+3=^;iy5~cdDQrOkQOwZQJZC$ys9;I^
zgj3>ZBU*<PHvn0xeeLFIk+b>biBvRIa=7Ij8dHY99`4vYwO)NogOV_JnzYsI`QiM<
z2_2*1Jan!rmS8d<Be3}#`qPow>xhiFzZA&xddM8POx;|&AR*=-4t4y<sOB-y+<x~$
z>IXO+zX$=6x_~kM4kOe9SfZR~wX(X%;5ibH*URI?RBdpGEWTqsCXc&0uG@tAq+fk5
zdt1&p$XD^P_+)Z`De6Gbq%LXD>Zr8MmiT~xe+(Uy6e@ZJ(<EA|?8Db@EH`1ijUqv>
z1Ug7FYRmm>pN?7d4`J8S#i&GK&&dxI$e10cY@r>^6?2L<=(x5F7N_c|d{Q_BXvaKy
zaZU-|xpakQT_&DtcQ!8`<gfuXCV=bbbM3*Yu>J$~?VpfN@{I&q2=UTRMc>4@j*r|5
z$b5-kLPw>gl_2#yayhtBXLtKTry~yMo{Os(B{D+cm0AryBPfZ{0iFyWPyw7Q_%{sa
zKexb!<SBrl1;*Rt)4w}j=sL<((6ywmKozVukA+#A1k^6Q1w&yfh&0<c+&e3Rmx=j<
zN2&s9tzyNBzEph3)7s#kBT=UZQvev7Ah~tUYSdQiKB8_l$^rPix5H9=BZUrt?{_RK
z4yq$&_KcKO9=N6~2aU(2g969~f3yO15o!p81bnnO2N6~?K8jr9w`W=Y_KmgEb={AR
zI#UO*oxBKo-^+{M1NQ#0Qa&bw&O#SAWdA*1F}ER36Bg(f`C{AA^U>tn2o1ONU2gEe
zRLe9N7xShd?2Ny8(u=Yqz3gQM#q%Q;Kq><2-;QCNuN~r>WqXwCKGHnV0UgQF_;z#U
z8?<8oPxj4Ba#)*clfU?OACa)r|AX@Dv7^VMJ4d!N@soRLA_mke7mqeegcuSnRO+h-
zey1E%fWIKLE2>%Wmlf&oZmD%;*Q_^DlY>EK1(ToMRDf?i@>G3a==?=n<_1hP_G7qF
zJQVM88Im)z1V{1J_hrw(fa<a6eA2(hh22VL>MyR!pDI$3<8fD;G>0C5f{oN_YGNNC
z>uwJkdI$+}z7hNaOe933S*-(A!(5ONJRVEA%o(%&zQp<`T%XGiy|~lg<UC3jt#juI
zfM;jU7sPIy`SBC$Fn*@nz+MFzs8%a7po#gjijyEM40Bl!x2o#vANus(?*NkAC+7bE
z@QMy-4B@KAigLoK^=eT6$29Yk!USHyT2kG+7n{q826DT0kv*C#tTO%?%xy@2kVE_O
z5h(GClA^Fk)2csk+yn2UD<i_s502%>6c|YCcam%vkyDW-m?drBon#{7l~i3f8kqK`
zc&uwDR@=%G4%5HNwfGTVRtzAb3Wy0rN)(xr;tPg|x!$d9%#xOSA1W<zpDL~R5yY%x
zs!S&V>MUR?kz#NYV19#EVo_P8*k+dOQ>Fxl$Th6P|LYrpU`8e=ZP<kSzU#96qlZ&I
z?m}WMs9_;waq?2t`WNA0%Z&1%03W4q<lTKn3+hEo<q+X$R%(e1l=dA^oZSet+E<>~
z_pAd^>`cjrG%PJ%isU*a5fdQ!8aPIRIAXR6&C24Ff`BKt1QaeYqUQiFlI62u&QD}B
zYS^h2zH_LcY|L(nSuR*qILyK)GHv!iTvS#V!u?Sp^@Kx9n^uoBLG~A%`6G!p2ivR7
z0b3X%rp=x<McLksP~`;*6%Hd@?%uTkUw0;jW~EFVy;f)$^s=I{7}`MYH-#sxHBm&&
zC>3na2jf!xwj*f{WT+UVl#&^*1{As8))Br#f&3+YbYtmJzcH8X`FHmK;XVG+QYO^4
zDq~mHnziBogWB0Y2jS|kZcTMonip~N9R@$s)EC^FM}&dp2DbyP2<c+kzBeXDUF5jX
z_r<3RuD|m^FN^zi?=<u5lNYuHj+q5GNZrEo?6!(Y<jps05&m0eB@azoYm==9aQw&P
z)Ln7O;DB?qT)plEO8H4pV@~K&eb7aCS+g<deCi~YfIcboW+m3CN}u{@;@R$(d<K5#
zLb@bB7F%}jdP)2{sEwQg&R;e<3-fk+d{f(Z(2X_3h;MXY14GJ=>^)PlX{Z(_`a$7j
z?#o`f@%qn^F4UWDNj&l$Uc=U_Ljo6jS%pwB=v}L)-mvVv%D8XY>P_l+Gpm<~Dn)>a
z#$DKgQ#z*>+r#jNK5cF&66YCUU#N<Ho!~=Wz+rjOHn8yWJgY9Q%Kk`^C^5|UUpK4|
zG1G`SsI5;op~O~F&<MU1hFi9`G1@138UF&2;6t=^z?OCBbfZ)><@o>0Z@6bWN8@1~
za~Hq*>WpJc<6|WxxMc7}OZ`+%#uIz%xBcdjK&KW#l$(K2a<48Vz}p>qZPk>NO9W&H
z+`4>_A-JK8@0mE>UbZ>D!T-6vk^w-FRM={+0W}mxw@gNPBU~aN1<Bbni<%YTjSyp6
z@JfTdyoU5MDjB|dx(>u7B-?We!a?AW({?MFEvD4O0jq3FheyciILBB#$`g)x0ef;n
z1bjJV{k|0G?%z4BJmjgVUqZ<Y()J6}Ajx4|9MQ*!PglSO_`ic0XKrgc>bN;;rWgm!
zOFfCfH>?fbJz7;*F3f{#ja;EB(Ch4}eP@UQ`}9;A3TAUPkudxNK}dGTTgj9|xDNCm
zQD4%c<Mp(K)61zi?v{4=_v(tZPum&`YSf#NLa{gu5X?aTgTBrHPB}4r>EGt_hc&ld
z4}!W&gcWRQi=tizyf`1P?|x-6gL3*eUDQ!(wf67j@o3sSy+M%w%UL5v+R)Qg+#NpN
zG;UUwjtm)E8=~i0C&>kGa4%*pt~Oqf6F?r@6>~a)GykgONVsDXCeaSBBv*Z|u~bW4
zth2D7=177=fDurYvX}b`X23u<9LGjVPyKmvTQ)iw|19NTs4L1hA&eQsM)Pl0*$>Mx
zkkbk0R@Nd^g;U&-zwH3Jf>#ct@Bm#`=hr-cTW_ueZJ58EofAov#+PSAsUtwK)#ZfA
z{R<)@=ukj!Jc8Vqv#J=wO9}@!FIc8uqTJcpbT}gOOf9NtIeFEiuEQ#vbBExi_ctR<
z#}82dzo-_pOnY;XveZK$>gDO^)vVxb<>R`6&lhm`xsvHw(V-~C_zu&NjQT;LqSa#o
zGei|c*v`uH*;r)G6qkJUg1_MhPbwa8_M;QDdJUcu%h~)h9Zf2e4`}>J1{?2;u3yDA
z(iL~Kko*{D{0n3PgKDXu%QH|HVU<iB+Q`vY5EAfuK_o;W#|%n^iPkp&t3{)H(Kw|H
zWLmTQ$nB>kMk8S&-1E>FkJq9uqO8+XuCIj2hrGx76cEtw*917DX^h%)-44kAm-?3H
z0q#1o3;kwjbgI#x@!&bq<O24;5xPsR2GFNuB%PpDxS7X}iC^sCP-#AxKY5&i7f0k5
z+Sk;7+lQ4q&_TwO?Ujfo;F@#G$083advA*9^_(+KDSzK<8?_+*FHwV4|Nn!sx*qxa
z7f6OLAck{xX)GJJ`YkxC!?-xE-5Gi7&P**8vUl=b>ou-X4t~x{Q84YfaIj3)9DzSM
z&PBQ1now;!&8o?oZjtjj(Xr)B1&KvsTz(M|o||-#^){B)Tb9R<lSoRY4mF_?8E;Tm
zG)w<a1*rjSNY(<Pyg4v-NLZC6Ks4%Bb%8?h-zt2AU71Yz?&C^uhuGfQO|Q^9vun&3
zO6#pxMs83L+D_Dor9%(s^E4bnJysJs1Hd_G%|>fay=E$U%z|^5!fj)%B)dadhltOy
z$PuSV2e{Z~F!1+>xkS%EoDHO98cwsk1jZbw%if3}AsptrDlj!x&I<f`CxpMT_}1r~
zef&sh{ZruNjL|k`VnZ|mhgaJAKC&_-3_`JX8gX4RpnrZhM#^`_SB&$Og=E+X12`At
zx*Y6n1njnhQd*#E3r}^kGE?*rW_5tIcpE@SjgTD=*M6U-)s51S4T<&tx&u#auM{(!
zE{tASu(??dIkK8M=ViV>zB64>fwMtiNjsaxWPHWr-Pk%*DIB2Xt^6e#2f>JB4V%jS
ztR#gSF@u7Q(6zJCxelW8`kfKK>`B3sfOj?%k?*8ipIt<(4UmxO%J^C$CUELh3Q7yj
zxTc}E`6_lipd1tN`J*NDKE&iPs&l&?6kTy?T@dZ`S-TS`d<goz|J1cn(|vWrBkx^f
z4R-B4f5mKitKebD{?M;gpvwxZ|AVKz1GMljr<!zA0#)QG%(7`A>v@n6H)i8$x@o!L
z>XUN|!*%cPm{Bk`b%)W5M374HhJlaDi@PfEf)l`*AdH*_0r~j+0XYsvcMLh<wj1j_
zX%D-rnBbE(c2IlLP0)p%`_<;paZbs=buOGfQ(BLw40ZuIl5f=c)tB8Gav5lmJm;1`
zQ#Y_ZXrUx`qoeM%tv$!i7CCPzVM5x>BLnod*a2-*@Nk$EM!WQ+*~vzmiL)8YrH3SG
zjpm=^I5DaEhd8b7wEA)=AJ20V3E23sfS0uxQ%CiO{Kdw<<_<Ne_@Q99{);U|Kv+?h
zubMX7y@6kl>FzjWHu50R%Lm3ps3tg(?=;=8yFF59Bhn^kdJs2T)xririo<L7yK2dN
zR_&ccgGvOQXp}7gDP0qW1a@K*RC$$@5>fZSWpNQ&p%@HlX=L@qK0r7l>eY|85^fBv
zZ`fO(|JvW%yyM`Y1uXgjTr2P^HP<93dHEor2o!6pODI!`Yty+1gu4mSlIIdJGHUvU
zzg`QUd7Wsv8&e*D{Y=EXoud~<s0q)a-@Z8Cm8%*0M=ut0D{*&P39Y5e@{AUhRdN3A
zz_*EkH;Lc^$*f@<4-$1dx8Foan(eWLzf`Z-enEzjK&hzsqGY${GA>$wP^kM&nfTYL
zA-*Rz`DP?>D%Kbn2Tfv|Nlw4bFF<<&A}IjOBw4;EY(ANUK^ZwWE6PY5EBTbej|2}@
z%ZVePqf4-XS^<UwLbG5{y8naG`>-y;+0I}gzYKs}FRN5?r=9l+g;pQGQ?YOWB7I%t
zk{v@>$gGl(vG^1so<0iDGmS}K`Fi(55nm&}lEn&4_PdKVV2_YnaI#StYA=o%JmB^l
zNEcb#S0F)@-0X-_j%T+_O!_}KUei#V5tJF<d?AU-d!@1`OUZP?FjEte5p?oBU`#-_
zq`SqO2-rYICvOGU|2u0Wb<iRwJuStq<mL|UfEhwnyFAtn)!F6qL_;w)Oed|Z?`toj
zE@LjA53A-L*c?f@NElsJN_5HrOIEN>+19{E+0K2TZPPXhq`ICx;dWlfl8imJsEs&D
zvd?)VU{e<$(O<$sxC>7Hi}|wKId&zOv*fXJzf<(X9b_-``xnxL)`wQaj067T_`eD0
zS9C8T3Xu9BZmfXHw+VkYzQlf8x|XSm_?UlwX^9tHd-$pM$Q-q#0tWc>mKTqC?6S=3
zpSv6VfV+oZxvL%a+uCB#S$9~UrWqL`28!<w39`4Y>nWjlCv*??{k^SWVWuh<x~4g~
zk%H^!#oNauFV$TACR)K>2z)np;>bbf?SaUID&YQ@p-7d3m~c5Zgm9*RIXerCB=YXy
z4ga%a?6e*Viq-FXSGVB{=@9hwteLXRflEB5+yaHAjt{dp=7s#bI*f$!7#{m88XBPt
z7adYeP+|cs-XDtV1sVFQm#L}x^z2=gm)7)oJ>O>`;PnW2ZHMCIg=O9Ww_0C!8uRqm
z{bsv~5_Jj%wgEFc{btQ|viT=607GCU{`<yonDjvDx`m{tu%&h$o^MQu%+t(Ke5y(<
z`t@&Ah^SXk>H_Q9lbf9w3TsoJ{e&C+*I6ex*rqTOjh*(GRJNizyuF!EeYRhtv3UQK
zpP|Vx?mMON=sOlX31k7U2HAH3pe?WcU-Ep^`p8a_|AX@W1ifTMT9Ds#l2e?boo^L+
zaN!r}1s$r*)FbVjX>?hb4D4@luq_tltQKBt6?~jinh9PWryje_D5lhpmzQHKD)$&N
z(JYp#g*70fV~pR}eiKtMY7cAHxvAi$!NeCF13M9A7$S0yZLx%yQvTd4@*y8Uzy`od
zO!8JvGx^!UOc_(C;3hjl#TJPlvU6bN-xQ4pDR<aD0-oD8+&z}i0dRbos@}xlCjiN7
z15)+iCg!YNslNo8C{}3Z$GR7hNGTtUQN=jUjQf4Tk@2bp-#<MH!#fN3L^M}bKo^v;
zEHbV#SIFE|-n#u(++PAk4{Xc5I4w_)t$O-o8k7SYL`~a)FD9`CnULovv~Ef%C{eO!
zi3C?>Vr=^GmE{?LD`Swa<D@gpo6tI+sTQ-SS3j%M@&ptEbM;sy{eG9Nlx`idf)PpW
zu=}*{L=qMFOVVPnDCXujK!HwUjRbo*3Qx#1e)IopOFNmpoLiMamA|)laEOAXgX$Xj
ztxC^$VLOSBELQUSB$;J(0AyK2NE&I=hc<deBCzdO&0WO94_V(|Nkurhou|9?Yc!i1
zhK5H!64rw~AJhCK@SeQMU~_?Od?Hp^`K4}zYjpP_j&|!*P6|{Iv0<cr8%YlKKE*O6
zS_qvBylLcmf(MbRGt5kzeYU6D;a7hoyE$#{io2A476Hy?MWN2P6UVR1>p;mp56fUa
zMD|P;K%nzFVK$+j+D{-1z5kW{I|BsIQ8RMA5v1%^tuxf`ou){&WOVBd?<+E`CHs}v
z9r;UWGYOE-kcIYvQ5w@Jy;nVa)9}x9UQ8x2r4&{v=w)cyfuw=RaIh3XGmM-~h+pkY
zvPdveJKSljr35e4d+<!WueplB6x5b_BPm(h^$j?9XbXdxEEBlmMIV$b3S84dK5Zd6
zxTn>!QBmPuUr6PO&w--U*myY>!L2Yt<&{jX{i908X`?3g!;3WV%Zx-4=ji$4gLrC#
zD514}Z*^=rQX+1ElywSc|9unclz^a&|AYSm`~bV>N?>&d{d9j44&%u_8UD@XQv)&U
zu#4g(*LT>>yV%UqUjxO<x#ZUmW`DtiXMUIeNwXu0fmV$KL?%~H3f-=D%DmC;WU?02
zxN-i{z=nkt*UW9YF^41o8Q%mlhUF;IY&An$MC(H=xk6Z_qRRC}_Xm$?R*%x&I2U?|
z#Uq{_^rY(2tf;n#5@%`t3yLYVbg_9_8PoyRAV%VFKrZOJ4g#glHDGtKUg*Q+2|1m*
z6g36u;T3~4h1Ps<UtyAv96XzTO&fQnZTb~^<StK_by#q?=PBbzba(KcW%v;4;OEY0
zUsPeJq6-e~QsL&-@wa7;0e68Ajj1BK(QP!8vU{q!%e`bp4a*S&lf2897G7p|OjZU9
zn3KUKD3(&V%BDvmQ*P$#ZCO}IVvpzK?wGot4FrB_Xh|@ev7-c69GMhMXoTxYk7_6G
zABWy;tQ(#FRKt{?Drl($H*JSISUf6aqN@_-R@7*NY4cpCSa#U+OUCsl_13wi+bOds
zZlxxjjK(pL;ayo4e7eX%ZtxBRXF<V(f!|WY_B!Rkq6r8^=n4<NS?vWYYrOAFrf4K#
zSZqhBf3XI#h?vo7++&aqs~Ue_8-0hG;>s%aE42whBWHSI3Pk$iAGH-|BhSCuf$|wW
zHn-N+rVMI%Y$Y13gth;I#R)PV-8G`K2)mAX5w@mkSB&!rpe}}(fe|nb(aU+=(=wLc
zQZeU!d;xQRlR*%N_HG=gS;{b?ncFfHw9PapM-~K|Psc_tO1?P4vn{9!)taw1I@S-T
zjyx8Mhk<(GOU$N5*AV7#%+J#H@Y<6>loaOcv{>sK+h{bVKvIEFWyv4*VUMI=vR>hw
zm#*540a6e<>&lZa`9hyJnhHm`=z7OJS}u;A6(;Gune$+WUS?(<7-y(N*)FhK*s-bs
zZd8STt(^VoAoU=9{!yp8VJ-*xVxu8*VDL-OA==I|P`=w1UM_l=BA`Fx!o9{*4axkI
zP}){mP2SE`<ZD9zgZ%~dy<@bb%nFe8t2tvEZ1&P(hpVcuLFj?d1d+4nAh>g7ko1a#
zM5RtrX89ucY1YN^&5r^F0^$i@XCEnG!W)p}6BE78>myyp^;iMo!CDCA(JzKh%Pz9Q
zGCP-Ve#(~LvDm%+)UgniK^Zv*nK44gREOpd@lcERO9CizkG@VR4gtzI(+YRMR~n6Y
z&XP@|sKyQqnMDo8=yvBG+w}%oglx0yORekQy^hwLlM<FR^A51i%5`!ypZ{T@q(Ypm
zZw#GWLcFErKzLy%ClGU0{2Zi170Bn*UN;Ro<QOOZwMLI=6%hqQ<oBwqEFOJWJlpOr
z0XC7n(z#_iHMUZ?Vu9P*m9&uOp!5I%jEjdhfT+lVqWPw=c2b4?IyYs;V9F2@KMW9L
zK;*>~6IO8n?cO_GI3yHT?Dxa#gvv{P@`=IicF1cT<0v~*>hzI43U0xw14Z|09(r_*
zmjXEH{=~e#TTxLpjq!W%aTdV5C}XB846}*@Icu?ne>PZwht`U41v<ohaCVcQg<0g}
z1S~X^SdGCP<I}8y7{SKGF&AW_zX{x`+>JqJOu;p1NMx;+TdKRzrmj|wgzw^Qkm>z|
z&YukoQW^qfrO^fNAe-W8$KAGCqlCP1!@k@%QKoSY4G6ejo@#KTt_^f`a(wGKrbz2H
z<p2As$}07uD`{4+=f0+t?>o6O(I94ZNl!CIxkap5P)cG);~kkz8-vAei;TyQ^d);z
zB)2nHIlbNuZpwIgzhGX?JbvpHX}H6i|7toWPyIIimsN74AaWRfGRZK1McA#nj%FVi
zruK&vy^PW68I5l6;;HjkETod!m7q!@J%Um~H%~h_vrQ^q)W0g2o|tZBPI|boIQbq3
zN{poWFIE5FO{DJsHT5gpj8Mx?MY=6y{vMBg_FT?F9ae6`!Ax5w=X;^ZNS%u#MyT2q
z8Uu}>TddienXIewaQX)3amIK^nFslJY-1(9tGmKU$4s6dL$-Bg{O5v)0;5-afdBx8
z2STo3P`F>X_T$a}gUIo_fa(51i83=t<B<!~VY0<_b%^!D9*mE3%fcW37o-L?MQL0Q
zM5_`wSN3}8LnlM0x(6U9TLF>bh1l>y#c)PI^Glf?_>hYIGKC`u`qQ-C)z0pusWr)3
zjt664K>d@zg_iAxqT5sA^2;yp0O%^HvnyhN>ys2vKP2|?#y52Kt|0Bi3j80TCLzsY
z7W>4RT9Dg0Jmq|}{r&6zM1-KAn8O4p+}6;${p<BHMWq?=eTDBP^g<S*Kc&OTFB@<4
zhO6WK?KXlzhlH&et4yCv%_fite4tXyPh*R;#P?vXXb6A-mPmx5`m(Qw<h|)5J9b<^
z1&K=i5Y%Hd+z~s_<9`3{x!v4f1OeXYz818PvNj9lO(c!56H!^uMd=4o?&Xo9==_d>
zIWF7+jt#iqKHrk{>5OPZ_ljNc6$n$;L$x>Mez{pNWM?ovY&BcQ_;r^<o0s9iIDZ`F
zo(LE=^1yo@`XYP$=XVew6~U*O2^g_jpWa42w-D5@V$1IU6HT7%3qX1mt<@ba|J4V~
zs{{AU9VhtEk5AmqcX{+DJ&??|W7IPEsBNEAh-=u<)|d6QcnC^LrY5N!@4V1bHCtF4
zlk8bBNtAY_{zw>%kX}sqif_~M&%HcFa9bFy*3|_NZ??WzwG=_w{%3WCKyU-r-rKkq
z6jor#RhpJ@fwu^#Heq<HRi7C$4|VOshioO#ZrRG_dOKG+7LIfDWE9XG`|V3xaB84#
zO#SDlBmt&xEcm{qq6FoNm7dzpFrWX3#y6O9*a2g@k~9wX0WR^1^DKebbra&(gw}_S
zk(@3F%`8Q16d`@=`JPL%e0JTH$o|ktK$CO|g`MRjXZg6p+RrJ}HkVlnN8CPk8=wBg
zEu`B~KAdO)nUee)`MPQjfql?*zyE{%0q3X=PgEAOmLkwA<*_K~h``H>nikNmE8TA7
zj*V#yT(Z1Xc5lEWo4KRE7d2{Dsg(taHMcf@`yDl;TZxcqZ`2cqkO}$x?5*JFFvT$h
zh0o0!kD+=7blk_Ke2y*}WmoupxEnnXkt#66;2s^6{Cg%Pi$DsY57%N@aIOM0&{lxd
z`6J2zq<pvn1T>c8d%nHQ>f9X<PWy`SRmFLH&a}NuLg>bK0D6FqF3?t&bOYf_&xT4+
z;_nRWX#p?%LX|jjuaF3cGH`*tMP49kBNn(<NuzU>xY#EPfGesl_=HY|tMjlPW22##
zB^htX_~N|f)l*0UWZ!j~|M{sWpOe44lqYl~s92Rez7=l{shE@7Soqi<uId(;bfm@c
z@27o^H6k&-&ev*49P<*5x1*6{$P8w%^X<ZmZU$KjXhb%=P@8t92PE&r-1zqG;5H}j
z@?~6+^0Zm6$a;no`A8+3LdCB1kNSz~S|lpZ-|T@#f<pjhc*N7-ppRV`3H8vV=mQhe
zr1rS&fxwM&Z)jG=?6jI~pB%(Z@)O#eCxAJNRA9(-|3jI(oTZvVU&cB%UV);u;B_)w
zrHf%{$;~I#OBe&RhhVz+0LJS}fKhxfPWvsMbE=qAmAhbpK(xQX`u*FRK|#GXxP=1w
zRgua;p4EDWz4au8u6K_Nci-*J%dO?+(pS%S<?c-T50#3JAgjGXH#wM8P74Q_lOAL?
zxfc|3EN7}e7tsU$i+%23z{?#mopvX?&j@^}$+=g<+P_g9o`wrOxhwlXJ9K}tn2&OU
z1}(Xj9rXn_-O%3Gzacm$2_11+=Mlo1vGQAA-bHZEf>K*ZiG*(Vn~oE<nPA8@k{0Ba
zvo<%o2w4em>5Bg|)r;r__stw}9;N^DQqO5-Lspn@fYaC_+p1!Nr6qFG+@tewkZZlT
z4@eY~gU)luf88E@Hm%Zmt?!gPP0))8Vq{jS1gw|W<K^u(N_9TCfA27;cL;t4#9O!j
zw#F^607bn*|AYJk{s6suAgk2a=fAs+8R-q=DepO;huc$i;6zkcB688-0lJ9FW%(_3
z-W8eCNI<AQzb3rig6xs*FZ*}-J`JO-v87@e++$8S(K6ghhO9OGJ&3#nWpl*`#6s(Y
zthX!wmi+sUWkm6i&{R>+RT&Sdp2S>Z75ga}B`JKxds@nq@DF0F$pNHf8>om?<2hLp
zjV9~~@;BfAGU6PKwCrsm_1fy{J{ynGkOp<2HeKL-@6rlbhW_ALA=ID!5V?k5(uIb5
zU+TXrCRNHDM%G!uk_I3y@1#^kS5C+RS6(zk8ecBjUVMk(wa`aO<q{}Op<FxKLW&&l
z*i@&Pn*nQWq|*4wAg|0V<w3nYj4B(!_cZg~Ocfa|#lU<E43|oqxyDj|BCFY9TZzAR
zn7e5vp9qJ0C5VSa9nd}slBcqUGNAna!wXm7HPR7AGdCD+%jLj_GycC7Zvf9=Qk{y%
zWds7oD39n=vawSNajql!GtY(l#<E-<|MFD-BGl3kVoDpbHDMKE%xU!U;cJ+gNFA`U
zc5?CigZK(MAV>Qw0At8;J?hSw*455XbJTv4fU-ATAgL&jK)aBO#+)0|E<&&rf24&6
zB`rGyEqz=c_l;g7uqea2^htQNT}g4aESB}(xBdb~neX7{X5<;4_uYbDOYRbS0g73q
zYyI?b__R+cnNDLsyMus^rI(m8jd{37X1>2s_?+;&h0aj}-3!_qUQ=h4#8IojMWpS*
zLvCTuB%IzcdtoFE{pZut0AMLA%&179ex<mI^<yVbX6C?)DKNYgQp?=UTh*G>+wNQg
zBarC*Z&iv}q{+g$yd%3Yxswa8Wv-7lOoS~&Wb9|6HJeQ&dina+@kY&|gb_&85C0T+
zIJKIxmo6WdgB3>21<|;sGSQHFF@tRj6KRGpos_sF|5ip(!dUv2XIr(l<?am`Vq_y;
z5k1-AwY}}elB-2MQs`Jw!gr%bm@?5ylz`vqZjz&IKY=@i|Naib|AWZ$08++lX_J2;
ztauulidTw`bC}RK(T;+8d9JG$)EYAB&+CPd3&pA{!A>GD>4Ty6CT$vdzdF#Vi*8^^
z$vfO+XT%A6xQHr%w+;wG)$i+m(DdnAux-u6ji!<~Hlj72M^Y>FaGMu;kGxv-mW|s^
z8B9Ky3jeah{@ypy(WYJ7jayW!sVM-fk0mz;QCnp&j2J(s^Smp?95AEDNkIgN^CTyn
zwZy>!+m$fdbN~6yLiAl_PD=2mi-^C{2|gq&aXaaMXxW@Vy*5UcM!bv)f*){c>Wn)w
z`u5hEA$V|0D`QpUG2L%<F-SVr%$X1#KViu+CpK_4C60ZG1u4PsA5t!=Xo*Y)Z>lUt
z)Q4jvpWFn_)OWWHMDEv7HKbea2YMuuESoQ(z_%AORpRM$%qmT%??-%KJ1@ahN3K*7
z5z5(g#EfRoGPZ=1H%^HRJCWE%x<!n6?pjcoIJ~CpX1@8<m~;UUdOrgsQo^Kj#5E%f
z3X)Gx%l}K-rNe5uHA<i>B@29p0=5xU?B45RrT4IMmKWftn+F3*lo>pbD}b^P(&sPW
z9W;ClMNj)|NWn%5A4N3G#A8dnWJL|jP+T7~<J5<+k0%jEH_IH_%~Wn2Is$v*>?e&_
zy3TuE<(T<(zj&B7LI;ZqcQQ{|hN`m@HuVBER?1oqU>{mIt41+rQ|y+N{^R{kfoR%q
zSm%cdL$#b41VKu{Ntq-<f2KmJGQ^M?=hCZf@@T_<dIt@D<kU>Wcah;)#g6b1xVnAg
z`Y$sop1D^sTN_<ri)1(h`=E+I!ygs;xM30kKzthX5wv>1dT4kBo4puw(cid*U{<Fl
zjlk-_NBVn#;>CL1n=v~f8200S79jU8xFJ|%ZVQb@)cOqqHOHrQsO`p*cvVtSHrDOK
zN&kcS{s6m@mEakyBTr(EIMj+=Djl`jcQ<;Lu3mOR+GXT7Ae0{i{Z4A&CkL^hiazf#
zD7g8FMBYn!$7jmK*gebtMqp`%XPVsShJ1W2R|<8BqEg3QR-0!In)!&pU8^S^RoFjx
zb>yZS8b0PHkyEViz2|QoJ;7Af`74nrRpU(m`EsFcow&>-&=w2}s)}ewoCm-9a)!K^
zC1`wN4g<+&Ae{_CiP8-=+IrG^xAV7TXyc?BTDwS4AuG(blnR(~$c(R_YP4AeCn46P
z?Dzmg|M$)hV)ebE+swUifsYMqmqaBrAA=|FdIs}om<?9hU&%h&`Hl15@2rNsWI@ir
zR=y5rr`Xq|KlUdG&S@ILtx&AkW@<Qh&HKReYwFK73Xj^}5J102Qi0u;4^DQVqGO;K
zUc_O%KAYPv?{{<AyKAEEOuVN|oNAM7n8pThvKwVNJg-z+o!4ygeNXIrVCh04lVK}K
z)A1N=<fQ)&11138zK71)pH4#|fbK@`g!N^JG_K{@eA1YiKW=x%*1Q#3P^p$OAu3Q3
z0HS;^R|WwZTL!0Cbq<+d_P({&YKY-Vuzc8j^pX8By{l->nK*^D{uo}6pb<z0ZTrS0
zjguh}KQ%la36Xp!<5}lnmpXX{>{WR|WWTHNfum45LZGUs<RPN5O1(Gh4~)Dh@8-iz
zQq|Wt$MDSwqdGHe%SNl)2nntF?NtqYUYXdq-4JTv?+Je0F<KjLKel&ZOn_B+3z*_$
z1~6>r^_k3V9aa8~tdE_#qE70o8b81#{x<_;LBN6nL2=a_hjqx>6zuUC7p#LFm%9>g
zeh~0LAsdcPaRuBdhbtk(WBt-;*!SLCi#$@SuiQNpP}6O?C-`By|Je=V{G<lgJ|Au7
zx=pH6BXCrDh{!B#Bke<Qd#g8A%`?GFn|$vad;y-H47XeJSuoS=%_r*FdSzcmk)l1(
z2Wgh{tsB~IKhmfM>dAP;NdJTW1O5QLV<x(begMHN{$8=n+;ddZ2RT3prT&9t7}Dwh
z)(taTh{PIKB$8WYe9d*TRx-0VDp?+AI%<1g`UzJV2y|ARmADNzqz(80#a75>@<|1v
zN*+CV?l0Y#^r3Rl9TK|*dX%1J>h{FvlTi4hxb1;vSd&jE@2HODnD19d^G^F33Nu9y
z?;DDOXfXV1q>d4dVhsvonPud{awGbgzuYL`<Ss?k^%geHP7+hx1CE5Tk1d)1i}WuS
zB3j;RK6oK@C-paXWkuq0k!Si!@uYsZL-~T3iy%`U3e3*Hhk;{J2qJU2W9=`l=?Ctz
zASh+@yP&CT6{D<8LpYBW$+yX1fFDIFLEc>rM!S**`6(F$%B<#$g&48>QswdXZK`b<
z0j>E5P-7?SH7~AVa7wp-_i~jx)}EnPeCO^Eb^iTH_)<*5SKeSoqdC<02!E!yNwxYC
zj+kk?n%6gpom?WDqZ8rJnFmp$f}ymWiKgUQGiYSP;k--HMMR2+=jP!Eu>A2R;3lHe
zwJ6+gxJ&2}oWA(wyAyVVmc`ic4CGwAPb;s>1K;a}aOUjzb;-k$)A(80F&AjFL-xXo
zfbO)^8xR17uiV(&7nkjkuW!5VZ$IpFrPzQTA8T01PGJBF_iT#+2)zKZ(!BQV>Gbna
z`!b7f%weqq)_t^A=Y$=>Z_JMEh)Bu3IAj3$Tw17mjM+=5S-1%<G8<2}qe<nN!q1GI
z#W<Fhze5vBvT{9nW@2Y>ZMOye>*aJ;d`GnstpVs;EA$t}#C^nJ>%PI^9QGEG2-oEy
zwuHd%KSo>4cPvVzCdI%L_B9>1SxdN$uvY|gK_}j;%jViW>EDdGhaN?xt62FXB9jf^
zvBRV#;_GH82|TOj@^M~6Nu{s*pSBoEB>{~!I&&-(t?T+A5?P=DfnBrk_k7nDIdTzs
z=3dz!pNan}Ycpig(gc10vCQgvaPPg4TqDlSIqew-FB+vW(uQl2=ejZub@DC_`E$>3
z&6}AW?27V30wns{n(S-LPXB}d0Q9=n%R@7M8xGrrOFHlWxJVF*Hn`RO;7$tRv`^a#
zU#fP|xRGx*D$4UY$KxGNw7fi7Ikn@Bm(Y@w*W!+J2UFTjvoolDQj<r>m|TAp*Gegu
z@$?S8`VtE`a(3FAZc>^__!(#QNDx9SJWGE2vbxA16t`!Y>`d~HZ>uc^CSlkUY5KF`
z3O$BpO@1nocaB)W$k_a+bWp;)^RX;+E3F766@eEzyyvD=7|4XFrgkZR-GWSw*=Rx^
zd*CjIuBhZvEwI@q@_5RmZDS!=goyYthx;tLlwSw+X>OX!?w+dXj-2-jb?^zd;-WHG
zqvVMyDaZ>6o45b0T67;k)4PD|C21V8$V@$ybKU%=iAJb#;i~|CVC|!nVj_)quEtNw
z>62a4`bq6!hbvA^>a-q{U@WUzMP^0!^|%7V9p}r;ffORB)clVj;UQqFgMfNr5xj|i
zMUswK4LV#+!%e<%%BD8DRj~ugAu#v7?9t*aK&h{HBnZtM@N)ZND~EYAEWqB~<__9r
z#3|2No1PvHk)xH_a1D<&ss7PF*rGfxSi-C>3}wKU@97cvx<U72INwx1ne3EcFKTs3
z(pl!*9JcSRj{Nkc_QAl{eSMK!XW_pO+Ovn2ZWiz88y;$fOC+}IK!Iu`8{iIMGGqQp
zP`zk1T>b$>%X#OK=}kDJ$Fjc`qEeOx@T2w^eBeQXOS&!wm8LCa^leG>c2h6lTVYJ5
zll49EGu~qDb7L4#f-=rv=WA6D@kZ|^To14fP6k4T=*GNP7ZgfJEZyVOf!i6_T?RTM
zUrI-h)EyKZSzw8m+l17~X9G0<YKTSmI?=#NV}{p*4V}OtO5w9?m(BsL)ZNXbIc}+R
zMq-O0H>#-XtWBLx`M56yDFV;};TSkgzmp4-NI~2hpTcX6Zl`W`*0g+JGUmeG_7c6_
z#7a_`vH&?{)R}@;4vS8r?{JC3_rV)41j&)3yEZpf0ZebK_+RE4pOL#zhCE{hTJARf
zi8Y-cIf~yMnkK>miEcR>q2$|agUbA<#kXSxs<%)7gZu;dyX~jMBB_dI*q7*0VR@)^
z1%6VB7L6$`l)G!*0jy(g-QF+}XrQAS2Y}Q*iyH#ZnmX0c$xuvXBmB89dcii9=w)1l
zaQXDR{r-xAAiBTd`ETortM)O#o|V`~5NwXicC>7)%W^O=tPk!c$$L+;6`*?2?J#gg
zoSjmB)*gWdg!};5C7^XDX+M0SHUV|K&opT?_hO1ksb?(Y2GwR3QCeIbGF`sI-{wiT
zupn<Tu|q;sL-XeX>liC{Ri#=Zk<3W{%DmhRVaFiC^jOT2dN>*?8uqDfuOAy`KvPSA
z!ouk0{+`wDg?+CGn`}_hyd*8_yHUl<=*ylBfNP*03$3W8QkCIQy*9XnyYA-G0fV?7
zNzdQ&n4Zl^TJ3pPvsSc2i=Q&XW45Dg2Ywexn3Oa$?K>#%?{A15B$0z|^+%sQnVMwR
zlxt3&sxEC0OHAW@m%f_jF<>#URr<tBzdYvnmx6W$i=py+G38(c`GI~EOx3<JEE#JT
zn>I@=+Yea~f`lKV448PQA+0baa{)x?jqyag2y5c?dPMgFN;F(P=Ar9uGT42e#Laf*
z62|rj>b1}@#cKSSZN|#Q6Vo+?sI*HsrUmLrD6$1}^-^=ELPf56>}6~d#@#Du5@cd+
zWN7TCi>JJ!6C2X*$*|uyunHE92hysLph|I0y=F1(zPp>P=qUWtG{{S`THFIuOEB)L
z8Xr8wC|vVVT`6;m-7v`5Bp0{{7+W;sx{;^3KjfVuv0qUUa*6l)B!w7}N9aC5PnrO9
z8oS;ajOW*rvS|W$J8RT$$?IJ<f|yKrahA3DG?{%8Npc9DP(CiGFuSPC(5iO*fw=rq
zq@|zx4=i*7fil!BC-bd5IvOIeR}#`jtDmzVz;&Gal1sG$uDN{as?JJrlvI=DWa7O$
z<yIVE_DN*qjfS#xv*$$R*cB|xC-R|Rt;orF#si)PA`$-nZ=n56wPp{Osmfyuf>>ew
z!PCN7cK=n4eO|LwnOAI<((sZiT&F+x{*Stfqe<3*S^|awLlj_!|AYMm`aP;yvaq4c
z887aNVRj}-n>TpS+JxGdUnt7_6q?lh4U5<KE=m#dVH%yfM672Qha<z{q}hY45l|6k
z{G`2_r_C7!+u$rn)ish<HH+%Z%a6qbO4MSNR18E7z;uAT`zKdI@=DP+mv`>F-}Q*y
z{OJ~_g_JnU9$do~1h%hOB109OWqJD|t+qM1Xp1I{ra)8H%#e$rVdRy1Wi$MjXUO<A
z4|7zUr3UUShOQyCv2tBN)yO2Uat<fnl}?esZj_NiU{XZVpq^C|ru!~O$HWOhU!X<2
zlWr^8dVP`Ems+7p`sGC8;n|&#x8Gq<B!<Edp@w895ZD^4r-|*n|LZ`GC~B#xi#aij
zDaX5@*UvX~8jiAgA%l0=F1;0$cCWiYy|jj9tfIs%+fi)b-VpqYj@Z3lC=F=<Ylm+U
zyR3mtj(8YeDIeWA0|-rtf5$yy9_>zsf@XqR-oibH%8-&|hK+hSy$CW5aBlPex7V<P
zlSJNzK8jO>u$~1c;3fk6^-$fSk+>JCMnFbuDf*oTi=u;Npof2C$pXZb-F4wE+?`4&
z8E<Gw>{pM3ixB!PasU2<BFES5dRu!PEko-V^Q~78TL0W8Ze<=th#jM_kjr+nj|^>w
z(*<d0kh#H<NJj%GwjZn=1%T}3O~Tw7T<@$`{^*TdyAnV|_t%HmOa7Kv6h^pKB2U`U
z#ZbLx(v}NL{bV$xME?e`0SwgmP5dL(blqBc->UaCxtWN7_y1lnW*W3d5ch;IdFv;7
zl>S06n$5hnzPLxiB3Ef<(mfKY&hn83DU{&O1JI9g5;*Y&zt!~;bTw~qH-%6j)Jxa^
zT)jzIuDux2sJ<L%Db+^8YynaQSWAXQ*)q|0AiM*Dy*HFZ@48yrb?iXEd06;r!5J&$
z@+?Ar#0YiqC#*)({nQG3{EphGK4-%I>1x=Sb~{ymbwOVHepsC!ao5&BTeJB3Y7x>F
z>ld1ah1QkN(zc3zam-GiBb+IHzkM{p7evhyQ4y{zlvkIxYe>*jC@3g5yQ^A&|AYSv
z{tUfkac!=0RtATXr_ItSuALEX4Yta)YhSsei3-u-AvJb0E%-y#q43k^(zg9Kie}sp
zwxqgUm9?}@#(jg`5zIHzy|py<ZPCW9%>HGDom$6317W$t4M%meO&5(wTheNAs+b&<
zhH>vWi%Pf+B!#l9b$3NEpYfI}++a2%*X$4oj;*t-e_!?EiNgd>HIf@8vY+e0--RSo
zU#Ln2Xd$vDB85g9{GD<pqiLg>Az>ED+XlX#vkt6spapDu=ig~caa;H+DVtK;vg-=d
zvAt;hu`<1ncz;vlY40{7VEUzi-8!F%-<x#kxjSWOheoO?u|0At;+YBwegjWs4VNE8
zYi7>T{`>bWAi6reFp=9sKUnI&Xok{^(R05mL=Id#Wu&cc@gP0$*1Le7jup<tjhIt1
zmOa#h#$Q``Ddb7YoQQPy3THj|HT{|V2GrsEg~ARKxh^{Rc(@>Zm}h5TBK#i#iC?*O
z;!=GGFuOcna8H#qSK|u4Et!7BE4`%}J)6cnD1#o;L#zpswlYM6+67A$KB+>3)<faa
z?`pB)Ux5+1tk`zm);@u-%xiWb+Lj~P4Z`2`eFdkXko~mz!Db!^NA27#KBO$VKC8*C
ztF$Fx`aoy<T$~^Y=E$>a^8g7d$^9-IQ%0+q9vY}DhTr=*BidukJq?$Vxh#H_WZ2Ob
z%E<F=3LJ+>l>f*?;Q27(;av$Mpz^q0ZEzY>)U-~j5SqFn2QZ&g{p<dL!>Y`?W~-?o
zL41hAN~G)M5HjHh75I1O>W-kauBDp+YJqw4nkQMifTwcL#VqoAfeHM<wg~`$1pEnx
z$9?@UA6~)B_jebCX1SJoQ5S!qIasD9N3Fm%OfPYI_~;;EV9IJ4mB{#5R@VI3ovJ(r
z?lPRSU~@(iTR2=;?;iBJ2a;6^r8zc6XFO{WNsG+!vfAeVWJOTr-iNA`hwKvbdRx?R
z8R)RobYt#5QdVm49{MjK&#-(M=5I!6(-fsg#rD1=VJkS`J}B<+DZIRqh`fZj9QC4u
zwPv*zEq$(wJn^l}iaT40nh^C=*;{xD*~%y<D;ErYqWHejE&u((JiQ{gcG~xkYI3RZ
zTdG$nJrNuy!x!<YnpikV5(TSXWM>;uV2MYN=_`>tZi2snLcXK>pwUp=$(O!(m#P1-
zjw(RN4ZoTZ)Aq<EYB2k{*L`D_>Wo32?t1O~f+Hsk*n?XCgZ~Qt1HEK#M(m*6kYBV9
zYypDX0jUR8_`Ej>1R=xG%lm{WIE(3VM{fwc9OvkZD88E3C;4xmNmlJUREnUoV?ibt
zDMKi|l?=jbgx@))WDSNs=)Ts&Ah`tA>mn{}O*58IxXBNA%^ycex>qwk3^63;1y%Qv
z{Mi%AZ;vKVt!K)^Dr(T?)Ld~|i?A8lzrnWew@NO%5Ht7)4<uY_QFO|h+g)Pw9g!0;
z?$Ey$LnZBIv*kBSpZ#V{dj#|jrO%WYLGolRq@S#g5tquPb`&w07ywjf8$eG+(KV2E
zJ~78;TteR@s1fIFzb^;q%@^342TZw4O5FWnW`~=S6hpCAYfwG-%>Xff);1>hI6*_x
z*W4Nl2s>|8Z}ThX&S|y9{;k`Q{}^<8f0)9nUA;p|%C({+odX&LGFd#wC4xUzH<z!#
z#UfQ5a#zN^p*)VoSlHC<5WPL?6_xI8SJ!F>>BjM1jdKj(8sOugEs-z`@^u0Xy`3*f
zHGN)weldK6<U_KMg*Q8{>a2p=_%+lVfW)pE<A->ZE4)j&-D}fpmW+R9Xut&YX*NjB
ztG{N?!9(5H!IS~TyS#d41-(9GVG*N54R;{!bPFL!DI9)xBFq~WX+Q81>5LfX+H&z9
zNO()Cuh7L<7Q9Q=vr2%FVQLis-HGH^BxSyY)ThIwzz)GCj!!i~JU;S&A`w4@k~DHt
zfluiEf;cWMqs&8exj{NerQiHMW!!_@*tkShwflD5LjK<rGq!kyGu4=P6-|yjvuOlH
zPWv0z`l>i$;%IO-JN!n{I(}Q(DT2exlqE{QKQtu%UJk?f$(gkNS~QkvlEU!6$Mm;D
zHA@)dn>d?rvUHtu-{~08wQlgn0Dl<&@rMo|^t~`e<XprhVn>N4>sljE@m%-WLzP>%
zpgD;;p_me%8+&pw#-d)1DaF~wvjQ+ZeGvTwiuzrfna-oh^5ftx;Ps+p5!zBdNUAye
zE+b)bl5+p&YzYk3DG$~+HqinP%O7uO=(PawwwEH;tRu~5C{At0jHd|I{_;COCT<C-
zs;Z0uWZ|GhouNdMfqTLL|AYP?{3CwdHYqnA=lg}!ruE(}=Y=n3g~Bx&$f`VC)t}r(
z#&7qbbA9LGHRE-i)By|{00**a1Djz0eR?UPl%=2?{%a-Lia=*=0l<fel$dbUql_-F
zEL9#CC}0)A`X2{tij{AcAaImmhy;`*#^)?}rN4XU^%fII;vu&svn(1=O3n4=9a{ce
zLvOgDYh8W=AtZ6a9uNuzi$<kd7zaX{&SoUpLgCUBZ+pN?zAu3Mxx}aF{2iej$I0zt
zPSP0^ONFaWry18NMSKXb{%mvGKmY&$00000000000000000000000000000000000
z0000000002mEBnThit6`8)avUGoFZdwzSA%u@ub-KH=^ofW9j}ZZua$5ouM_^Mwvs
z3(6=DKeED0!JF%>zyiF`(n5|Jf$P_xd0yw&W(r(P01vgqSNB4dNsL26mh%X>kg{Wp
zvF@pKkN^ZEk=u_H=|9c}pIkR2xexFFFsZ0mrsV)zw$5n!l~6MFOv*r#-I03hLvZUm
z`3>R=$6mA2ym-_g;7Eh&4R^EwH8tSjd7pt<8P>B`F3Pvop}<rp0a4W>(t)!}0jEBh
zSXM!3sqMxTL$ne<o&S*)g@6=EVt2tWKP_HfGHVXBq8wbgG@wang_9{&&F#3}@vTc`
zDFot(A-L!4=?JnvG}y~XJeR^micuZlez5vj+it-e2KFx|o6Xu+poN(urAI(wdHa*N
zsUIk#q2iX9RqDq+>{KR=lncp_u<d;6UX(}QHv5ogZ2GNBlc|9fkhikou?hvb7WE*v
z*ZNNE7WE+DNZ6<0S({t@E$TtQk+J+-hb3TnNY}R}!t*!)Gk+<53gZ{#%jUKt^3nKx
zw!CR^3}VFrOAt2RNuQXLbF)^4(tH+=ble8F0j`XPsQb#wHRcP|#b<Dh84r56thR9~
zZZ7-xG_LS#?RcgSCapgG9UV&gB>4)Meq&G0VsKJXNe$Zp^`l%Bg>2&q!rNM)00000
z01PNVOtp^-%&H3Fzu!AfZto&oOsBYLfSjU~@XAzSb}B71<7nr}QG7mC?7bh7YX0bv
zY-~~DcV4tZGfraF(Bv%sdlGZwn)q5V@OKLXu_y$X>2qLif#q&lDj3~K%7BTlAK<W=
z%qb&Y)!YZ?Xdkr)oOX4N|6GH!2ZuVeVcs3bVCynBpHqP^xtJvls<VmGBum<(TuRGz
z6a$bOhmYOq!_%46HjX^pCM0hOxF2ZbYL%rUa1k`-pNeHw^LHFn%F6#Ji$9l)n8Ufu
z=lm35pg-Oba7RzFOT9#EYCSE`?6<=c?}Ng7e{5Dpe1fbBYNb)b(xpFYk!ph>T0^>N
z3<#qbzA%gxKtlb6Z(&=(bbvWQqdjLPpn{5kCrV8=x~S-!wfmAHj1gO~t>C&m7e|sS
zb``uAM}w3hVO!c*SUExj5nlEcy`_bM9H9XOSEAQ9*|1a%{1}^q&761$3v+k~2fyRA
x_7<+fk!nfzk|$5M3TA|tnq1In_D357*%=>M9MBzkI(8$xi-vWgg#ZIuPLRn=x!nK&
new file mode 100644
--- /dev/null
+++ b/content/media/test/bug1066943.webm^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-store
--- a/content/media/test/manifest.js
+++ b/content/media/test/manifest.js
@@ -182,16 +182,17 @@ var gPlayTests = [
   // we can handle playing files when only push very little audio data to the
   // hardware.
   { name:"spacestorm-1000Hz-100ms.ogg", type:"audio/ogg", duration:0.099 },
 
   // Opus data in an ogg container
   { name:"detodos.opus", type:"audio/ogg; codecs=opus", duration:2.9135 },
   // Opus data in a webm container
   { name:"detodos.webm", type:"audio/webm; codecs=opus", duration:2.9135 },
+  { name:"bug1066943.webm", type:"audio/webm; codecs=opus", duration:1.383 },
 
   // Multichannel Opus in an ogg container
   { name:"test-1-mono.opus", type:"audio/ogg; codecs=opus", duration:1.044 },
   { name:"test-2-stereo.opus", type:"audio/ogg; codecs=opus", duration:2.925 },
   { name:"test-3-LCR.opus", type:"audio/ogg; codecs=opus", duration:4.214 },
   { name:"test-4-quad.opus", type:"audio/ogg; codecs=opus", duration:6.234 },
   { name:"test-5-5.0.opus", type:"audio/ogg; codecs=opus", duration:7.558 },
   { name:"test-6-5.1.opus", type:"audio/ogg; codecs=opus", duration:10.333 },
--- a/content/media/test/mochitest.ini
+++ b/content/media/test/mochitest.ini
@@ -102,16 +102,18 @@ support-files =
   bug557094.ogv^headers^
   bug580982.webm
   bug580982.webm^headers^
   bug603918.webm
   bug603918.webm^headers^
   bug604067.webm
   bug604067.webm^headers^
   bug883173.vtt
+  bug1066943.webm
+  bug1066943.webm^headers^
   can_play_type_dash.js
   can_play_type_ogg.js
   can_play_type_wave.js
   can_play_type_webm.js
   cancellable_request.sjs
   chain.ogg
   chain.ogg^headers^
   chain.ogv
--- a/content/media/webm/WebMReader.cpp
+++ b/content/media/webm/WebMReader.cpp
@@ -551,18 +551,18 @@ bool WebMReader::DecodeAudioPacket(neste
   if (!decoded_frames.isValid()) {
     NS_WARNING("Int overflow adding decoded_frames");
     return false;
   }
   if (tstamp_frames.value() > decoded_frames.value()) {
 #ifdef DEBUG
     CheckedInt64 usecs = FramesToUsecs(tstamp_frames.value() - decoded_frames.value(), rate);
     LOG(PR_LOG_DEBUG, ("WebMReader detected gap of %lld, %lld frames, in audio stream\n",
-      usecs.isValid() ? usecs.value() : -1,
-      tstamp_frames.value() - decoded_frames.value()));
+                       usecs.isValid() ? usecs.value() : -1,
+                       tstamp_frames.value() - decoded_frames.value()));
 #endif
     mPacketCount++;
     mAudioStartUsec = tstamp_usecs;
     mAudioFrames = 0;
   }
 
   int32_t total_frames = 0;
   for (uint32_t i = 0; i < count; ++i) {
@@ -666,47 +666,45 @@ bool WebMReader::DecodeAudioPacket(neste
           mSkip -= frames;
           LOG(PR_LOG_DEBUG, ("Opus decoder skipping %d frames"
                              " (whole packet)", frames));
           return true;
         }
         int32_t keepFrames = frames - skipFrames;
         int samples = keepFrames * channels;
         nsAutoArrayPtr<AudioDataValue> trimBuffer(new AudioDataValue[samples]);
-        for (int i = 0; i < samples; i++)
-          trimBuffer[i] = buffer[skipFrames*channels + i];
+        PodCopy(trimBuffer.get(), buffer.get() + skipFrames*channels, samples);
         startTime = startTime + FramesToUsecs(skipFrames, rate);
         frames = keepFrames;
         buffer = trimBuffer;
 
         mSkip -= skipFrames;
         LOG(PR_LOG_DEBUG, ("Opus decoder skipping %d frames", skipFrames));
       }
 
       int64_t discardPadding = 0;
       r = nestegg_packet_discard_padding(aPacket, &discardPadding);
       if (discardPadding > 0) {
-        CheckedInt64 discardFrames = UsecsToFrames(discardPadding * NS_PER_USEC, rate);
+        CheckedInt64 discardFrames = UsecsToFrames(discardPadding / NS_PER_USEC, rate);
         if (!discardFrames.isValid()) {
           NS_WARNING("Int overflow in DiscardPadding");
           return false;
         }
-        int32_t keepFrames = frames - discardFrames.value();
-        if (keepFrames > 0) {
-          int samples = keepFrames * channels;
-          nsAutoArrayPtr<AudioDataValue> trimBuffer(new AudioDataValue[samples]);
-          for (int i = 0; i < samples; i++)
-            trimBuffer[i] = buffer[i];
-          frames = keepFrames;
-          buffer = trimBuffer;
-        } else {
+        if (discardFrames.value() >= frames) {
           LOG(PR_LOG_DEBUG, ("Opus decoder discarding whole packet"
-                             " ( %d frames) as padding", frames));
+                             " (%d frames) as padding (%lld discarded)",
+                             frames, discardFrames.value()));
           return true;
         }
+        int32_t keepFrames = frames - discardFrames.value();
+        int32_t samples = keepFrames * channels;
+        nsAutoArrayPtr<AudioDataValue> trimBuffer(new AudioDataValue[samples]);
+        PodCopy(trimBuffer.get(), buffer.get(), samples);
+        frames = keepFrames;
+        buffer = trimBuffer;
       }
 
       // Apply the header gain if one was specified.
 #ifdef MOZ_SAMPLE_TYPE_FLOAT32
       if (mOpusParser->mGain != 1.0f) {
         float gain = mOpusParser->mGain;
         int samples = frames * channels;
         for (int i = 0; i < samples; i++) {
--- a/dom/bindings/parser/WebIDL.py
+++ b/dom/bindings/parser/WebIDL.py
@@ -3400,16 +3400,17 @@ class IDLArgument(IDLObjectWithIdentifie
         self.variadic = variadic
         self.dictionaryMember = dictionaryMember
         self._isComplete = False
         self.enforceRange = False
         self.clamp = False
         self._allowTreatNonCallableAsNull = False
 
         assert not variadic or optional
+        assert not variadic or not defaultValue
 
     def addExtendedAttributes(self, attrs):
         attrs = self.checkForStringHandlingExtendedAttributes(
             attrs,
             isDictionaryMember=self.dictionaryMember,
             isOptional=self.optional)
         for attribute in attrs:
             identifier = attribute.identifier()
@@ -3448,19 +3449,19 @@ class IDLArgument(IDLObjectWithIdentifie
             type = self.type.complete(scope)
             assert not isinstance(type, IDLUnresolvedType)
             assert not isinstance(type, IDLTypedefType)
             assert not isinstance(type.name, IDLUnresolvedIdentifier)
             self.type = type
 
         if ((self.type.isDictionary() or
              self.type.isUnion() and self.type.unroll().hasDictionaryType) and
-            self.optional and not self.defaultValue):
-            # Default optional dictionaries to null, for simplicity,
-            # so the codegen doesn't have to special-case this.
+            self.optional and not self.defaultValue and not self.variadic):
+            # Default optional non-variadic dictionaries to null,
+            # for simplicity, so the codegen doesn't have to special-case this.
             self.defaultValue = IDLNullValue(self.location)
         elif self.type.isAny():
             assert (self.defaultValue is None or
                     isinstance(self.defaultValue, IDLNullValue))
             # optional 'any' values always have a default value
             if self.optional and not self.defaultValue and not self.variadic:
                 # Set the default value to undefined, for simplicity, so the
                 # codegen doesn't have to special-case this.
--- a/dom/bindings/test/TestBindingHeader.h
+++ b/dom/bindings/test/TestBindingHeader.h
@@ -709,16 +709,17 @@ public:
   void PassOtherDictionary(const GrandparentDict&);
   void PassSequenceOfDictionaries(JSContext*, const Sequence<Dict>&);
   void PassMozMapOfDictionaries(const MozMap<GrandparentDict>&);
   void PassDictionaryOrLong(JSContext*, const Dict&);
   void PassDictionaryOrLong(int32_t);
   void PassDictContainingDict(JSContext*, const DictContainingDict&);
   void PassDictContainingSequence(JSContext*, const DictContainingSequence&);
   void ReceiveDictContainingSequence(JSContext*, DictContainingSequence&);
+  void PassVariadicDictionary(JSContext*, const Sequence<Dict>&);
 
   // Typedefs
   void ExerciseTypedefInterfaces1(TestInterface&);
   already_AddRefed<TestInterface> ExerciseTypedefInterfaces2(TestInterface*);
   void ExerciseTypedefInterfaces3(TestInterface&);
 
   // Static methods and attributes
   static void StaticMethod(const GlobalObject&, bool);
--- a/dom/bindings/test/TestCodeGen.webidl
+++ b/dom/bindings/test/TestCodeGen.webidl
@@ -681,16 +681,17 @@ interface TestInterface {
   // No support for nullable dictionaries inside a sequence (nor should there be)
   //  void passSequenceOfNullableDictionaries(sequence<Dict?> x);
   void passDictionaryOrLong(optional Dict x);
   void passDictionaryOrLong(long x);
 
   void passDictContainingDict(optional DictContainingDict arg);
   void passDictContainingSequence(optional DictContainingSequence arg);
   DictContainingSequence receiveDictContainingSequence();
+  void passVariadicDictionary(Dict... arg);
 
   // EnforceRange/Clamp tests
   void dontEnforceRangeOrClamp(byte arg);
   void doEnforceRange([EnforceRange] byte arg);
   void doClamp([Clamp] byte arg);
   [EnforceRange] attribute byte enforcedByte;
   [Clamp] attribute byte clampedByte;
 
--- a/dom/bindings/test/TestExampleGen.webidl
+++ b/dom/bindings/test/TestExampleGen.webidl
@@ -545,16 +545,17 @@ interface TestExampleInterface {
   // No support for nullable dictionaries inside a sequence (nor should there be)
   //  void passSequenceOfNullableDictionaries(sequence<Dict?> x);
   void passDictionaryOrLong(optional Dict x);
   void passDictionaryOrLong(long x);
 
   void passDictContainingDict(optional DictContainingDict arg);
   void passDictContainingSequence(optional DictContainingSequence arg);
   DictContainingSequence receiveDictContainingSequence();
+  void passVariadicDictionary(Dict... arg);
 
   // EnforceRange/Clamp tests
   void dontEnforceRangeOrClamp(byte arg);
   void doEnforceRange([EnforceRange] byte arg);
   void doClamp([Clamp] byte arg);
   [EnforceRange] attribute byte enforcedByte;
   [Clamp] attribute byte clampedByte;
 
--- a/dom/bindings/test/TestJSImplGen.webidl
+++ b/dom/bindings/test/TestJSImplGen.webidl
@@ -131,19 +131,18 @@ interface TestJSImplInterface {
   [LenientFloat]
   attribute double lenientDoubleAttr;
 
   // Castable interface types
   // XXXbz add tests for throwing versions of all the castable interface stuff
   TestJSImplInterface receiveSelf();
   TestJSImplInterface? receiveNullableSelf();
 
-  // Callback interface ignores 'resultNotAddRefed'. See bug 843272.
-  //TestJSImplInterface receiveWeakSelf();
-  //TestJSImplInterface? receiveWeakNullableSelf();
+  TestJSImplInterface receiveWeakSelf();
+  TestJSImplInterface? receiveWeakNullableSelf();
 
   // A version to test for casting to TestJSImplInterface&
   void passSelf(TestJSImplInterface arg);
   void passNullableSelf(TestJSImplInterface? arg);
   attribute TestJSImplInterface nonNullSelf;
   attribute TestJSImplInterface? nullableSelf;
   [Cached, Pure]
   readonly attribute TestJSImplInterface cachedSelf;
@@ -165,50 +164,47 @@ interface TestJSImplInterface {
   [NewObject]
   sequence<TestNonWrapperCacheInterface>? receiveNonWrapperCacheInterfaceNullableSequence();
   [NewObject]
   sequence<TestNonWrapperCacheInterface?>? receiveNullableNonWrapperCacheInterfaceNullableSequence();
 
   // Non-castable interface types
   IndirectlyImplementedInterface receiveOther();
   IndirectlyImplementedInterface? receiveNullableOther();
-  // Callback interface ignores 'resultNotAddRefed'. See bug 843272.
-  //IndirectlyImplementedInterface receiveWeakOther();
-  //IndirectlyImplementedInterface? receiveWeakNullableOther();
+  IndirectlyImplementedInterface receiveWeakOther();
+  IndirectlyImplementedInterface? receiveWeakNullableOther();
 
   void passOther(IndirectlyImplementedInterface arg);
   void passNullableOther(IndirectlyImplementedInterface? arg);
   attribute IndirectlyImplementedInterface nonNullOther;
   attribute IndirectlyImplementedInterface? nullableOther;
   // Optional arguments
   void passOptionalOther(optional IndirectlyImplementedInterface? arg);
   void passOptionalNonNullOther(optional IndirectlyImplementedInterface arg);
   void passOptionalOtherWithDefault(optional IndirectlyImplementedInterface? arg = null);
 
   // External interface types
   TestExternalInterface receiveExternal();
   TestExternalInterface? receiveNullableExternal();
-  // Callback interface ignores 'resultNotAddRefed'. See bug 843272.
-  //TestExternalInterface receiveWeakExternal();
-  //TestExternalInterface? receiveWeakNullableExternal();
+  TestExternalInterface receiveWeakExternal();
+  TestExternalInterface? receiveWeakNullableExternal();
   void passExternal(TestExternalInterface arg);
   void passNullableExternal(TestExternalInterface? arg);
   attribute TestExternalInterface nonNullExternal;
   attribute TestExternalInterface? nullableExternal;
   // Optional arguments
   void passOptionalExternal(optional TestExternalInterface? arg);
   void passOptionalNonNullExternal(optional TestExternalInterface arg);
   void passOptionalExternalWithDefault(optional TestExternalInterface? arg = null);
 
   // Callback interface types
   TestCallbackInterface receiveCallbackInterface();
   TestCallbackInterface? receiveNullableCallbackInterface();
-  // Callback interface ignores 'resultNotAddRefed'. See bug 843272.
-  //TestCallbackInterface receiveWeakCallbackInterface();
-  //TestCallbackInterface? receiveWeakNullableCallbackInterface();
+  TestCallbackInterface receiveWeakCallbackInterface();
+  TestCallbackInterface? receiveWeakNullableCallbackInterface();
   void passCallbackInterface(TestCallbackInterface arg);
   void passNullableCallbackInterface(TestCallbackInterface? arg);
   attribute TestCallbackInterface nonNullCallbackInterface;
   attribute TestCallbackInterface? nullableCallbackInterface;
   // Optional arguments
   void passOptionalCallbackInterface(optional TestCallbackInterface? arg);
   void passOptionalNonNullCallbackInterface(optional TestCallbackInterface arg);
   void passOptionalCallbackInterfaceWithDefault(optional TestCallbackInterface? arg = null);
@@ -565,16 +561,17 @@ interface TestJSImplInterface {
   // No support for nullable dictionaries inside a sequence (nor should there be)
   //  void passSequenceOfNullableDictionaries(sequence<Dict?> x);
   void passDictionaryOrLong(optional Dict x);
   void passDictionaryOrLong(long x);
 
   void passDictContainingDict(optional DictContainingDict arg);
   void passDictContainingSequence(optional DictContainingSequence arg);
   DictContainingSequence receiveDictContainingSequence();
+  void passVariadicDictionary(Dict... arg);
 
   // EnforceRange/Clamp tests
   void dontEnforceRangeOrClamp(byte arg);
   void doEnforceRange([EnforceRange] byte arg);
   void doClamp([Clamp] byte arg);
   [EnforceRange] attribute byte enforcedByte;
   [Clamp] attribute byte clampedByte;
 
--- a/dom/canvas/WebGL2Context.h
+++ b/dom/canvas/WebGL2Context.h
@@ -140,24 +140,30 @@ public:
 
 
     // ------------------------------------------------------------------------
     // Multiple Render Targets - WebGL2ContextMRTs.cpp
     // TODO(djg): Implemented in WebGLContext
 /*
     void DrawBuffers(const dom::Sequence<GLenum>& buffers);
 */
+
+    void ClearBufferiv_base(GLenum buffer, GLint drawbuffer, const GLint* value);
+    void ClearBufferuiv_base(GLenum buffer, GLint drawbuffer, const GLuint* value);
+    void ClearBufferfv_base(GLenum buffer, GLint drawbuffer, const GLfloat* value);
+
     void ClearBufferiv(GLenum buffer, GLint drawbuffer, const dom::Int32Array& value);
     void ClearBufferiv(GLenum buffer, GLint drawbuffer, const dom::Sequence<GLint>& value);
     void ClearBufferuiv(GLenum buffer, GLint drawbuffer, const dom::Uint32Array& value);
     void ClearBufferuiv(GLenum buffer, GLint drawbuffer, const dom::Sequence<GLuint>& value);
     void ClearBufferfv(GLenum buffer, GLint drawbuffer, const dom::Float32Array& value);
     void ClearBufferfv(GLenum buffer, GLint drawbuffer, const dom::Sequence<GLfloat>& value);
     void ClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
 
+    bool ValidateClearBuffer(const char* info, GLenum buffer, GLint drawbuffer, size_t elemCount);
 
     // -------------------------------------------------------------------------
     // Query Objects - WebGL2ContextQueries.cpp
     // TODO(djg): Implemented in WebGLContext
     /* already_AddRefed<WebGLQuery> CreateQuery();
     void DeleteQuery(WebGLQuery* query);
     bool IsQuery(WebGLQuery* query);
     void BeginQuery(GLenum target, WebGLQuery* query);
--- a/dom/canvas/WebGL2ContextMRTs.cpp
+++ b/dom/canvas/WebGL2ContextMRTs.cpp
@@ -4,49 +4,139 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "WebGL2Context.h"
 #include "GLContext.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
+bool WebGL2Context::ValidateClearBuffer(const char* info, GLenum buffer, GLint drawbuffer, size_t elemCount)
+{
+    size_t requiredElements = -1;
+    GLint maxDrawbuffer = -1;
+    switch (buffer) {
+      case LOCAL_GL_COLOR:
+      case LOCAL_GL_FRONT:
+      case LOCAL_GL_BACK:
+      case LOCAL_GL_LEFT:
+      case LOCAL_GL_RIGHT:
+      case LOCAL_GL_FRONT_AND_BACK:
+          requiredElements = 4;
+          maxDrawbuffer = mGLMaxDrawBuffers - 1;
+          break;
+
+      case LOCAL_GL_DEPTH:
+      case LOCAL_GL_STENCIL:
+          requiredElements = 1;
+          maxDrawbuffer = 0;
+          break;
+
+      default:
+          ErrorInvalidEnumInfo(info, buffer);
+          return false;
+    }
+
+    if (drawbuffer < 0 || drawbuffer > maxDrawbuffer) {
+        ErrorInvalidValue("%s: invalid drawbuffer %d. This buffer only supports drawbuffer values between 0 and %d",
+                          info, drawbuffer, maxDrawbuffer);
+        return false;
+    }
+
+    if (elemCount < requiredElements) {
+        ErrorInvalidValue("%s: Not enough elements. Require %u. Given %u.",
+                          info, requiredElements, elemCount);
+        return false;
+    }
+    return true;
+}
+
+// Common base functionality. These a good candidates to be moved into WebGLContextUnchecked.cpp
+void
+WebGL2Context::ClearBufferiv_base(GLenum buffer, GLint drawbuffer, const GLint* value)
+{
+    MakeContextCurrent();
+    gl->fClearBufferiv(buffer, drawbuffer, value);
+}
+
+void
+WebGL2Context::ClearBufferuiv_base(GLenum buffer, GLint drawbuffer, const GLuint* value)
+{
+    MakeContextCurrent();
+    gl->fClearBufferuiv(buffer, drawbuffer, value);
+}
+
+void
+WebGL2Context::ClearBufferfv_base(GLenum buffer, GLint drawbuffer, const GLfloat* value)
+{
+    MakeContextCurrent();
+    gl->fClearBufferfv(buffer, drawbuffer, value);
+}
+
 void
 WebGL2Context::ClearBufferiv(GLenum buffer, GLint drawbuffer, const dom::Int32Array& value)
 {
-    MOZ_CRASH("Not Implemented.");
+    if (!ValidateClearBuffer("clearBufferiv", buffer, drawbuffer, value.Length())) {
+        return;
+    }
+
+    ClearBufferiv_base(buffer, drawbuffer, value.Data());
 }
 
 void
 WebGL2Context::ClearBufferiv(GLenum buffer, GLint drawbuffer, const dom::Sequence<GLint>& value)
 {
-    MOZ_CRASH("Not Implemented.");
+    if (!ValidateClearBuffer("clearBufferiv", buffer, drawbuffer, value.Length())) {
+        return;
+    }
+
+    ClearBufferiv_base(buffer, drawbuffer, value.Elements());
 }
 
 void
 WebGL2Context::ClearBufferuiv(GLenum buffer, GLint drawbuffer, const dom::Uint32Array& value)
 {
-    MOZ_CRASH("Not Implemented.");
+    if (!ValidateClearBuffer("clearBufferuiv", buffer, drawbuffer, value.Length())) {
+        return;
+    }
+
+    ClearBufferuiv_base(buffer, drawbuffer, value.Data());
 }
 
 void
 WebGL2Context::ClearBufferuiv(GLenum buffer, GLint drawbuffer, const dom::Sequence<GLuint>& value)
 {
-    MOZ_CRASH("Not Implemented.");
+    if (!ValidateClearBuffer("clearBufferuiv", buffer, drawbuffer, value.Length())) {
+        return;
+    }
+
+    ClearBufferuiv_base(buffer, drawbuffer, value.Elements());
 }
 
 void
 WebGL2Context::ClearBufferfv(GLenum buffer, GLint drawbuffer, const dom::Float32Array& value)
 {
-    MOZ_CRASH("Not Implemented.");
+    if (!ValidateClearBuffer("clearBufferfv", buffer, drawbuffer, value.Length())) {
+        return;
+    }
+
+    ClearBufferfv_base(buffer, drawbuffer, value.Data());
 }
 
 void
 WebGL2Context::ClearBufferfv(GLenum buffer, GLint drawbuffer, const dom::Sequence<GLfloat>& value)
 {
-    MOZ_CRASH("Not Implemented.");
+    if (!ValidateClearBuffer("clearBufferfv", buffer, drawbuffer, value.Length())) {
+        return;
+    }
+
+    ClearBufferfv_base(buffer, drawbuffer, value.Elements());
 }
 
 void
 WebGL2Context::ClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
 {
-    MOZ_CRASH("Not Implemented.");
+    if (buffer != LOCAL_GL_DEPTH_STENCIL) {
+        return ErrorInvalidEnumInfo("clearBufferfi: buffer", buffer);
+    }
+    MakeContextCurrent();
+    gl->fClearBufferfi(buffer, drawbuffer, depth, stencil);
 }
--- a/dom/settings/SettingsManager.js
+++ b/dom/settings/SettingsManager.js
@@ -81,16 +81,24 @@ SettingsLock.prototype = {
   },
 
   get closed() {
     return !this._open;
   },
 
   _closeHelper: function() {
     if (DEBUG) debug("closing lock " + this._id);
+    // sendMessage can get queued to run later in a thread via
+    // _closeHelper, but the SettingsManager may have died in between
+    // the time it was scheduled and the time it runs. Make sure our
+    // window is valid before sending, otherwise just ignore.
+    if (!this._settingsManager._window) {
+      if (DEBUG) debug("SettingsManager died, cannot send " + aMessageName + " message window principal.");
+      return;
+    }
     this._open = false;
     this._closeCalled = false;
     if (!this._requests || Object.keys(this._requests).length == 0) {
       if (DEBUG) debug("Requests exhausted, finalizing " + this._id);
       this._settingsManager.unregisterLock(this._id);
       this.sendMessage("Settings:Finalize", {lockID: this._id});
     } else {
       if (DEBUG) debug("Requests left: " + Object.keys(this._requests).length);
@@ -259,17 +267,17 @@ SettingsManager.prototype = {
     this._locks.push(lock._id);
     return lock;
   },
 
   unregisterLock: function(aLockID) {
     let lock_index = this._locks.indexOf(aLockID);
     if (lock_index != -1) {
       if (DEBUG) debug("Unregistering lock " + aLockID);
-      this._locks.splice(lock_index, -1);
+      this._locks.splice(lock_index, 1);
     }
   },
   
   receiveMessage: function(aMessage) {
     if (DEBUG) debug("Settings::receiveMessage: " + aMessage.name);
     let msg = aMessage.json;
 
     switch (aMessage.name) {
--- a/dom/settings/SettingsRequestManager.jsm
+++ b/dom/settings/SettingsRequestManager.jsm
@@ -575,19 +575,21 @@ let SettingsRequestManager = {
       if (DEBUG) debug("Lock no longer alive, cannot run tasks");
       return;
     }
     let currentTask = lock.tasks.shift();
     let promises = [];
     while (currentTask) {
       if (DEBUG) debug("Running Operation " + currentTask.operation);
       if (lock.finalizing) {
+        // We should really never get to this point, but if we do,
+        // fail every task that happens.
         Cu.reportError("Settings lock trying to run more tasks after finalizing. Ignoring tasks, but this is bad. Lock: " + aLockID);
-        continue;
-      }
+        currentTask.defer.reject("Cannot call new task after finalizing");
+      } else {
       let p;
       switch (currentTask.operation) {
         case "get":
           p = this.taskGet(currentTask);
           break;
         case "set":
           p = this.taskSet(currentTask);
           break;
@@ -602,16 +604,17 @@ let SettingsRequestManager = {
           p.reject("Invalid operation: " + currentTask.operation);
       }
       p.then(function(ret) {
         ret.task.defer.resolve("results" in ret ? ret.results : null);
       }.bind(currentTask), function(ret) {
         ret.task.defer.reject(ret.error);
       });
       promises.push(p);
+      }
       currentTask = lock.tasks.shift();
     }
   },
 
   consumeTasks: function() {
     if (this.settingsLockQueue.length == 0) {
       if (DEBUG) debug("Nothing to run!");
       return;
@@ -703,29 +706,31 @@ let SettingsRequestManager = {
       this.children.splice(index, 1);
       this.mmPrincipals.delete(aMsgMgr);
     }
     if (DEBUG) debug("Principal/MessageManager pairs left: " + this.mmPrincipals.size);
   },
 
   removeLock: function(aLockID) {
     if (DEBUG) debug("Removing lock " + aLockID);
+    if (this.lockInfo[aLockID]) {
     let transaction = this.lockInfo[aLockID]._transaction;
     if (transaction) {
       try {
         transaction.abort();
       } catch (e) {
         if (e.name == "InvalidStateError") {
           if (DEBUG) debug("Transaction for " + aLockID + " closed already");
         } else {
           throw e;
         }
       }
     }
     delete this.lockInfo[aLockID];
+    }
     let index = this.settingsLockQueue.indexOf(aLockID);
     if (index > -1) {
       this.settingsLockQueue.splice(index, 1);
     }
     // If index is 0, the lock we just removed was at the head of
     // the queue, so possibly queue the next lock if it's
     // consumable.
     if (index == 0) {
--- a/gfx/2d/DrawTargetCairo.cpp
+++ b/gfx/2d/DrawTargetCairo.cpp
@@ -1383,16 +1383,23 @@ DrawTargetCairo::CreateSimilarDrawTarget
   gfxCriticalError() << "Failed to create similar cairo surface! Size: " << aSize << " Status: " << cairo_surface_status(similar);
 
   return nullptr;
 }
 
 bool
 DrawTargetCairo::InitAlreadyReferenced(cairo_surface_t* aSurface, const IntSize& aSize, SurfaceFormat* aFormat)
 {
+  if (cairo_surface_status(aSurface)) {
+    gfxCriticalError() << "Attempt to create DrawTarget for invalid surface. "
+                       << aSize << " Cairo Status: " << cairo_surface_status(aSurface);
+    cairo_surface_destroy(aSurface);
+    return false;
+  }
+
   mContext = cairo_create(aSurface);
   mSurface = aSurface;
   mSize = aSize;
   mFormat = aFormat ? *aFormat : CairoContentToGfxFormat(cairo_surface_get_content(aSurface));
 
   // Cairo image surface have a bug where they will allocate a mask surface (for clipping)
   // the size of the clip extents, and don't take the surface extents into account.
   // Add a manual clip to the surface extents to prevent this.
--- a/gfx/2d/DrawTargetD2D.cpp
+++ b/gfx/2d/DrawTargetD2D.cpp
@@ -1343,31 +1343,31 @@ bool
 DrawTargetD2D::Init(const IntSize &aSize, SurfaceFormat aFormat)
 {
   HRESULT hr;
 
   mSize = aSize;
   mFormat = aFormat;
 
   if (!Factory::GetDirect3D10Device()) {
-    gfxDebug() << "Failed to Init Direct2D DrawTarget (No D3D10 Device set.)";
+    gfxCriticalError() << "Failed to Init Direct2D DrawTarget (No D3D10 Device set.)";
     return false;
   }
   mDevice = Factory::GetDirect3D10Device();
 
   CD3D10_TEXTURE2D_DESC desc(DXGIFormat(aFormat),
                              mSize.width,
                              mSize.height,
                              1, 1);
   desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
 
   hr = mDevice->CreateTexture2D(&desc, nullptr, byRef(mTexture));
 
   if (FAILED(hr)) {
-    gfxDebug() << "Failed to init Direct2D DrawTarget. Size: " << mSize << " Code: " << hr;
+    gfxCriticalError() << "Failed to init Direct2D DrawTarget. Size: " << mSize << " Code: " << hr;
     return false;
   }
 
   if (!InitD2DRenderTarget()) {
     return false;
   }
 
   mRT->Clear(D2D1::ColorF(0, 0));
@@ -1388,17 +1388,17 @@ DrawTargetD2D::Init(ID3D10Texture2D *aTe
   }
 
   RefPtr<ID3D10Device> device;
   mTexture->GetDevice(byRef(device));
 
   hr = device->QueryInterface((ID3D10Device1**)byRef(mDevice));
 
   if (FAILED(hr)) {
-    gfxWarning() << "Failed to get D3D10 device from texture.";
+    gfxCriticalError() << "Failed to get D3D10 device from texture.";
     return false;
   }
 
   D3D10_TEXTURE2D_DESC desc;
   mTexture->GetDesc(&desc);
   mSize.width = desc.Width;
   mSize.height = desc.Height;
 
@@ -1507,16 +1507,17 @@ DrawTargetD2D::PopCachedLayer(ID2D1Rende
   aRT->PopLayer();
   mCurrentCachedLayer--;
 }
 
 bool
 DrawTargetD2D::InitD2DRenderTarget()
 {
   if (!factory()) {
+    gfxCriticalError() << "No valid D2D factory available.";
     return false;
   }
 
   mRT = CreateRTForTexture(mTexture, mFormat);
 
   if (!mRT) {
     return false;
   }
@@ -1955,17 +1956,17 @@ DrawTargetD2D::CreateRTForTexture(ID3D10
   HRESULT hr;
 
   RefPtr<IDXGISurface> surface;
   RefPtr<ID2D1RenderTarget> rt;
 
   hr = aTexture->QueryInterface((IDXGISurface**)byRef(surface));
 
   if (FAILED(hr)) {
-    gfxWarning() << "Failed to QI texture to surface.";
+    gfxCriticalError() << "Failed to QI texture to surface.";
     return nullptr;
   }
 
   D3D10_TEXTURE2D_DESC desc;
   aTexture->GetDesc(&desc);
 
   D2D1_ALPHA_MODE alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
 
@@ -1973,17 +1974,17 @@ DrawTargetD2D::CreateRTForTexture(ID3D10
     alphaMode = D2D1_ALPHA_MODE_IGNORE;
   }
 
   D2D1_RENDER_TARGET_PROPERTIES props =
     D2D1::RenderTargetProperties(D2D1_RENDER_TARGET_TYPE_DEFAULT, D2D1::PixelFormat(desc.Format, alphaMode));
   hr = factory()->CreateDxgiSurfaceRenderTarget(surface, props, byRef(rt));
 
   if (FAILED(hr)) {
-    gfxWarning() << "Failed to create D2D render target for texture.";
+    gfxCriticalError() << "Failed to create D2D render target for texture.";
     return nullptr;
   }
 
   return rt.forget();
 }
 
 void
 DrawTargetD2D::EnsureViews()
--- a/gfx/gl/GLContext.cpp
+++ b/gfx/gl/GLContext.cpp
@@ -1007,16 +1007,33 @@ GLContext::InitWithPrefix(const char *pr
             if (!LoadSymbols(useCore ? coreSymbols : extSymbols, trygl, prefix)) {
                 NS_ERROR("GL supports query objects iv getter without supplying its function.");
 
                 MarkUnsupported(GLFeature::get_query_object_iv);
                 ClearSymbols(coreSymbols);
             }
         }
 
+        if (IsSupported(GLFeature::clear_buffers)) {
+            SymLoadStruct clearBuffersSymbols[] = {
+                { (PRFuncPtr*) &mSymbols.fClearBufferfi,  { "ClearBufferfi",  nullptr } },
+                { (PRFuncPtr*) &mSymbols.fClearBufferfv,  { "ClearBufferfv",  nullptr } },
+                { (PRFuncPtr*) &mSymbols.fClearBufferiv,  { "ClearBufferiv",  nullptr } },
+                { (PRFuncPtr*) &mSymbols.fClearBufferuiv, { "ClearBufferuiv", nullptr } },
+                END_SYMBOLS
+            };
+
+            if (!LoadSymbols(clearBuffersSymbols, trygl, prefix)) {
+                NS_ERROR("GL supports clear_buffers without supplying its functions.");
+
+                MarkUnsupported(GLFeature::clear_buffers);
+                ClearSymbols(clearBuffersSymbols);
+            }
+        }
+
         if (IsSupported(GLFeature::draw_buffers)) {
             SymLoadStruct coreSymbols[] = {
                 { (PRFuncPtr*) &mSymbols.fDrawBuffers, { "DrawBuffers", nullptr } },
                 END_SYMBOLS
             };
 
             SymLoadStruct extSymbols[] = {
                 { (PRFuncPtr*) &mSymbols.fDrawBuffers, { "DrawBuffersARB", "DrawBuffersEXT", nullptr } },
--- a/gfx/gl/GLContext.h
+++ b/gfx/gl/GLContext.h
@@ -75,16 +75,17 @@ namespace mozilla {
 }
 
 namespace mozilla {
 namespace gl {
 
 MOZ_BEGIN_ENUM_CLASS(GLFeature)
     bind_buffer_offset,
     blend_minmax,
+    clear_buffers,
     depth_texture,
     draw_buffers,
     draw_instanced,
     draw_range_elements,
     element_index_uint,
     ES2_compatibility,
     ES3_compatibility,
     frag_color_float,
@@ -941,16 +942,40 @@ private:
 
 public:
     void fClear(GLbitfield mask) {
         BeforeGLDrawCall();
         raw_fClear(mask);
         AfterGLDrawCall();
     }
 
+    void fClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) {
+        BEFORE_GL_CALL;
+        mSymbols.fClearBufferfi(buffer, drawbuffer, depth, stencil);
+        AFTER_GL_CALL;
+    }
+
+    void fClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat* value) {
+        BEFORE_GL_CALL;
+        mSymbols.fClearBufferfv(buffer, drawbuffer, value);
+        AFTER_GL_CALL;
+    }
+
+    void fClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint* value) {
+        BEFORE_GL_CALL;
+        mSymbols.fClearBufferiv(buffer, drawbuffer, value);
+        AFTER_GL_CALL;
+    }
+
+    void fClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint* value) {
+        BEFORE_GL_CALL;
+        mSymbols.fClearBufferuiv(buffer, drawbuffer, value);
+        AFTER_GL_CALL;
+    }
+
     void fClearColor(GLclampf r, GLclampf g, GLclampf b, GLclampf a) {
         BEFORE_GL_CALL;
         mSymbols.fClearColor(r, g, b, a);
         AFTER_GL_CALL;
     }
 
     void fClearStencil(GLint s) {
         BEFORE_GL_CALL;
--- a/gfx/gl/GLContextFeatures.cpp
+++ b/gfx/gl/GLContextFeatures.cpp
@@ -67,16 +67,25 @@ static const FeatureInfo sFeatureInfoArr
         300, // OpenGL ES version
         GLContext::Extension_None,
         {
             GLContext::EXT_blend_minmax,
             GLContext::Extensions_End
         }
     },
     {
+        "clear_buffers",
+        300, // OpenGL version
+        300, // OpenGL ES version
+        GLContext::Extension_None,
+        {
+            GLContext::Extensions_End
+        }
+    },
+    {
         "depth_texture",
         200, // OpenGL version
         300, // OpenGL ES version
         GLContext::Extension_None,
         {
             GLContext::ARB_depth_texture,
             GLContext::OES_depth_texture,
             // Intentionally avoid putting ANGLE_depth_texture here,
--- a/gfx/gl/GLContextSymbols.h
+++ b/gfx/gl/GLContextSymbols.h
@@ -60,16 +60,24 @@ struct GLContextSymbols
     typedef void (GLAPIENTRY * PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
     PFNGLBLENDFUNCSEPARATEPROC fBlendFuncSeparate;
     typedef void (GLAPIENTRY * PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage);
     PFNGLBUFFERDATAPROC fBufferData;
     typedef void (GLAPIENTRY * PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data);
     PFNGLBUFFERSUBDATAPROC fBufferSubData;
     typedef void (GLAPIENTRY * PFNGLCLEARPROC) (GLbitfield);
     PFNGLCLEARPROC fClear;
+    typedef void (GLAPIENTRY * PFNGLCLEARBUFFERFIPROC) (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
+    PFNGLCLEARBUFFERFIPROC fClearBufferfi;
+    typedef void (GLAPIENTRY * PFNGLCLEARBUFFERFVPROC) (GLenum buffer, GLint drawbuffer, const GLfloat* value);
+    PFNGLCLEARBUFFERFVPROC fClearBufferfv;
+    typedef void (GLAPIENTRY * PFNGLCLEARBUFFERIVPROC) (GLenum buffer, GLint drawbuffer, const GLint* value);
+    PFNGLCLEARBUFFERIVPROC fClearBufferiv;
+    typedef void (GLAPIENTRY * PFNGLCLEARBUFFERUIVPROC) (GLenum buffer, GLint drawbuffer, const GLuint* value);
+    PFNGLCLEARBUFFERUIVPROC fClearBufferuiv;
     typedef void (GLAPIENTRY * PFNGLCLEARCOLORPROC) (GLclampf, GLclampf, GLclampf, GLclampf);
     PFNGLCLEARCOLORPROC fClearColor;
     typedef void (GLAPIENTRY * PFNGLCLEARSTENCILPROC) (GLint);
     PFNGLCLEARSTENCILPROC fClearStencil;
     typedef void (GLAPIENTRY * PFNGLCOLORMASKPROC) (realGLboolean red, realGLboolean green, realGLboolean blue, realGLboolean alpha);
     PFNGLCOLORMASKPROC fColorMask;
     typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE2D) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *pixels);
     PFNGLCOMPRESSEDTEXIMAGE2D fCompressedTexImage2D;
--- a/image/src/RasterImage.cpp
+++ b/image/src/RasterImage.cpp
@@ -247,17 +247,18 @@ public:
   {
     MOZ_ASSERT(NS_IsMainThread());
 
     nsRefPtr<RasterImage> image = weakImage.get();
     if (image) {
       image->UnlockImage();
     }
 
-    if (DiscardingEnabled() && dstFrame) {
+    if (dstFrame) {
+      dstFrame->SetOptimizable();
       dstFrame->SetDiscardable();
     }
 
     // Release everything except dstFrame, which we keep around for RasterImage
     // to retrieve.
     srcRef.reset();
     dstRef.reset();
   }
@@ -1417,31 +1418,27 @@ RasterImage::DecodingComplete()
   // We now have one of the qualifications for discarding. Re-evaluate.
   if (CanDiscard()) {
     NS_ABORT_IF_FALSE(!DiscardingActive(),
                       "We shouldn't have been discardable before this");
     rv = DiscardTracker::Reset(&mDiscardTrackerNode);
     CONTAINER_ENSURE_SUCCESS(rv);
   }
 
-  // If there's only 1 frame, optimize it. Optimizing animated images
+  // If there's only 1 frame, mark it as optimizable. Optimizing animated images
   // is not supported.
   //
   // We don't optimize the frame for multipart images because we reuse
   // the frame.
   if ((GetNumFrames() == 1) && !mMultipart) {
-    // CanForciblyDiscard is used instead of CanForciblyDiscardAndRedecode
-    // because we know decoding is complete at this point and this is not
-    // an animation
     nsRefPtr<imgFrame> firstFrame = mFrameBlender.RawGetFrame(0);
+    firstFrame->SetOptimizable();
     if (DiscardingEnabled() && CanForciblyDiscard()) {
       firstFrame->SetDiscardable();
     }
-    rv = firstFrame->Optimize();
-    NS_ENSURE_SUCCESS(rv, rv);
   }
 
   // Double-buffer our frame in the multipart case, since we'll start decoding
   // into the first frame again immediately and this produces severe tearing.
   if (mMultipart) {
     if (GetNumFrames() == 1) {
       mMultipartDecodedFrame = mFrameBlender.SwapFrame(GetCurrentFrameIndex(),
                                                        mMultipartDecodedFrame);
@@ -2602,16 +2599,21 @@ void
 RasterImage::RequestScale(imgFrame* aFrame, nsIntSize aSize)
 {
   // We can't store more than one scaled version of an image right now, so if
   // there's more than one instance of this image, bail.
   if (mLockCount != 1) {
     return;
   }
 
+  // We don't scale frames which aren't fully decoded.
+  if (!aFrame->ImageComplete()) {
+    return;
+  }
+
   // We also can't scale if we can't lock the image data for this frame.
   RawAccessFrameRef frameRef = aFrame->RawAccessRef();
   if (!frameRef) {
     return;
   }
 
   // If we have an outstanding request, signal it to stop (if it can).
   if (mScaleRequest) {
--- a/image/src/imgFrame.cpp
+++ b/image/src/imgFrame.cpp
@@ -117,16 +117,17 @@ imgFrame::imgFrame() :
   mTimeout(100),
   mDisposalMethod(0), /* imgIContainer::kDisposeNotSpecified */
   mLockCount(0),
   mBlendMethod(1), /* imgIContainer::kBlendOver */
   mSinglePixel(false),
   mCompositingFailed(false),
   mNonPremult(false),
   mDiscardable(false),
+  mOptimizable(false),
   mInformedDiscardTracker(false)
 {
   static bool hasCheckedOptimize = false;
   if (!hasCheckedOptimize) {
     if (PR_GetEnv("MOZ_DISABLE_IMAGE_OPTIMIZE")) {
       gDisableOptimize = true;
     }
     hasCheckedOptimize = true;
@@ -293,18 +294,20 @@ imgFrame::InitWithDrawable(gfxDrawable* 
   }
 
   return NS_OK;
 }
 
 nsresult imgFrame::Optimize()
 {
   MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(mLockCount == 1,
+             "Should only optimize when holding the lock exclusively");
 
-  if (gDisableOptimize)
+  if (!mOptimizable || gDisableOptimize)
     return NS_OK;
 
   if (mPalettedImageData || mOptSurface || mSinglePixel)
     return NS_OK;
 
   // Don't do single-color opts on non-premult data.
   // Cairo doesn't support non-premult single-colors.
   if (mNonPremult)
@@ -396,16 +399,25 @@ nsresult imgFrame::Optimize()
 #endif
 
   if (mOptSurface) {
     mVBuf = nullptr;
     mVBufPtr = nullptr;
     mImageSurface = nullptr;
   }
 
+#ifdef MOZ_WIDGET_ANDROID
+  // On Android, free mImageSurface unconditionally if we're discardable.
+  // XXX(seth): We'd eventually like to do this on all platforms, but right now
+  // we'd read back from the GPU too much to make it worthwhile.
+  if (mDiscardable) {
+    mImageSurface = nullptr;
+  }
+#endif
+
   return NS_OK;
 }
 
 DrawableFrameRef
 imgFrame::DrawableRef()
 {
   return DrawableFrameRef(this);
 }
@@ -447,17 +459,17 @@ imgFrame::SurfaceForDrawing(bool        
     // Fill 'available' with whatever we've got
     if (mSinglePixel) {
       target->FillRect(ToRect(aRegion.Intersect(available).Rect()),
                        ColorPattern(mSinglePixelColor),
                        DrawOptions(1.0f, CompositionOp::OP_SOURCE));
     } else {
       SurfacePattern pattern(aSurface,
                              ExtendMode::REPEAT,
-                             ToMatrix(aContext->CurrentMatrix()));
+                             Matrix::Translation(mDecoded.x, mDecoded.y));
       target->FillRect(ToRect(aRegion.Intersect(available).Rect()), pattern);
     }
 
     RefPtr<SourceSurface> newsurf = target->Snapshot();
     return SurfaceWithFormat(new gfxSurfaceDrawable(newsurf, ThebesIntSize(size)), target->GetFormat());
   }
 
   // Not tiling, and we have a surface, so we can account for
@@ -714,52 +726,50 @@ nsresult imgFrame::LockImageData()
   mVBufPtr = mVBuf;
   return NS_OK;
 }
 
 nsresult imgFrame::UnlockImageData()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  NS_ABORT_IF_FALSE(mLockCount != 0, "Unlocking an unlocked image!");
-  if (mLockCount == 0) {
+  MOZ_ASSERT(mLockCount > 0, "Unlocking an unlocked image!");
+  if (mLockCount <= 0) {
     return NS_ERROR_FAILURE;
   }
 
+  // If we're about to become unlocked, we don't need to hold on to our data
+  // surface anymore. (But we don't need to do anything for paletted images,
+  // which don't have surfaces.)
+  if (mLockCount == 1 && !mPalettedImageData) {
+    // Convert the data surface to a GPU surface or a single color if possible.
+    // This will also release mImageSurface if possible.
+    Optimize();
+    
+    // Allow the OS to release our data surface.
+    mVBufPtr = nullptr;
+  }
+
   mLockCount--;
 
-  NS_ABORT_IF_FALSE(mLockCount >= 0, "Unbalanced locks and unlocks");
-  if (mLockCount < 0) {
-    return NS_ERROR_FAILURE;
-  }
-
-  // If we are not the last lock, there's nothing to do.
-  if (mLockCount != 0) {
-    return NS_OK;
-  }
-
-  // Paletted images don't have surfaces, so there's nothing to do.
-  if (mPalettedImageData)
-    return NS_OK;
-
-  mVBufPtr = nullptr;
-  if (mVBuf && mDiscardable) {
-    mImageSurface = nullptr;
-  }
-
   return NS_OK;
 }
 
-void imgFrame::SetDiscardable()
+void
+imgFrame::SetDiscardable()
 {
   MOZ_ASSERT(mLockCount, "Expected to be locked when SetDiscardable is called");
-  // Disabled elsewhere due to the cost of calling GetSourceSurfaceForSurface.
-#ifdef MOZ_WIDGET_ANDROID
   mDiscardable = true;
-#endif
+}
+
+void
+imgFrame::SetOptimizable()
+{
+  MOZ_ASSERT(mLockCount, "Expected to be locked when SetOptimizable is called");
+  mOptimizable = true;
 }
 
 TemporaryRef<SourceSurface>
 imgFrame::GetSurface()
 {
   if (mOptSurface) {
     if (mOptSurface->IsValid())
       return mOptSurface;
--- a/image/src/imgFrame.h
+++ b/image/src/imgFrame.h
@@ -69,18 +69,16 @@ public:
    * case.
    */
   nsresult InitWithDrawable(gfxDrawable* aDrawable,
                             const nsIntSize& aSize,
                             const SurfaceFormat aFormat,
                             GraphicsFilter aFilter,
                             uint32_t aImageFlags);
 
-  nsresult Optimize();
-
   DrawableFrameRef DrawableRef();
   RawAccessFrameRef RawAccessRef();
 
   bool Draw(gfxContext* aContext, const ImageRegion& aRegion,
             const nsIntMargin& aPadding, GraphicsFilter aFilter,
             uint32_t aImageFlags);
 
   nsresult ImageUpdated(const nsIntRect &aUpdateRect);
@@ -113,16 +111,17 @@ public:
 
   bool GetCompositingFailed() const;
   void SetCompositingFailed(bool val);
 
   nsresult LockImageData();
   nsresult UnlockImageData();
 
   void SetDiscardable();
+  void SetOptimizable();
 
   TemporaryRef<SourceSurface> GetSurface();
   TemporaryRef<DrawTarget> GetDrawTarget();
 
   Color
   SinglePixelColor()
   {
     return mSinglePixelColor;
@@ -146,16 +145,18 @@ public:
 
     return ((1 << mPaletteDepth) * sizeof(uint32_t));
   }
 
 private: // methods
 
   ~imgFrame();
 
+  nsresult Optimize();
+
   struct SurfaceWithFormat {
     nsRefPtr<gfxDrawable> mDrawable;
     SurfaceFormat mFormat;
     SurfaceWithFormat() {}
     SurfaceWithFormat(gfxDrawable* aDrawable, SurfaceFormat aFormat)
      : mDrawable(aDrawable), mFormat(aFormat) {}
     bool IsValid() { return !!mDrawable; }
   };
@@ -200,16 +201,17 @@ private: // data
 
   SurfaceFormat mFormat;
   uint8_t      mPaletteDepth;
   int8_t       mBlendMethod;
   bool mSinglePixel;
   bool mCompositingFailed;
   bool mNonPremult;
   bool mDiscardable;
+  bool mOptimizable;
 
   /** Have we called DiscardTracker::InformAllocation()? */
   bool mInformedDiscardTracker;
 
   friend class DrawableFrameRef;
   friend class RawAccessFrameRef;
 };
 
--- a/image/test/reftest/gif/reftest.list
+++ b/image/test/reftest/gif/reftest.list
@@ -17,16 +17,19 @@
 random == delaytest.html?transparent-animation.gif transparent-animation-finalframe.gif # incorrect timing dependence (bug 558678)
 
 # test for bug 641198
 skip-if(B2G) random-if(Android) == test_bug641198.html animation2a-finalframe.gif # bug 773482
 
 # Bug 1062886: a gif with a single color and an offset
 == one-color-offset.gif one-color-offset-ref.gif
 
+# Bug 1068230
+== tile-transform.html tile-transform-ref.html
+
 # webcam-simulacrum.mgif is a hand-edited file containing red.gif and blue.gif,
 # concatenated together with the relevant headers for
 # multipart/x-mixed-replace. Specifically, with the headers in
 # webcam-simulacrum.mjpg^headers^, the web browser will get the following:
 #
 # HTTP 200 OK
 # Content-Type: multipart/x-mixed-replace;boundary=BOUNDARYOMG
 # 
new file mode 100644
--- /dev/null
+++ b/image/test/reftest/gif/tile-transform-ref.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1068230
+-->
+<html>
+<head>
+  <title>Intermediate surface should be transformed correctly when tiling an image</title>
+</head>
+<body>
+<button style="margin: 10px; padding: 10px; border: none; background: url('tiletest-ref.png');"></button>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/image/test/reftest/gif/tile-transform.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1068230
+-->
+<html>
+<head>
+  <title>Intermediate surface should be transformed correctly when tiling an image</title>
+</head>
+<body>
+<button style="margin: 10px; padding: 10px; border: none; background: url('tiletest.gif');"></button>
+</body>
+</html>
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..b493899cc87a4e872d18b27927b4e40eb630bab3
GIT binary patch
literal 282
zc%17D@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!5(0ceTp1WFIleOpd|;4x&Y<vs
zLE}1u!3743;|vb_89cT#_^)ROU%`;DfFWZ#Lw-L)MLR=%14DZ`Lw^Co^bCgi@eIo&
z7&Zhj>~Lo|;J|Rgg5iPz!*vaY`w9%t#Tnl7Gkj-fuz09)251*!NswPKgTu2MX+Tbf
zr;B4q#NoHs9GMy!7+5cQx(aEwbiJ$huD*TqUwIdMnBvCC8md~IQAzrR6Eal#gw`JM
zTr}CjJ4U6dbM+AgL$5n3?}Yd}Js)X)oK)d`MyUIU*2jrIymEwoI@V2)f5Hx>>g(jV
We=vT$$h87!CxfS}pUXO@geCxKJz+Zl
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..7a04c9654a671361133f554050efda4b2c12ffc2
GIT binary patch
literal 156
zc${<hbhEHbWMoia_`<-z@tr~71B1kK289O<8rK;NE-+XeXK>ih;IW;-e?3F^3WkIQ
z3>niI^7|Po+8OE_7~0Dj`U@DQXE4l<XILJ=upxk9hdaXo2Zj?C3>OR-u4^#dS73N9
z&hVa};X6A65Gej+0Z|M(3=E7wD9^yaDybmA!5k>TK1qZ7vIW10r*LSb__R#v>y?TO
F)&TJcDXstj
--- a/layout/base/RestyleTracker.cpp
+++ b/layout/base/RestyleTracker.cpp
@@ -44,19 +44,23 @@ CollectLaterSiblings(nsISupports* aEleme
       element->HasFlag(collector->tracker->RestyleBit()) &&
       (aData->mRestyleHint & eRestyle_LaterSiblings)) {
     collector->elements->AppendElement(element);
   }
 
   return PL_DHASH_NEXT;
 }
 
+struct RestyleEnumerateData : RestyleTracker::Hints {
+  nsRefPtr<dom::Element> mElement;
+};
+
 struct RestyleCollector {
   RestyleTracker* tracker;
-  RestyleTracker::RestyleEnumerateData** restyleArrayPtr;
+  RestyleEnumerateData** restyleArrayPtr;
 };
 
 static PLDHashOperator
 CollectRestyles(nsISupports* aElement,
                 nsAutoPtr<RestyleTracker::RestyleData>& aData,
                 void* aRestyleCollector)
 {
   dom::Element* element =
@@ -86,20 +90,18 @@ CollectRestyles(nsISupports* aElement,
                (aData->mChangeHint & nsChangeHint_ReconstructFrame),
                "Why did this not get handled while processing mRestyleRoots?");
 
   // Unset the restyle bits now, so if they get readded later as we
   // process we won't clobber that adding of the bit.
   element->UnsetFlags(collector->tracker->RestyleBit() |
                       collector->tracker->RootBit());
 
-  RestyleTracker::RestyleEnumerateData** restyleArrayPtr =
-    collector->restyleArrayPtr;
-  RestyleTracker::RestyleEnumerateData* currentRestyle =
-    *restyleArrayPtr;
+  RestyleEnumerateData** restyleArrayPtr = collector->restyleArrayPtr;
+  RestyleEnumerateData* currentRestyle = *restyleArrayPtr;
   currentRestyle->mElement = element;
   currentRestyle->mRestyleHint = aData->mRestyleHint;
   currentRestyle->mChangeHint = aData->mChangeHint;
 
   // Increment to the next slot in the array
   *restyleArrayPtr = currentRestyle + 1;
 
   return PL_DHASH_NEXT;
@@ -226,18 +228,16 @@ RestyleTracker::DoProcessRestyles()
       mPendingRestyles.Clear();
 
       for (RestyleEnumerateData* currentRestyle = restylesToProcess;
            currentRestyle != lastRestyle;
            ++currentRestyle) {
         ProcessOneRestyle(currentRestyle->mElement,
                           currentRestyle->mRestyleHint,
                           currentRestyle->mChangeHint);
-
-        MOZ_ASSERT(currentRestyle->mDescendants.IsEmpty());
       }
     }
   }
 
   mRestyleManager->EndProcessingRestyles();
 }
 
 bool
--- a/layout/base/RestyleTracker.h
+++ b/layout/base/RestyleTracker.h
@@ -282,30 +282,32 @@ public:
     return mRestyleBits & ELEMENT_PENDING_RESTYLE_FLAGS;
   }
 
   // Return our ELEMENT_IS_POTENTIAL_(ANIMATION_)RESTYLE_ROOT bit
   Element::FlagsType RootBit() const {
     return mRestyleBits & ~ELEMENT_PENDING_RESTYLE_FLAGS;
   }
 
-  struct RestyleData {
+  struct Hints {
+    nsRestyleHint mRestyleHint;       // What we want to restyle
+    nsChangeHint mChangeHint;         // The minimal change hint for "self"
+  };
+
+  struct RestyleData : Hints {
     RestyleData() {
       mRestyleHint = nsRestyleHint(0);
       mChangeHint = NS_STYLE_HINT_NONE;
     }
 
     RestyleData(nsRestyleHint aRestyleHint, nsChangeHint aChangeHint) {
       mRestyleHint = aRestyleHint;
       mChangeHint = aChangeHint;
     }
 
-    nsRestyleHint mRestyleHint;       // What we want to restyle
-    nsChangeHint mChangeHint;         // The minimal change hint for "self"
-
     // Descendant elements we must check that we ended up restyling, ordered
     // with the same invariant as mRestyleRoots.  The elements here are those
     // that we called AddPendingRestyle for and found the element this is
     // the RestyleData for as its nearest restyle root.
     nsTArray<nsRefPtr<Element>> mDescendants;
   };
 
   /**
@@ -335,20 +337,16 @@ public:
   void AddRestyleRootsIfAwaitingRestyle(
                                   const nsTArray<nsRefPtr<Element>>& aElements);
 
   /**
    * The document we're associated with.
    */
   inline nsIDocument* Document() const;
 
-  struct RestyleEnumerateData : public RestyleData {
-    nsRefPtr<Element> mElement;
-  };
-
 private:
   bool AddPendingRestyleToTable(Element* aElement, nsRestyleHint aRestyleHint,
                                 nsChangeHint aMinChangeHint);
 
   /**
    * Handle a single mPendingRestyles entry.  aRestyleHint must not
    * include eRestyle_LaterSiblings; that needs to be dealt with
    * before calling this function.
@@ -469,17 +467,22 @@ RestyleTracker::AddPendingRestyle(Elemen
       //
       // As with the mRestyleRoots array, mDescendants maintains the
       // invariant that if two elements appear in the array and one
       // is an ancestor of the other, that the ancestor appears after
       // the descendant.
       RestyleData* curData;
       mPendingRestyles.Get(cur, &curData);
       NS_ASSERTION(curData, "expected to find a RestyleData for cur");
-      curData->mDescendants.AppendElement(aElement);
+      // If cur has an eRestyle_ForceDescendants restyle hint, then we
+      // know that we will get to all descendants.  Don't bother
+      // recording the descendant to restyle in that case.
+      if (!(curData->mRestyleHint & eRestyle_ForceDescendants)) {
+        curData->mDescendants.AppendElement(aElement);
+      }
     }
   }
 
   mHaveLaterSiblingRestyles =
     mHaveLaterSiblingRestyles || (aRestyleHint & eRestyle_LaterSiblings) != 0;
   return hadRestyleLaterSiblings;
 }
 
--- a/layout/base/nsDocumentViewer.cpp
+++ b/layout/base/nsDocumentViewer.cpp
@@ -4462,27 +4462,34 @@ nsDocumentViewer::IsInitializedForPrintP
 void
 nsDocumentViewer::InitializeForPrintPreview()
 {
   mInitializedForPrintPreview = true;
 }
 
 void
 nsDocumentViewer::SetPrintPreviewPresentation(nsViewManager* aViewManager,
-                                                nsPresContext* aPresContext,
-                                                nsIPresShell* aPresShell)
+                                              nsPresContext* aPresContext,
+                                              nsIPresShell* aPresShell)
 {
   if (mPresShell) {
     DestroyPresShell();
   }
 
   mWindow = nullptr;
   mViewManager = aViewManager;
   mPresContext = aPresContext;
   mPresShell = aPresShell;
+
+  if (ShouldAttachToTopLevel()) {
+    DetachFromTopLevelWidget();
+    nsView* rootView = mViewManager->GetRootView();
+    rootView->AttachToTopLevelWidget(mParentWidget);
+    mAttachedToParent = true;
+  }
 }
 
 // Fires the "document-shown" event so that interested parties are aware of it.
 NS_IMETHODIMP
 nsDocumentShownDispatcher::Run()
 {
   nsCOMPtr<nsIObserverService> observerService =
     mozilla::services::GetObserverService();
--- a/layout/style/ImportRule.h
+++ b/layout/style/ImportRule.h
@@ -29,17 +29,18 @@ class ImportRule MOZ_FINAL : public Rule
 public:
   ImportRule(nsMediaList* aMedia, const nsString& aURLSpec,
              uint32_t aLineNumber, uint32_t aColumnNumber);
 private:
   // for |Clone|
   ImportRule(const ImportRule& aCopy);
   ~ImportRule();
 public:
-  NS_DECL_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(ImportRule, nsIStyleRule)
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
 
   DECL_STYLE_RULE_INHERIT
 
 #ifdef HAVE_CPP_AMBIGUITY_RESOLVING_USING
   using Rule::GetStyleSheet; // unhide since nsIDOMCSSImportRule has its own GetStyleSheet
 #endif
 
   // nsIStyleRule methods
--- a/layout/style/nsCSSRules.cpp
+++ b/layout/style/nsCSSRules.cpp
@@ -365,21 +365,23 @@ ImportRule::ImportRule(const ImportRule&
 
 ImportRule::~ImportRule()
 {
   if (mChildSheet) {
     mChildSheet->SetOwnerRule(nullptr);
   }
 }
 
-NS_IMPL_ADDREF(ImportRule)
-NS_IMPL_RELEASE(ImportRule)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(ImportRule)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(ImportRule)
+
+NS_IMPL_CYCLE_COLLECTION(ImportRule, mMedia, mChildSheet)
 
 // QueryInterface implementation for ImportRule
-NS_INTERFACE_MAP_BEGIN(ImportRule)
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ImportRule)
   NS_INTERFACE_MAP_ENTRY(nsIStyleRule)
   NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
   NS_INTERFACE_MAP_ENTRY(nsIDOMCSSImportRule)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStyleRule)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSImportRule)
 NS_INTERFACE_MAP_END
 
 IMPL_STYLE_RULE_INHERIT(ImportRule, Rule)
--- a/mozglue/build/WindowsDllBlocklist.cpp
+++ b/mozglue/build/WindowsDllBlocklist.cpp
@@ -151,16 +151,19 @@ static DllBlockInfo sWindowsDllBlocklist
   // Topcrash with V-bates, bug 1002748 and bug 1023239
   { "libinject.dll", UNVERSIONED },
   { "libinject2.dll", 0x537DDC93, DllBlockInfo::USE_TIMESTAMP },
   { "libredir2.dll", 0x5385B7ED, DllBlockInfo::USE_TIMESTAMP },
 
   // Crashes with RoboForm2Go written against old SDK, bug 988311
   { "rf-firefox-22.dll", ALL_VERSIONS },
 
+  // Crashes with DesktopTemperature, bug 1046382
+  { "dtwxsvc.dll", 0x53153234, DllBlockInfo::USE_TIMESTAMP },
+
   { nullptr, 0 }
 };
 
 #ifndef STATUS_DLL_NOT_FOUND
 #define STATUS_DLL_NOT_FOUND ((DWORD)0xC0000135L)
 #endif
 
 // define this for very verbose dll load debug spew
--- a/testing/marionette/client/marionette/tests/unit/test_set_window_size.py
+++ b/testing/marionette/client/marionette/tests/unit/test_set_window_size.py
@@ -17,17 +17,17 @@ class TestSetWindowSize(MarionetteTestCa
         # error is returned if that is the case; therefore if the window is maximized
         # at the start of this test, returning to the original size via set_window_size
         # size will result in error; so reset to original size minus 1 pixel width
         if self.start_size['width'] == self.max_width and self.start_size['height'] == self.max_height:
             self.start_size['width']-=1
         self.marionette.set_window_size(self.start_size['width'], self.start_size['height'])
         super(MarionetteTestCase, self).tearDown()
 
-    def test_set_window_size(self):
+    def test_that_we_can_get_and_set_window_size(self):
         # event handler
         self.marionette.execute_script("""
         window.wrappedJSObject.rcvd_event = false;
         window.onresize = function() {
             window.wrappedJSObject.rcvd_event = true;
         };
         """)
 
@@ -37,14 +37,19 @@ class TestSetWindowSize(MarionetteTestCa
         self.marionette.set_window_size(width, height)
         self.wait_for_condition(lambda m: m.execute_script("return window.wrappedJSObject.rcvd_event;"))
         size = self.marionette.window_size
         self.assertEqual(size['width'], width,
                          "Window width is %s but should be %s" % (size['width'], width))
         self.assertEqual(size['height'], height,
                          "Window height is %s but should be %s" % (size['height'], height))
 
+    def test_that_we_throw_an_error_when_trying_to_set_maximum_size(self):
+        # valid size
+        width = self.max_width - 100
+        height = self.max_height - 100
+        self.marionette.set_window_size(width, height)
         # invalid size (cannot maximize)
         with self.assertRaisesRegexp(MarionetteException, "Invalid requested size"):
             self.marionette.set_window_size(self.max_width, self.max_height)
         size = self.marionette.window_size
         self.assertEqual(size['width'], width, "Window width should not have changed")
         self.assertEqual(size['height'], height, "Window height should not have changed")
--- a/testing/marionette/client/marionette/tests/unit/test_typing.py
+++ b/testing/marionette/client/marionette/tests/unit/test_typing.py
@@ -163,67 +163,75 @@ class TestTyping(MarionetteTestCase):
         self.assertTrue("up: 37" in result.text.strip())
 
         element.send_keys(Keys.ARROW_RIGHT)
         self.assertTrue("down: 39" in result.text.strip())
         self.assertTrue("up: 39" in result.text.strip())
 
         #  And leave no rubbish/printable keys in the "keyReporter"
         self.assertEqual(element.get_attribute("value"), "")
-  
+
+    ''' Disabled. Reenable in Bug 1068728
     def testNumericShiftKeys(self):
         test_html = self.marionette.absolute_url("javascriptPage.html")
         self.marionette.navigate(test_html)
 
         result = self.marionette.find_element("id", "result")
         element = self.marionette.find_element("id", "keyReporter")
         numericShiftsEtc = "~!@#$%^&*()_+{}:i\"<>?|END~"
         element.send_keys(numericShiftsEtc)
         self.assertEqual(element.get_attribute("value"), numericShiftsEtc)
         self.assertTrue(" up: 16" in result.text.strip())
+    '''
 
     def testLowerCaseAlphaKeys(self):
         test_html = self.marionette.absolute_url("javascriptPage.html")
         self.marionette.navigate(test_html)
 
         element = self.marionette.find_element("id", "keyReporter")
         lowerAlphas = "abcdefghijklmnopqrstuvwxyz"
         element.send_keys(lowerAlphas)
         self.assertEqual(element.get_attribute("value"), lowerAlphas)
 
+    ''' Disabled. Reenable in Bug 1068735
     def testUppercaseAlphaKeys(self):
         test_html = self.marionette.absolute_url("javascriptPage.html")
         self.marionette.navigate(test_html)
 
         result = self.marionette.find_element("id", "result")
         element = self.marionette.find_element("id", "keyReporter")
         upperAlphas = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
         element.send_keys(upperAlphas)
         self.assertEqual(element.get_attribute("value"), upperAlphas)
         self.assertTrue(" up: 16" in result.text.strip())
+    '''
 
+    ''' Disabled. Reenable in Bug 1068726
     def testAllPrintableKeys(self):
         test_html = self.marionette.absolute_url("javascriptPage.html")
         self.marionette.navigate(test_html)
 
         result = self.marionette.find_element("id", "result")
         element = self.marionette.find_element("id", "keyReporter")
         allPrintable = "!\"#$%&'()*+,-./0123456789:<=>?@ ABCDEFGHIJKLMNOPQRSTUVWXYZ [\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
         element.send_keys(allPrintable)
 
         self.assertTrue(element.get_attribute("value"), allPrintable)
         self.assertTrue(" up: 16" in result.text.strip())
+    '''
 
+    ''' Disabled. Reenable in Bug 1068733
     def testSpecialSpaceKeys(self):
         test_html = self.marionette.absolute_url("javascriptPage.html")
         self.marionette.navigate(test_html)
 
         element = self.marionette.find_element("id", "keyReporter")
         element.send_keys("abcd" + Keys.SPACE + "fgh" + Keys.SPACE + "ij")
         self.assertEqual(element.get_attribute("value"), "abcd fgh ij")
+    '''
 
     def testShouldTypeAnInteger(self):
         test_html = self.marionette.absolute_url("javascriptPage.html")
         self.marionette.navigate(test_html)
 
         element = self.marionette.find_element("id", "keyReporter")
         element.send_keys(1234)
         self.assertEqual(element.get_attribute("value"), "1234")
--- a/testing/marionette/client/marionette/tests/unit/unit-tests.ini
+++ b/testing/marionette/client/marionette/tests/unit/unit-tests.ini
@@ -37,17 +37,16 @@ b2g = false
 [test_elementState_chrome.py]
 b2g = false
 [test_text.py]
 [test_text_chrome.py]
 disabled = "Bug 896046"
 
 [test_clearing.py]
 [test_typing.py]
-disabled = "Bug 123456"
 
 [test_log.py]
 [test_emulator.py]
 browser = false
 qemu = true
 
 [test_execute_async_script.py]
 [test_execute_script.py]
--- a/testing/marionette/marionette-listener.js
+++ b/testing/marionette/marionette-listener.js
@@ -1585,203 +1585,19 @@ function isElementSelected(msg) {
 
 /**
  * Send keys to element
  */
 function sendKeysToElement(msg) {
   let command_id = msg.json.command_id;
 
   let el = elementManager.getKnownElement(msg.json.id, curFrame);
-  if (checkVisible(el)) {
-    el.focus();
-    var value = msg.json.value.join("");
-    let hasShift = null;
-    let hasCtrl = null;
-    let hasAlt = null;
-    let hasMeta = null;
-    for (var i = 0; i < value.length; i++) {
-      let upper = value.charAt(i).toUpperCase();
-      var keyCode = null;
-      var c = value.charAt(i);
-      switch (c) {
-        case '\uE001':
-          keyCode = "VK_CANCEL";
-          break;
-        case '\uE002':
-          keyCode = "VK_HELP";
-          break;
-        case '\uE003':
-          keyCode = "VK_BACK_SPACE";
-          break;
-        case '\uE004':
-          keyCode = "VK_TAB";
-          break;
-        case '\uE005':
-          keyCode = "VK_CLEAR";
-          break;
-        case '\uE006':
-        case '\uE007':
-          keyCode = "VK_RETURN";
-          break;
-        case '\uE008':
-          keyCode = "VK_SHIFT";
-          hasShift = !hasShift;
-          break;
-        case '\uE009':
-          keyCode = "VK_CONTROL";
-          controlKey = !controlKey;
-          break;
-        case '\uE00A':
-          keyCode = "VK_ALT";
-          altKey = !altKey;
-          break;
-        case '\uE03D':
-          keyCode = "VK_META";
-          metaKey = !metaKey;
-          break;
-        case '\uE00B':
-          keyCode = "VK_PAUSE";
-          break;
-        case '\uE00C':
-          keyCode = "VK_ESCAPE";
-          break;
-        case '\uE00D':
-          keyCode = "VK_Space";  // printable
-          break;
-        case '\uE00E':
-          keyCode = "VK_PAGE_UP";
-          break;
-        case '\uE00F':
-          keyCode = "VK_PAGE_DOWN";
-          break;
-        case '\uE010':
-          keyCode = "VK_END";
-          break;
-        case '\uE011':
-          keyCode = "VK_HOME";
-          break;
-        case '\uE012':
-          keyCode = "VK_LEFT";
-          break;
-        case '\uE013':
-          keyCode = "VK_UP";
-          break;
-        case '\uE014':
-          keyCode = "VK_RIGHT";
-          break;
-        case '\uE015':
-          keyCode = "VK_DOWN";
-          break;
-        case '\uE016':
-          keyCode = "VK_INSERT";
-          break;
-        case '\uE017':
-          keyCode = "VK_DELETE";
-          break;
-        case '\uE018':
-          keyCode = "VK_SEMICOLON";
-          break;
-        case '\uE019':
-          keyCode = "VK_EQUALS";
-          break;
-        case '\uE01A':
-          keyCode = "VK_NUMPAD0";
-          break;
-        case '\uE01B':
-          keyCode = "VK_NUMPAD1";
-          break;
-        case '\uE01C':
-          keyCode = "VK_NUMPAD2";
-          break;
-        case '\uE01D':
-          keyCode = "VK_NUMPAD3";
-          break;
-        case '\uE01E':
-          keyCode = "VK_NUMPAD4";
-          break;
-        case '\uE01F':
-          keyCode = "VK_NUMPAD5";
-          break;
-        case '\uE020':
-          keyCode = "VK_NUMPAD6";
-          break;
-        case '\uE021':
-          keyCode = "VK_NUMPAD7";
-          break;
-        case '\uE022':
-          keyCode = "VK_NUMPAD8";
-          break;
-        case '\uE023':
-          keyCode = "VK_NUMPAD9";
-          break;
-        case '\uE024':
-          keyCode = "VK_MULTIPLY";
-          break;
-        case '\uE025':
-          keyCode = "VK_ADD";
-          break;
-        case '\uE026':
-          keyCode = "VK_SEPARATOR";
-          break;
-        case '\uE027':
-          keyCode = "VK_SUBTRACT";
-          break;
-        case '\uE028':
-          keyCode = "VK_DECIMAL";
-          break;
-        case '\uE029':
-          keyCode = "VK_DIVIDE";
-          break;
-        case '\uE031':
-          keyCode = "VK_F1";
-          break;
-        case '\uE032':
-          keyCode = "VK_F2";
-          break;
-        case '\uE033':
-          keyCode = "VK_F3";
-          break;
-        case '\uE034':
-          keyCode = "VK_F4";
-          break;
-        case '\uE035':
-          keyCode = "VK_F5";
-          break;
-        case '\uE036':
-          keyCode = "VK_F6";
-          break;
-        case '\uE037':
-          keyCode = "VK_F7";
-          break;
-        case '\uE038':
-          keyCode = "VK_F8";
-          break;
-        case '\uE039':
-          keyCode = "VK_F9";
-          break;
-        case '\uE03A':
-          keyCode = "VK_F10";
-          break;
-        case '\uE03B':
-          keyCode = "VK_F11";
-          break;
-        case '\uE03C':
-          keyCode = "VK_F12";
-          break;
-      }
-      hasShift = value.charAt(i) == upper;
-      utils.synthesizeKey(keyCode || value[i],
-                          { shiftKey: hasShift, ctrlKey: hasCtrl, altKey: hasAlt, metaKey: hasMeta },
-                          curFrame);
-    };
-    sendOk(command_id);
-  }
-  else {
-    sendError("Element is not visible", 11, null, command_id)
-  }
+  let keysToSend = msg.json.value;
+
+  utils.sendKeysToElement(curFrame, el, keysToSend, sendOk, sendError, command_id);
 }
 
 /**
  * Get the element's top left-hand corner point.
  */
 function getElementLocation(msg) {
   let command_id = msg.json.command_id;
   try {
--- a/testing/marionette/marionette-sendkeys.js
+++ b/testing/marionette/marionette-sendkeys.js
@@ -11,370 +11,205 @@
  *
  *  Unless required by applicable law or agreed to in writing, software
  *  distributed under the License is distributed on an "AS IS" BASIS,
  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
 
-
-var type = function(doc, element, text, releaseModifiers,
-    opt_keysState) {
-
-  var currentTextLength = element.value ? element.value.length : 0;
-  element.selectionStart = currentTextLength;
-  element.selectionEnd = currentTextLength;
-
-  // For consistency between native and synthesized events, convert common
-  // escape sequences to their Key enum aliases.
-  text = text.replace(new RegExp('\b', 'g'), '\uE003').   // DOM_VK_BACK_SPACE
-      replace(/\t/g, '\uE004').                           // DOM_VK_TAB
-      replace(/(\r\n|\n|\r)/g, '\uE006');                 // DOM_VK_RETURN
-
-  var controlKey = false;
-  var shiftKey = false;
-  var altKey = false;
-  var metaKey = false;
-  if (opt_keysState) {
-    controlKey = opt_keysState.control;
-    shiftKey = opt_keysState.shiftKey;
-    altKey = opt_keysState.alt;
-    metaKey = opt_keysState.meta;
-  }
-
-  shiftCount = 0;
-
-  var upper = text.toUpperCase();
-
-  for (var i = 0; i < text.length; i++) {
-    var c = text.charAt(i);
-
-    // NULL key: reset modifier key states, and continue
+let {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
+let loader = Cc["@mozilla.org/moz/jssubscript-loader;1"]
+               .getService(Ci.mozIJSSubScriptLoader);
 
-    if (c == '\uE000') {
-      if (controlKey) {
-        var kCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_CONTROL;
-        keyEvent(doc, element, "keyup", kCode, 0,
-            controlKey = false, shiftKey, altKey, metaKey, false);
-      }
-
-      if (shiftKey) {
-        var kCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_SHIFT;
-        keyEvent(doc, element, "keyup", kCode, 0,
-            controlKey, shiftKey = false, altKey, metaKey, false);
-      }
-
-      if (altKey) {
-        var kCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_ALT;
-        keyEvent(doc, element, "keyup", kCode, 0,
-            controlKey, shiftKey, altKey = false, metaKey, false);
-      }
-
-      if (metaKey) {
-        var kCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_META;
-        keyEvent(doc, element, "keyup", kCode, 0,
-            controlKey, shiftKey, altKey, metaKey = false, false);
-      }
-
-      continue;
-    }
-
-    // otherwise decode keyCode, charCode, modifiers ...
-
-    var modifierEvent = "";
-    var charCode = 0;
-    var keyCode = 0;
+let utils = {};
+loader.loadSubScript("chrome://marionette/content/EventUtils.js", utils);
+loader.loadSubScript("chrome://marionette/content/ChromeUtils.js", utils);
 
-    if (c == '\uE001') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_CANCEL;
-    } else if (c == '\uE002') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_HELP;
-    } else if (c == '\uE003') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_BACK_SPACE;
-    } else if (c == '\uE004') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_TAB;
-    } else if (c == '\uE005') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_CLEAR;
-    } else if (c == '\uE006' || c == '\uE007') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_RETURN;
-    } else if (c == '\uE008') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_SHIFT;
-      shiftKey = !shiftKey;
-      modifierEvent = shiftKey ? "keydown" : "keyup";
-    } else if (c == '\uE009') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_CONTROL;
-      controlKey = !controlKey;
-      modifierEvent = controlKey ? "keydown" : "keyup";
-    } else if (c == '\uE00A') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_ALT;
-      altKey = !altKey;
-      modifierEvent = altKey ? "keydown" : "keyup";
-    } else if (c == '\uE03D') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_META;
-      metaKey = !metaKey;
-      modifierEvent = metaKey ? "keydown" : "keyup";
-    } else if (c == '\uE00B') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_PAUSE;
-    } else if (c == '\uE00C') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_ESCAPE;
-    } else if (c == '\uE00D') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_SPACE;
-      keyCode = charCode = ' '.charCodeAt(0);  // printable
-    } else if (c == '\uE00E') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_PAGE_UP;
-    } else if (c == '\uE00F') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_PAGE_DOWN;
-    } else if (c == '\uE010') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_END;
-    } else if (c == '\uE011') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_HOME;
-    } else if (c == '\uE012') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_LEFT;
-    } else if (c == '\uE013') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_UP;
-    } else if (c == '\uE014') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_RIGHT;
-    } else if (c == '\uE015') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_DOWN;
-    } else if (c == '\uE016') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_INSERT;
-    } else if (c == '\uE017') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_DELETE;
-    } else if (c == '\uE018') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_SEMICOLON;
-      charCode = ';'.charCodeAt(0);
-    } else if (c == '\uE019') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_EQUALS;
-      charCode = '='.charCodeAt(0);
-    } else if (c == '\uE01A') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_NUMPAD0;
-      charCode = '0'.charCodeAt(0);
-    } else if (c == '\uE01B') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_NUMPAD1;
-      charCode = '1'.charCodeAt(0);
-    } else if (c == '\uE01C') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_NUMPAD2;
-      charCode = '2'.charCodeAt(0);
-    } else if (c == '\uE01D') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_NUMPAD3;
-      charCode = '3'.charCodeAt(0);
-    } else if (c == '\uE01E') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_NUMPAD4;
-      charCode = '4'.charCodeAt(0);
-    } else if (c == '\uE01F') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_NUMPAD5;
-      charCode = '5'.charCodeAt(0);
-    } else if (c == '\uE020') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_NUMPAD6;
-      charCode = '6'.charCodeAt(0);
-    } else if (c == '\uE021') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_NUMPAD7;
-      charCode = '7'.charCodeAt(0);
-    } else if (c == '\uE022') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_NUMPAD8;
-      charCode = '8'.charCodeAt(0);
-    } else if (c == '\uE023') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_NUMPAD9;
-      charCode = '9'.charCodeAt(0);
-    } else if (c == '\uE024') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_MULTIPLY;
-      charCode = '*'.charCodeAt(0);
-    } else if (c == '\uE025') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_ADD;
-      charCode = '+'.charCodeAt(0);
-    } else if (c == '\uE026') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_SEPARATOR;
-      charCode = ','.charCodeAt(0);
-    } else if (c == '\uE027') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_SUBTRACT;
-      charCode = '-'.charCodeAt(0);
-    } else if (c == '\uE028') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_DECIMAL;
-      charCode = '.'.charCodeAt(0);
-    } else if (c == '\uE029') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_DIVIDE;
-      charCode = '/'.charCodeAt(0);
-    } else if (c == '\uE031') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_F1;
-    } else if (c == '\uE032') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_F2;
-    } else if (c == '\uE033') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_F3;
-    } else if (c == '\uE034') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_F4;
-    } else if (c == '\uE035') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_F5;
-    } else if (c == '\uE036') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_F6;
-    } else if (c == '\uE037') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_F7;
-    } else if (c == '\uE038') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_F8;
-    } else if (c == '\uE039') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_F9;
-    } else if (c == '\uE03A') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_F10;
-    } else if (c == '\uE03B') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_F11;
-    } else if (c == '\uE03C') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_F12;
-    } else if (c == ',' || c == '<') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_COMMA;
-      charCode = c.charCodeAt(0);
-    } else if (c == '.' || c == '>') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_PERIOD;
-      charCode = c.charCodeAt(0);
-    } else if (c == '/' || c == '?') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_SLASH;
-      charCode = text.charCodeAt(i);
-    } else if (c == '`' || c == '~') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_BACK_QUOTE;
-      charCode = c.charCodeAt(0);
-    } else if (c == '{' || c == '[') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_OPEN_BRACKET;
-      charCode = c.charCodeAt(0);
-    } else if (c == '\\' || c == '|') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_BACK_SLASH;
-      charCode = c.charCodeAt(0);
-    } else if (c == '}' || c == ']') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_CLOSE_BRACKET;
-      charCode = c.charCodeAt(0);
-    } else if (c == '\'' || c == '"') {
-      keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_QUOTE;
-      charCode = c.charCodeAt(0);
-    } else {
-      keyCode = upper.charCodeAt(i);
-      charCode = text.charCodeAt(i);
+function sendKeysToElement (document, element, keysToSend, successCallback, errorCallback, command_id) {
+  if (checkVisible(element)) {
+    element.focus();
+    var value = keysToSend.join("");
+    let hasShift = null;
+    let hasCtrl = null;
+    let hasAlt = null;
+    let hasMeta = null;
+    for (var i = 0; i < value.length; i++) {
+      let upper = value.charAt(i).toUpperCase();
+      var keyCode = null;
+      var c = value.charAt(i);
+      switch (c) {
+        case '\uE001':
+          keyCode = "VK_CANCEL";
+          break;
+        case '\uE002':
+          keyCode = "VK_HELP";
+          break;
+        case '\uE003':
+          keyCode = "VK_BACK_SPACE";
+          break;
+        case '\uE004':
+          keyCode = "VK_TAB";
+          break;
+        case '\uE005':
+          keyCode = "VK_CLEAR";
+          break;
+        case '\uE006':
+        case '\uE007':
+          keyCode = "VK_RETURN";
+          break;
+        case '\uE008':
+          keyCode = "VK_SHIFT";
+          hasShift = !hasShift;
+          break;
+        case '\uE009':
+          keyCode = "VK_CONTROL";
+          controlKey = !controlKey;
+          break;
+        case '\uE00A':
+          keyCode = "VK_ALT";
+          altKey = !altKey;
+          break;
+        case '\uE03D':
+          keyCode = "VK_META";
+          metaKey = !metaKey;
+          break;
+        case '\uE00B':
+          keyCode = "VK_PAUSE";
+          break;
+        case '\uE00C':
+          keyCode = "VK_ESCAPE";
+          break;
+        case '\uE00D':
+          keyCode = "VK_SPACE";  // printable
+          break;
+        case '\uE00E':
+          keyCode = "VK_PAGE_UP";
+          break;
+        case '\uE00F':
+          keyCode = "VK_PAGE_DOWN";
+          break;
+        case '\uE010':
+          keyCode = "VK_END";
+          break;
+        case '\uE011':
+          keyCode = "VK_HOME";
+          break;
+        case '\uE012':
+          keyCode = "VK_LEFT";
+          break;
+        case '\uE013':
+          keyCode = "VK_UP";
+          break;
+        case '\uE014':
+          keyCode = "VK_RIGHT";
+          break;
+        case '\uE015':
+          keyCode = "VK_DOWN";
+          break;
+        case '\uE016':
+          keyCode = "VK_INSERT";
+          break;
+        case '\uE017':
+          keyCode = "VK_DELETE";
+          break;
+        case '\uE018':
+          keyCode = "VK_SEMICOLON";
+          break;
+        case '\uE019':
+          keyCode = "VK_EQUALS";
+          break;
+        case '\uE01A':
+          keyCode = "VK_NUMPAD0";
+          break;
+        case '\uE01B':
+          keyCode = "VK_NUMPAD1";
+          break;
+        case '\uE01C':
+          keyCode = "VK_NUMPAD2";
+          break;
+        case '\uE01D':
+          keyCode = "VK_NUMPAD3";
+          break;
+        case '\uE01E':
+          keyCode = "VK_NUMPAD4";
+          break;
+        case '\uE01F':
+          keyCode = "VK_NUMPAD5";
+          break;
+        case '\uE020':
+          keyCode = "VK_NUMPAD6";
+          break;
+        case '\uE021':
+          keyCode = "VK_NUMPAD7";
+          break;
+        case '\uE022':
+          keyCode = "VK_NUMPAD8";
+          break;
+        case '\uE023':
+          keyCode = "VK_NUMPAD9";
+          break;
+        case '\uE024':
+          keyCode = "VK_MULTIPLY";
+          break;
+        case '\uE025':
+          keyCode = "VK_ADD";
+          break;
+        case '\uE026':
+          keyCode = "VK_SEPARATOR";
+          break;
+        case '\uE027':
+          keyCode = "VK_SUBTRACT";
+          break;
+        case '\uE028':
+          keyCode = "VK_DECIMAL";
+          break;
+        case '\uE029':
+          keyCode = "VK_DIVIDE";
+          break;
+        case '\uE031':
+          keyCode = "VK_F1";
+          break;
+        case '\uE032':
+          keyCode = "VK_F2";
+          break;
+        case '\uE033':
+          keyCode = "VK_F3";
+          break;
+        case '\uE034':
+          keyCode = "VK_F4";
+          break;
+        case '\uE035':
+          keyCode = "VK_F5";
+          break;
+        case '\uE036':
+          keyCode = "VK_F6";
+          break;
+        case '\uE037':
+          keyCode = "VK_F7";
+          break;
+        case '\uE038':
+          keyCode = "VK_F8";
+          break;
+        case '\uE039':
+          keyCode = "VK_F9";
+          break;
+        case '\uE03A':
+          keyCode = "VK_F10";
+          break;
+        case '\uE03B':
+          keyCode = "VK_F11";
+          break;
+        case '\uE03C':
+          keyCode = "VK_F12";
+          break;
+      }
+      hasShift = value.charAt(i) == upper;
+      utils.synthesizeKey(keyCode || value[i],
+                          { shiftKey: hasShift, ctrlKey: hasCtrl, altKey: hasAlt, metaKey: hasMeta },
+                          document);
     }
-
-    // generate modifier key event if needed, and continue
-
-    if (modifierEvent) {
-      keyEvent(doc, element, modifierEvent, keyCode, 0,
-          controlKey, shiftKey, altKey, metaKey, false);
-      continue;
-    }
-
-    // otherwise, shift down if needed
-
-    var needsShift = false;
-    if (charCode) {
-      needsShift = /[A-Z\!\$\^\*\(\)\+\{\}\:\?\|~@#%&_"<>]/.test(c);
-    }
-
-    if (needsShift && !shiftKey) {
-      var kCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_SHIFT;
-      keyEvent(doc, element, "keydown", kCode, 0,
-          controlKey, true, altKey, metaKey, false);
-      shiftCount += 1;
-    }
-
-    // generate key[down/press/up] for key
-
-    var pressCode = keyCode;
-    if (charCode >= 32 && charCode < 127) {
-      pressCode = 0;
-      if (!needsShift && shiftKey && charCode > 32) {
-        // If typing a lowercase character key and the shiftKey is down, the
-        // charCode should be mapped to the shifted key value. This assumes
-        // a default 104 international keyboard layout.
-        if (charCode >= 97 && charCode <= 122) {
-          charCode = charCode + 65 - 97;  // [a-z] -> [A-Z]
-        } else {
-          var mapFrom = '`1234567890-=[]\\;\',./';
-          var mapTo = '~!@#$%^&*()_+{}|:"<>?';
-
-          var value = String.fromCharCode(charCode).
-              replace(/([\[\\\.])/g, '\\$1');
-          var index = mapFrom.search(value);
-          if (index >= 0) {
-            charCode = mapTo.charCodeAt(index);
-          }
-        }
-      }
-    }
-
-    var accepted =
-        keyEvent(doc, element, "keydown", keyCode, 0,
-            controlKey, needsShift || shiftKey, altKey, metaKey, false);
-
-    keyEvent(doc, element, "keypress", pressCode, charCode,
-        controlKey, needsShift || shiftKey, altKey, metaKey, !accepted);
-
-    keyEvent(doc, element, "keyup", keyCode, 0,
-        controlKey, needsShift || shiftKey, altKey, metaKey, false);
-
-    // shift up if needed
-
-    if (needsShift && !shiftKey) {
-      var kCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_SHIFT;
-      keyEvent(doc, element, "keyup", kCode, 0,
-          controlKey, false, altKey, metaKey, false);
-    }
+    successCallback(command_id);
   }
-
-  // exit cleanup: keyup active modifier keys
-
-  if (controlKey && releaseModifiers) {
-    var kCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_CONTROL;
-    keyEvent(doc, element, "keyup", kCode, 0,
-        controlKey = false, shiftKey, altKey, metaKey, false);
-  }
-
-  if (shiftKey && releaseModifiers) {
-    var kCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_SHIFT;
-    keyEvent(doc, element, "keyup", kCode, 0,
-        controlKey, shiftKey = false, altKey, metaKey, false);
-  }
-
-  if (altKey && releaseModifiers) {
-    var kCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_ALT;
-    keyEvent(doc, element, "keyup", kCode, 0,
-        controlKey, shiftKey, altKey = false, metaKey, false);
-  }
-
-  if (metaKey && releaseModifiers) {
-    var kCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_META;
-    keyEvent(doc, element, "keyup", kCode, 0,
-        controlKey, shiftKey, altKey, metaKey = false, false);
+  else {
+    errorCallback("Element is not visible", 11, null, command_id);
   }
-
-  return {
-    shiftKey: shiftKey,
-    alt: altKey,
-    meta: metaKey,
-    control: controlKey
-  };
-};
-
-
-var keyEvent = function(doc, element, type, keyCode, charCode,
-                          controlState, shiftState, altState, metaState,
-                          shouldPreventDefault) {
-  var preventDefault = shouldPreventDefault == undefined ? false
-      : shouldPreventDefault;
-
-  var keyboardEvent = doc.createEvent("KeyEvents");
-  var currentView = doc.defaultView;
-
-  keyboardEvent.initKeyEvent(
-      type, //  in DOMString typeArg,
-      true, //  in boolean canBubbleArg
-      true, //  in boolean cancelableArg
-      currentView, //  in nsIDOMAbstractView viewArg
-      controlState, //  in boolean ctrlKeyArg
-      altState, //  in boolean altKeyArg
-      shiftState, //  in boolean shiftKeyArg
-      metaState, //  in boolean metaKeyArg
-      keyCode, //  in unsigned long keyCodeArg
-      charCode);    //  in unsigned long charCodeArg
-
-  if (preventDefault) {
-    keyboardEvent.preventDefault();
-  }
-
-  var win = doc.defaultView;
-  var domUtil = win.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
-                .getInterface(Components.interfaces.nsIDOMWindowUtils);
-  return domUtil.dispatchDOMEventViaPresShell(element, keyboardEvent, true);
-};
-
+};
\ No newline at end of file
--- a/testing/marionette/marionette-server.js
+++ b/testing/marionette/marionette-server.js
@@ -2415,18 +2415,18 @@ MarionetteServerConnection.prototype = {
    * bars, title bars, etc.
    *
    * An error will be returned if the requested window size would result
    * in the window being in the maximized state.
    */
   setWindowSize: function MDA_setWindowSize(aRequest) {
     this.command_id = this.getCommandId();
 
-    if (appName == "B2G") {
-      this.sendError("Not supported on B2G", 405, null, this.command_id);
+    if (appName !== "Firefox") {
+      this.sendError("Not supported on mobile", 405, null, this.command_id);
       return;
     }
 
     try {
       var width = parseInt(aRequest.parameters.width);
       var height = parseInt(aRequest.parameters.height);
     }
     catch(e) {
--- a/toolkit/components/aboutmemory/content/aboutMemory.js
+++ b/toolkit/components/aboutmemory/content/aboutMemory.js
@@ -816,30 +816,51 @@ function makeDReportMap(aJSONReports)
 
     assert(jr.process     !== undefined, "Missing process");
     assert(jr.path        !== undefined, "Missing path");
     assert(jr.kind        !== undefined, "Missing kind");
     assert(jr.units       !== undefined, "Missing units");
     assert(jr.amount      !== undefined, "Missing amount");
     assert(jr.description !== undefined, "Missing description");
 
-    // Strip out some non-deterministic stuff that prevents clean diffs --
-    // e.g. PIDs, addresses, null principal UUIDs. (Note that we don't strip
-    // out all UUIDs because some of them -- such as those used by add-ons --
-    // are deterministic.)
+    // Strip out some non-deterministic stuff that prevents clean diffs.
+    // Ideally the memory reports themselves would contain information about
+    // which parts of the the process and path need to be stripped -- saving us
+    // from hardwiring knowledge of specific reporters here -- but we have no
+    // mechanism for that. (Any future redesign of how memory reporters work
+    // should include such a mechanism.)
+
+    // Strip PIDs:
+    // - pid 123
+    // - pid=123
     let pidRegex = /pid([ =])\d+/g;
     let pidSubst = "pid$1NNN";
-    let strippedProcess = jr.process.replace(pidRegex, pidSubst);
-    let strippedPath = jr.path.replace(/0x[0-9A-Fa-f]+/g, "0xNNN");
-    strippedPath = strippedPath.replace(pidRegex, pidSubst);
-    strippedPath = strippedPath.replace(
+    let process = jr.process.replace(pidRegex, pidSubst);
+    let path = jr.path.replace(pidRegex, pidSubst);
+
+    // Strip addresses:
+    // - .../js-zone(0x12345678)/...
+    // - .../zone(0x12345678)/...
+    // - .../worker(<URL>, 0x12345678)/...
+    path = path.replace(/zone\(0x[0-9A-Fa-f]+\)\//, "zone(0xNNN)/");
+    path = path.replace(/\/worker\((.+), 0x[0-9A-Fa-f]+\)\//,
+                        "/worker($1, 0xNNN)/");
+
+    // Strip top window IDs:
+    // - explicit/window-objects/top(<URL>, id=123)/...
+    path = path.replace(/^(explicit\/window-objects\/top\(.*, id=)\d+\)/,
+                        "$1NNN)");
+
+    // Strip null principal UUIDs (but not other UUIDs, because they may be
+    // deterministic, such as those used by add-ons).
+    path = path.replace(
       /moz-nullprincipal:{........-....-....-....-............}/g,
       "moz-nullprincipal:{NNNNNNNN-NNNN-NNNN-NNNN-NNNNNNNNNNNN}");
-    let processPath = strippedProcess + kProcessPathSep + strippedPath;
 
+    let processPath = process + kProcessPathSep + path;
     let rOld = dreportMap[processPath];
     if (rOld === undefined) {
       dreportMap[processPath] =
         new DReport(jr.kind, jr.units, jr.amount, jr.description, 1, undefined);
     } else {
       rOld.merge(jr);
     }
   }
--- a/toolkit/components/aboutmemory/tests/memory-reports-diff1.json
+++ b/toolkit/components/aboutmemory/tests/memory-reports-diff1.json
@@ -15,17 +15,23 @@
 
     {"process": "P", "path": "a/b", "kind": 2, "units": 0, "amount": 1000000, "description": "Desc."},
     {"process": "P", "path": "a/c/d", "kind": 2, "units": 0, "amount": 2000000, "description": "Desc."},
     {"process": "P", "path": "a/c/e", "kind": 2, "units": 0, "amount": 2000000, "description": "Desc."},
     {"process": "P", "path": "a/c/f", "kind": 2, "units": 0, "amount": 3000000, "description": "Desc."},
     {"process": "P", "path": "a/c/g", "kind": 2, "units": 0, "amount": 3000000, "description": "Desc."},
     {"process": "P", "path": "a/h", "kind": 2, "units": 0, "amount": 1000, "description": "Desc."},
 
-    {"process": "P2 (pid 22)", "path": "z-moz-nullprincipal:{85e250f3-57ae-46c4-a11e-4176dd39d9c5} 0x1234-blah(0x2345) pid 123 pid=45678", "kind": 2, "units": 0, "amount": 33, "description": "Desc."},
+    {"process": "P2 (pid 22)", "path": "p1 (pid 123)", "kind": 2, "units": 0, "amount": 33, "description": "Desc."},
+    {"process": "P2 (pid 22)", "path": "p2 (blah, pid=123)", "kind": 2, "units": 0, "amount": 33, "description": "Desc."},
+    {"process": "P2 (pid 22)", "path": "p3/zone(0x1234)/p3", "kind": 2, "units": 0, "amount": 33, "description": "Desc."},
+    {"process": "P2 (pid 22)", "path": "p4/js-zone(0x1234)/p4", "kind": 2, "units": 0, "amount": 33, "description": "Desc."},
+    {"process": "P2 (pid 22)", "path": "p5/worker(foo.com, 0x1234)/p5", "kind": 2, "units": 0, "amount": 33, "description": "Desc."},
+    {"process": "P2 (pid 22)", "path": "explicit/window-objects/top(bar.com, id=123)/...", "kind": 0, "units": 0, "amount": 33, "description": "Desc."},
+    {"process": "P2 (pid 22)", "path": "p6/z-moz-nullprincipal:{85e250f3-57ae-46c4-a11e-4176dd39d9c5}/p6", "kind": 2, "units": 0, "amount": 33, "description": "Desc."},
 
     {"process": "P3", "path": "p3", "kind": 2, "units": 0, "amount": 55, "description": "Desc."},
 
     {"process": "P5", "path": "p5", "kind": 2, "units": 0, "amount": 0, "description": "Desc."},
 
     {"process": "P7", "path": "p7", "kind": 2, "units": 0, "amount": 5, "description": "Desc."},
 
     {"process": "P8", "path": "p8/a/b/c/d", "kind": 2, "units": 0, "amount": 3, "description": "Desc."},
--- a/toolkit/components/aboutmemory/tests/memory-reports-diff2.json
+++ b/toolkit/components/aboutmemory/tests/memory-reports-diff2.json
@@ -16,17 +16,23 @@
 
     {"process": "P", "path": "a/b", "kind": 2, "units": 0, "amount": 2000000, "description": "Desc."},
     {"process": "P", "path": "a/c/d", "kind": 2, "units": 0, "amount": 2998000, "description": "Desc."},
     {"process": "P", "path": "a/c/e", "kind": 2, "units": 0, "amount": 1001000, "description": "Desc."},
     {"process": "P", "path": "a/c/f", "kind": 2, "units": 0, "amount": 3001000, "description": "Desc."},
     {"process": "P", "path": "a/c/g", "kind": 2, "units": 0, "amount": 3001000, "description": "Desc."},
     {"process": "P", "path": "a/h", "kind": 2, "units": 0, "amount": 2000, "description": "Desc."},
 
-    {"process": "P2 (pid 33)", "path": "z-moz-nullprincipal:{161effaa-c1f7-4010-a08e-e7c9aea01aed} 0x5678-blah(0x6789) pid 456 pid=7890", "kind": 2, "units": 0, "amount": 44, "description": "Desc."},
+    {"process": "P2 (pid 22)", "path": "p1 (pid 456)", "kind": 2, "units": 0, "amount": 44, "description": "Desc."},
+    {"process": "P2 (pid 22)", "path": "p2 (blah, pid=456)", "kind": 2, "units": 0, "amount": 44, "description": "Desc."},
+    {"process": "P2 (pid 22)", "path": "p3/zone(0x5678)/p3", "kind": 2, "units": 0, "amount": 44, "description": "Desc."},
+    {"process": "P2 (pid 22)", "path": "p4/js-zone(0x5678)/p4", "kind": 2, "units": 0, "amount": 44, "description": "Desc."},
+    {"process": "P2 (pid 22)", "path": "p5/worker(foo.com, 0x5678)/p5", "kind": 2, "units": 0, "amount": 44, "description": "Desc."},
+    {"process": "P2 (pid 22)", "path": "explicit/window-objects/top(bar.com, id=456)/...", "kind": 0, "units": 0, "amount": 44, "description": "Desc."},
+    {"process": "P2 (pid 22)", "path": "p6/z-moz-nullprincipal:{161effaa-c1f7-4010-a08e-e7c9aea01aed}/p6", "kind": 2, "units": 0, "amount": 44, "description": "Desc."},
 
     {"process": "P4", "path": "p4", "kind": 2, "units": 0, "amount": 66, "description": "Desc."},
 
     {"process": "P6", "path": "p6", "kind": 2, "units": 0, "amount": 0, "description": "Desc."},
 
     {"process": "P7", "path": "p7/b", "kind": 2, "units": 0, "amount": 3, "description": "Desc."},
     {"process": "P7", "path": "p7/c", "kind": 2, "units": 0, "amount": 4, "description": "Desc."},
 
--- a/toolkit/components/aboutmemory/tests/test_aboutmemory3.xul
+++ b/toolkit/components/aboutmemory/tests/test_aboutmemory3.xul
@@ -300,19 +300,39 @@ 0.96 MB (100.0%) -- a\n\
 │  └──0.00 MB (00.20%) ++ (2 tiny)\n\
 └──0.00 MB (00.10%) ── h\n\
 \n\
  0.00 MB ── canvas-2d-pixel-bytes [2] [+]\n\
 -0.00 MB ── foobar [-]\n\
 \n\
 End of P\n\
 P2 (pid NNN)\n\
+\n\
+WARNING: the 'heap-allocated' memory reporter does not work for this platform and/or configuration. This means that 'heap-unclassified' is not shown and the 'explicit' tree shows less memory than it should.\n\
+Explicit Allocations\n\
+\n\
+0.00 MB (100.0%) -- explicit\n\
+└──0.00 MB (100.0%) ── window-objects/top(bar.com, id=NNN)/...\n\
+\n\
 Other Measurements\n\
 \n\
-0.00 MB ── z-moz-nullprincipal:{NNNNNNNN-NNNN-NNNN-NNNN-NNNNNNNNNNNN} 0xNNN-blah(0xNNN) pid NNN pid=NNN\n\
+0.00 MB (100.0%) -- p3\n\
+└──0.00 MB (100.0%) ── zone(0xNNN)/p3\n\
+\n\
+0.00 MB (100.0%) -- p4\n\
+└──0.00 MB (100.0%) ── js-zone(0xNNN)/p4\n\
+\n\
+0.00 MB (100.0%) -- p5\n\
+└──0.00 MB (100.0%) ── worker(foo.com, 0xNNN)/p5\n\
+\n\
+0.00 MB (100.0%) -- p6\n\
+└──0.00 MB (100.0%) ── z-moz-nullprincipal:{NNNNNNNN-NNNN-NNNN-NNNN-NNNNNNNNNNNN}/p6\n\
+\n\
+0.00 MB ── p1 (pid NNN)\n\
+0.00 MB ── p2 (blah, pid=NNN)\n\
 \n\
 End of P2 (pid NNN)\n\
 P3\n\
 Other Measurements\n\
 \n\
 -0.00 MB ── p3 [-]\n\
 \n\
 End of P3\n\
@@ -375,19 +395,39 @@ 1,002,000 B (100.0%) -- a\n\
 │      └──1,000 B (00.10%) ── g\n\
 └──────1,000 B (00.10%) ── h\n\
 \n\
 3,000 B ── canvas-2d-pixel-bytes [2] [+]\n\
  -100 B ── foobar [-]\n\
 \n\
 End of P\n\
 P2 (pid NNN)\n\
+\n\
+WARNING: the 'heap-allocated' memory reporter does not work for this platform and/or configuration. This means that 'heap-unclassified' is not shown and the 'explicit' tree shows less memory than it should.\n\
+Explicit Allocations\n\
+\n\
+11 B (100.0%) -- explicit\n\
+└──11 B (100.0%) ── window-objects/top(bar.com, id=NNN)/...\n\
+\n\
 Other Measurements\n\
 \n\
-11 B ── z-moz-nullprincipal:{NNNNNNNN-NNNN-NNNN-NNNN-NNNNNNNNNNNN} 0xNNN-blah(0xNNN) pid NNN pid=NNN\n\
+11 B (100.0%) -- p3\n\
+└──11 B (100.0%) ── zone(0xNNN)/p3\n\
+\n\
+11 B (100.0%) -- p4\n\
+└──11 B (100.0%) ── js-zone(0xNNN)/p4\n\
+\n\
+11 B (100.0%) -- p5\n\
+└──11 B (100.0%) ── worker(foo.com, 0xNNN)/p5\n\
+\n\
+11 B (100.0%) -- p6\n\
+└──11 B (100.0%) ── z-moz-nullprincipal:{NNNNNNNN-NNNN-NNNN-NNNN-NNNNNNNNNNNN}/p6\n\
+\n\
+11 B ── p1 (pid NNN)\n\
+11 B ── p2 (blah, pid=NNN)\n\
 \n\
 End of P2 (pid NNN)\n\
 P3\n\
 Other Measurements\n\
 \n\
 -55 B ── p3 [-]\n\
 \n\
 End of P3\n\
--- a/xpcom/base/SystemMemoryReporter.cpp
+++ b/xpcom/base/SystemMemoryReporter.cpp
@@ -538,16 +538,18 @@ private:
         }
 
       } else {
         aName.AppendLiteral("other-files");
         if (EndsWithLiteral(basename, ".xpi")) {
           aName.AppendLiteral("/extensions");
         } else if (dirname.Find("/fontconfig") != -1) {
           aName.AppendLiteral("/fontconfig");
+        } else {
+          aName.AppendLiteral("/misc");
         }
         aTag = aName;
         aName.Append('/');
       }
 
       aName.Append(basename);
       aDesc.Append(absPath);
     } else {