Merge m-c to fx-team, a=merge CLOSED TREE
authorWes Kocher <wkocher@mozilla.com>
Tue, 20 Oct 2015 15:30:21 -0700
changeset 303788 78dec2028dd2565cd386c6b1f57921060f300a67
parent 303787 545fdb4211b7ffbdcf196ae5ee3c30bf6c166aae (current diff)
parent 303764 f397034950304b845175f8dab8fccbdd0e8bf995 (diff)
child 303789 32ad1a5a53f5429d925f53d1755231dcfde57fcb
push id1001
push userraliiev@mozilla.com
push dateMon, 18 Jan 2016 19:06:03 +0000
treeherdermozilla-release@8b89261f3ac4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone44.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge m-c to fx-team, a=merge CLOSED TREE
testing/web-platform/meta/service-workers/cache-storage/serviceworker/cache-add.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/serviceworker/cache-delete.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/serviceworker/cache-match.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/serviceworker/cache-put.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/serviceworker/cache-storage-keys.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/serviceworker/cache-storage-match.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/serviceworker/cache-storage.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/window/cache-match.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/window/cache-put.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/window/cache-storage-match.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/worker/cache-add.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/worker/cache-delete.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/worker/cache-match.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/worker/cache-put.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/worker/cache-storage-keys.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/worker/cache-storage-match.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/worker/cache-storage.https.html.ini
testing/web-platform/mozilla/meta/service-workers/service-worker/fetch-request-xhr.https.html.ini
testing/web-platform/mozilla/meta/service-workers/service-worker/request-end-to-end.https.html.ini
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -948,17 +948,17 @@ pref("dom.mozInputMethod.enabled", true)
 // Absolute path to the devtool unix domain socket file used
 // to communicate with a usb cable via adb forward
 pref("devtools.debugger.unix-domain-socket", "/data/local/debugger-socket");
 
 // enable Skia/GL (OpenGL-accelerated 2D drawing) for large enough 2d canvases,
 // falling back to Skia/software for smaller canvases
 #ifdef MOZ_WIDGET_GONK
 pref("gfx.canvas.azure.backends", "skia");
-pref("gfx.canvas.azure.accelerated", false);
+pref("gfx.canvas.azure.accelerated", true);
 #endif
 
 // Turn on dynamic cache size for Skia
 pref("gfx.canvas.skiagl.dynamic-cache", true);
 
 // Limit skia to canvases the size of the device screen or smaller
 pref("gfx.canvas.max-size-for-skia-gl", -1);
 
--- a/b2g/config/aries/sources.xml
+++ b/b2g/config/aries/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="3491a49da4d4ce45b8a682e95d0ce68892c2b8ea"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="11eb5d4cb2675d359d277ae17772bc75f7ccedbc"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c1bbb66f52f9e2d76ce97e7b3aa0cb29957cd7d8"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="31a7849fe9a8b743d6f5e5facc212f0ef9d57499"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="48d8c7c950745f1b166b42125e6f0d3293d71636"/>
--- a/b2g/config/dolphin/sources.xml
+++ b/b2g/config/dolphin/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="3491a49da4d4ce45b8a682e95d0ce68892c2b8ea"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="11eb5d4cb2675d359d277ae17772bc75f7ccedbc"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c1bbb66f52f9e2d76ce97e7b3aa0cb29957cd7d8"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="31a7849fe9a8b743d6f5e5facc212f0ef9d57499"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="48d8c7c950745f1b166b42125e6f0d3293d71636"/>
--- a/b2g/config/emulator-ics/sources.xml
+++ b/b2g/config/emulator-ics/sources.xml
@@ -14,17 +14,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="1b0db93fb6b870b03467aff50d6419771ba0d88c">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="3491a49da4d4ce45b8a682e95d0ce68892c2b8ea"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="11eb5d4cb2675d359d277ae17772bc75f7ccedbc"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c1bbb66f52f9e2d76ce97e7b3aa0cb29957cd7d8"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="4ace9aaee0e048dfda11bb787646c59982a3dc80"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="c72c9278ddc2f442d193474993d36e7f2cfb08c4"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="31a7849fe9a8b743d6f5e5facc212f0ef9d57499"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="34ea6163f9f0e0122fb0bb03607eccdca31ced7a"/>
   <project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
   <!-- Stock Android things -->
--- a/b2g/config/emulator-jb/sources.xml
+++ b/b2g/config/emulator-jb/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="660169a3d7e034a892359e39135e8c2785a6ad6f">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="3491a49da4d4ce45b8a682e95d0ce68892c2b8ea"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="11eb5d4cb2675d359d277ae17772bc75f7ccedbc"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c1bbb66f52f9e2d76ce97e7b3aa0cb29957cd7d8"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="31a7849fe9a8b743d6f5e5facc212f0ef9d57499"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="0c28789b9957913be975eb002a22323f93585d4c"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="48d8c7c950745f1b166b42125e6f0d3293d71636"/>
   <project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
--- a/b2g/config/emulator-kk/sources.xml
+++ b/b2g/config/emulator-kk/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="3491a49da4d4ce45b8a682e95d0ce68892c2b8ea"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="11eb5d4cb2675d359d277ae17772bc75f7ccedbc"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c1bbb66f52f9e2d76ce97e7b3aa0cb29957cd7d8"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="31a7849fe9a8b743d6f5e5facc212f0ef9d57499"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="48d8c7c950745f1b166b42125e6f0d3293d71636"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="0c28789b9957913be975eb002a22323f93585d4c"/>
--- a/b2g/config/emulator-l/sources.xml
+++ b/b2g/config/emulator-l/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="c9d4fe680662ee44a4bdea42ae00366f5df399cf">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="3491a49da4d4ce45b8a682e95d0ce68892c2b8ea"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="11eb5d4cb2675d359d277ae17772bc75f7ccedbc"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c1bbb66f52f9e2d76ce97e7b3aa0cb29957cd7d8"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="31a7849fe9a8b743d6f5e5facc212f0ef9d57499"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="48d8c7c950745f1b166b42125e6f0d3293d71636"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="0c28789b9957913be975eb002a22323f93585d4c"/>
--- a/b2g/config/emulator/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -14,17 +14,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="1b0db93fb6b870b03467aff50d6419771ba0d88c">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="3491a49da4d4ce45b8a682e95d0ce68892c2b8ea"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="11eb5d4cb2675d359d277ae17772bc75f7ccedbc"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c1bbb66f52f9e2d76ce97e7b3aa0cb29957cd7d8"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="4ace9aaee0e048dfda11bb787646c59982a3dc80"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="c72c9278ddc2f442d193474993d36e7f2cfb08c4"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="31a7849fe9a8b743d6f5e5facc212f0ef9d57499"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="34ea6163f9f0e0122fb0bb03607eccdca31ced7a"/>
   <project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
   <!-- Stock Android things -->
--- a/b2g/config/flame-kk/sources.xml
+++ b/b2g/config/flame-kk/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="3491a49da4d4ce45b8a682e95d0ce68892c2b8ea"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="11eb5d4cb2675d359d277ae17772bc75f7ccedbc"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c1bbb66f52f9e2d76ce97e7b3aa0cb29957cd7d8"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="31a7849fe9a8b743d6f5e5facc212f0ef9d57499"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="48d8c7c950745f1b166b42125e6f0d3293d71636"/>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,9 +1,9 @@
 {
     "git": {
-        "git_revision": "3491a49da4d4ce45b8a682e95d0ce68892c2b8ea", 
+        "git_revision": "11eb5d4cb2675d359d277ae17772bc75f7ccedbc", 
         "remote": "https://git.mozilla.org/releases/gaia.git", 
         "branch": ""
     }, 
-    "revision": "6458b8861154bf7e28971ce85d49e404ac96da29", 
+    "revision": "6575311e4b9daab959d80f17cf77bea4c91660a6", 
     "repo_path": "integration/gaia-central"
 }
--- a/b2g/config/nexus-4-kk/sources.xml
+++ b/b2g/config/nexus-4-kk/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="3491a49da4d4ce45b8a682e95d0ce68892c2b8ea"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="11eb5d4cb2675d359d277ae17772bc75f7ccedbc"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c1bbb66f52f9e2d76ce97e7b3aa0cb29957cd7d8"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="31a7849fe9a8b743d6f5e5facc212f0ef9d57499"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="48d8c7c950745f1b166b42125e6f0d3293d71636"/>
--- a/b2g/config/nexus-4/sources.xml
+++ b/b2g/config/nexus-4/sources.xml
@@ -13,17 +13,17 @@
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="660169a3d7e034a892359e39135e8c2785a6ad6f">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="3491a49da4d4ce45b8a682e95d0ce68892c2b8ea"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="11eb5d4cb2675d359d277ae17772bc75f7ccedbc"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c1bbb66f52f9e2d76ce97e7b3aa0cb29957cd7d8"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="31a7849fe9a8b743d6f5e5facc212f0ef9d57499"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="0c28789b9957913be975eb002a22323f93585d4c"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="48d8c7c950745f1b166b42125e6f0d3293d71636"/>
   <project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
--- a/b2g/config/nexus-5-l/sources.xml
+++ b/b2g/config/nexus-5-l/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="c9d4fe680662ee44a4bdea42ae00366f5df399cf">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="3491a49da4d4ce45b8a682e95d0ce68892c2b8ea"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="11eb5d4cb2675d359d277ae17772bc75f7ccedbc"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c1bbb66f52f9e2d76ce97e7b3aa0cb29957cd7d8"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="31a7849fe9a8b743d6f5e5facc212f0ef9d57499"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="48d8c7c950745f1b166b42125e6f0d3293d71636"/>
--- a/b2g/installer/package-manifest.in
+++ b/b2g/installer/package-manifest.in
@@ -795,16 +795,28 @@
 @RESPATH@/res/table-add-row-before-hover.gif
 @RESPATH@/res/table-add-row-before.gif
 @RESPATH@/res/table-remove-column-active.gif
 @RESPATH@/res/table-remove-column-hover.gif
 @RESPATH@/res/table-remove-column.gif
 @RESPATH@/res/table-remove-row-active.gif
 @RESPATH@/res/table-remove-row-hover.gif
 @RESPATH@/res/table-remove-row.gif
+@RESPATH@/res/accessiblecaret.png
+@RESPATH@/res/accessiblecaret@1.5x.png
+@RESPATH@/res/accessiblecaret@2.25x.png
+@RESPATH@/res/accessiblecaret@2x.png
+@RESPATH@/res/accessiblecaret_tilt_left.png
+@RESPATH@/res/accessiblecaret_tilt_left@1.5x.png
+@RESPATH@/res/accessiblecaret_tilt_left@2.25x.png
+@RESPATH@/res/accessiblecaret_tilt_left@2x.png
+@RESPATH@/res/accessiblecaret_tilt_right.png
+@RESPATH@/res/accessiblecaret_tilt_right@1.5x.png
+@RESPATH@/res/accessiblecaret_tilt_right@2.25x.png
+@RESPATH@/res/accessiblecaret_tilt_right@2x.png
 @RESPATH@/res/text_caret.png
 @RESPATH@/res/text_caret@1.5x.png
 @RESPATH@/res/text_caret@2.25x.png
 @RESPATH@/res/text_caret@2x.png
 @RESPATH@/res/text_caret_tilt_left.png
 @RESPATH@/res/text_caret_tilt_left@1.5x.png
 @RESPATH@/res/text_caret_tilt_left@2.25x.png
 @RESPATH@/res/text_caret_tilt_left@2x.png
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -744,16 +744,28 @@
 @RESPATH@/res/table-add-row-before-hover.gif
 @RESPATH@/res/table-add-row-before.gif
 @RESPATH@/res/table-remove-column-active.gif
 @RESPATH@/res/table-remove-column-hover.gif
 @RESPATH@/res/table-remove-column.gif
 @RESPATH@/res/table-remove-row-active.gif
 @RESPATH@/res/table-remove-row-hover.gif
 @RESPATH@/res/table-remove-row.gif
+@RESPATH@/res/accessiblecaret.png
+@RESPATH@/res/accessiblecaret@1.5x.png
+@RESPATH@/res/accessiblecaret@2.25x.png
+@RESPATH@/res/accessiblecaret@2x.png
+@RESPATH@/res/accessiblecaret_tilt_left.png
+@RESPATH@/res/accessiblecaret_tilt_left@1.5x.png
+@RESPATH@/res/accessiblecaret_tilt_left@2.25x.png
+@RESPATH@/res/accessiblecaret_tilt_left@2x.png
+@RESPATH@/res/accessiblecaret_tilt_right.png
+@RESPATH@/res/accessiblecaret_tilt_right@1.5x.png
+@RESPATH@/res/accessiblecaret_tilt_right@2.25x.png
+@RESPATH@/res/accessiblecaret_tilt_right@2x.png
 @RESPATH@/res/text_caret.png
 @RESPATH@/res/text_caret@1.5x.png
 @RESPATH@/res/text_caret@2.25x.png
 @RESPATH@/res/text_caret@2x.png
 @RESPATH@/res/text_caret_tilt_left.png
 @RESPATH@/res/text_caret_tilt_left@1.5x.png
 @RESPATH@/res/text_caret_tilt_left@2.25x.png
 @RESPATH@/res/text_caret_tilt_left@2x.png
--- a/build/autoconf/icu.m4
+++ b/build/autoconf/icu.m4
@@ -94,23 +94,17 @@ if test -n "$USE_ICU"; then
         case "$OS_TARGET" in
             WINNT)
                 ICU_LIB_NAMES="icuin icuuc icudt"
                 MOZ_ICU_DBG_SUFFIX=
                 if test -n "$MOZ_DEBUG" -a -z "$MOZ_NO_DEBUG_RTL"; then
                     MOZ_ICU_DBG_SUFFIX=d
                 fi
                 ;;
-            Android)
-                if test -z "$gonkdir"; then
-                    AC_MSG_ERROR([ECMAScript Internationalization API is not yet supported on this platform])
-                fi
-                ICU_LIB_NAMES="icui18n icuuc icudata"
-                ;;
-            Darwin|Linux|DragonFly|FreeBSD|NetBSD|OpenBSD|GNU/kFreeBSD|SunOS)
+            Darwin|Linux|DragonFly|FreeBSD|NetBSD|OpenBSD|GNU/kFreeBSD|SunOS|Android)
                 ICU_LIB_NAMES="icui18n icuuc icudata"
                 ;;
             *)
                 AC_MSG_ERROR([ECMAScript Internationalization API is not yet supported on this platform])
         esac
     fi
 fi
 
@@ -274,16 +268,18 @@ if test -z "$BUILDING_JS" -o -n "$JS_STA
             if test -z "$MOZ_OPTIMIZE"; then
                 ICU_CFLAGS="$ICU_CFLAGS -Od"
                 ICU_CXXFLAGS="$ICU_CXXFLAGS -Od"
             fi
         fi
 
         if test -n "$gonkdir"; then
             ICU_CXXFLAGS="-I$gonkdir/abi/cpp/include $ICU_CXXFLAGS"
+        elif test "$OS_TARGET" = Android -a "$MOZ_ANDROID_CXX_STL" = mozstlport; then
+            ICU_CXXFLAGS="-I$_topsrcdir/build/gabi++/include $ICU_CXXFLAGS"
         fi
 
         if test -z "$MOZ_SHARED_ICU"; then
           ICU_CXXFLAGS="$ICU_CXXFLAGS -DU_STATIC_IMPLEMENTATION"
           ICU_CFLAGS="$ICU_CFLAGS -DU_STATIC_IMPLEMENTATION"
           if test "$GNU_CC"; then
             ICU_CFLAGS="$ICU_CFLAGS -fvisibility=hidden"
             ICU_CXXFLAGS="$ICU_CXXFLAGS -fvisibility=hidden"
new file mode 100644
--- /dev/null
+++ b/build/gabi++/Android.mk
@@ -0,0 +1,55 @@
+LOCAL_PATH:= $(call my-dir)
+
+libgabi++_cflags := \
+	-I$(LOCAL_PATH)/include 
+
+libgabi++_common_src_files := \
+	src/array_type_info.cc \
+	src/class_type_info.cc \
+        src/delete.cc \
+	src/dynamic_cast.cc \
+	src/enum_type_info.cc \
+	src/function_type_info.cc \
+        src/new.cc \
+	src/pbase_type_info.cc \
+	src/pointer_type_info.cc \
+	src/pointer_to_member_type_info.cc \
+	src/si_class_type_info.cc \
+	src/type_info.cc \
+	src/vmi_class_type_info.cc
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_CPP_EXTENSION := .cc
+
+LOCAL_SRC_FILES:= $(libgabi++_common_src_files)
+
+LOCAL_MODULE:= libgabi++
+
+LOCAL_CFLAGS := $(libgabi++_cflags)
+
+LOCAL_RTTI_FLAG := -frtti
+
+LOCAL_SYSTEM_SHARED_LIBRARIES := libc
+
+include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_CPP_EXTENSION := .cc
+
+LOCAL_SRC_FILES:= $(libgabi++_common_src_files)
+
+LOCAL_MODULE:= libgabi++
+
+LOCAL_CFLAGS := $(libgabi++_cflags)
+
+LOCAL_RTTI_FLAG := -frtti
+
+LOCAL_SYSTEM_SHARED_LIBRARIES := libc
+
+include $(BUILD_STATIC_LIBRARY)
new file mode 100644
--- /dev/null
+++ b/build/gabi++/README.mozilla
@@ -0,0 +1,1 @@
+This copy of libgabi++ is from Android 5.0 source code on https://android.googlesource.com/platform/abi/cpp/.  Tag is android-5.0.0_r1.
new file mode 100644
--- /dev/null
+++ b/build/gabi++/include/cxxabi.h
@@ -0,0 +1,183 @@
+// Copyright (C) 2011 The Android Open Source Project
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the distribution.
+// 3. Neither the name of the project nor the names of its contributors
+//    may be used to endorse or promote products derived from this software
+//    without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+// SUCH DAMAGE.
+//
+
+#ifndef __GABIXX_CXXABI_H__
+#define __GABIXX_CXXABI_H__
+
+#include <typeinfo>
+
+namespace __cxxabiv1
+{
+  extern "C" void __cxa_pure_virtual();
+
+  // Derived types of type_info below are based on 2.9.5 of C++ ABI.
+
+  // Typeinfo for fundamental types.
+  class __fundamental_type_info : public std::type_info
+  {
+  public:
+    ~__fundamental_type_info();
+  };
+
+  // Typeinfo for array types.
+  class __array_type_info : public std::type_info
+  {
+  public:
+    ~__array_type_info();
+  };
+
+  // Typeinfo for function types.
+  class __function_type_info : public std::type_info
+  {
+  public:
+    ~__function_type_info();
+  };
+
+  // Typeinfo for enum types.
+  class __enum_type_info : public std::type_info
+  {
+  public:
+    ~__enum_type_info();
+  };
+
+  // Typeinfo for classes with no bases.
+  class __class_type_info : public std::type_info
+  {
+  public:
+    ~__class_type_info();
+
+    enum class_type_info_code
+      {
+        CLASS_TYPE_INFO_CODE,
+        SI_CLASS_TYPE_INFO_CODE,
+        VMI_CLASS_TYPE_INFO_CODE
+      };
+
+    virtual class_type_info_code
+    code() const { return CLASS_TYPE_INFO_CODE; }
+  };
+
+  // Typeinfo for classes containing only a single, public, non-virtual base at
+  // offset zero.
+  class __si_class_type_info : public __class_type_info
+  {
+  public:
+    ~__si_class_type_info();
+    const __class_type_info *__base_type;
+
+    virtual __class_type_info::class_type_info_code
+    code() const { return SI_CLASS_TYPE_INFO_CODE; }
+  };
+
+  struct __base_class_type_info
+  {
+  public:
+    const __class_type_info *__base_type;
+
+    // All but the lower __offset_shift bits of __offset_flags are a signed
+    // offset. For a non-virtual base, this is the offset in the object of the
+    // base subobject. For a virtual base, this is the offset in the virtual
+    // table of the virtual base offset for the virtual base referenced
+    // (negative).
+    long __offset_flags;
+
+    enum __offset_flags_masks
+      {
+        __virtual_mask = 0x1,
+        __public_mask = 0x2,
+        __offset_shift = 8
+      };
+
+    bool inline
+    is_virtual() const { return (__offset_flags & __virtual_mask) != 0; }
+
+    bool inline
+    is_public() const { return (__offset_flags & __public_mask) != 0; }
+
+    // FIXME: Right-shift of signed integer is implementation dependent.
+    long inline
+    offset() const { return __offset_flags >> __offset_shift; }
+
+    long inline
+    flags() const { return __offset_flags & ((1L << __offset_shift) - 1); }
+  };
+
+  // Typeinfo for classes with bases that do not satisfy the
+  // __si_class_type_info constraints.
+  class __vmi_class_type_info : public __class_type_info
+  {
+  public:
+    ~__vmi_class_type_info();
+    unsigned int __flags;
+    unsigned int __base_count;
+    __base_class_type_info __base_info[1];
+
+    enum __flags_masks
+      {
+        __non_diamond_repeat_mask = 0x1,
+        __diamond_shaped_mask = 0x2
+      };
+
+    virtual __class_type_info::class_type_info_code
+    code() const { return VMI_CLASS_TYPE_INFO_CODE; }
+  };
+
+  class __pbase_type_info : public std::type_info
+  {
+  public:
+    ~__pbase_type_info();
+    unsigned int __flags;
+    const std::type_info *__pointee;
+
+    enum __masks
+      {
+        __const_mask = 0x1,
+        __volatile_mask = 0x2,
+        __restrict_mask = 0x4,
+        __incomplete_mask = 0x8,
+        __incomplete_class_mask = 0x10
+      };
+  };
+
+  class __pointer_type_info : public __pbase_type_info
+  {
+  public:
+    ~__pointer_type_info();
+  };
+
+  class __pointer_to_member_type_info : public __pbase_type_info
+  {
+  public:
+    ~__pointer_to_member_type_info();
+  };
+}
+
+namespace abi = __cxxabiv1;
+
+#endif /* defined(__GABIXX_CXXABI_H__) */
+
new file mode 100644
--- /dev/null
+++ b/build/gabi++/include/new
@@ -0,0 +1,56 @@
+// Copyright (C) 2011 The Android Open Source Project
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the distribution.
+// 3. Neither the name of the project nor the names of its contributors
+//    may be used to endorse or promote products derived from this software
+//    without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+// SUCH DAMAGE.
+//
+// new: Dynamic storage management.
+
+#ifndef __GABIXX_NEW__
+#define __GABIXX_NEW__
+
+#include <cstddef>
+
+namespace std
+{
+  struct nothrow_t {};
+  extern const nothrow_t nothrow;
+  typedef void (*new_handler)();
+}
+
+// FIXME: Need to handle exceptions.
+void* operator new(std::size_t size) throw(/*std::bad_alloc*/);
+void* operator new(std::size_t size, const std::nothrow_t&) throw();
+void  operator delete(void* ptr) throw();
+void  operator delete(void*, const std::nothrow_t&) throw();
+void* operator new[](std::size_t size) throw(/*std::bad_alloc*/);
+void* operator new[](std::size_t size, const std::nothrow_t&) throw();
+void  operator delete[](void* ptr) throw();
+void  operator delete[](void* const, std::nothrow_t&) throw();
+void* operator new(std::size_t size, void* ptr) throw();
+void* operator new[](std::size_t size, void* ptr) throw();
+void  operator delete(void* ptr, void*) throw();
+void  operator delete[](void* ptr, void*) throw();
+
+#endif // __GABIXX_NEW__
new file mode 100644
--- /dev/null
+++ b/build/gabi++/include/typeinfo
@@ -0,0 +1,76 @@
+// Copyright (C) 2011 The Android Open Source Project
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the distribution.
+// 3. Neither the name of the project nor the names of its contributors
+//    may be used to endorse or promote products derived from this software
+//    without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+// SUCH DAMAGE.
+//
+// typeinfo: RTTI support header.
+//
+// References:
+// Itanium C++ ABI at http://www.codesourcery.com/public/cxx-abi/abi.html.
+// IHI0041A C++ Application Binary Interface for the ARM architecture.
+// Linux Standard Base C++ Specification for S390X 4.1.
+//
+
+#ifndef __GABIXX_TYPEINFO__
+#define __GABIXX_TYPEINFO__
+
+namespace std
+{
+  // Defintion of type_info based on example in C++ ABI section 2.9.3
+  class type_info
+  {
+  public:
+    virtual
+    ~type_info();
+
+    // Whether two type_infos corresponds to the same types.
+    bool
+    operator==(const type_info &ti) const;
+
+    // Whether two type_infos corresponds to the different types.
+    bool
+    operator!=(const type_info &ti) const;
+
+    bool
+    before(const type_info &ti) const;
+
+    // Return name of type.
+    const char*
+    name() const { return __type_name; }
+
+  private:
+    // Assignment of type_info is not allowed.
+    type_info (const type_info& rhs);
+
+    type_info&
+    operator=(const type_info& rhs);
+
+    // Mangled name of type.
+    const char *__type_name;
+  };
+
+} // namespace std
+
+#endif // _GABIXX_TYPEINFO_
new file mode 100644
--- /dev/null
+++ b/build/gabi++/moz.build
@@ -0,0 +1,36 @@
+# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+Library('gabi++')
+
+SOURCES += [
+    'src/array_type_info.cc',
+    'src/class_type_info.cc',
+    'src/delete.cc',
+    'src/dynamic_cast.cc',
+    'src/enum_type_info.cc',
+    'src/function_type_info.cc',
+    'src/fundamental_type_info.cc',
+    'src/new.cc',
+    'src/pbase_type_info.cc',
+    'src/pointer_to_member_type_info.cc',
+    'src/pointer_type_info.cc',
+    'src/si_class_type_info.cc',
+    'src/type_info.cc',
+    'src/vmi_class_type_info.cc',
+]
+
+LOCAL_INCLUDES += [
+    'include'
+]
+
+DISABLE_STL_WRAPPING = True
+NO_VISIBILITY_FLAGS = True
+
+CXXFLAGS += [
+    '-fexceptions',
+    '-frtti'
+]
new file mode 100644
--- /dev/null
+++ b/build/gabi++/src/array_type_info.cc
@@ -0,0 +1,37 @@
+// Copyright (C) 2011 The Android Open Source Project
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the distribution.
+// 3. Neither the name of the project nor the names of its contributors
+//    may be used to endorse or promote products derived from this software
+//    without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+// SUCH DAMAGE.
+//
+// fundamental_type_info.cc: Methods for __fundamental_type_info.
+
+#include <cxxabi.h>
+
+namespace __cxxabiv1
+{
+  __fundamental_type_info::~__fundamental_type_info()
+  {
+  }
+} // namespace __cxxabiv1
new file mode 100644
--- /dev/null
+++ b/build/gabi++/src/class_type_info.cc
@@ -0,0 +1,37 @@
+// Copyright (C) 2011 The Android Open Source Project
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the distribution.
+// 3. Neither the name of the project nor the names of its contributors
+//    may be used to endorse or promote products derived from this software
+//    without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+// SUCH DAMAGE.
+//
+// class_type_info.cc: Methods for __class_type_info.
+
+#include <cxxabi.h>
+
+namespace __cxxabiv1
+{
+  __class_type_info::~__class_type_info()
+  {
+  }
+} // namespace __cxxabiv1
new file mode 100644
--- /dev/null
+++ b/build/gabi++/src/delete.cc
@@ -0,0 +1,38 @@
+// Copyright (C) 2011 The Android Open Source Project
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the distribution.
+// 3. Neither the name of the project nor the names of its contributors
+//    may be used to endorse or promote products derived from this software
+//    without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+// SUCH DAMAGE.
+//
+// delete.cc: delete operator
+
+#include <stdlib.h>
+#include <new>
+
+void
+operator delete(void* ptr) throw()
+{
+  if (ptr)
+    free(ptr);
+}
new file mode 100644
--- /dev/null
+++ b/build/gabi++/src/dynamic_cast.cc
@@ -0,0 +1,356 @@
+// Copyright (C) 2011 The Android Open Source Project
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the distribution.
+// 3. Neither the name of the project nor the names of its contributors
+//    may be used to endorse or promote products derived from this software
+//    without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+// SUCH DAMAGE.
+//
+// dynamic_cast.cc: RTTI support.
+//
+// References:
+// Itanium C++ ABI at http://www.codesourcery.com/public/cxx-abi/abi.html
+// IHI0041A C++ Application Binary Interface for the ARM architecture.
+//
+
+#include <cxxabi.h>
+
+#include <cstddef>
+#include <cassert>
+
+namespace
+{
+  // Adjust a pointer by an offset.
+
+  const void*
+  adjust_pointer(const void* p, std::ptrdiff_t off)
+  {
+    // FIXME: should we align pointer after adjustment?
+    const char *cp = reinterpret_cast<const char*>(p) + off;
+    return reinterpret_cast<const void*>(cp);
+  }
+
+  // Return the vtable pointer of a polymorphic object pointed by p.
+
+  inline const void*
+  get_vtable(const void* p)
+  {
+    return *reinterpret_cast<void*const*>(p);
+  }
+
+  // Return a pointer to a __class_type_info in a vtable.
+
+  inline const abi::__class_type_info*
+  get_class_type_info(const void* vtable)
+  {
+    const void* type_info_ptr = adjust_pointer(vtable, -sizeof(void*));
+    return *reinterpret_cast<abi::__class_type_info*const*>(type_info_ptr);
+  }
+
+  // Return offset to object in a vtable.
+
+  inline std::ptrdiff_t
+  get_offset_to_top(const void* vtable)
+  {
+    const void* type_info_ptr_address = adjust_pointer(vtable, -sizeof(void*));
+    const void* offset_to_top_address =
+      adjust_pointer(type_info_ptr_address, -sizeof(std::ptrdiff_t));
+    return *reinterpret_cast<const std::ptrdiff_t*>(offset_to_top_address);
+  }
+
+  // Return the virtual pointer to the most derived object of referred by a
+  // pointer p.
+
+  const void*
+  get_most_derived_object(const void* p)
+  {
+    const void* vtable = get_vtable(p);
+    std::ptrdiff_t offset_to_top = get_offset_to_top(vtable);
+    return adjust_pointer(p, offset_to_top);
+  }
+
+  // We assume that -1 cannot be a valid pointer to object.
+  const void * const ambiguous_object =
+    reinterpret_cast<const void*>(-1);
+
+  // Return a pointer to the subobject described by base_info.
+
+  const void*
+  get_subobject(const void* object,
+                const void* vtable,
+                const abi::__base_class_type_info* base_info)
+  {
+    long offset = base_info->offset();
+    if (base_info->is_virtual())
+      {
+        const std::ptrdiff_t* virtual_base_offset_address =
+          static_cast<const std::ptrdiff_t*> (adjust_pointer(vtable, offset));
+        offset = *virtual_base_offset_address;
+      }
+    return adjust_pointer(object, offset);
+  }
+
+  // Helper of __dyanmic_cast to walk the type tree of an object.
+
+  const void *
+  walk_object(const void *object,
+              const abi::__class_type_info *type,
+              const void *match_object,
+              const abi::__class_type_info *match_type)
+  {
+    if (*type == *match_type)
+      return (match_object == NULL || object == match_object) ? object : NULL;
+
+    switch(type->code())
+      {
+      case abi::__class_type_info::CLASS_TYPE_INFO_CODE:
+        // This isn't not the class you're looking for.
+        return NULL;
+
+      case abi::__class_type_info::SI_CLASS_TYPE_INFO_CODE:
+        // derived type has a single public base at offset 0.
+        {
+          const abi::__si_class_type_info* ti =
+            static_cast<const abi::__si_class_type_info*>(type);
+          return walk_object(object, ti->__base_type, match_object,
+                             match_type);
+        }
+
+      case abi::__class_type_info::VMI_CLASS_TYPE_INFO_CODE:
+        {
+          const void* vtable = get_vtable(object);
+          const abi::__vmi_class_type_info* ti =
+            static_cast<const abi::__vmi_class_type_info*>(type);
+
+          // Look at all direct bases.
+          const void* result = NULL;
+          for (unsigned i = 0; i < ti->__base_count; ++i)
+            {
+              if (!ti->__base_info[i].is_public())
+                continue;
+
+              const void *subobject =
+                get_subobject(object, vtable, &ti->__base_info[i]);
+              const void* walk_subobject_result =
+                walk_object(subobject, ti->__base_info[i].__base_type,
+                            match_object, match_type);
+
+              if (walk_subobject_result == ambiguous_object)
+                return ambiguous_object;
+              else if (walk_subobject_result != NULL)
+                {
+                  if (result == NULL)
+                    {
+                      result = walk_subobject_result;
+                    }
+                  else if (result != walk_subobject_result)
+                    return ambiguous_object;
+                }
+            }
+          return result;
+        }
+
+      default:
+        assert(0);
+      }
+    return NULL;
+  }
+
+  // Bookkeeping structure for derived-to-base cast in the general case.
+  struct cast_context
+  {
+  public:
+    const void* object;
+    const abi::__class_type_info *src_type;
+    const abi::__class_type_info *dst_type;
+    std::ptrdiff_t src2dst_offset;
+
+    const void* dst_object;
+    const void* result;
+
+    cast_context(const void* obj, const abi::__class_type_info *src,
+                 const abi::__class_type_info *dst, std::ptrdiff_t offset)
+      : object(obj), src_type(src), dst_type(dst), src2dst_offset(offset),
+        dst_object(NULL), result(NULL)
+    { }
+  };
+
+  // based-to-derive cast in the general case.
+
+  void
+  base_to_derived_cast(const void *object,
+                       const abi::__class_type_info *type,
+                       cast_context* context)
+  {
+    const void* saved_dst_object = context->dst_object;
+    bool is_dst_type = *type == *context->dst_type;
+    if (is_dst_type)
+      context->dst_object = object;
+
+    if (object == context->object
+        && context->dst_object != NULL
+        && *type == *context->src_type)
+      {
+        if (context->result == NULL)
+          context->result = context->dst_object;
+        else if (context->result != context->dst_object)
+          context->result = ambiguous_object;
+        context->dst_object = saved_dst_object;
+        return;
+      }
+
+    switch(type->code())
+      {
+      case abi::__class_type_info::CLASS_TYPE_INFO_CODE:
+        // This isn't not the class you're looking for.
+        break;
+
+      case abi::__class_type_info::SI_CLASS_TYPE_INFO_CODE:
+        // derived type has a single public base at offset 0.
+        {
+          const abi::__si_class_type_info* ti =
+            static_cast<const abi::__si_class_type_info*>(type);
+          base_to_derived_cast(object, ti->__base_type, context);
+          break;
+        }
+
+      case abi::__class_type_info::VMI_CLASS_TYPE_INFO_CODE:
+        {
+          const void* vtable = get_vtable(object);
+          const abi::__vmi_class_type_info* ti =
+            static_cast<const abi::__vmi_class_type_info*>(type);
+
+          // Look at all direct bases.
+          for (unsigned i = 0; i < ti->__base_count; ++i)
+            {
+              if (!ti->__base_info[i].is_public())
+                continue;
+
+              const void *subobject =
+                get_subobject(object, vtable, &ti->__base_info[i]);
+              base_to_derived_cast(subobject, ti->__base_info[i].__base_type,
+                                   context);
+
+              // FIXME: Use flags in base_info to optimize search.
+              if (context->result == ambiguous_object)
+                break;
+            }
+          break;
+        }
+
+      default:
+        assert(0);
+      }
+     context->dst_object = saved_dst_object;
+  }
+} // namespace
+
+namespace __cxxabiv1
+{
+#define DYNAMIC_CAST_NO_HINT -1
+#define DYNAMIC_CAST_NOT_PUBLIC_BASE -2
+#define DYNAMIC_CAST_MULTIPLE_PUBLIC_NONVIRTUAL_BASE -3
+
+  /* v: source address to be adjusted; nonnull, and since the
+   *    source object is polymorphic, *(void**)v is a virtual pointer.
+   * src: static type of the source object.
+   * dst: destination type (the "T" in "dynamic_cast<T>(v)").
+   * src2dst_offset: a static hint about the location of the
+   *    source subobject with respect to the complete object;
+   *    special negative values are:
+   *       -1: no hint
+   *       -2: src is not a public base of dst
+   *       -3: src is a multiple public base type but never a
+   *           virtual base type
+   *    otherwise, the src type is a unique public nonvirtual
+   *    base type of dst at offset src2dst_offset from the
+   *    origin of dst.
+   */
+  extern "C" void*
+  __dynamic_cast (const void *v,
+                  const abi::__class_type_info *src,
+                  const abi::__class_type_info *dst,
+                  std::ptrdiff_t src2dst_offset)
+  {
+    const void* most_derived_object = get_most_derived_object(v);
+    const void* vtable = get_vtable(most_derived_object);
+    const abi::__class_type_info* most_derived_class_type_info =
+      get_class_type_info(vtable);
+
+    // If T is not a public base type of the most derived class referred
+    // by v, the cast always fails.
+    void* t_object =
+      const_cast<void*>(walk_object(most_derived_object,
+                                    most_derived_class_type_info, NULL, dst));
+    if (t_object == NULL)
+      return NULL;
+
+    // C++ ABI 2.9.7 The dynamic_cast Algorithm:
+    //
+    // If, in the most derived object pointed (referred) to by v, v points
+    // (refers) to a public base class subobject of a T object [note: this can
+    // be checked at compile time], and if only one object of type T is derived
+    // from the subobject pointed (referred) to by v, the result is a pointer
+    // (an lvalue referring) to that T object.
+
+    // We knew that src is not a public base, so base-to-derived cast
+    // is not possible.  This works even if there are multiple subobjects
+    // of type T in the most derived object.
+    if (src2dst_offset != DYNAMIC_CAST_NOT_PUBLIC_BASE)
+      {
+        // If it is known that v points to a public base class subobject
+        // of a T object, simply adjust the pointer by the offset.
+        if (t_object != ambiguous_object && src2dst_offset >= 0)
+          return const_cast<void*>(adjust_pointer(v, -src2dst_offset));
+
+        // If there is only one T type subobject, we only need to look at
+        // there.  Otherwise, look for the subobject referred by v in the
+        // most derived object.
+        cast_context context(v, src, dst, src2dst_offset);
+        if (t_object != ambiguous_object)
+          base_to_derived_cast(t_object, dst, &context);
+        else
+          base_to_derived_cast(most_derived_object,
+                               most_derived_class_type_info, &context);
+
+        if (context.result != NULL && context.result != ambiguous_object)
+          return const_cast<void*>(context.result);
+      }
+
+    // C++ ABI 2.9.7 The dynamic_cast Algorithm:
+    //
+    // Otherwise, if v points (refers) to a public base class subobject of the
+    // most derived object, and the type of the most derived object has an
+    // unambiguous public base class of type T, the result is a pointer (an
+    // lvalue referring) to the T subobject of the most derived object.
+    // Otherwise, the run-time check fails.
+
+    // Check to see if T is a unambiguous public base class.
+    if (t_object == ambiguous_object)
+      return NULL;
+
+    // See if v refers to a public base class subobject.
+    const void* v_object =
+      walk_object(most_derived_object, most_derived_class_type_info, v, src);
+    return v_object == v ? t_object : NULL;
+  }
+} // namespace __cxxabiv1
new file mode 100644
--- /dev/null
+++ b/build/gabi++/src/enum_type_info.cc
@@ -0,0 +1,37 @@
+// Copyright (C) 2011 The Android Open Source Project
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the distribution.
+// 3. Neither the name of the project nor the names of its contributors
+//    may be used to endorse or promote products derived from this software
+//    without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+// SUCH DAMAGE.
+//
+// enum_type_info.cc: Methods for __enum_type_info.
+
+#include <cxxabi.h>
+
+namespace __cxxabiv1
+{
+  __enum_type_info::~__enum_type_info()
+  {
+  }
+} // namespace __cxxabiv1
new file mode 100644
--- /dev/null
+++ b/build/gabi++/src/function_type_info.cc
@@ -0,0 +1,37 @@
+// Copyright (C) 2011 The Android Open Source Project
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the distribution.
+// 3. Neither the name of the project nor the names of its contributors
+//    may be used to endorse or promote products derived from this software
+//    without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+// SUCH DAMAGE.
+//
+// function_type_info.cc: Methods for __function_type_info.
+
+#include <cxxabi.h>
+
+namespace __cxxabiv1
+{
+  __function_type_info::~__function_type_info()
+  {
+  }
+} // namespace __cxxabiv1
new file mode 100644
--- /dev/null
+++ b/build/gabi++/src/fundamental_type_info.cc
@@ -0,0 +1,37 @@
+// Copyright (C) 2011 The Android Open Source Project
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the distribution.
+// 3. Neither the name of the project nor the names of its contributors
+//    may be used to endorse or promote products derived from this software
+//    without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+// SUCH DAMAGE.
+//
+// array_type_info.cc: Methods for __array_type_info.
+
+#include <cxxabi.h>
+
+namespace __cxxabiv1
+{
+  __array_type_info::~__array_type_info()
+  {
+  }
+} // namespace __cxxabiv1
new file mode 100644
--- /dev/null
+++ b/build/gabi++/src/new.cc
@@ -0,0 +1,42 @@
+// Copyright (C) 2011 The Android Open Source Project
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the distribution.
+// 3. Neither the name of the project nor the names of its contributors
+//    may be used to endorse or promote products derived from this software
+//    without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+// SUCH DAMAGE.
+//
+
+#include <stdlib.h>
+#include <new>
+
+// FIXME: need to handle exceptions
+void*
+operator new(std::size_t size) throw (/*std::bad_alloc*/)
+{
+  void* ptr = malloc(size);
+#if 0
+  if (ptr == NULL)
+    throw std::bad_alloc();
+#endif
+  return ptr;
+}
new file mode 100644
--- /dev/null
+++ b/build/gabi++/src/pbase_type_info.cc
@@ -0,0 +1,37 @@
+// Copyright (C) 2011 The Android Open Source Project
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the distribution.
+// 3. Neither the name of the project nor the names of its contributors
+//    may be used to endorse or promote products derived from this software
+//    without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+// SUCH DAMAGE.
+//
+// pbase_type_info.cc: Methods for __pbase_type_info.
+
+#include <cxxabi.h>
+
+namespace __cxxabiv1
+{
+  __pbase_type_info::~__pbase_type_info()
+  {
+  }
+} // namespace __cxxabiv1
new file mode 100644
--- /dev/null
+++ b/build/gabi++/src/pointer_to_member_type_info.cc
@@ -0,0 +1,37 @@
+// Copyright (C) 2011 The Android Open Source Project
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the distribution.
+// 3. Neither the name of the project nor the names of its contributors
+//    may be used to endorse or promote products derived from this software
+//    without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+// SUCH DAMAGE.
+//
+// pointer_to_member_type_info.cc: Methods for __pointer_to_member_type_info.
+
+#include <cxxabi.h>
+
+namespace __cxxabiv1
+{
+  __pointer_to_member_type_info::~__pointer_to_member_type_info()
+  {
+  }
+} // namespace __cxxabiv1
new file mode 100644
--- /dev/null
+++ b/build/gabi++/src/pointer_type_info.cc
@@ -0,0 +1,37 @@
+// Copyright (C) 2011 The Android Open Source Project
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the distribution.
+// 3. Neither the name of the project nor the names of its contributors
+//    may be used to endorse or promote products derived from this software
+//    without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+// SUCH DAMAGE.
+//
+// pointer_type_info.cc: Methods for __pointer_type_info.
+
+#include <cxxabi.h>
+
+namespace __cxxabiv1
+{
+  __pointer_type_info::~__pointer_type_info()
+  {
+  }
+} // namespace __cxxabiv1
new file mode 100644
--- /dev/null
+++ b/build/gabi++/src/si_class_type_info.cc
@@ -0,0 +1,37 @@
+// Copyright (C) 2011 The Android Open Source Project
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the distribution.
+// 3. Neither the name of the project nor the names of its contributors
+//    may be used to endorse or promote products derived from this software
+//    without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+// SUCH DAMAGE.
+//
+// si_class_type_info.cc: Methods for __si_class_type_info.
+
+#include <cxxabi.h>
+
+namespace __cxxabiv1
+{
+  __si_class_type_info::~__si_class_type_info()
+  {
+  }
+} // namespace __cxxabiv1
new file mode 100644
--- /dev/null
+++ b/build/gabi++/src/type_info.cc
@@ -0,0 +1,75 @@
+// Copyright (C) 2011 The Android Open Source Project
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the distribution.
+// 3. Neither the name of the project nor the names of its contributors
+//    may be used to endorse or promote products derived from this software
+//    without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+// SUCH DAMAGE.
+//
+// type_info.cc: Methods for std::type_info.
+//
+
+#include <cxxabi.h>
+#ifdef __ARM_EABI__
+// ARM EABI requires string comprison for mangled type names for type_info
+// equality.
+#include <string.h>
+#endif
+
+#include <typeinfo>
+
+namespace std
+{
+  type_info::~type_info()
+  {
+  }
+
+  bool
+  type_info::operator==(const type_info& rhs) const
+  {
+#ifdef __ARM_EABI__
+    // IHI0041A CPPABI 3.2.5.6.  Because of weak linkage and share libraries,
+    // we perform string comparison.
+    return strcmp(this->__type_name, rhs.__type_name) == 0;
+#else
+    return this == &rhs;
+#endif
+  }
+
+  bool
+  type_info::operator!=(const type_info& rhs) const
+  {
+    return !this->operator==(rhs);
+  }
+
+  bool
+  type_info::before(const type_info& rhs) const
+  {
+#ifdef __ARM_EABI__
+    // IHI0041A CPPABI 3.2.5.6.  Because of weak linkage and share libraries,
+    // we perform string comparison.
+    return strcmp(this->__type_name, rhs.__type_name) < 0;
+#else
+    return this < &rhs;
+#endif
+  }
+} // end namespace std
new file mode 100644
--- /dev/null
+++ b/build/gabi++/src/vmi_class_type_info.cc
@@ -0,0 +1,37 @@
+// Copyright (C) 2011 The Android Open Source Project
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the distribution.
+// 3. Neither the name of the project nor the names of its contributors
+//    may be used to endorse or promote products derived from this software
+//    without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+// SUCH DAMAGE.
+//
+// vmi_class_type_info.cc: Methods for __vmi_class_type_info.
+
+#include <cxxabi.h>
+
+namespace __cxxabiv1
+{
+  __vmi_class_type_info::~__vmi_class_type_info()
+  {
+  }
+} // namespace __cxxabiv1
new file mode 100644
--- /dev/null
+++ b/build/gabi++/use_rtti.mk
@@ -0,0 +1,8 @@
+# To use RTTI, "include abi/cpp/use_rtti.mk" in your target.
+
+LOCAL_C_INCLUDES := \
+	abi/cpp/include \
+	$(LOCAL_C_INCLUDES)
+
+LOCAL_RTTI_FLAG := -frtti
+LOCAL_SHARED_LIBRARIES += libgabi++
--- a/build/moz.build
+++ b/build/moz.build
@@ -12,16 +12,18 @@ SPHINX_TREES['buildsystem'] = 'docs'
 
 if CONFIG['OS_ARCH'] == 'WINNT':
     DIRS += ['win32']
 else:
     DIRS += ['unix']
 
 if CONFIG['OS_TARGET'] == 'Android' and CONFIG['MOZ_ANDROID_CXX_STL'] == 'mozstlport':
     DIRS += ['stlport']
+    if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android' and CONFIG['ENABLE_INTL_API']:
+        DIRS += ['gabi++']
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
     DIRS += ['annotationProcessors']
     TEST_DIRS += [
         'mobile/sutagent/android',
         'mobile/sutagent/android/watcher',
         'mobile/sutagent/android/ffxcp',
         'mobile/sutagent/android/fencp',
--- a/config/external/icu/Makefile.in
+++ b/config/external/icu/Makefile.in
@@ -42,19 +42,19 @@ target:: buildicu
 # - Force ICU to use the standard suffix for object files because expandlibs
 #   will discard all files with a non-standard suffix (bug 857450).
 # - Options for genrb: -k strict parsing; -R omit collation tailoring rules.
 buildicu::
 # ICU's build system is full of races, so force non-parallel build.
 # Msys screws up GENRBOPTS when it contains spaces, so all genrb flags need
 # to be stuck together. See https://bugzilla.mozilla.org/show_bug.cgi?id=1034594#c34
 ifdef CROSS_COMPILE
-	+$(MAKE) -j1 -C $(DEPTH)/intl/icu/host STATIC_O=$(OBJ_SUFFIX) GENRBOPTS='-kRC'
+	+ASAN_OPTIONS=detect_leaks=0 $(MAKE) -j1 -C $(DEPTH)/intl/icu/host STATIC_O=$(OBJ_SUFFIX) GENRBOPTS='-kRC'
 endif
-	+$(MAKE) -j1 -C $(DEPTH)/intl/icu/target STATIC_O=$(OBJ_SUFFIX) GENRBOPTS='-kR'
+	+ASAN_OPTIONS=detect_leaks=0 $(MAKE) -j1 -C $(DEPTH)/intl/icu/target STATIC_O=$(OBJ_SUFFIX) GENRBOPTS='-kR'
 	$(ICU_LIB_RENAME)
 
 distclean clean::
 ifdef CROSS_COMPILE
 	+$(MAKE) -C $(DEPTH)/intl/icu/host $@ STATIC_O=$(OBJ_SUFFIX)
 endif
 	+$(MAKE) -C $(DEPTH)/intl/icu/target $@ STATIC_O=$(OBJ_SUFFIX)
 
--- a/config/external/icu/moz.build
+++ b/config/external/icu/moz.build
@@ -16,8 +16,12 @@ else:
             l,
             CONFIG['MOZ_ICU_DBG_SUFFIX']
         )]
 
     if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
         OS_LIBS += [
             'gabi++',
         ]
+    if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android' and CONFIG['MOZ_ANDROID_CXX_STL'] == 'mozstlport':
+        USE_LIBS += [
+            'gabi++'
+        ]
--- a/config/external/nss/nss.def
+++ b/config/external/nss/nss.def
@@ -398,19 +398,16 @@ PK11_Logout
 PK11_LogoutAll
 PK11_MakeIDFromPubKey
 PK11_MechanismToAlgtag
 PK11_MergeTokens
 PK11_NeedLogin
 PK11_NeedUserInit
 PK11_ParamFromIV
 PK11_PBEKeyGen
-PK11_PQG_DestroyParams
-PK11_PQG_DestroyVerify
-PK11_PQG_ParamGen
 PK11_PrivDecrypt
 PK11_PrivDecryptPKCS1
 PK11_ProtectedAuthenticationPath
 PK11_PubDeriveWithKDF
 PK11_PubEncrypt
 PK11_PubEncryptPKCS1
 PK11_PubUnwrapSymKey
 PK11_PubWrapSymKey
@@ -680,9 +677,8 @@ VFY_CreateContext
 VFY_DestroyContext
 VFY_End
 VFY_EndWithSignature
 VFY_Update
 VFY_VerifyData
 VFY_VerifyDataWithAlgorithmID
 VFY_VerifyDigestDirect
 _SGN_VerifyPKCS1DigestInfo
-PK11_PQG_ParamGenV2
--- a/configure.in
+++ b/configure.in
@@ -48,17 +48,17 @@ dnl ====================================
 _SUBDIR_HOST_LDFLAGS="$HOST_LDFLAGS"
 _SUBDIR_CONFIG_ARGS="$ac_configure_args"
 
 dnl Set the version number of the libs included with mozilla
 dnl ========================================================
 MOZJPEG=62
 MOZPNG=10617
 NSPR_VERSION=4
-NSPR_MINVER=4.10.8
+NSPR_MINVER=4.10.10
 NSS_VERSION=3
 
 dnl Set the minimum version of toolkit libs used by mozilla
 dnl ========================================================
 GLIB_VERSION=2.22
 # 2_26 is the earliest version we can set GLIB_VERSION_MIN_REQUIRED.
 # The macro won't be used when compiling with earlier versions anyway.
 GLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_26
@@ -3422,17 +3422,17 @@ dnl = If NSS was not detected in the sys
 dnl = use the one in the source tree (mozilla/security/nss)
 dnl ========================================================
 
 MOZ_ARG_WITH_BOOL(system-nss,
 [  --with-system-nss       Use system installed NSS],
     _USE_SYSTEM_NSS=1 )
 
 if test -n "$_USE_SYSTEM_NSS"; then
-    AM_PATH_NSS(3.19.2, [MOZ_NATIVE_NSS=1], [AC_MSG_ERROR([you don't have NSS installed or your version is too old])])
+    AM_PATH_NSS(3.20.1, [MOZ_NATIVE_NSS=1], [AC_MSG_ERROR([you don't have NSS installed or your version is too old])])
 fi
 
 if test -n "$MOZ_NATIVE_NSS"; then
    NSS_LIBS="$NSS_LIBS -lcrmf"
 else
    NSS_CFLAGS='-I$(LIBXUL_DIST)/include/nss'
 
    if test -z "$GNU_CC" -a "$OS_ARCH" = "WINNT"; then
@@ -9105,22 +9105,20 @@ HAVE_SYS_STATFS_H
 HAVE_SYS_VFS_H
 HAVE_SYS_MOUNT_H
 "
 
 dnl ========================================================
 dnl ICU Support
 dnl ========================================================
 
-# Internationalization isn't built or exposed by default in non-desktop
-# builds.  Bugs to enable:
-#
-#   Android:  bug 864843
-
-if test "$MOZ_WIDGET_TOOLKIT" = "android"; then
+# Internationalization is not built or exposed on Fennec.
+# See Bug 1215256
+
+if test "$MOZ_BUILD_APP" = "mobile/android"; then
     _INTL_API=no
 else
     _INTL_API=yes
 fi
 
 if test "$MOZ_WIDGET_TOOLKIT" = "cocoa"; then
     USE_ICU=1
 fi
--- a/dom/base/StructuredCloneHolder.cpp
+++ b/dom/base/StructuredCloneHolder.cpp
@@ -857,39 +857,40 @@ WriteFormData(JSStructuredCloneWriter* a
   public:
     Closure(JSStructuredCloneWriter* aWriter,
             StructuredCloneHolder* aHolder)
       : mWriter(aWriter),
         mHolder(aHolder)
     { }
 
     static bool
-    Write(const nsString& aName, bool isFile, const nsString& aValue,
-          File* aFile, void* aClosure)
+    Write(const nsString& aName, const OwningFileOrUSVString& aValue,
+          void* aClosure)
     {
       Closure* closure = static_cast<Closure*>(aClosure);
       if (!WriteString(closure->mWriter, aName)) {
         return false;
       }
 
-      if (isFile) {
-        BlobImpl* blobImpl = aFile->Impl();
+      if (aValue.IsFile()) {
+        BlobImpl* blobImpl = aValue.GetAsFile()->Impl();
         if (!JS_WriteUint32Pair(closure->mWriter, SCTAG_DOM_BLOB,
                                 closure->mHolder->BlobImpls().Length())) {
           return false;
         }
 
         closure->mHolder->BlobImpls().AppendElement(blobImpl);
         return true;
       }
 
       size_t charSize = sizeof(nsString::char_type);
-      if (!JS_WriteUint32Pair(closure->mWriter, 0, aValue.Length()) ||
-          !JS_WriteBytes(closure->mWriter, aValue.get(),
-                         aValue.Length() * charSize)) {
+      if (!JS_WriteUint32Pair(closure->mWriter, 0,
+                              aValue.GetAsUSVString().Length()) ||
+          !JS_WriteBytes(closure->mWriter, aValue.GetAsUSVString().get(),
+                         aValue.GetAsUSVString().Length() * charSize)) {
         return false;
       }
 
       return true;
     }
   };
   Closure closure(aWriter, aHolder);
   return aFormData->ForEach(Closure::Write, &closure);
--- a/dom/base/nsFormData.cpp
+++ b/dom/base/nsFormData.cpp
@@ -56,28 +56,28 @@ CreateNewFileInstance(Blob& aBlob, const
 // nsISupports
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsFormData)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsFormData)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mOwner)
 
   for (uint32_t i = 0, len = tmp->mFormData.Length(); i < len; ++i) {
-    ImplCycleCollectionUnlink(tmp->mFormData[i].fileValue);
+    ImplCycleCollectionUnlink(tmp->mFormData[i].value);
   }
 
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsFormData)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwner)
 
   for (uint32_t i = 0, len = tmp->mFormData.Length(); i < len; ++i) {
-   ImplCycleCollectionTraverse(cb,tmp->mFormData[i].fileValue,
-                               "mFormData[i].fileValue", 0);
+    ImplCycleCollectionTraverse(cb, tmp->mFormData[i].value,
+                                "mFormData[i].GetAsFile()", 0);
   }
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(nsFormData)
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsFormData)
@@ -122,48 +122,37 @@ nsFormData::Delete(const nsAString& aNam
   for (uint32_t i = mFormData.Length(); i-- > 0; ) {
     if (aName.Equals(mFormData[i].name)) {
       mFormData.RemoveElementAt(i);
     }
   }
 }
 
 void
-nsFormData::ExtractValue(const FormDataTuple& aTuple,
-                         OwningFileOrUSVString* aOutValue)
-{
-  if (aTuple.valueIsFile) {
-    aOutValue->SetAsFile() = aTuple.fileValue;
-  } else {
-    aOutValue->SetAsUSVString() = aTuple.stringValue;
-  }
-}
-
-void
 nsFormData::Get(const nsAString& aName,
                 Nullable<OwningFileOrUSVString>& aOutValue)
 {
   for (uint32_t i = 0; i < mFormData.Length(); ++i) {
     if (aName.Equals(mFormData[i].name)) {
-      ExtractValue(mFormData[i], &aOutValue.SetValue());
+      aOutValue.SetValue() = mFormData[i].value;
       return;
     }
   }
 
   aOutValue.SetNull();
 }
 
 void
 nsFormData::GetAll(const nsAString& aName,
                    nsTArray<OwningFileOrUSVString>& aValues)
 {
   for (uint32_t i = 0; i < mFormData.Length(); ++i) {
     if (aName.Equals(mFormData[i].name)) {
       OwningFileOrUSVString* element = aValues.AppendElement();
-      ExtractValue(mFormData[i], element);
+      *element = mFormData[i].value;
     }
   }
 }
 
 bool
 nsFormData::Has(const nsAString& aName)
 {
   for (uint32_t i = 0; i < mFormData.Length(); ++i) {
@@ -224,16 +213,36 @@ nsFormData::Set(const nsAString& aName, 
   FormDataTuple* tuple = RemoveAllOthersAndGetFirstFormDataTuple(aName);
   if (tuple) {
     SetNameValuePair(tuple, aName, aValue);
   } else {
     Append(aName, aValue);
   }
 }
 
+uint32_t
+nsFormData::GetIterableLength() const
+{
+  return mFormData.Length();
+}
+
+const nsAString&
+nsFormData::GetKeyAtIndex(uint32_t aIndex) const
+{
+  MOZ_ASSERT(aIndex < mFormData.Length());
+  return mFormData[aIndex].name;
+}
+
+const OwningFileOrUSVString&
+nsFormData::GetValueAtIndex(uint32_t aIndex) const
+{
+  MOZ_ASSERT(aIndex < mFormData.Length());
+  return mFormData[aIndex].value;
+}
+
 // -------------------------------------------------------------------------
 // nsIDOMFormData
 
 NS_IMETHODIMP
 nsFormData::Append(const nsAString& aName, nsIVariant* aValue)
 {
   uint16_t dataType;
   nsresult rv = aValue->GetDataType(&dataType);
@@ -292,21 +301,23 @@ nsFormData::Constructor(const GlobalObje
 
 NS_IMETHODIMP
 nsFormData::GetSendInfo(nsIInputStream** aBody, uint64_t* aContentLength,
                         nsACString& aContentType, nsACString& aCharset)
 {
   nsFSMultipartFormData fs(NS_LITERAL_CSTRING("UTF-8"), nullptr);
 
   for (uint32_t i = 0; i < mFormData.Length(); ++i) {
-    if (mFormData[i].valueIsFile) {
-      fs.AddNameFilePair(mFormData[i].name, mFormData[i].fileValue);
-    }
-    else {
-      fs.AddNameValuePair(mFormData[i].name, mFormData[i].stringValue);
+    if (mFormData[i].value.IsFile()) {
+      fs.AddNameFilePair(mFormData[i].name, mFormData[i].value.GetAsFile());
+    } else if (mFormData[i].value.IsUSVString()) {
+      fs.AddNameValuePair(mFormData[i].name,
+                          mFormData[i].value.GetAsUSVString());
+    } else {
+      fs.AddNameFilePair(mFormData[i].name, nullptr);
     }
   }
 
   fs.GetContentType(aContentType);
   aCharset.Truncate();
   *aContentLength = 0;
   NS_ADDREF(*aBody = fs.GetSubmissionBody(aContentLength));
 
--- a/dom/base/nsFormData.h
+++ b/dom/base/nsFormData.h
@@ -32,52 +32,49 @@ class nsFormData final : public nsIDOMFo
                          public nsFormSubmission,
                          public nsWrapperCache
 {
 private:
   ~nsFormData() {}
 
   typedef mozilla::dom::Blob Blob;
   typedef mozilla::dom::File File;
+  typedef mozilla::dom::OwningFileOrUSVString OwningFileOrUSVString;
 
   struct FormDataTuple
   {
     nsString name;
-    nsString stringValue;
-    RefPtr<File> fileValue;
-    bool valueIsFile;
+    OwningFileOrUSVString value;
   };
 
   // Returns the FormDataTuple to modify. This may be null, in which case
   // no element with aName was found.
   FormDataTuple*
   RemoveAllOthersAndGetFirstFormDataTuple(const nsAString& aName);
 
   void SetNameValuePair(FormDataTuple* aData,
                         const nsAString& aName,
                         const nsAString& aValue)
   {
     MOZ_ASSERT(aData);
     aData->name = aName;
-    aData->stringValue = aValue;
-    aData->valueIsFile = false;
+    aData->value.SetAsUSVString() = aValue;
   }
 
   void SetNameFilePair(FormDataTuple* aData,
                        const nsAString& aName,
                        File* aFile)
   {
     MOZ_ASSERT(aData);
     aData->name = aName;
-    aData->fileValue = aFile;
-    aData->valueIsFile = true;
+    if (aFile) {
+      aData->value.SetAsFile() = aFile;
+    }
   }
 
-  void ExtractValue(const FormDataTuple& aTuple,
-                    mozilla::dom::OwningFileOrUSVString* aOutValue);
 public:
   explicit nsFormData(nsISupports* aOwner = nullptr);
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsFormData,
                                                          nsIDOMFormData)
 
   NS_DECL_NSIDOMFORMDATA
@@ -95,55 +92,58 @@ public:
   static already_AddRefed<nsFormData>
   Constructor(const mozilla::dom::GlobalObject& aGlobal,
               const mozilla::dom::Optional<mozilla::dom::NonNull<mozilla::dom::HTMLFormElement> >& aFormElement,
               mozilla::ErrorResult& aRv);
   void Append(const nsAString& aName, const nsAString& aValue);
   void Append(const nsAString& aName, Blob& aBlob,
               const mozilla::dom::Optional<nsAString>& aFilename);
   void Delete(const nsAString& aName);
-  void Get(const nsAString& aName, mozilla::dom::Nullable<mozilla::dom::OwningFileOrUSVString>& aOutValue);
-  void GetAll(const nsAString& aName, nsTArray<mozilla::dom::OwningFileOrUSVString>& aValues);
+  void Get(const nsAString& aName, mozilla::dom::Nullable<OwningFileOrUSVString>& aOutValue);
+  void GetAll(const nsAString& aName, nsTArray<OwningFileOrUSVString>& aValues);
   bool Has(const nsAString& aName);
   void Set(const nsAString& aName, Blob& aBlob,
            const mozilla::dom::Optional<nsAString>& aFilename);
   void Set(const nsAString& aName, const nsAString& aValue);
 
+  uint32_t GetIterableLength() const;
+  const nsAString& GetKeyAtIndex(uint32_t aIndex) const;
+  const OwningFileOrUSVString& GetValueAtIndex(uint32_t aIndex) const;
+
   // nsFormSubmission
   virtual nsresult GetEncodedSubmission(nsIURI* aURI,
                                         nsIInputStream** aPostDataStream) override;
   virtual nsresult AddNameValuePair(const nsAString& aName,
                                     const nsAString& aValue) override
   {
     FormDataTuple* data = mFormData.AppendElement();
     SetNameValuePair(data, aName, aValue);
     return NS_OK;
   }
   virtual nsresult AddNameFilePair(const nsAString& aName,
                                    File* aFile) override;
 
-  typedef bool (*FormDataEntryCallback)(const nsString& aName, bool aIsFile,
-                                        const nsString& aValue,
-                                        File* aFile, void* aClosure);
+  typedef bool (*FormDataEntryCallback)(const nsString& aName,
+                                        const OwningFileOrUSVString& aValue,
+                                        void* aClosure);
 
   uint32_t
   Length() const
   {
     return mFormData.Length();
   }
 
   // Stops iteration and returns false if any invocation of callback returns
   // false. Returns true otherwise.
   bool
   ForEach(FormDataEntryCallback aFunc, void* aClosure)
   {
     for (uint32_t i = 0; i < mFormData.Length(); ++i) {
       FormDataTuple& tuple = mFormData[i];
-      if (!aFunc(tuple.name, tuple.valueIsFile, tuple.stringValue,
-                 tuple.fileValue, aClosure)) {
+      if (!aFunc(tuple.name, tuple.value, aClosure)) {
         return false;
       }
     }
 
     return true;
   }
 
 private:
--- a/dom/bluetooth/bluedroid/hfp-fallback/BluetoothHfpManager.cpp
+++ b/dom/bluetooth/bluedroid/hfp-fallback/BluetoothHfpManager.cpp
@@ -86,17 +86,17 @@ void
 BluetoothHfpManager::OnGetServiceChannel(const nsAString& aDeviceAddress,
                                          const nsAString& aServiceUuid,
                                          int aChannel)
 {
   MOZ_ASSERT(false);
 }
 
 void
-BluetoothHfpManager::OnUpdateSdpRecords(const nsAString& aDeviceAddress)
+BluetoothHfpManager::OnUpdateSdpRecords(const BluetoothAddress& aDeviceAddress)
 {
   MOZ_ASSERT(false);
 }
 
 /**
  * BluetoothHfpManagerBase function
  */
 bool
--- a/dom/bluetooth/common/BluetoothRilListener.cpp
+++ b/dom/bluetooth/common/BluetoothRilListener.cpp
@@ -236,22 +236,16 @@ TelephonyListener::CallStateChanged(uint
 
 NS_IMETHODIMP
 TelephonyListener::EnumerateCallState(nsITelephonyCallInfo* aInfo)
 {
   return HandleCallInfo(aInfo, false);
 }
 
 NS_IMETHODIMP
-TelephonyListener::ConferenceCallStateChanged(uint16_t aCallState)
-{
-  return NS_OK;
-}
-
-NS_IMETHODIMP
 TelephonyListener::EnumerateCallStateComplete()
 {
   return NS_OK;
 }
 
 NS_IMETHODIMP
 TelephonyListener::SupplementaryServiceNotification(uint32_t aServiceId,
                                                     int32_t aCallIndex,
--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -5593,16 +5593,18 @@ CanvasRenderingContext2D::GetCanvasLayer
 
     GLuint skiaGLTex = SkiaGLTex();
     if (skiaGLTex) {
       SkiaGLGlue* glue = gfxPlatform::GetPlatform()->GetSkiaGLGlue();
       MOZ_ASSERT(glue);
 
       data.mGLContext = glue->GetGLContext();
       data.mFrontbufferGLTex = skiaGLTex;
+      PersistentBufferProvider *provider = GetBufferProvider(aManager);
+      data.mBufferProvider = provider;
     } else {
       PersistentBufferProvider *provider = GetBufferProvider(aManager);
       data.mBufferProvider = provider;
     }
 
     if (userData && userData->IsForContext(this) && aOldLayer->IsDataValid(data)) {
       RefPtr<CanvasLayer> ret = aOldLayer;
       return ret.forget();
@@ -5643,16 +5645,18 @@ CanvasRenderingContext2D::GetCanvasLayer
 
   GLuint skiaGLTex = SkiaGLTex();
   if (skiaGLTex) {
     SkiaGLGlue* glue = gfxPlatform::GetPlatform()->GetSkiaGLGlue();
     MOZ_ASSERT(glue);
 
     data.mGLContext = glue->GetGLContext();
     data.mFrontbufferGLTex = skiaGLTex;
+    PersistentBufferProvider *provider = GetBufferProvider(aManager);
+    data.mBufferProvider = provider;
   } else {
     PersistentBufferProvider *provider = GetBufferProvider(aManager);
     data.mBufferProvider = provider;
   }
 
   canvasLayer->Initialize(data);
   uint32_t flags = mOpaque ? Layer::CONTENT_OPAQUE : 0;
   canvasLayer->SetContentFlags(flags);
--- a/dom/fetch/Headers.h
+++ b/dom/fetch/Headers.h
@@ -97,16 +97,29 @@ public:
     return mInternalHeaders->Has(aName, aRv);
   }
 
   void Set(const nsACString& aName, const nsACString& aValue, ErrorResult& aRv)
   {
     mInternalHeaders->Set(aName, aValue, aRv);
   }
 
+  uint32_t GetIterableLength() const
+  {
+    return mInternalHeaders->GetIterableLength();
+  }
+  const nsString GetKeyAtIndex(unsigned aIndex) const
+  {
+    return mInternalHeaders->GetKeyAtIndex(aIndex);
+  }
+  const nsString GetValueAtIndex(unsigned aIndex) const
+  {
+    return mInternalHeaders->GetValueAtIndex(aIndex);
+  }
+
   // ChromeOnly
   HeadersGuardEnum Guard() const
   {
     return mInternalHeaders->Guard();
   }
 
   void SetGuard(HeadersGuardEnum aGuard, ErrorResult& aRv)
   {
--- a/dom/fetch/InternalHeaders.h
+++ b/dom/fetch/InternalHeaders.h
@@ -46,35 +46,53 @@ private:
 
 public:
   explicit InternalHeaders(HeadersGuardEnum aGuard = HeadersGuardEnum::None)
     : mGuard(aGuard)
   {
   }
 
   explicit InternalHeaders(const InternalHeaders& aOther)
-    : mGuard(aOther.mGuard)
+    : mGuard(HeadersGuardEnum::None)
   {
     ErrorResult result;
     Fill(aOther, result);
     MOZ_ASSERT(!result.Failed());
+    // Note that it's important to set the guard after Fill(), to make sure
+    // that Fill() doesn't fail if aOther is immutable.
+    mGuard = aOther.mGuard;
   }
 
   explicit InternalHeaders(const nsTArray<Entry>&& aHeaders,
                            HeadersGuardEnum aGuard = HeadersGuardEnum::None);
 
   void Append(const nsACString& aName, const nsACString& aValue,
               ErrorResult& aRv);
   void Delete(const nsACString& aName, ErrorResult& aRv);
   void Get(const nsACString& aName, nsCString& aValue, ErrorResult& aRv) const;
   void GetAll(const nsACString& aName, nsTArray<nsCString>& aResults,
               ErrorResult& aRv) const;
   bool Has(const nsACString& aName, ErrorResult& aRv) const;
   void Set(const nsACString& aName, const nsACString& aValue, ErrorResult& aRv);
 
+  uint32_t GetIterableLength() const
+  {
+    return mList.Length();
+  }
+  const NS_ConvertASCIItoUTF16 GetKeyAtIndex(unsigned aIndex) const
+  {
+    MOZ_ASSERT(aIndex < mList.Length());
+    return NS_ConvertASCIItoUTF16(mList[aIndex].mName);
+  }
+  const NS_ConvertASCIItoUTF16 GetValueAtIndex(unsigned aIndex) const
+  {
+    MOZ_ASSERT(aIndex < mList.Length());
+    return NS_ConvertASCIItoUTF16(mList[aIndex].mValue);
+  }
+
   void Clear();
 
   HeadersGuardEnum Guard() const { return mGuard; }
   void SetGuard(HeadersGuardEnum aGuard, ErrorResult& aRv);
 
   void Fill(const InternalHeaders& aInit, ErrorResult& aRv);
   void Fill(const Sequence<Sequence<nsCString>>& aInit, ErrorResult& aRv);
   void Fill(const MozMap<nsCString>& aInit, ErrorResult& aRv);
--- a/dom/html/test/formData_test.js
+++ b/dom/html/test/formData_test.js
@@ -100,16 +100,66 @@ function testFilename() {
   file = new File(["hi"], "file2.txt");
   f.append("file2", file, "fakename.txt");
   ok(f.get("file2") !== file, "Retrieved File object should be new File object if explicit filename is passed.");
   is(f.get("file2").name, "fakename.txt", "File's filename should be explicitly passed name.");
   f.append("file3", new File(["hi"], ""));
   is(f.get("file3").name, "", "File's filename is returned even if empty.");
 }
 
+function testIterable() {
+  var fd = new FormData();
+  fd.set('1','2');
+  fd.set('2','4');
+  fd.set('3','6');
+  fd.set('4','8');
+  fd.set('5','10');
+
+  var key_iter = fd.keys();
+  var value_iter = fd.values();
+  var entries_iter = fd.entries();
+  for (var i = 0; i < 5; ++i) {
+    var v = i + 1;
+    var key = key_iter.next();
+    var value = value_iter.next();
+    var entry = entries_iter.next();
+    is(key.value, v.toString(), "Correct Key iterator: " + v.toString());
+    ok(!key.done, "key.done is false");
+    is(value.value, (v * 2).toString(), "Correct Value iterator: " + (v * 2).toString());
+    ok(!value.done, "value.done is false");
+    is(entry.value[0], v.toString(), "Correct Entry 0 iterator: " + v.toString());
+    is(entry.value[1], (v * 2).toString(), "Correct Entry 1 iterator: " + (v * 2).toString());
+    ok(!entry.done, "entry.done is false");
+  }
+
+  var last = key_iter.next();
+  ok(last.done, "Nothing more to read.");
+  is(last.value, undefined, "Undefined is the last key");
+
+  last = value_iter.next();
+  ok(last.done, "Nothing more to read.");
+  is(last.value, undefined, "Undefined is the last value");
+
+  last = entries_iter.next();
+  ok(last.done, "Nothing more to read.");
+
+  key_iter = fd.keys();
+  key_iter.next();
+  key_iter.next();
+  fd.delete('1');
+  fd.delete('2');
+  fd.delete('3');
+  fd.delete('4');
+  fd.delete('5');
+
+  last = key_iter.next();
+  ok(last.done, "Nothing more to read.");
+  is(last.value, undefined, "Undefined is the last key");
+}
+
 function testSend(doneCb) {
   var xhr = new XMLHttpRequest();
   xhr.open("POST", "form_submit_server.sjs");
   xhr.onload = function () {
     var response = xhr.response;
 
     for (var entry of response) {
       is(entry.body, 'hey');
@@ -156,12 +206,13 @@ function testSend(doneCb) {
 function runTest(doneCb) {
   testHas();
   testGet();
   testGetAll();
   testDelete();
   testSet();
   testIterate();
   testFilename();
+  testIterable();
   // Finally, send an XHR and verify the response matches.
   testSend(doneCb);
 }
 
--- a/dom/media/MediaStreamGraph.cpp
+++ b/dom/media/MediaStreamGraph.cpp
@@ -2107,16 +2107,17 @@ SourceMediaStream::AddTrackInternal(Trac
                                     MediaSegment* aSegment, uint32_t aFlags)
 {
   MutexAutoLock lock(mMutex);
   nsTArray<TrackData> *track_data = (aFlags & ADDTRACK_QUEUED) ?
                                     &mPendingTracks : &mUpdateTracks;
   TrackData* data = track_data->AppendElement();
   data->mID = aID;
   data->mInputRate = aRate;
+  data->mResamplerChannelCount = 0;
   data->mStart = aStart;
   data->mEndOfFlushedData = aStart;
   data->mCommands = TRACK_CREATE;
   data->mData = aSegment;
   if (!(aFlags & ADDTRACK_QUEUED) && GraphImpl()) {
     GraphImpl()->EnsureNextIteration();
   }
 }
--- a/dom/media/webaudio/OscillatorNode.cpp
+++ b/dom/media/webaudio/OscillatorNode.cpp
@@ -32,16 +32,18 @@ public:
     , mDestination(aDestination->Stream())
     , mStart(-1)
     , mStop(STREAM_TIME_MAX)
     // Keep the default values in sync with OscillatorNode::OscillatorNode.
     , mFrequency(440.f)
     , mDetune(0.f)
     , mType(OscillatorType::Sine)
     , mPhase(0.)
+    , mFinalFrequency(0.)
+    , mPhaseIncrement(0.)
     , mRecomputeParameters(true)
     , mCustomLength(0)
   {
     MOZ_ASSERT(NS_IsMainThread());
     mBasicWaveFormCache = aDestination->Context()->GetBasicWaveFormCache();
   }
 
   void SetSourceStream(AudioNodeStream* aSource)
--- a/dom/presentation/PresentationDeviceManager.cpp
+++ b/dom/presentation/PresentationDeviceManager.cpp
@@ -16,17 +16,16 @@
 #include "PresentationSessionRequest.h"
 
 namespace mozilla {
 namespace dom {
 
 NS_IMPL_ISUPPORTS(PresentationDeviceManager,
                   nsIPresentationDeviceManager,
                   nsIPresentationDeviceListener,
-                  nsIPresentationDeviceEventListener,
                   nsIObserver,
                   nsISupportsWeakReference)
 
 PresentationDeviceManager::PresentationDeviceManager()
 {
 }
 
 PresentationDeviceManager::~PresentationDeviceManager()
@@ -175,17 +174,16 @@ PresentationDeviceManager::AddDevice(nsI
   NS_ENSURE_ARG(aDevice);
   MOZ_ASSERT(NS_IsMainThread());
 
   if (NS_WARN_IF(mDevices.Contains(aDevice))) {
     return NS_ERROR_FAILURE;
   }
 
   mDevices.AppendElement(aDevice);
-  aDevice->SetListener(this);
 
   NotifyDeviceChange(aDevice, MOZ_UTF16("add"));
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 PresentationDeviceManager::RemoveDevice(nsIPresentationDevice* aDevice)
@@ -193,17 +191,16 @@ PresentationDeviceManager::RemoveDevice(
   NS_ENSURE_ARG(aDevice);
   MOZ_ASSERT(NS_IsMainThread());
 
   int32_t index = mDevices.IndexOf(aDevice);
   if (NS_WARN_IF(index < 0)) {
     return NS_ERROR_FAILURE;
   }
 
-  mDevices[index]->SetListener(nullptr);
   mDevices.RemoveElementAt(index);
 
   NotifyDeviceChange(aDevice, MOZ_UTF16("remove"));
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
@@ -216,17 +213,16 @@ PresentationDeviceManager::UpdateDevice(
     return NS_ERROR_FAILURE;
   }
 
   NotifyDeviceChange(aDevice, MOZ_UTF16("update"));
 
   return NS_OK;
 }
 
-// nsIPresentationDeviceListener
 NS_IMETHODIMP
 PresentationDeviceManager::OnSessionRequest(nsIPresentationDevice* aDevice,
                                             const nsAString& aUrl,
                                             const nsAString& aPresentationId,
                                             nsIPresentationControlChannel* aControlChannel)
 {
   NS_ENSURE_ARG(aDevice);
   NS_ENSURE_ARG(aControlChannel);
--- a/dom/presentation/PresentationDeviceManager.h
+++ b/dom/presentation/PresentationDeviceManager.h
@@ -14,25 +14,23 @@
 #include "nsCOMArray.h"
 #include "nsWeakReference.h"
 
 namespace mozilla {
 namespace dom {
 
 class PresentationDeviceManager final : public nsIPresentationDeviceManager
                                       , public nsIPresentationDeviceListener
-                                      , public nsIPresentationDeviceEventListener
                                       , public nsIObserver
                                       , public nsSupportsWeakReference
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIPRESENTATIONDEVICEMANAGER
   NS_DECL_NSIPRESENTATIONDEVICELISTENER
-  NS_DECL_NSIPRESENTATIONDEVICEEVENTLISTENER
   NS_DECL_NSIOBSERVER
 
   PresentationDeviceManager();
 
 private:
   virtual ~PresentationDeviceManager();
 
   void Init();
--- a/dom/presentation/interfaces/nsIPresentationDevice.idl
+++ b/dom/presentation/interfaces/nsIPresentationDevice.idl
@@ -1,54 +1,32 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 
 interface nsIPresentationControlChannel;
-interface nsIPresentationDevice;
-
-/*
- * Event callbacks from remote presentation device.
- */
-[scriptable, uuid(81984458-b9d1-4731-a26a-ba62ab339aac)]
-interface nsIPresentationDeviceEventListener : nsISupports
-{
-  /*
-   * Callback while the remote device is requesting to start a presentation session.
-   * @param url The URL requested to open by remote device.
-   * @param presentationId The Id for representing this session.
-   * @param controlChannel The control channel for this session.
-   */
-  void onSessionRequest(in nsIPresentationDevice device,
-                        in DOMString url,
-                        in DOMString presentationId,
-                        in nsIPresentationControlChannel controlChannel);
-};
 
 /*
  * Remote device.
  */
-[scriptable, uuid(7fac99d4-9b19-4b8d-b5cd-5da8adbe58f1)]
+[scriptable, uuid(b1e0a7af-5936-4066-8f2e-f789fb9a7e8f)]
 interface nsIPresentationDevice : nsISupports
 {
   // The unique Id for the device. UUID is recommanded.
   readonly attribute AUTF8String id;
 
   // The human-readable name of this device.
   readonly attribute AUTF8String name;
 
   //TODO expose more info in order to fulfill UX spec
   // The category of this device, could be "wifi", "bluetooth", "hdmi", etc.
   readonly attribute AUTF8String type;
 
-  // The listener for handling remote session request.
-  attribute nsIPresentationDeviceEventListener listener;
-
   /*
    * Establish a control channel to this device.
    * @param url The URL requested to open by remote device.
    * @param presentationId The Id for representing this session.
    * @returns The control channel for this session.
    * @throws  NS_ERROR_FAILURE if the establishment fails
    */
   nsIPresentationControlChannel establishControlChannel(in DOMString url,
--- a/dom/presentation/interfaces/nsIPresentationDeviceProvider.idl
+++ b/dom/presentation/interfaces/nsIPresentationDeviceProvider.idl
@@ -1,29 +1,42 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 
 interface nsIPresentationDevice;
+interface nsIPresentationControlChannel;
 
 %{C++
 #define PRESENTATION_DEVICE_PROVIDER_CATEGORY "presentation-device-provider"
 %}
 
 /*
- * The callbacks for any device updates.
+ * The callbacks for any device updates and session request.
  */
-[scriptable, uuid(7f9f0514-d957-485a-90e8-57cc3acbf15b)]
+[scriptable, uuid(46fd372b-2e40-4179-9b36-0478d141e440)]
 interface nsIPresentationDeviceListener: nsISupports
 {
   void addDevice(in nsIPresentationDevice device);
   void removeDevice(in nsIPresentationDevice device);
   void updateDevice(in nsIPresentationDevice device);
+
+  /*
+   * Callback while the remote device is requesting to start a presentation session.
+   * @param device The remote device that sent session request.
+   * @param url The URL requested to open by remote device.
+   * @param presentationId The Id for representing this session.
+   * @param controlChannel The control channel for this session.
+   */
+  void onSessionRequest(in nsIPresentationDevice device,
+                        in DOMString url,
+                        in DOMString presentationId,
+                        in nsIPresentationControlChannel controlChannel);
 };
 
 /*
  * Device provider for any device protocol, can be registered as default
  * providers by adding its contractID to category "presentation-device-provider".
  */
 [scriptable, uuid(3db2578a-0f50-44ad-b01b-28427b71b7bf)]
 interface nsIPresentationDeviceProvider: nsISupports
--- a/dom/presentation/interfaces/nsITCPPresentationServer.idl
+++ b/dom/presentation/interfaces/nsITCPPresentationServer.idl
@@ -1,32 +1,60 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 
-interface nsIPresentationDevice;
+interface nsIPresentationControlChannel;
+
+%{C++
+#define TCP_PRESENTATION_SERVER_CONTACT_ID \
+  "@mozilla.org/presentation-device/tcp-presentation-server;1"
+%}
 
-[scriptable, uuid(b0dc6b1f-5f6f-455d-a917-90d0ad37186b)]
+/*
+ * The device information required for establishing TCP control channel.
+ */
+[scriptable, uuid(7fce55c0-2470-4a41-a3b9-c35fbe55f206)]
+interface nsITCPDeviceInfo: nsISupports
+{
+  readonly attribute AUTF8String id;
+  readonly attribute AUTF8String host;
+  readonly attribute uint16_t port;
+};
+
+[scriptable, uuid(fbb890a9-9e95-47d1-a425-86fd95881d81)]
 interface nsITCPPresentationServerListener: nsISupports
 {
   /**
    * Callback while the server socket stops listening.
    * @param   aReason
    *          The reason of the socket close. NS_OK for manually |close|.
    *          <other-error> on failure.
    */
   void onClose(in nsresult aReason);
+
+  /**
+   * Callback while the remote host is requesting to start a presentation session.
+   * @param aDeviceInfo The device information related to the remote host.
+   * @param aUrl The URL requested to open by remote device.
+   * @param aPresentationId The Id for representing this session.
+   * @param aControlChannel The control channel for this session.
+   */
+  void onSessionRequest(in nsITCPDeviceInfo aDeviceInfo,
+                        in DOMString aUrl,
+                        in DOMString aPresentationId,
+                        in nsIPresentationControlChannel aControlChannel);
 };
 
 /**
  * TCP presentation server which can be used by discovery services.
  */
-[scriptable, uuid(fcadc9fe-f1e9-4f74-b9d3-9cd6b74afc9e)]
+[scriptable, uuid(494237ec-c567-41ab-afc9-82d26c4fe1dc)]
 interface nsITCPPresentationServer: nsISupports
 {
   /**
    * This method initializes a TCP presentation server.
    * @param   aId
    *          The unique Id for the device within the discovery scope. If aId
    *          is null, empty string or opt-out, the TCP presentation server
    *          should not work until the |id| is set appropriately.
@@ -34,80 +62,37 @@ interface nsITCPPresentationServer: nsIS
    *          The port of the server socket.  Pass 0 or opt-out to indicate no
    *          preference, and a port will be selected automatically.
    * @throws  NS_ERROR_FAILURE if the server socket has been inited or the
    *          server socket can not be inited.
    */
   void init([optional] in AUTF8String aId, [optional] in uint16_t aPort);
 
   /**
+   * Request session to designated remote TCP device.
+   * @param   aDeviceInfo
+   *          The remtoe device info for establish connection.
+   * @param   aUrl
+   *          The URL requested to open by remote device.
+   * @param   aPresentationId
+   *          The Id for representing this session.
+   * @returns The control channel for this session.
+   * @throws  NS_ERROR_FAILURE if the server socket has been inited or the
+   *          server socket can not be inited.
+   */
+  nsIPresentationControlChannel requestSession(in nsITCPDeviceInfo aDeviceInfo,
+                                               in DOMString aUrl,
+                                               in DOMString aPresentationId);
+
+  /**
    * Close server socket and call |listener.onClose(NS_OK)|
    */
   void close();
 
   /**
-   * Create TCPDevice for this server.
-   * @param   aId
-   *          The unique Id for the discovered device
-   * @param   aName
-   *          The human-readable name of the discovered device
-   * @param   aType
-   *          The category of the discovered device
-   * @param   aHost
-   *          The host of the provided control channel of the discovered device
-   * @param   aPort
-   *          The port of the provided control channel of the discovered device
-   * @returns The created device
-   * @throws  NS_ERROR_INVALID_ARG if a TCPDevice with |aId| have existed.
-   */
-  nsIPresentationDevice createTCPDevice(in AUTF8String aId,
-                                        in AUTF8String aName,
-                                        in AUTF8String aType,
-                                        in AUTF8String aHost,
-                                        in uint16_t aPort);
-
-  /**
-   * Update TCPDevice for this server.
-   * @param   aId
-   *          The unique Id for the discovered device
-   * @param   aName
-   *          The human-readable name of the discovered device
-   * @param   aType
-   *          The category of the discovered device
-   * @param   aHost
-   *          The host of the provided control channel of the discovered device
-   * @param   aPort
-   *          The port of the provided control channel of the discovered device
-   * @returns The updated device
-   * @throws  NS_ERROR_INVALID_ARG if a TCPDevice with |aId| does not existed.
-   */
-  nsIPresentationDevice updateTCPDevice(in AUTF8String aId,
-                                        in AUTF8String aName,
-                                        in AUTF8String aType,
-                                        in AUTF8String aHost,
-                                        in uint16_t aPort);
-
-  /**
-   * Get TCPDevice with |aID|.
-   * @param   aId
-   *          The unique Id for the query device
-   * @returns The queried device; return |undefined|
-   * @throws  NS_ERROR_INVALID_ARG if a TCPDevice with |aId| does not exist.
-   */
-  nsIPresentationDevice getTCPDevice(in AUTF8String aId);
-
-  /**
-   * Remove TCPDevice with |aID|.
-   * @param   aId
-   *          The unique Id for the device which needs to be removed
-   * @throws  NS_ERROR_INVALID_ARG if a TCPDevice with |aId| does not exist.
-   */
-  void removeTCPDevice(in AUTF8String aId);
-
-  /**
    * Get the listen port of the TCP socket, valid after |init|. 0 indicates
    * the server socket is not inited or closed.
    */
   readonly attribute uint16_t port;
 
   /**
    * The id of the TCP presentation server. The setter should be use if the |id|
    * is not set by the |init|. Moreover, if the |id| is not set by |init|, the
--- a/dom/presentation/provider/MulticastDNSDeviceProvider.cpp
+++ b/dom/presentation/provider/MulticastDNSDeviceProvider.cpp
@@ -7,27 +7,23 @@
 #include "MainThreadUtils.h"
 #include "mozilla/Logging.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Services.h"
 #include "mozilla/unused.h"
 #include "nsAutoPtr.h"
 #include "nsComponentManagerUtils.h"
 #include "nsIObserverService.h"
-#include "nsIPresentationDevice.h"
 #include "nsServiceManagerUtils.h"
 
 #define PREF_PRESENTATION_DISCOVERY "dom.presentation.discovery.enabled"
 #define PREF_PRESENTATION_DISCOVERY_TIMEOUT_MS "dom.presentation.discovery.timeout_ms"
 #define PREF_PRESENTATION_DISCOVERABLE "dom.presentation.discoverable"
 #define PREF_PRESENTATION_DEVICE_NAME "dom.presentation.device.name"
 
-#define TCP_PRESENTATION_SERVER_CONTACT_ID \
-  "@mozilla.org/presentation-device/tcp-presentation-server;1"
-
 #define SERVICE_TYPE "_mozilla_papi._tcp."
 
 inline static PRLogModuleInfo*
 GetProviderLog()
 {
   static PRLogModuleInfo* log = PR_NewLogModule("MulticastDNSDeviceProvider");
   return log;
 }
@@ -43,16 +39,68 @@ namespace presentation {
 static const char* kObservedPrefs[] = {
   PREF_PRESENTATION_DISCOVERY,
   PREF_PRESENTATION_DISCOVERY_TIMEOUT_MS,
   PREF_PRESENTATION_DISCOVERABLE,
   PREF_PRESENTATION_DEVICE_NAME,
   nullptr
 };
 
+namespace {
+
+class TCPDeviceInfo final : public nsITCPDeviceInfo
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSITCPDEVICEINFO
+
+  explicit TCPDeviceInfo(const nsACString& aId,
+                         const nsACString& aHost,
+                         const uint16_t aPort)
+    : mId(aId)
+    , mHost(aHost)
+    , mPort(aPort)
+  {
+  }
+
+private:
+  virtual ~TCPDeviceInfo() {}
+
+  nsCString mId;
+  nsCString mHost;
+  uint16_t mPort;
+};
+
+NS_IMPL_ISUPPORTS(TCPDeviceInfo,
+                  nsITCPDeviceInfo)
+
+// nsITCPDeviceInfo
+NS_IMETHODIMP
+TCPDeviceInfo::GetId(nsACString& aId)
+{
+  aId = mId;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+TCPDeviceInfo::GetHost(nsACString& aHost)
+{
+  aHost = mHost;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+TCPDeviceInfo::GetPort(uint16_t* aPort)
+{
+  *aPort = mPort;
+  return NS_OK;
+}
+
+} //anonymous namespace
+
 /**
  * This wrapper is used to break circular-reference problem.
  */
 class DNSServiceWrappedListener final
   : public nsIDNSServiceDiscoveryListener
   , public nsIDNSRegistrationListener
   , public nsIDNSServiceResolveListener
   , public nsITCPPresentationServerListener
@@ -257,43 +305,54 @@ MulticastDNSDeviceProvider::StopDiscover
     mDiscoveryRequest->Cancel(aReason);
     mDiscoveryRequest = nullptr;
   }
 
   return NS_OK;
 }
 
 nsresult
+MulticastDNSDeviceProvider::RequestSession(Device* aDevice,
+                                           const nsAString& aUrl,
+                                           const nsAString& aPresentationId,
+                                           nsIPresentationControlChannel** aRetVal)
+{
+  MOZ_ASSERT(aDevice);
+  MOZ_ASSERT(mPresentationServer);
+
+  RefPtr<TCPDeviceInfo> deviceInfo = new TCPDeviceInfo(aDevice->Id(),
+                                                       aDevice->Host(),
+                                                       aDevice->Port());
+
+  return mPresentationServer->RequestSession(deviceInfo, aUrl, aPresentationId, aRetVal);
+}
+
+nsresult
 MulticastDNSDeviceProvider::AddDevice(const nsACString& aServiceName,
                                       const nsACString& aServiceType,
                                       const nsACString& aHost,
                                       const uint16_t aPort)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mPresentationServer);
 
-  nsresult rv;
-
-  nsCOMPtr<nsIPresentationDevice> device;
-  if (NS_WARN_IF(NS_FAILED(rv =
-      mPresentationServer->CreateTCPDevice(aHost, /* ID */
-                                           aServiceName,
-                                           aServiceType,
-                                           aHost,
-                                           aPort,
-                                           getter_AddRefs(device))))) {
-    return rv;
-  }
+  RefPtr<Device> device = new Device(aHost, /* ID */
+                                     aServiceName,
+                                     aServiceType,
+                                     aHost,
+                                     aPort,
+                                     DeviceState::eActive,
+                                     this);
 
   nsCOMPtr<nsIPresentationDeviceListener> listener;
   if (NS_SUCCEEDED(GetListener(getter_AddRefs(listener))) && listener) {
     unused << listener->AddDevice(device);
   }
 
-  mDevices.AppendElement(Device(aHost, DeviceState::eActive));
+  mDevices.AppendElement(device);
 
   return NS_OK;
 }
 
 nsresult
 MulticastDNSDeviceProvider::UpdateDevice(const uint32_t aIndex,
                                          const nsACString& aServiceName,
                                          const nsACString& aServiceType,
@@ -302,110 +361,116 @@ MulticastDNSDeviceProvider::UpdateDevice
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mPresentationServer);
 
   if (NS_WARN_IF(aIndex >= mDevices.Length())) {
     return NS_ERROR_INVALID_ARG;
   }
 
-  nsresult rv;
-
-  nsCOMPtr<nsIPresentationDevice> device;
-  if (NS_WARN_IF(NS_FAILED(rv =
-      mPresentationServer->UpdateTCPDevice(aHost, /* ID */
-                                           aServiceName,
-                                           aServiceType,
-                                           aHost,
-                                           aPort,
-                                           getter_AddRefs(device))))) {
-    return rv;
-  }
+  RefPtr<Device> device = mDevices[aIndex];
+  device->Update(aServiceName, aServiceType, aHost, aPort);
+  device->ChangeState(DeviceState::eActive);
 
   nsCOMPtr<nsIPresentationDeviceListener> listener;
   if (NS_SUCCEEDED(GetListener(getter_AddRefs(listener))) && listener) {
     unused << listener->UpdateDevice(device);
   }
 
-  mDevices[aIndex].state = DeviceState::eActive;
-
   return NS_OK;
 }
 
 nsresult
 MulticastDNSDeviceProvider::RemoveDevice(const uint32_t aIndex)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mPresentationServer);
 
   if (NS_WARN_IF(aIndex >= mDevices.Length())) {
     return NS_ERROR_INVALID_ARG;
   }
 
-  nsCString deviceId = mDevices[aIndex].id;
-  LOG_I("RemoveDevice: %s", deviceId.get());
+  RefPtr<Device> device = mDevices[aIndex];
 
-  nsCOMPtr<nsIPresentationDevice> device;
-  if (NS_FAILED(mPresentationServer->GetTCPDevice(deviceId,
-                                                  getter_AddRefs(device)))) {
-    LOG_I("ignore non-existing device: %s", deviceId.get());
-    return NS_OK;
-  }
-
-  nsresult rv;
-  if (NS_WARN_IF(NS_FAILED(rv = mPresentationServer->RemoveTCPDevice(deviceId)))) {
-    return rv;
-  }
+  LOG_I("RemoveDevice: %s", device->Id().get());
+  mDevices.RemoveElementAt(aIndex);
 
   nsCOMPtr<nsIPresentationDeviceListener> listener;
   if (NS_SUCCEEDED(GetListener(getter_AddRefs(listener))) && listener) {
     unused << listener->RemoveDevice(device);
   }
 
-  mDevices.RemoveElementAt(aIndex);
   return NS_OK;
 }
 
 bool
-MulticastDNSDeviceProvider::FindDevice(const nsACString& aId,
-                                       uint32_t& aIndex)
+MulticastDNSDeviceProvider::FindDeviceById(const nsACString& aId,
+                                           uint32_t& aIndex)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  size_t index = mDevices.IndexOf(Device(aId, DeviceState::eUnknown),
-                                  0,
-                                  DeviceIdComparator());
+  RefPtr<Device> device = new Device(aId,
+                                     /* aName = */ EmptyCString(),
+                                     /* aType = */ EmptyCString(),
+                                     /* aHost = */ EmptyCString(),
+                                     /* aPort = */ 0,
+                                     /* aState = */ DeviceState::eUnknown,
+                                     /* aProvider = */ nullptr);
+  size_t index = mDevices.IndexOf(device, 0, DeviceIdComparator());
+
+  if (index == mDevices.NoIndex) {
+    return false;
+  }
+
+  aIndex = index;
+  return true;
+}
+
+bool
+MulticastDNSDeviceProvider::FindDeviceByHost(const nsACString& aHost,
+                                             uint32_t& aIndex)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  RefPtr<Device> device = new Device(/* aId = */ EmptyCString(),
+                                     /* aName = */ EmptyCString(),
+                                     /* aType = */ EmptyCString(),
+                                     aHost,
+                                     /* aPort = */ 0,
+                                     /* aState = */ DeviceState::eUnknown,
+                                     /* aProvider = */ nullptr);
+  size_t index = mDevices.IndexOf(device, 0, DeviceHostComparator());
 
   if (index == mDevices.NoIndex) {
     return false;
   }
 
   aIndex = index;
   return true;
 }
 
 void
 MulticastDNSDeviceProvider::MarkAllDevicesUnknown()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   for (auto& device : mDevices) {
-    device.state = DeviceState::eUnknown;
+    device->ChangeState(DeviceState::eUnknown);
   }
 }
 
 void
 MulticastDNSDeviceProvider::ClearUnknownDevices()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   size_t i = mDevices.Length();
   while (i > 0) {
     --i;
-    if (mDevices[i].state == DeviceState::eUnknown) {
+    if (mDevices[i]->State() == DeviceState::eUnknown) {
       NS_WARN_IF(NS_FAILED(RemoveDevice(i)));
     }
   }
 }
 
 void
 MulticastDNSDeviceProvider::ClearDevices()
 {
@@ -584,17 +649,17 @@ MulticastDNSDeviceProvider::OnServiceLos
   LOG_I("OnServiceLost: %s", serviceName.get());
 
   nsAutoCString host;
   if (NS_WARN_IF(NS_FAILED(rv = aServiceInfo->GetHost(host)))) {
     return rv;
   }
 
   uint32_t index;
-  if (!FindDevice(host, index)) {
+  if (!FindDeviceById(host, index)) {
     // given device was not found
     return NS_OK;
   }
 
   if (NS_WARN_IF(NS_FAILED(rv = RemoveDevice(index)))) {
     return rv;
   }
 
@@ -716,17 +781,17 @@ MulticastDNSDeviceProvider::OnServiceRes
   }
 
   nsAutoCString serviceType;
   if (NS_WARN_IF(NS_FAILED(rv = aServiceInfo->GetServiceType(serviceType)))) {
     return rv;
   }
 
   uint32_t index;
-  if (FindDevice(host, index)) {
+  if (FindDeviceById(host, index)) {
     return UpdateDevice(index,
                         serviceName,
                         serviceType,
                         host,
                         port);
   } else {
     return AddDevice(serviceName,
                      serviceType,
@@ -753,22 +818,62 @@ MulticastDNSDeviceProvider::OnClose(nsre
 {
   LOG_I("OnClose: %x", aReason);
   MOZ_ASSERT(NS_IsMainThread());
 
   UnregisterService(aReason);
 
   nsresult rv;
 
-  if (mDiscoveryEnabled && NS_WARN_IF(NS_FAILED(rv = ForceDiscovery()))) {
+  if (mDiscoverable && NS_WARN_IF(NS_FAILED(rv = RegisterService()))) {
     return rv;
   }
 
-  if (mDiscoverable && NS_WARN_IF(NS_FAILED(rv = RegisterService()))) {
-    return rv;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+MulticastDNSDeviceProvider::OnSessionRequest(nsITCPDeviceInfo* aDeviceInfo,
+                                             const nsAString& aUrl,
+                                             const nsAString& aPresentationId,
+                                             nsIPresentationControlChannel* aControlChannel)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  nsAutoCString host;
+  unused << aDeviceInfo->GetHost(host);
+
+  LOG_I("OnSessionRequest: %s", host.get());
+
+  RefPtr<Device> device;
+  uint32_t index;
+  if (FindDeviceByHost(host, index)) {
+    device = mDevices[index];
+  } else {
+    // create a one-time device object for non-discoverable controller
+    // this device will not be listed in available device list and cannot
+    // be used for requesting session.
+    nsAutoCString id;
+    unused << aDeviceInfo->GetId(id);
+    uint16_t port;
+    unused << aDeviceInfo->GetPort(&port);
+
+    device = new Device(id,
+                        /* aName = */ id,
+                        /* aType = */ EmptyCString(),
+                        host,
+                        port,
+                        DeviceState::eActive,
+                        /* aProvider = */ nullptr);
+  }
+
+  nsCOMPtr<nsIPresentationDeviceListener> listener;
+  if (NS_SUCCEEDED(GetListener(getter_AddRefs(listener))) && listener) {
+    unused << listener->OnSessionRequest(device, aUrl, aPresentationId,
+                                         aControlChannel);
   }
 
   return NS_OK;
 }
 
 // nsIObserver
 NS_IMETHODIMP
 MulticastDNSDeviceProvider::Observe(nsISupports* aSubject,
@@ -853,11 +958,52 @@ MulticastDNSDeviceProvider::OnServiceNam
 
   if (mDiscoverable) {
     return RegisterService();
   }
 
   return NS_OK;
 }
 
+// MulticastDNSDeviceProvider::Device
+NS_IMPL_ISUPPORTS(MulticastDNSDeviceProvider::Device,
+                  nsIPresentationDevice)
+
+// nsIPresentationDevice
+NS_IMETHODIMP
+MulticastDNSDeviceProvider::Device::GetId(nsACString& aId)
+{
+  aId = mId;
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+MulticastDNSDeviceProvider::Device::GetName(nsACString& aName)
+{
+  aName = mName;
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+MulticastDNSDeviceProvider::Device::GetType(nsACString& aType)
+{
+  aType = mType;
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+MulticastDNSDeviceProvider::Device::EstablishControlChannel(const nsAString& aUrl,
+                                                            const nsAString& aPresentationId,
+                                                            nsIPresentationControlChannel** aRetVal)
+{
+  if (!mProvider) {
+    return NS_ERROR_FAILURE;
+  }
+
+  return mProvider->RequestSession(this, aUrl, aPresentationId, aRetVal);
+}
+
 } // namespace presentation
 } // namespace dom
 } // namespace mozilla
--- a/dom/presentation/provider/MulticastDNSDeviceProvider.h
+++ b/dom/presentation/provider/MulticastDNSDeviceProvider.h
@@ -6,16 +6,17 @@
 #ifndef mozilla_dom_presentation_provider_MulticastDNSDeviceProvider_h
 #define mozilla_dom_presentation_provider_MulticastDNSDeviceProvider_h
 
 #include "mozilla/RefPtr.h"
 #include "nsCOMPtr.h"
 #include "nsICancelable.h"
 #include "nsIDNSServiceDiscovery.h"
 #include "nsIObserver.h"
+#include "nsIPresentationDevice.h"
 #include "nsIPresentationDeviceProvider.h"
 #include "nsITCPPresentationServer.h"
 #include "nsITimer.h"
 #include "nsString.h"
 #include "nsTArray.h"
 #include "nsWeakPtr.h"
 
 namespace mozilla {
@@ -47,51 +48,125 @@ public:
   nsresult Uninit();
 
 private:
   enum class DeviceState : uint32_t {
     eUnknown,
     eActive
   };
 
-  struct Device final {
-    explicit Device(const nsACString& aId, DeviceState aState)
-      : id(aId), state(aState)
+  class Device final : public nsIPresentationDevice
+  {
+  public:
+    NS_DECL_ISUPPORTS
+    NS_DECL_NSIPRESENTATIONDEVICE
+
+    explicit Device(const nsACString& aId,
+                    const nsACString& aName,
+                    const nsACString& aType,
+                    const nsACString& aHost,
+                    const uint16_t aPort,
+                    DeviceState aState,
+                    MulticastDNSDeviceProvider* aProvider)
+      : mId(aId)
+      , mName(aName)
+      , mType(aType)
+      , mHost(aHost)
+      , mPort(aPort)
+      , mState(aState)
+      , mProvider(aProvider)
     {
     }
 
-    nsCString id;
-    DeviceState state;
+    const nsCString& Id() const
+    {
+      return mId;
+    }
+
+    const nsCString& Host() const
+    {
+      return mHost;
+    }
+
+    const uint16_t Port() const
+    {
+      return mPort;
+    }
+
+    const DeviceState State() const
+    {
+      return mState;
+    }
+
+    void ChangeState(DeviceState aState)
+    {
+      mState = aState;
+    }
+
+    void Update(const nsACString& aName,
+                const nsACString& aType,
+                const nsACString& aHost,
+                const uint16_t aPort)
+    {
+      mName = aName;
+      mType = aType;
+      mHost = aHost;
+      mPort = aPort;
+    }
+
+  private:
+    virtual ~Device() = default;
+
+    nsCString mId;
+    nsCString mName;
+    nsCString mType;
+    nsCString mHost;
+    uint16_t mPort;
+    DeviceState mState;
+    MulticastDNSDeviceProvider* mProvider;
   };
 
   struct DeviceIdComparator {
-    bool Equals(const Device& aA, const Device& aB) const {
-      return aA.id == aB.id;
+    bool Equals(const RefPtr<Device>& aA, const RefPtr<Device>& aB) const {
+      return aA->Id() == aB->Id();
+    }
+  };
+
+  struct DeviceHostComparator {
+    bool Equals(const RefPtr<Device>& aA, const RefPtr<Device>& aB) const {
+      return aA->Host() == aB->Host();
     }
   };
 
   virtual ~MulticastDNSDeviceProvider();
   nsresult RegisterService();
   nsresult UnregisterService(nsresult aReason);
   nsresult StopDiscovery(nsresult aReason);
+  nsresult RequestSession(Device* aDevice,
+                          const nsAString& aUrl,
+                          const nsAString& aPresentationId,
+                          nsIPresentationControlChannel** aRetVal);
 
   // device manipulation
   nsresult AddDevice(const nsACString& aServiceName,
                      const nsACString& aServiceType,
                      const nsACString& aHost,
                      const uint16_t aPort);
   nsresult UpdateDevice(const uint32_t aIndex,
                         const nsACString& aServiceName,
                         const nsACString& aServiceType,
                         const nsACString& aHost,
                         const uint16_t aPort);
   nsresult RemoveDevice(const uint32_t aIndex);
-  bool FindDevice(const nsACString& aId,
+  bool FindDeviceById(const nsACString& aId,
                       uint32_t& aIndex);
 
+  bool FindDeviceByHost(const nsACString& aHost,
+                        uint32_t& aIndex);
+
   void MarkAllDevicesUnknown();
   void ClearUnknownDevices();
   void ClearDevices();
 
   // preferences
   nsresult OnDiscoveryChanged(bool aEnabled);
   nsresult OnDiscoveryTimeoutChanged(uint32_t aTimeoutMs);
   nsresult OnDiscoverableChanged(bool aEnabled);
@@ -101,17 +176,17 @@ private:
   nsWeakPtr mDeviceListener;
   nsCOMPtr<nsITCPPresentationServer> mPresentationServer;
   nsCOMPtr<nsIDNSServiceDiscovery> mMulticastDNS;
   RefPtr<DNSServiceWrappedListener> mWrappedListener;
 
   nsCOMPtr<nsICancelable> mDiscoveryRequest;
   nsCOMPtr<nsICancelable> mRegisterRequest;
 
-  nsTArray<Device> mDevices;
+  nsTArray<RefPtr<Device>> mDevices;
 
   bool mDiscoveryEnabled = false;
   bool mIsDiscovering = false;
   uint32_t mDiscveryTimeoutMs;
   nsCOMPtr<nsITimer> mDiscoveryTimer;
 
   bool mDiscoverable = false;
 
--- a/dom/presentation/provider/TCPPresentationServer.js
+++ b/dom/presentation/provider/TCPPresentationServer.js
@@ -9,29 +9,26 @@ Cu.import("resource://gre/modules/XPCOMU
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/NetUtil.jsm");
 
 const DEBUG = Services.prefs.getBoolPref("dom.presentation.tcp_server.debug");
 function log(aMsg) {
   dump("-*- TCPPresentationServer.js: " + aMsg + "\n");
 }
 
-function TCPDeviceInfo(aHost, aPort, aId, aName, aType) {
+function TCPDeviceInfo(aHost, aPort, aId) {
   this.host = aHost;
   this.port = aPort;
   this.id = aId;
-  this.name = aName;
-  this.type = aType;
 }
 
 function TCPPresentationServer() {
   this._id = null;
   this._port = 0;
   this._serverSocket = null;
-  this._devices = new Map(); // id -> device
 }
 
 TCPPresentationServer.prototype = {
   /**
    * If a user agent connects to this server, we create a control channel but
    * hand it to |TCPDevice.listener| when the initial information exchange
    * finishes. Therefore, we hold the control channels in this period.
    */
@@ -108,130 +105,80 @@ TCPPresentationServer.prototype = {
   get listener() {
     return this._listener;
   },
 
   _isInit: function() {
     return this._id !== null && this._serverSocket !== null;
   },
 
-  createTCPDevice: function(aId, aName, aType, aHost, aPort) {
-    DEBUG && log("TCPPresentationServer - createTCPDevice with id: " + aId);
-    if (this._devices.has(aId)) {
-      throw Cr.NS_ERROR_INVALID_ARG;
-    }
-
-    this._devices.set(aId, new TCPDevice(this, {id: aId,
-                                                name: aName,
-                                                type: aType,
-                                                host: aHost,
-                                                port: aPort}));
-    return this._devices.get(aId);
-  },
-
-  updateTCPDevice: function(aId, aName, aType, aHost, aPort) {
-    DEBUG && log("TCPPresentationServer - updateTCPDevice with id: " + aId);
-    if (!this._devices.has(aId)) {
-      throw Cr.NS_ERROR_INVALID_ARG;
-    }
-
-    let device = this._devices.get(aId);
-    device.name = aName;
-    device.type = aType;
-    device.host = aHost;
-    device.port = aPort;
-
-    return device;
-  },
-
-  getTCPDevice: function(aId) {
-    DEBUG && log("TCPPresentationServer - getTCPDevice with id: " + aId);
-    if (!this._devices.has(aId)) {
-      throw Cr.NS_ERROR_INVALID_ARG;
-    }
-    return this._devices.get(aId);
-  },
-
-  removeTCPDevice: function(aId) {
-    DEBUG && log("TCPPresentationServer - removeTCPDevice with id: " + aId);
-    if (!this._devices.has(aId)) {
-      throw Cr.NS_ERROR_INVALID_ARG;
-    }
-    this._devices.delete(aId);
-  },
-
-  requestSession: function(aDevice, aUrl, aPresentationId) {
+  requestSession: function(aDeviceInfo, aUrl, aPresentationId) {
     if (!this._isInit()) {
       DEBUG && log("TCPPresentationServer - has not initialized; requestSession fails");
       return null;
     }
-    DEBUG && log("TCPPresentationServer - requestSession to " + aDevice.name
+    DEBUG && log("TCPPresentationServer - requestSession to " + aDeviceInfo.id
                  + ": " + aUrl + ", " + aPresentationId);
 
     let sts = Cc["@mozilla.org/network/socket-transport-service;1"]
                 .getService(Ci.nsISocketTransportService)
 
     let socketTransport;
     try {
       socketTransport = sts.createTransport(null,
                                             0,
-                                            aDevice.host,
-                                            aDevice.port,
+                                            aDeviceInfo.host,
+                                            aDeviceInfo.port,
                                             null);
     } catch (e) {
       DEBUG && log("TCPPresentationServer - createTransport throws: " + e);
       // Pop the exception to |TCPDevice.establishControlChannel|
       throw Cr.NS_ERROR_FAILURE;
     }
     return new TCPControlChannel(this,
                                  socketTransport,
-                                 aDevice,
+                                 aDeviceInfo,
                                  aPresentationId,
                                  "sender",
                                  aUrl);
   },
 
-  responseSession: function(aDevice, aSocketTransport) {
+  responseSession: function(aDeviceInfo, aSocketTransport) {
     if (!this._isInit()) {
       DEBUG && log("TCPPresentationServer - has not initialized; responseSession fails");
       return null;
     }
     DEBUG && log("TCPPresentationServer - responseSession to "
-                 + JSON.stringify(aDevice));
+                 + JSON.stringify(aDeviceInfo));
     return new TCPControlChannel(this,
                                  aSocketTransport,
-                                 aDevice,
+                                 aDeviceInfo,
                                  null, // presentation ID
                                  "receiver",
                                  null // url
                                  );
   },
 
   // Triggered by TCPControlChannel
-  onSessionRequest: function(aId, aUrl, aPresentationId, aControlChannel) {
-    let device = this._devices.get(aId);
-    if (!device) {
-      //XXX Bug 1136565 - should have a way to recovery
-      DEBUG && log("TCPPresentationServer - onSessionRequest not found device for id: "
-                   + aId );
-      return;
-    }
-    device.listener.onSessionRequest(device,
-                                     aUrl,
-                                     aPresentationId,
-                                     aControlChannel);
+  onSessionRequest: function(aDeviceInfo, aUrl, aPresentationId, aControlChannel) {
+    DEBUG && log("TCPPresentationServer - onSessionRequest: "
+                 + aDeviceInfo.host + ":" + aDeviceInfo.port);
+    this.listener.onSessionRequest(aDeviceInfo,
+                                   aUrl,
+                                   aPresentationId,
+                                   aControlChannel);
     this.releaseControlChannel(aControlChannel);
   },
 
   // nsIServerSocketListener (Triggered by nsIServerSocket.init)
   onSocketAccepted: function(aServerSocket, aClientSocket) {
     DEBUG && log("TCPPresentationServer - onSocketAccepted: "
                  + aClientSocket.host + ":" + aClientSocket.port);
-    let device = new TCPDeviceInfo(aClientSocket.host, aClientSocket.port);
-    this.holdControlChannel(this.responseSession(device, aClientSocket));
+    let deviceInfo = new TCPDeviceInfo(aClientSocket.host, aClientSocket.port);
+    this.holdControlChannel(this.responseSession(deviceInfo, aClientSocket));
   },
 
   holdControlChannel: function(aControlChannel) {
     this._controlChannels.push(aControlChannel);
   },
 
   releaseControlChannel: function(aControlChannel) {
     let index = this._controlChannels.indexOf(aControlChannel);
@@ -259,17 +206,16 @@ TCPPresentationServer.prototype = {
     DEBUG && log("TCPPresentationServer - close");
     if (this._serverSocket) {
       DEBUG && log("TCPPresentationServer - close server socket");
       this._serverSocket.close();
       this._serverSocket = null;
     }
     this._id = null;
     this._port = 0;
-    this._devices && this._devices.clear();
   },
 
   classID: Components.ID("{f4079b8b-ede5-4b90-a112-5b415a931deb}"),
   QueryInterface : XPCOMUtils.generateQI([Ci.nsIServerSocketListener,
                                           Ci.nsITCPPresentationServer]),
 };
 
 function ChannelDescription(aInit) {
@@ -337,23 +283,23 @@ function discriptionAsJson(aDescription)
       json.dataChannelSDP = aDescription.dataChannelSDP;
       break;
   }
   return json;
 }
 
 function TCPControlChannel(presentationServer,
                            transport,
-                           device,
+                           deviceInfo,
                            presentationId,
                            direction,
                            url) {
   DEBUG && log("create TCPControlChannel: " + presentationId + " with role: "
                + direction);
-  this._device = device;
+  this._deviceInfo = deviceInfo;
   this._presentationId = presentationId;
   this._direction = direction;
   this._transport = transport;
   this._url = url;
 
   this._presentationServer =  presentationServer;
 
   let currentThread = Services.tm.currentThread;
@@ -537,23 +483,23 @@ TCPControlChannel.prototype = {
                createInstance(Ci.nsIInputStreamPump);
     this._pump.init(this._input, -1, -1, 0, 0, false);
     this._pump.asyncRead(this, null);
   },
 
   // Handle command from remote side
   _handleMessage: function(aMsg) {
     DEBUG && log("TCPControlChannel - handleMessage from "
-                 + JSON.stringify(this._device) + ": " + JSON.stringify(aMsg));
+                 + JSON.stringify(this._deviceInfo) + ": " + JSON.stringify(aMsg));
     switch (aMsg.type) {
       case "requestSession:Init": {
-        this._device.id = aMsg.id;
+        this._deviceInfo.id = aMsg.id;
         this._url = aMsg.url;
         this._presentationId = aMsg.presentationId;
-        this._presentationServer.onSessionRequest(aMsg.id,
+        this._presentationServer.onSessionRequest(this._deviceInfo,
                                                   aMsg.url,
                                                   aMsg.presentationId,
                                                   this);
         this._notifyOpened();
         break;
       }
       case "requestSession:Offer": {
         this._onOffer(aMsg.offer);
@@ -683,48 +629,9 @@ TCPControlChannel.prototype = {
     }
   },
 
   classID: Components.ID("{fefb8286-0bdc-488b-98bf-0c11b485c955}"),
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationControlChannel,
                                          Ci.nsIStreamListener]),
 };
 
-function TCPDevice(aPresentationServer, aInfo) {
-  DEBUG && log("create TCPDevice");
-  this.id = aInfo.id;
-  this.name = aInfo.name;
-  this.type = aInfo.type
-  this.host = aInfo.host;
-  this.port = aInfo.port;
-
-  this._presentationServer = aPresentationServer;
-  this._listener = null;
-}
-
-TCPDevice.prototype = {
-  establishControlChannel: function(aUrl, aPresentationId) {
-    DEBUG && log("TCPDevice - establishControlChannel: " + aUrl + ", "
-                 + aPresentationId);
-    return this._presentationServer
-               .requestSession(this._getDeviceInfo(), aUrl, aPresentationId);
-  },
-  get listener() {
-    return this._listener;
-  },
-  set listener(aListener) {
-    DEBUG && log("TCPDevice - set listener");
-    this._listener = aListener;
-  },
-
-  _getDeviceInfo: function() {
-    return new TCPDeviceInfo(this.host,
-                             this.port,
-                             this.id,
-                             this.name,
-                             this.type);
-  },
-
-  classID: Components.ID("{d6492549-a4f2-4a0c-9a93-00f0e9918b0a}"),
-  QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationDevice]),
-};
-
 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([TCPPresentationServer]);
--- a/dom/presentation/tests/mochitest/PresentationSessionChromeScript.js
+++ b/dom/presentation/tests/mochitest/PresentationSessionChromeScript.js
@@ -162,25 +162,16 @@ const mockedDevice = {
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationDevice]),
   id: 'id',
   name: 'name',
   type: 'type',
   establishControlChannel: function(url, presentationId) {
     sendAsyncMessage('control-channel-established');
     return mockedControlChannel;
   },
-  set listener(listener) {
-    this._listener = listener;
-  },
-  get listener() {
-    return this._listener;
-  },
-  simulateSessionRequest: function(url, presentationId, controlChannel) {
-    this._listener.onSessionRequest(this, url, presentationId, controlChannel);
-  },
 };
 
 const mockedDevicePrompt = {
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationDevicePrompt,
                                          Ci.nsIFactory]),
   createInstance: function(aOuter, aIID) {
     if (aOuter) {
       throw Components.results.NS_ERROR_NO_AGGREGATION;
@@ -353,17 +344,20 @@ addMessageListener('trigger-device-promp
   mockedDevicePrompt.simulateSelect();
 });
 
 addMessageListener('trigger-device-prompt-cancel', function() {
   mockedDevicePrompt.simulateCancel();
 });
 
 addMessageListener('trigger-incoming-session-request', function(url) {
-  mockedDevice.simulateSessionRequest(url, sessionId, mockedControlChannel);
+  var deviceManager = Cc['@mozilla.org/presentation-device/manager;1']
+                      .getService(Ci.nsIPresentationDeviceManager);
+  deviceManager.QueryInterface(Ci.nsIPresentationDeviceListener)
+	       .onSessionRequest(mockedDevice, url, sessionId, mockedControlChannel);
 });
 
 addMessageListener('trigger-incoming-offer', function() {
   mockedControlChannel.simulateOnOffer();
 });
 
 addMessageListener('trigger-incoming-answer', function() {
   mockedControlChannel.simulateOnAnswer();
--- a/dom/presentation/tests/xpcshell/test_multicast_dns_device_provider.js
+++ b/dom/presentation/tests/xpcshell/test_multicast_dns_device_provider.js
@@ -9,16 +9,17 @@ const { classes: Cc, interfaces: Ci, man
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
 const INFO_CONTRACT_ID = "@mozilla.org/toolkit/components/mdnsresponder/dns-info;1";
 const PROVIDER_CONTRACT_ID = "@mozilla.org/presentation-device/multicastdns-provider;1";
 const SD_CONTRACT_ID = "@mozilla.org/toolkit/components/mdnsresponder/dns-sd;1";
 const UUID_CONTRACT_ID = "@mozilla.org/uuid-generator;1";
+const SERVER_CONTRACT_ID = "@mozilla.org/presentation-device/tcp-presentation-server;1";
 
 const PREF_DISCOVERY = "dom.presentation.discovery.enabled";
 const PREF_DISCOVERABLE = "dom.presentation.discoverable";
 
 var registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar);
 
 function MockFactory(aClass) {
   this._cls = aClass;
@@ -164,16 +165,17 @@ function TestPresentationDeviceListener(
 }
 TestPresentationDeviceListener.prototype = {
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationDeviceListener,
                                          Ci.nsISupportsWeakReference]),
 
   addDevice: function(device) { this.devices[device.id] = device; },
   removeDevice: function(device) { delete this.devices[device.id]; },
   updateDevice: function(device) { this.devices[device.id] = device; },
+  onSessionRequest: function(device, url, presentationId, controlChannel) {},
 
   count: function() {
     var size = 0, key;
     for (key in this.devices) {
         if (this.devices.hasOwnProperty(key)) {
           ++size;
         }
     }
@@ -363,16 +365,241 @@ function addDevice() {
   Assert.equal(listener.count(), 1);
 
   provider.listener = null;
   Assert.equal(listener.count(), 1);
 
   run_next_test();
 }
 
+function handleSessionRequest() {
+  Services.prefs.setBoolPref(PREF_DISCOVERY, true);
+
+  const testUrl = "http://example.com";
+  const testPresentationId = "test-presentation-id";
+
+  let mockDevice = createDevice("device.local",
+                                12345,
+                                "service.name",
+                                "_mozilla_papi._tcp");
+  let mockSDObj = {
+    QueryInterface: XPCOMUtils.generateQI([Ci.nsIDNSServiceDiscovery]),
+    startDiscovery: function(serviceType, listener) {
+      listener.onDiscoveryStarted(serviceType);
+      listener.onServiceFound(createDevice("",
+                                           0,
+                                           mockDevice.serviceName,
+                                           mockDevice.serviceType));
+      return {
+        QueryInterface: XPCOMUtils.generateQI([Ci.nsICancelable]),
+        cancel: function() {}
+      };
+    },
+    registerService: function(serviceInfo, listener) {},
+    resolveService: function(serviceInfo, listener) {
+      listener.onServiceResolved(createDevice(mockDevice.host,
+                                              mockDevice.port,
+                                              mockDevice.serviceName,
+                                              mockDevice.serviceType));
+    }
+  };
+
+  let mockServerObj = {
+    QueryInterface: XPCOMUtils.generateQI([Ci.nsITCPPresentationServer]),
+    requestSession: function(deviceInfo, url, presentationId) {
+      this.request = {
+        deviceInfo: deviceInfo,
+        url: url,
+        presentationId: presentationId,
+      };
+      return {
+        QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationControlChannel]),
+      };
+    },
+  };
+
+  let contractHookSD = new ContractHook(SD_CONTRACT_ID, mockSDObj);
+  let contractHookServer = new ContractHook(SERVER_CONTRACT_ID, mockServerObj);
+  let provider = Cc[PROVIDER_CONTRACT_ID].createInstance(Ci.nsIPresentationDeviceProvider);
+  let listener = {
+    QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationDeviceListener,
+                                           Ci.nsISupportsWeakReference]),
+    addDevice: function(device) {
+      this.device = device;
+    },
+  };
+
+  provider.listener = listener;
+
+  let controlChannel = listener.device.establishControlChannel(testUrl, testPresentationId);
+
+  Assert.equal(mockServerObj.request.deviceInfo.id, mockDevice.host);
+  Assert.equal(mockServerObj.request.deviceInfo.host, mockDevice.host);
+  Assert.equal(mockServerObj.request.deviceInfo.port, mockDevice.port);
+  Assert.equal(mockServerObj.request.url, testUrl);
+  Assert.equal(mockServerObj.request.presentationId, testPresentationId);
+
+  provider.listener = null;
+
+  run_next_test();
+}
+
+function handleOnSessionRequest() {
+  Services.prefs.setBoolPref(PREF_DISCOVERY, true);
+
+  let mockDevice = createDevice("device.local",
+                                12345,
+                                "service.name",
+                                "_mozilla_papi._tcp");
+  let mockSDObj = {
+    QueryInterface: XPCOMUtils.generateQI([Ci.nsIDNSServiceDiscovery]),
+    startDiscovery: function(serviceType, listener) {
+      listener.onDiscoveryStarted(serviceType);
+      listener.onServiceFound(createDevice("",
+                                           0,
+                                           mockDevice.serviceName,
+                                           mockDevice.serviceType));
+      return {
+        QueryInterface: XPCOMUtils.generateQI([Ci.nsICancelable]),
+        cancel: function() {}
+      };
+    },
+    registerService: function(serviceInfo, listener) {},
+    resolveService: function(serviceInfo, listener) {
+      listener.onServiceResolved(createDevice(mockDevice.host,
+                                              mockDevice.port,
+                                              mockDevice.serviceName,
+                                              mockDevice.serviceType));
+    }
+  };
+
+  let mockServerObj = {
+    QueryInterface: XPCOMUtils.generateQI([Ci.nsITCPPresentationServer]),
+    init: function() {},
+    sessionRequest: function() {},
+    close: function() {},
+    id: '',
+    port: 0,
+    listener: null,
+  };
+
+  let contractHookSD = new ContractHook(SD_CONTRACT_ID, mockSDObj);
+  let contractHookServer = new ContractHook(SERVER_CONTRACT_ID, mockServerObj);
+  let provider = Cc[PROVIDER_CONTRACT_ID].createInstance(Ci.nsIPresentationDeviceProvider);
+  let listener = {
+    QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationDeviceListener,
+                                           Ci.nsISupportsWeakReference]),
+    addDevice: function(device) {},
+    removeDevice: function(device) {},
+    updateDevice: function(device) {},
+    onSessionRequest: function(device, url, presentationId, controlChannel) {
+      Assert.ok(true, "recieve onSessionRequest event");
+      this.request = {
+        deviceId: device.id,
+        url: url,
+        presentationId: presentationId,
+      };
+    }
+  };
+
+  provider.listener = listener;
+
+  const deviceInfo = {
+    QueryInterface: XPCOMUtils.generateQI([Ci.nsITCPDeviceInfo]),
+    id: mockDevice.host,
+    host: mockDevice.host,
+    port: 54321,
+  };
+
+  const testUrl = "http://example.com";
+  const testPresentationId = "test-presentation-id";
+  const testControlChannel = {
+    QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationControlChannel]),
+  };
+  provider.QueryInterface(Ci.nsITCPPresentationServerListener)
+          .onSessionRequest(deviceInfo, testUrl, testPresentationId, testControlChannel);
+
+  Assert.equal(listener.request.deviceId, deviceInfo.id);
+  Assert.equal(listener.request.url, testUrl);
+  Assert.equal(listener.request.presentationId, testPresentationId);
+
+  provider.listener = null;
+
+  run_next_test();
+}
+
+function handleOnSessionRequestFromUnknownDevice() {
+  let mockSDObj = {
+    QueryInterface: XPCOMUtils.generateQI([Ci.nsIDNSServiceDiscovery]),
+    startDiscovery: function(serviceType, listener) {},
+    registerService: function(serviceInfo, listener) {},
+    resolveService: function(serviceInfo, listener) {}
+  };
+
+  let mockServerObj = {
+    QueryInterface: XPCOMUtils.generateQI([Ci.nsITCPPresentationServer]),
+    init: function() {},
+    sessionRequest: function() {},
+    close: function() {},
+    id: '',
+    port: 0,
+    listener: null,
+  };
+
+  let contractHookSD = new ContractHook(SD_CONTRACT_ID, mockSDObj);
+  let contractHookServer = new ContractHook(SERVER_CONTRACT_ID, mockServerObj);
+  let provider = Cc[PROVIDER_CONTRACT_ID].createInstance(Ci.nsIPresentationDeviceProvider);
+  let listener = {
+    QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationDeviceListener,
+                                           Ci.nsISupportsWeakReference]),
+    addDevice: function(device) {
+      Assert.ok(false, "shouldn't create any new device");
+    },
+    removeDevice: function(device) {
+      Assert.ok(false, "shouldn't remote any device");
+    },
+    updateDevice: function(device) {
+      Assert.ok(false, "shouldn't update any device");
+    },
+    onSessionRequest: function(device, url, presentationId, controlChannel) {
+      Assert.ok(true, "recieve onSessionRequest event");
+      this.request = {
+        deviceId: device.id,
+        url: url,
+        presentationId: presentationId,
+      };
+    }
+  };
+
+  provider.listener = listener;
+
+  const deviceInfo = {
+    QueryInterface: XPCOMUtils.generateQI([Ci.nsITCPDeviceInfo]),
+    id: "unknown-device.local",
+    host: "unknown-device.local",
+    port: 12345,
+  };
+
+  const testUrl = "http://example.com";
+  const testPresentationId = "test-presentation-id";
+  const testControlChannel = {
+    QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationControlChannel]),
+  };
+  provider.QueryInterface(Ci.nsITCPPresentationServerListener)
+          .onSessionRequest(deviceInfo, testUrl, testPresentationId, testControlChannel);
+
+  Assert.equal(listener.request.deviceId, deviceInfo.id);
+  Assert.equal(listener.request.url, testUrl);
+  Assert.equal(listener.request.presentationId, testPresentationId);
+
+  provider.listener = null;
+
+  run_next_test();
+}
+
 function noAddDevice() {
   Services.prefs.setBoolPref(PREF_DISCOVERY, false);
 
   let mockDevice = createDevice("device.local", 12345, "service.name", "_mozilla_papi._tcp");
   let mockObj = {
     QueryInterface: XPCOMUtils.generateQI([Ci.nsIDNSServiceDiscovery]),
     startDiscovery: function(serviceType, listener) {
       Assert.ok(false, "shouldn't perform any device discovery");
@@ -709,16 +936,19 @@ function run_test() {
     Services.prefs.clearUserPref(PREF_DISCOVERY);
     Services.prefs.clearUserPref(PREF_DISCOVERABLE);
   });
 
   add_test(registerService);
   add_test(noRegisterService);
   add_test(registerServiceDynamically);
   add_test(addDevice);
+  add_test(handleSessionRequest);
+  add_test(handleOnSessionRequest);
+  add_test(handleOnSessionRequestFromUnknownDevice);
   add_test(noAddDevice);
   add_test(addDeviceDynamically);
   add_test(updateDevice);
   add_test(diffDiscovery);
   add_test(serverClosed);
 
   run_next_test();
 }
--- a/dom/presentation/tests/xpcshell/test_presentation_device_manager.js
+++ b/dom/presentation/tests/xpcshell/test_presentation_device_manager.js
@@ -40,26 +40,16 @@ var testProvider = {
 var testDevice = {
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationDevice]),
   id: 'id',
   name: 'name',
   type: 'type',
   establishControlChannel: function(url, presentationId) {
     return null;
   },
-  set listener(listener) {
-    this._listener = listener;
-  },
-  get listener() {
-    return this._listener;
-  },
-
-  simulateSessionRequest: function(url, presentationId, controlChannel) {
-    this._listener.onSessionRequest(this, url, presentationId, controlChannel);
-  },
 };
 
 function addProvider() {
   Object.defineProperty(testProvider, 'listener', {
     configurable: true,
     set: function(listener) {
       Assert.strictEqual(listener, manager, 'listener setter is invoked by PresentationDeviceManager');
       delete testProvider.listener;
@@ -139,17 +129,18 @@ function sessionRequest() {
     let request = subject.QueryInterface(Ci.nsIPresentationSessionRequest);
 
     Assert.equal(request.device.id, testDevice.id, 'expected device');
     Assert.equal(request.url, testUrl, 'expected requesting URL');
     Assert.equal(request.presentationId, testPresentationId, 'expected presentation Id');
 
     run_next_test();
   }, 'presentation-session-request', false);
-  testDevice.simulateSessionRequest(testUrl, testPresentationId, testControlChannel);
+  manager.QueryInterface(Ci.nsIPresentationDeviceListener)
+         .onSessionRequest(testDevice, testUrl, testPresentationId, testControlChannel);
 }
 
 function removeDevice() {
   Services.obs.addObserver(function observer(subject, topic, data) {
     Services.obs.removeObserver(observer, topic);
 
     let updatedDevice = subject.QueryInterface(Ci.nsIPresentationDevice);
     Assert.equal(updatedDevice.id, testDevice.id, 'expected device id');
--- a/dom/presentation/tests/xpcshell/test_tcp_control_channel.js
+++ b/dom/presentation/tests/xpcshell/test_tcp_control_channel.js
@@ -60,32 +60,24 @@ function loopOfferAnser() {
 
   testPresentationServer();
 }
 
 
 function testPresentationServer() {
   let yayFuncs = makeJointSuccess(['controllerControlChannelClose',
                                    'presenterControlChannelClose']);
-  let controllerDevice, controllerControlChannel;
-  let presenterDevice, presenterControlChannel;
+  let controllerControlChannel;
 
+  tps.listener = {
 
-  controllerDevice = tps.createTCPDevice('controllerID',
-                                         'controllerName',
-                                         'testType',
-                                         '127.0.0.1',
-                                         CONTROLLER_CONTROL_CHANNEL_PORT)
-                        .QueryInterface(Ci.nsIPresentationDevice);
-
-  controllerDevice.listener = {
-
-    onSessionRequest: function(device, url, presentationId, controlChannel) {
+    onSessionRequest: function(deviceInfo, url, presentationId, controlChannel) {
       controllerControlChannel = controlChannel;
-      Assert.strictEqual(device, controllerDevice, 'expected device object');
+      Assert.equal(deviceInfo.id, tps.id, 'expected device id');
+      Assert.equal(deviceInfo.host, '127.0.0.1', 'expected device host');
       Assert.equal(url, 'http://example.com', 'expected url');
       Assert.equal(presentationId, 'testPresentationId', 'expected presentation id');
 
       controllerControlChannel.listener = {
         status: 'created',
         onOffer: function(aOffer) {
           Assert.equal(this.status, 'opened', '1. controllerControlChannel: get offer, send answer');
           this.status = 'onOffer';
@@ -111,38 +103,33 @@ function testPresentationServer() {
           this.status = 'opened';
         },
         notifyClosed: function(aReason) {
           Assert.equal(this.status, 'onOffer', '3. controllerControlChannel: closed');
           Assert.equal(aReason, Cr.NS_OK, 'presenterControlChannel notify closed NS_OK');
           this.status = 'closed';
           yayFuncs.controllerControlChannelClose();
         },
-        QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationDeviceEventListener]),
+        QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationControlChannelListener]),
       };
     },
 
-    QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationControlChannelListener]),
+    QueryInterface: XPCOMUtils.generateQI([Ci.nsITCPPresentationServerListener]),
   };
 
-  presenterDevice = tps.createTCPDevice('presentatorID',
-                                        'presentatorName',
-                                        'testType',
-                                        '127.0.0.1',
-                                        PRESENTER_CONTROL_CHANNEL_PORT)
-                       .QueryInterface(Ci.nsIPresentationDevice);
+  let presenterDeviceInfo = {
+    id: 'presentatorID',
+    host: '127.0.0.1',
+    port: PRESENTER_CONTROL_CHANNEL_PORT,
+    QueryInterface: XPCOMUtils.generateQI([Ci.nsITCPDeviceInfo]),
+  };
 
-  presenterDevice.listener = {
-    onSessionRequest: function(device, url, presentationId, controlChannel) {
-      Assert.ok(false, 'presenterDevice.listener.onSessionRequest should not be called');
-    },
-  }
-
-  presenterControlChannel =
-  presenterDevice.establishControlChannel('http://example.com', 'testPresentationId');
+  let presenterControlChannel = tps.requestSession(presenterDeviceInfo,
+                                                   'http://example.com',
+                                                   'testPresentationId');
 
   presenterControlChannel.listener = {
     status: 'created',
     onOffer: function(offer) {
       Assert.ok(false, 'get offer');
     },
     onAnswer: function(aAnswer) {
       Assert.equal(this.status, 'opened', '2. presenterControlChannel: get answer, close channel');
@@ -206,28 +193,22 @@ function shutdown()
     onClose: function(aReason) {
       Assert.equal(aReason, Cr.NS_OK, 'TCPPresentationServer close success');
       run_next_test();
     },
   }
   tps.close();
 }
 
-function setPref() {
-  Services.prefs.setBoolPref("dom.presentation.tcp_server.debug", true);
-  run_next_test();
-}
-
-function clearPref() {
-  Services.prefs.clearUserPref("dom.presentation.tcp_server.debug");
-  run_next_test();
-}
-
-add_test(setPref);
 add_test(loopOfferAnser);
 add_test(setOffline);
 add_test(oneMoreLoop);
 add_test(shutdown);
-add_test(clearPref);
 
 function run_test() {
+  Services.prefs.setBoolPref("dom.presentation.tcp_server.debug", true);
+
+  do_register_cleanup(() => {
+    Services.prefs.clearUserPref("dom.presentation.tcp_server.debug");
+  });
+
   run_next_test();
 }
--- a/dom/requestsync/RequestSyncService.jsm
+++ b/dom/requestsync/RequestSyncService.jsm
@@ -96,17 +96,19 @@ this.RequestSyncService = {
     // Loading all the data from the database into the _registrations map.
     // Any incoming message will be stored and processed when the async
     // operation is completed.
 
     this.dbTxn("readonly", function(aStore) {
       aStore.openCursor().onsuccess = event => {
         let cursor = event.target.result;
         if (cursor) {
-          this.addRegistration(cursor.value, cursor.continue);
+          this.addRegistration(cursor.value, function() {
+            cursor.continue();
+          });
         }
       }
     }.bind(this),
     function() {
       debug("initialization done");
     },
     function() {
       dump("ERROR!! RequestSyncService - Failed to retrieve data from the database.\n");
--- a/dom/settings/SettingsDB.jsm
+++ b/dom/settings/SettingsDB.jsm
@@ -35,17 +35,17 @@ const TYPED_ARRAY_THINGS = new Set([
   "Uint16Array",
   "Int32Array",
   "Uint32Array",
   "Float32Array",
   "Float64Array",
 ]);
 
 this.SETTINGSDB_NAME = "settings";
-this.SETTINGSDB_VERSION = 5;
+this.SETTINGSDB_VERSION = 6;
 this.SETTINGSSTORE_NAME = "settings";
 
 Cu.import("resource://gre/modules/IndexedDBHelper.jsm");
 Cu.import("resource://gre/modules/FileUtils.jsm");
 Cu.import("resource://gre/modules/NetUtil.jsm");
 
 this.SettingsDB = function SettingsDB() {}
 
--- a/dom/telephony/Telephony.cpp
+++ b/dom/telephony/Telephony.cpp
@@ -339,17 +339,17 @@ Telephony::HandleCallInfo(nsITelephonyCa
                       isConference, isSwitchable, isMergeable);
     // The newly created call is an incoming call.
     if (call &&
         state == TelephonyCallState::Incoming) {
       nsresult rv = DispatchCallEvent(NS_LITERAL_STRING("incoming"), call);
       NS_ENSURE_SUCCESS(rv, rv);
     }
     return NS_OK;
-  } 
+  }
 
   // Update an existing call
   call->UpdateEmergency(isEmergency);
   call->UpdateSwitchable(isSwitchable);
   call->UpdateMergeable(isMergeable);
 
   nsAutoString number;
   aInfo->GetNumber(number);
@@ -718,49 +718,42 @@ Telephony::WindowAudioCaptureChanged()
   return NS_OK;
 }
 
 // nsITelephonyListener
 
 NS_IMETHODIMP
 Telephony::CallStateChanged(uint32_t aLength, nsITelephonyCallInfo** aAllInfo)
 {
+  // Update call state
   nsresult rv;
   for (uint32_t i = 0; i < aLength; ++i) {
     rv = HandleCallInfo(aAllInfo[i]);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
   }
 
+  // Update conference state
+  mGroup->ChangeState();
+
   rv = HandleAudioAgentState();
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 Telephony::EnumerateCallState(nsITelephonyCallInfo* aInfo)
 {
   return HandleCallInfo(aInfo);
 }
 
 NS_IMETHODIMP
-Telephony::ConferenceCallStateChanged(uint16_t aCallState)
-{
-  // The current design of Telephony Stack gaurantees that the calls within a
-  // call group are updated before this method being called, so we can let a
-  // call update its state by its own, and we can discard |aCallState| here.
-  // Anyway, this method is going to be deprecated in Bug 1155072.
-  mGroup->ChangeState();
-  return NS_OK;
-}
-
-NS_IMETHODIMP
 Telephony::EnumerateCallStateComplete()
 {
   // Set conference state.
   mGroup->ChangeState();
 
   HandleAudioAgentState();
   if (mReadyPromise) {
     mReadyPromise->MaybeResolve(JS::UndefinedHandleValue);
--- a/dom/telephony/gonk/TelephonyService.js
+++ b/dom/telephony/gonk/TelephonyService.js
@@ -364,17 +364,16 @@ MobileConnectionListener.prototype = {
 
 function TelephonyService() {
   this._numClients = gRadioInterfaceLayer.numRadioInterfaces;
   this._listeners = [];
 
   this._isDialing = false;
   this._cachedDialRequest = null;
   this._currentCalls = {};
-  this._currentConferenceState = nsITelephonyService.CALL_STATE_UNKNOWN;
   this._audioStates = [];
   this._ussdSessions = [];
 
   this._cdmaCallWaitingNumber = null;
 
   this._updateDebugFlag();
   this.defaultServiceId = this._getDefaultServiceId();
 
@@ -2035,17 +2034,16 @@ TelephonyService.prototype = {
       let calls = [];
       for (let index in this._currentCalls[aClientId]) {
         let call = this._currentCalls[aClientId][index];
         call.state = nsITelephonyService.CALL_STATE_CONNECTED;
         call.isConference = true;
         calls.push(call);
       }
       this._handleCallStateChanged(aClientId, calls);
-      this._handleConferenceCallStateChanged(nsITelephonyService.CALL_STATE_CONNECTED);
 
       aCallback.notifySuccess();
     });
   },
 
   conferenceCall: function(aClientId, aCallback) {
     if (Object.keys(this._currentCalls[aClientId]).length < 2) {
       aCallback.notifyError(RIL.GECKO_ERROR_GENERIC_FAILURE);
@@ -2079,17 +2077,16 @@ TelephonyService.prototype = {
     let parentCall = this._currentCalls[aClientId][CDMA_FIRST_CALL_INDEX];
 
     this._disconnectCalls(aClientId, [childCall]);
 
     parentCall.isConference = false;
     parentCall.isSwitchable = true;
     parentCall.isMergeable = true;
     this._handleCallStateChanged(aClientId, [childCall, parentCall]);
-    this._handleConferenceCallStateChanged(nsITelephonyService.CALL_STATE_UNKNOWN);
   },
 
   // See 3gpp2, S.R0006-522-A v1.0. Table 4, XID 6S.
   // Release the third party. Optionally apply a warning tone. Connect the
   // controlling subscriber and the second party. Go to the 2-way state.
   _separateCallCdma: function(aClientId, aCallIndex, aCallback) {
     this._sendToRilWorker(aClientId, "cdmaFlash", null, response => {
       if (response.errorMsg) {
@@ -2123,21 +2120,34 @@ TelephonyService.prototype = {
     // In cdma, ril only maintains one call index.
     if (this._isCdmaClient(aClientId)) {
       this._sendToRilWorker(aClientId, "hangUpCall",
                             { callIndex: CDMA_FIRST_CALL_INDEX },
                             this._defaultCallbackHandler.bind(this, aCallback));
       return;
     }
 
-    let foreground = this._currentConferenceState == nsITelephonyService.CALL_STATE_CONNECTED;
-    this._sendToRilWorker(aClientId,
-                          foreground ? "hangUpForeground" : "hangUpBackground",
-                          null,
-                          this._defaultCallbackHandler.bind(this, aCallback));
+    // Find a conference call, and send the corresponding request to RIL worker.
+    for (let index in this._currentCalls[aClientId]) {
+      let call = this._currentCalls[aClientId][index];
+      if (!call.isConference) {
+        continue;
+      }
+
+      let command = call.state === nsITelephonyService.CALL_STATE_CONNECTED ?
+                    "hangUpForeground" : "hangUpBackground";
+      this._sendToRilWorker(aClientId, command, null,
+                            this._defaultCallbackHandler.bind(this, aCallback));
+      return;
+    }
+
+    // There is no conference call.
+    if (DEBUG) debug("hangUpConference: " +
+                     "No conference call in modem[" + aClientId + "].");
+    aCallback.notifyError(RIL.GECKO_ERROR_GENERIC_FAILURE);
   },
 
   _switchConference: function(aClientId, aCallback) {
     // Cannot hold/resume a conference in cdma.
     if (this._isCdmaClient(aClientId)) {
       aCallback.notifyError(RIL.GECKO_ERROR_GENERIC_FAILURE);
       return;
     }
@@ -2349,22 +2359,16 @@ TelephonyService.prototype = {
     disconnectedCalls.forEach(call => changedCalls.add(call));
 
     // Detect conference and update isConference flag.
     let [newConferenceState, conferenceChangedCalls] = this._updateConference(aClientId);
     conferenceChangedCalls.forEach(call => changedCalls.add(call));
 
     this._handleCallStateChanged(aClientId, [...changedCalls]);
 
-    // Should handle conferenceCallStateChange after callStateChanged and
-    // callDisconnected.
-    if (newConferenceState != this._currentConferenceState) {
-      this._handleConferenceCallStateChanged(newConferenceState);
-    }
-
     this._updateAudioState(aClientId);
 
     // Handle cached dial request.
     if (this._cachedDialRequest && !this._isActive(aClientId)) {
       if (DEBUG) debug("All calls held. Perform the cached dial request.");
 
       let request = this._cachedDialRequest;
       this._sendDialCallRequest(request.clientId, request.options,
@@ -2434,22 +2438,16 @@ TelephonyService.prototype = {
         }
       }
     }
 
     this._notifyAllListeners("supplementaryServiceNotification",
                              [aClientId, callIndex, notification]);
   },
 
-  _handleConferenceCallStateChanged: function(aState) {
-    if (DEBUG) debug("handleConferenceCallStateChanged: " + aState);
-    this._currentConferenceState = aState;
-    this._notifyAllListeners("conferenceCallStateChanged", [aState]);
-  },
-
   notifyUssdReceived: function(aClientId, aMessage, aSessionEnded) {
     if (DEBUG) {
       debug("notifyUssdReceived for " + aClientId + ": " +
             aMessage + " (sessionEnded : " + aSessionEnded + ")");
     }
 
     let oldSession = this._ussdSessions[aClientId];
     this._ussdSessions[aClientId] =
--- a/dom/telephony/gonk/TelephonyUtils.jsm
+++ b/dom/telephony/gonk/TelephonyUtils.jsm
@@ -92,17 +92,16 @@ this.TelephonyUtils = {
         enumerateCallStateComplete: function() {},
         enumerateCallState: function() {},
         callStateChanged: function() {
           if (!self.hasAnyCalls(aClientId)) {
             TelephonyService.unregisterListener(this);
             resolve();
           }
         },
-        conferenceCallStateChanged: function() {},
         supplementaryServiceNotification: function() {},
         notifyError: function() {},
         notifyCdmaCallWaiting: function() {},
         notifyConferenceError: function() {}
       };
 
       TelephonyService.registerListener(listener);
     });
--- a/dom/telephony/ipc/PTelephony.ipdl
+++ b/dom/telephony/ipc/PTelephony.ipdl
@@ -124,18 +124,16 @@ sync protocol PTelephony {
   manager PContent;
   manages PTelephonyRequest;
 
 child:
   NotifyCallStateChanged(nsTelephonyCallInfo[] aAllInfo);
 
   NotifyCdmaCallWaiting(uint32_t aClientId, IPCCdmaWaitingCallData aData);
 
-  NotifyConferenceCallStateChanged(uint16_t aCallState);
-
   NotifyConferenceError(nsString aName, nsString aMessage);
 
   NotifySupplementaryService(uint32_t aClientId, int32_t aCallIndex,
                              uint16_t aNotification);
 
 parent:
   /**
    * Sent when the child no longer needs to use PTelephony.
--- a/dom/telephony/ipc/TelephonyChild.cpp
+++ b/dom/telephony/ipc/TelephonyChild.cpp
@@ -76,25 +76,16 @@ TelephonyChild::RecvNotifyCdmaCallWaitin
                                   aData.number(),
                                   aData.numberPresentation(),
                                   aData.name(),
                                   aData.namePresentation());
   return true;
 }
 
 bool
-TelephonyChild::RecvNotifyConferenceCallStateChanged(const uint16_t& aCallState)
-{
-  MOZ_ASSERT(mService);
-
-  mService->ConferenceCallStateChanged(aCallState);
-  return true;
-}
-
-bool
 TelephonyChild::RecvNotifyConferenceError(const nsString& aName,
                                           const nsString& aMessage)
 {
   MOZ_ASSERT(mService);
 
   mService->NotifyConferenceError(aName, aMessage);
   return true;
 }
--- a/dom/telephony/ipc/TelephonyChild.h
+++ b/dom/telephony/ipc/TelephonyChild.h
@@ -37,19 +37,16 @@ protected:
   virtual bool
   RecvNotifyCallStateChanged(nsTArray<nsITelephonyCallInfo*>&& aAllInfo) override;
 
   virtual bool
   RecvNotifyCdmaCallWaiting(const uint32_t& aClientId,
                             const IPCCdmaWaitingCallData& aData) override;
 
   virtual bool
-  RecvNotifyConferenceCallStateChanged(const uint16_t& aCallState) override;
-
-  virtual bool
   RecvNotifyConferenceError(const nsString& aName,
                             const nsString& aMessage) override;
 
   virtual bool
   RecvNotifySupplementaryService(const uint32_t& aClientId,
                                  const int32_t& aCallIndex,
                                  const uint16_t& aNotification) override;
 
--- a/dom/telephony/ipc/TelephonyIPCService.cpp
+++ b/dom/telephony/ipc/TelephonyIPCService.cpp
@@ -372,25 +372,16 @@ TelephonyIPCService::CallStateChanged(ui
 {
   for (uint32_t i = 0; i < mListeners.Length(); i++) {
     mListeners[i]->CallStateChanged(aLength, aAllInfo);
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
-TelephonyIPCService::ConferenceCallStateChanged(uint16_t aCallState)
-{
-  for (uint32_t i = 0; i < mListeners.Length(); i++) {
-    mListeners[i]->ConferenceCallStateChanged(aCallState);
-  }
-  return NS_OK;
-}
-
-NS_IMETHODIMP
 TelephonyIPCService::EnumerateCallStateComplete()
 {
   MOZ_CRASH("Not a EnumerateCalls request!");
 }
 
 NS_IMETHODIMP
 TelephonyIPCService::EnumerateCallState(nsITelephonyCallInfo* aInfo)
 {
--- a/dom/telephony/ipc/TelephonyParent.cpp
+++ b/dom/telephony/ipc/TelephonyParent.cpp
@@ -282,25 +282,16 @@ TelephonyParent::CallStateChanged(uint32
   for (uint32_t i = 0; i < aLength; i++) {
     allInfo.AppendElement(aAllInfo[i]);
   }
 
   return SendNotifyCallStateChanged(allInfo) ? NS_OK : NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
-TelephonyParent::ConferenceCallStateChanged(uint16_t aCallState)
-{
-  NS_ENSURE_TRUE(!mActorDestroyed, NS_ERROR_FAILURE);
-
-  return SendNotifyConferenceCallStateChanged(aCallState) ? NS_OK
-                                                          : NS_ERROR_FAILURE;
-}
-
-NS_IMETHODIMP
 TelephonyParent::EnumerateCallStateComplete()
 {
   MOZ_CRASH("Not a EnumerateCalls request!");
 }
 
 NS_IMETHODIMP
 TelephonyParent::EnumerateCallState(nsITelephonyCallInfo* aInfo)
 {
@@ -377,22 +368,16 @@ TelephonyRequestParent::SendResponse(con
 
 NS_IMETHODIMP
 TelephonyRequestParent::CallStateChanged(uint32_t aLength, nsITelephonyCallInfo** aAllInfo)
 {
   MOZ_CRASH("Not a TelephonyParent!");
 }
 
 NS_IMETHODIMP
-TelephonyRequestParent::ConferenceCallStateChanged(uint16_t aCallState)
-{
-  MOZ_CRASH("Not a TelephonyParent!");
-}
-
-NS_IMETHODIMP
 TelephonyRequestParent::EnumerateCallStateComplete()
 {
   NS_ENSURE_TRUE(!mActorDestroyed, NS_ERROR_FAILURE);
 
   return Send__delete__(this, EnumerateCallsResponse()) ? NS_OK : NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
--- a/dom/telephony/nsITelephonyService.idl
+++ b/dom/telephony/nsITelephonyService.idl
@@ -2,17 +2,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 
 interface nsIMobileCallForwardingOptions;
 interface nsITelephonyCallInfo;
 
-[scriptable, uuid(80faf34e-286b-4487-bd55-135bd92668b9)]
+[scriptable, uuid(baa9f5f3-5cab-40e0-81e9-ae0abd917907)]
 interface nsITelephonyListener : nsISupports
 {
   /**
    * Called when enumeration asked by nsITelephonyService::enumerateCalls
    * is completed.
    */
   void enumerateCallStateComplete();
 
@@ -25,27 +25,16 @@ interface nsITelephonyListener : nsISupp
 
   /**
    * Notified when a telephony call changes state.
    */
   void callStateChanged(in unsigned long length,
                         [array, size_is(length)] in nsITelephonyCallInfo allInfo);
 
   /**
-   * Called when participants of a conference call have been updated, and the
-   * conference call state changes.
-   *
-   * @param callState
-   *        Possible values are: nsITelephonyService::CALL_STATE_UNKNOWN,
-   *        nsITelephonyService::CALL_STATE_HELD,
-   *        nsITelephonyService::CALL_STATE_CONNECTED.
-   */
-  void conferenceCallStateChanged(in unsigned short callState);
-
-  /**
    * Notify when RIL receives supplementary service notification.
    *
    * @param clientId
             Indicate the RIL client, 0 ~ (number of client - 1).
    * @param callIndex
    *        Call identifier assigned by the RIL. -1 if not specified
    * @param notification
    *        One of the nsITelephonyService::NOTIFICATION_* values.
--- a/dom/telephony/test/marionette/test_TelephonyUtils.js
+++ b/dom/telephony/test/marionette/test_TelephonyUtils.js
@@ -40,17 +40,16 @@ function waitForStateChanged(aPredicate)
 
       callStateChanged: function(length, allInfo) {
         if (aPredicate(allInfo)) {
           resolve(allInfo);
           TelephonyService.unregisterListener(listener);
         }
       },
 
-      conferenceCallStateChanged: function() {},
       supplementaryServiceNotification: function() {},
       notifyError: function() {},
       notifyCdmaCallWaiting: function() {},
       notifyConferenceError: function() {}
     };
 
     TelephonyService.registerListener(listener);
   });
--- a/dom/tests/mochitest/fetch/test_headers_common.js
+++ b/dom/tests/mochitest/fetch/test_headers_common.js
@@ -8,26 +8,37 @@ function shouldThrow(func, expected, msg
     func();
   } catch(e) {
     err = e;
   } finally {
     ok(err instanceof expected, msg);
   }
 }
 
+function recursiveArrayCompare(actual, expected) {
+  is(Array.isArray(actual), Array.isArray(expected), "Both should either be arrays, or not");
+  if (Array.isArray(actual) && Array.isArray(expected)) {
+    var diff = actual.length !== expected.length;
+
+    for (var i = 0, n = actual.length; !diff && i < n; ++i) {
+      diff = recursiveArrayCompare(actual[i], expected[i]);
+    }
+
+    return diff;
+  } else {
+    return actual !== expected;
+  }
+}
+
 function arrayEquals(actual, expected, msg) {
   if (actual === expected) {
     return;
   }
 
-  var diff = actual.length !== expected.length;
-
-  for (var i = 0, n = actual.length; !diff && i < n; ++i) {
-    diff = actual[i] !== expected[i];
-  }
+  var diff = recursiveArrayCompare(actual, expected);
 
   ok(!diff, msg);
   if (diff) {
     is(actual, expected, msg);
   }
 }
 
 function checkHas(headers, name, msg) {
@@ -164,13 +175,65 @@ function TestFilledHeaders() {
   shouldThrow(function() {
     filled = new Headers([
       ["zxy"],
       ["uts", "321"]
     ]);
   }, TypeError, "Fill with non-tuple sequence should throw TypeError.");
 }
 
+function iterate(iter) {
+  var result = [];
+  for (var val = iter.next(); !val.done;) {
+    result.push(val.value);
+    val = iter.next();
+  }
+  return result;
+}
+
+function iterateForOf(iter) {
+  var result = [];
+  for (var value of iter) {
+    result.push(value);
+  }
+  return result;
+}
+
+function byteInflate(str) {
+  var encoder = new TextEncoder("utf-8");
+  var encoded = encoder.encode(str);
+  var result = "";
+  for (var i = 0; i < encoded.length; ++i) {
+    result += String.fromCharCode(encoded[i]);
+  }
+  return result
+}
+
+function TestHeadersIterator() {
+  var ehsanInflated = byteInflate("احسان");
+  var headers = new Headers();
+  headers.set("foo0", "bar0");
+  headers.append("foo", "bar");
+  headers.append("foo", ehsanInflated);
+  headers.append("Foo2", "bar2");
+  headers.set("Foo2", "baz2");
+  headers.set("foo3", "bar3");
+  headers.delete("foo0");
+  headers.delete("foo3");
+
+  var key_iter = headers.keys();
+  var value_iter = headers.values();
+  var entries_iter = headers.entries();
+
+  arrayEquals(iterate(key_iter), ["foo", "foo", "foo2"], "Correct key iterator");
+  arrayEquals(iterate(value_iter), ["bar", ehsanInflated, "baz2"], "Correct value iterator");
+  arrayEquals(iterate(entries_iter), [["foo", "bar"], ["foo", ehsanInflated], ["foo2", "baz2"]], "Correct entries iterator");
+
+  arrayEquals(iterateForOf(headers), [["foo", "bar"], ["foo", ehsanInflated], ["foo2", "baz2"]], "Correct entries iterator");
+  arrayEquals(iterateForOf(new Headers(headers)), [["foo", "bar"], ["foo", ehsanInflated], ["foo2", "baz2"]], "Correct entries iterator");
+}
+
 function runTest() {
   TestEmptyHeaders();
   TestFilledHeaders();
+  TestHeadersIterator();
   return Promise.resolve();
 }
--- a/dom/webidl/FormData.webidl
+++ b/dom/webidl/FormData.webidl
@@ -15,10 +15,10 @@ interface FormData {
   void append(USVString name, Blob value, optional USVString filename);
   void append(USVString name, USVString value);
   void delete(USVString name);
   FormDataEntryValue? get(USVString name);
   sequence<FormDataEntryValue> getAll(USVString name);
   boolean has(USVString name);
   void set(USVString name, Blob value, optional USVString filename);
   void set(USVString name, USVString value);
-  // iterable<USVString, FormDataEntryValue>; - Bug 1127703
+  iterable<USVString, FormDataEntryValue>;
 };
--- a/dom/webidl/Headers.webidl
+++ b/dom/webidl/Headers.webidl
@@ -22,13 +22,14 @@ enum HeadersGuardEnum {
  Exposed=(Window,Worker)]
 interface Headers {
   [Throws] void append(ByteString name, ByteString value);
   [Throws] void delete(ByteString name);
   [Throws] ByteString? get(ByteString name);
   [Throws] sequence<ByteString> getAll(ByteString name);
   [Throws] boolean has(ByteString name);
   [Throws] void set(ByteString name, ByteString value);
+  iterable<ByteString, ByteString>;
 
   // Used to test different guard states from mochitest.
   // Note: Must be set prior to populating headers or will throw.
   [ChromeOnly, SetterThrows] attribute HeadersGuardEnum guard;
 };
--- a/dom/workers/ServiceWorkerPrivate.cpp
+++ b/dom/workers/ServiceWorkerPrivate.cpp
@@ -1032,16 +1032,22 @@ private:
     MOZ_ASSERT(internalReq);
     internalReq->SetCreatedByFetchEvent();
 
     internalReq->SetBody(mUploadStream);
     internalReq->SetReferrer(NS_ConvertUTF8toUTF16(mReferrer));
 
     request->SetContentPolicyType(mContentPolicyType);
 
+    request->GetInternalHeaders()->SetGuard(HeadersGuardEnum::Immutable, result);
+    if (NS_WARN_IF(result.Failed())) {
+      result.SuppressException();
+      return false;
+    }
+
     // TODO: remove conditional on http here once app protocol support is
     //       removed from service worker interception
     MOZ_ASSERT_IF(mIsHttpChannel && internalReq->IsNavigationRequest(),
                   request->Redirect() == RequestRedirect::Manual);
 
     RootedDictionary<FetchEventInit> init(aCx);
     init.mRequest.Construct();
     init.mRequest.Value() = request;
--- a/editor/composer/moz.build
+++ b/editor/composer/moz.build
@@ -22,16 +22,28 @@ UNIFIED_SOURCES += [
     'nsComposerRegistration.cpp',
     'nsComposeTxtSrvFilter.cpp',
     'nsEditingSession.cpp',
     'nsEditorSpellCheck.cpp',
 ]
 
 FINAL_LIBRARY = 'xul'
 RESOURCE_FILES += [
+    'res/accessiblecaret.png',
+    'res/accessiblecaret@1.5x.png',
+    'res/accessiblecaret@2.25x.png',
+    'res/accessiblecaret@2x.png',
+    'res/accessiblecaret_tilt_left.png',
+    'res/accessiblecaret_tilt_left@1.5x.png',
+    'res/accessiblecaret_tilt_left@2.25x.png',
+    'res/accessiblecaret_tilt_left@2x.png',
+    'res/accessiblecaret_tilt_right.png',
+    'res/accessiblecaret_tilt_right@1.5x.png',
+    'res/accessiblecaret_tilt_right@2.25x.png',
+    'res/accessiblecaret_tilt_right@2x.png',
     'res/EditorOverride.css',
     'res/grabber.gif',
     'res/table-add-column-after-active.gif',
     'res/table-add-column-after-hover.gif',
     'res/table-add-column-after.gif',
     'res/table-add-column-before-active.gif',
     'res/table-add-column-before-hover.gif',
     'res/table-add-column-before.gif',
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..828315b9a720ed7b73460700890d9ad0f2433368
GIT binary patch
literal 15965
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
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..8b27c3c20aa1a3ab7a4eb4683e90364dc609131c
GIT binary patch
literal 16477
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
TsOK})4*+<&E#nj|4omzSK$IVh
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..685670e01aa9b2a644f73f8cbc87c70234bae9c0
GIT binary patch
literal 17193
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
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..bad59253f9564a0e9e9cb013f3a132258d372b1f
GIT binary patch
literal 17190
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
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..b96f674c28bcfb72a2f7e290b826d354e8a78a2b
GIT binary patch
literal 15894
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
F{6F<+`rH5j
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..840b2186825c54c5ab7321a30113a3d3b803e180
GIT binary patch
literal 16342
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
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..d69ca4fe4b36a360d9a2453e8604f3dc8c34789f
GIT binary patch
literal 17063
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
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..f76cb333c3215ed1b1768c8a059f72a42a1fd42a
GIT binary patch
literal 16756
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
YYK9v-qSWU}|1W|&V~*>uE{m4`2ev1NjQ{`u
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..6a95a96648d6fa1e5acd317eb9adb8ae0a4ea8b7
GIT binary patch
literal 15886
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
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..02dde485c10b8d441ac534d6f1abe951d3770d36
GIT binary patch
literal 16360
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
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..ec6a50f0a75dfbf466ca1ff1e0a29eece4a0befe
GIT binary patch
literal 17087
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
Fe*hL{J4FBh
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..c24e66d0adc1969b67a4cc1cb12ffb736d4d24bd
GIT binary patch
literal 16763
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
--- a/gfx/layers/CopyableCanvasLayer.cpp
+++ b/gfx/layers/CopyableCanvasLayer.cpp
@@ -56,16 +56,17 @@ CopyableCanvasLayer::Initialize(const Da
     mOriginPos = gl::OriginPos::BottomLeft;
 
     MOZ_ASSERT(mGLContext->IsOffscreen(), "canvas gl context isn't offscreen");
 
     if (aData.mFrontbufferGLTex) {
       gfx::IntSize size(aData.mSize.width, aData.mSize.height);
       mGLFrontbuffer = SharedSurface_Basic::Wrap(aData.mGLContext, size, aData.mHasAlpha,
                                                  aData.mFrontbufferGLTex);
+      mBufferProvider = aData.mBufferProvider;
     }
   } else if (aData.mBufferProvider) {
     mBufferProvider = aData.mBufferProvider;
   } else if (aData.mRenderer) {
     mAsyncRenderer = aData.mRenderer;
     mOriginPos = gl::OriginPos::BottomLeft;
   } else {
     MOZ_CRASH("CanvasLayer created without mSurface, mDrawTarget or mGLContext?");
@@ -80,32 +81,32 @@ CopyableCanvasLayer::IsDataValid(const D
   return mGLContext == aData.mGLContext;
 }
 
 void
 CopyableCanvasLayer::UpdateTarget(DrawTarget* aDestTarget)
 {
   if (mAsyncRenderer) {
     mSurface = mAsyncRenderer->GetSurface();
-  } else if (mBufferProvider) {
+  } else if (!mGLFrontbuffer && mBufferProvider) {
     mSurface = mBufferProvider->GetSnapshot();
   }
 
   if (!mGLContext && aDestTarget) {
     NS_ASSERTION(mSurface, "Must have surface to draw!");
     if (mSurface) {
       aDestTarget->CopySurface(mSurface,
                                IntRect(0, 0, mBounds.width, mBounds.height),
                                IntPoint(0, 0));
       mSurface = nullptr;
     }
     return;
   }
 
-  if (mBufferProvider || mAsyncRenderer) {
+  if ((!mGLFrontbuffer && mBufferProvider) || mAsyncRenderer) {
     return;
   }
 
   MOZ_ASSERT(mGLContext);
 
   SharedSurface* frontbuffer = nullptr;
   if (mGLFrontbuffer) {
     frontbuffer = mGLFrontbuffer.get();
--- a/gfx/layers/LayerScope.cpp
+++ b/gfx/layers/LayerScope.cpp
@@ -362,16 +362,48 @@ private:
     mozilla::UniquePtr<DrawSession> mSession;
     mozilla::UniquePtr<ContentMonitor> mContentMonitor;
     double mScale;
 };
 
 LayerScopeManager gLayerScopeManager;
 
 /*
+ * The static helper functions that set data into the packet
+ * 1. DumpRect
+ * 2. DumpFilter
+ */
+template<typename T>
+static void DumpRect(T* aPacketRect, const Rect& aRect)
+{
+    aPacketRect->set_x(aRect.x);
+    aPacketRect->set_y(aRect.y);
+    aPacketRect->set_w(aRect.width);
+    aPacketRect->set_h(aRect.height);
+}
+
+static void DumpFilter(TexturePacket* aTexturePacket, const Filter& aFilter)
+{
+    switch (aFilter) {
+        case Filter::GOOD:
+            aTexturePacket->set_mfilter(TexturePacket::GOOD);
+            break;
+        case Filter::LINEAR:
+            aTexturePacket->set_mfilter(TexturePacket::LINEAR);
+            break;
+        case Filter::POINT:
+            aTexturePacket->set_mfilter(TexturePacket::POINT);
+            break;
+        default:
+            MOZ_ASSERT(false, "Can't dump unexpected mFilter to texture packet!");
+            break;
+    }
+}
+
+/*
  * DebugGLData is the base class of
  * 1. DebugGLFrameStatusData (Frame start/end packet)
  * 2. DebugGLColorData (Color data packet)
  * 3. DebugGLTextureData (Texture data packet)
  * 4. DebugGLLayersData (Layers Tree data packet)
  * 5. DebugGLMetaData (Meta data packet)
  */
 class DebugGLData: public LinkedListElement<DebugGLData> {
@@ -431,36 +463,38 @@ protected:
 #ifdef MOZ_WIDGET_GONK
 // B2G optimization.
 class DebugGLGraphicBuffer final: public DebugGLData {
 public:
     DebugGLGraphicBuffer(void *layerRef,
                          GLenum target,
                          GLuint name,
                          const LayerRenderState &aState,
-                         bool aIsMask)
+                         bool aIsMask,
+                         UniquePtr<Packet> aPacket)
         : DebugGLData(Packet::TEXTURE),
           mLayerRef(reinterpret_cast<uint64_t>(layerRef)),
           mTarget(target),
           mName(name),
           mState(aState),
-          mIsMask(aIsMask)
+          mIsMask(aIsMask),
+          mPacket(Move(aPacket))
     {
     }
 
     virtual bool Write() override {
-        return WriteToStream(mPacket);
+        return WriteToStream(*mPacket);
     }
 
     bool TryPack(bool packData) {
         android::sp<android::GraphicBuffer> buffer = mState.mSurface;
         MOZ_ASSERT(buffer.get());
 
-        mPacket.set_type(mDataType);
-        TexturePacket* tp = mPacket.mutable_texture();
+        mPacket->set_type(mDataType);
+        TexturePacket* tp = mPacket->mutable_texture();
         tp->set_layerref(mLayerRef);
         tp->set_name(mName);
         tp->set_target(mTarget);
         tp->set_ismask(mIsMask);
 
         int pFormat = buffer->getPixelFormat();
         if (HAL_PIXEL_FORMAT_RGBA_8888 != pFormat &&
             HAL_PIXEL_FORMAT_RGBX_8888 != pFormat) {
@@ -512,52 +546,54 @@ public:
     }
 
 private:
     uint64_t mLayerRef;
     GLenum mTarget;
     GLuint mName;
     const LayerRenderState &mState;
     bool mIsMask;
-    Packet mPacket;
+    UniquePtr<Packet> mPacket;
 };
 #endif
 
 class DebugGLTextureData final: public DebugGLData {
 public:
     DebugGLTextureData(GLContext* cx,
                        void* layerRef,
                        GLenum target,
                        GLuint name,
                        DataSourceSurface* img,
-                       bool aIsMask)
+                       bool aIsMask,
+                       UniquePtr<Packet> aPacket)
         : DebugGLData(Packet::TEXTURE),
           mLayerRef(reinterpret_cast<uint64_t>(layerRef)),
           mTarget(target),
           mName(name),
           mContextAddress(reinterpret_cast<intptr_t>(cx)),
           mDatasize(0),
-          mIsMask(aIsMask)
+          mIsMask(aIsMask),
+          mPacket(Move(aPacket))
     {
         // pre-packing
         // DataSourceSurface may have locked buffer,
         // so we should compress now, and then it could
         // be unlocked outside.
         pack(img);
     }
 
     virtual bool Write() override {
-        return WriteToStream(mPacket);
+        return WriteToStream(*mPacket);
     }
 
 private:
     void pack(DataSourceSurface* aImage) {
-        mPacket.set_type(mDataType);
+        mPacket->set_type(mDataType);
 
-        TexturePacket* tp = mPacket.mutable_texture();
+        TexturePacket* tp = mPacket->mutable_texture();
         tp->set_layerref(mLayerRef);
         tp->set_name(mName);
         tp->set_target(mTarget);
         tp->set_dataformat(LOCAL_GL_RGBA);
         tp->set_glcontext(static_cast<uint64_t>(mContextAddress));
         tp->set_ismask(mIsMask);
 
         if (aImage) {
@@ -595,17 +631,17 @@ protected:
     uint64_t mLayerRef;
     GLenum mTarget;
     GLuint mName;
     intptr_t mContextAddress;
     uint32_t mDatasize;
     bool mIsMask;
 
     // Packet data
-    Packet mPacket;
+    UniquePtr<Packet> mPacket;
 };
 
 class DebugGLColorData final: public DebugGLData {
 public:
     DebugGLColorData(void* layerRef,
                      const Color& color,
                      int width,
                      int height)
@@ -716,28 +752,19 @@ public:
         for (int i = 0; i < 16; i++) {
           dp->add_mvmatrix(*element++);
         }
         dp->set_totalrects(mRects);
 
         MOZ_ASSERT(mRects > 0 && mRects < 4);
         for (size_t i = 0; i < mRects; i++) {
             // Vertex
-            layerscope::DrawPacket::Rect* pRect = dp->add_layerrect();
-            pRect->set_x(mLayerRects[i].x);
-            pRect->set_y(mLayerRects[i].y);
-            pRect->set_w(mLayerRects[i].width);
-            pRect->set_h(mLayerRects[i].height);
-
+            DumpRect(dp->add_layerrect(), mLayerRects[i]);
             // UV
-            pRect = dp->add_texturerect();
-            pRect->set_x(mTextureRects[i].x);
-            pRect->set_y(mTextureRects[i].y);
-            pRect->set_w(mTextureRects[i].width);
-            pRect->set_h(mTextureRects[i].height);
+            DumpRect(dp->add_texturerect(), mTextureRects[i]);
         }
 
         for (GLuint texId: mTexIDs) {
             dp->add_texids(texId);
         }
 
         return WriteToStream(packet);
     }
@@ -902,35 +929,39 @@ public:
     static void SetLayersTreeSendable(bool aSet) {sLayersTreeSendable = aSet;}
 
     static void SetLayersBufferSendable(bool aSet) {sLayersBufferSendable = aSet;}
 
     static bool GetLayersTreeSendable() {return sLayersTreeSendable;}
 
     static void ClearSentTextureIds();
 
-
 // Sender private functions
 private:
     static void SendColor(void* aLayerRef,
                           const Color& aColor,
                           int aWidth,
                           int aHeight);
     static void SendTextureSource(GLContext* aGLContext,
                                   void* aLayerRef,
                                   TextureSourceOGL* aSource,
                                   bool aFlipY,
-                                  bool aIsMask);
+                                  bool aIsMask,
+                                  UniquePtr<Packet> aPacket);
 #ifdef MOZ_WIDGET_GONK
     static bool SendGraphicBuffer(GLContext* aGLContext,
                                   void* aLayerRef,
                                   TextureSourceOGL* aSource,
                                   const TexturedEffect* aEffect,
                                   bool aIsMask);
 #endif
+    static void SetAndSendTexture(GLContext* aGLContext,
+                                  void* aLayerRef,
+                                  TextureSourceOGL* aSource,
+                                  const TexturedEffect* aEffect);
     static void SendTexturedEffect(GLContext* aGLContext,
                                    void* aLayerRef,
                                    const TexturedEffect* aEffect);
     static void SendMaskEffect(GLContext* aGLContext,
                                    void* aLayerRef,
                                    const EffectMask* aEffect);
     static void SendYCbCrEffect(GLContext* aGLContext,
                                 void* aLayerRef,
@@ -1039,17 +1070,18 @@ SenderHelper::GetTextureID(GLContext* aG
     return texID;
 }
 
 void
 SenderHelper::SendTextureSource(GLContext* aGLContext,
                                 void* aLayerRef,
                                 TextureSourceOGL* aSource,
                                 bool aFlipY,
-                                bool aIsMask)
+                                bool aIsMask,
+                                UniquePtr<Packet> aPacket)
 {
     MOZ_ASSERT(aGLContext);
     if (!aGLContext) {
         return;
     }
     GLuint texID = GetTextureID(aGLContext, aSource);
     if (HasTextureIdBeenSent(texID)) {
         return;
@@ -1065,17 +1097,17 @@ SenderHelper::SendTextureSource(GLContex
     // By sending 0 to ReadTextureImage rely upon aSource->BindTexture binding
     // texture correctly. texID is used for tracking in DebugGLTextureData.
     RefPtr<DataSourceSurface> img =
         aGLContext->ReadTexImageHelper()->ReadTexImage(0, textureTarget,
                                                          size,
                                                          shaderConfig, aFlipY);
     gLayerScopeManager.GetSocketManager()->AppendDebugData(
         new DebugGLTextureData(aGLContext, aLayerRef, textureTarget,
-                               texID, img, aIsMask));
+                               texID, img, aIsMask, Move(aPacket)));
 
     sSentTextureIds.push_back(texID);
     gLayerScopeManager.CurrentSession().mTexIDs.push_back(texID);
 
 }
 
 #ifdef MOZ_WIDGET_GONK
 bool
@@ -1087,19 +1119,26 @@ SenderHelper::SendGraphicBuffer(GLContex
     GLuint texID = GetTextureID(aGLContext, aSource);
     if (HasTextureIdBeenSent(texID)) {
         return false;
     }
     if (!aEffect->mState.mSurface.get()) {
         return false;
     }
 
+    // Expose packet creation here, so we could dump primary texture effect attributes.
+    auto packet = MakeUnique<layerscope::Packet>();
+    layerscope::TexturePacket* texturePacket = packet->mutable_texture();
+    texturePacket->set_mpremultiplied(aEffect->mPremultiplied);
+    DumpFilter(texturePacket, aEffect->mFilter);
+    DumpRect(texturePacket->mutable_mtexturecoords(), aEffect->mTextureCoords);
+
     GLenum target = aSource->GetTextureTarget();
     mozilla::UniquePtr<DebugGLGraphicBuffer> package =
-        MakeUnique<DebugGLGraphicBuffer>(aLayerRef, target, texID, aEffect->mState, aIsMask);
+        MakeUnique<DebugGLGraphicBuffer>(aLayerRef, target, texID, aEffect->mState, aIsMask, Move(packet));
 
     // The texure content in this TexureHost is not altered,
     // we don't need to send it again.
     bool changed = gLayerScopeManager.GetContentMonitor()->IsChangedOrNew(
         aEffect->mState.mTexture);
     if (!package->TryPack(changed)) {
         return false;
     }
@@ -1111,65 +1150,93 @@ SenderHelper::SendGraphicBuffer(GLContex
     gLayerScopeManager.CurrentSession().mTexIDs.push_back(texID);
 
     gLayerScopeManager.GetContentMonitor()->ClearChangedHost(aEffect->mState.mTexture);
     return true;
 }
 #endif
 
 void
+SenderHelper::SetAndSendTexture(GLContext* aGLContext,
+                                void* aLayerRef,
+                                TextureSourceOGL* aSource,
+                                const TexturedEffect* aEffect)
+{
+    // Expose packet creation here, so we could dump primary texture effect attributes.
+    auto packet = MakeUnique<layerscope::Packet>();
+    layerscope::TexturePacket* texturePacket = packet->mutable_texture();
+    texturePacket->set_mpremultiplied(aEffect->mPremultiplied);
+    DumpFilter(texturePacket, aEffect->mFilter);
+    DumpRect(texturePacket->mutable_mtexturecoords(), aEffect->mTextureCoords);
+    SendTextureSource(aGLContext, aLayerRef, aSource, false, false, Move(packet));
+}
+
+void
 SenderHelper::SendTexturedEffect(GLContext* aGLContext,
                                  void* aLayerRef,
                                  const TexturedEffect* aEffect)
 {
     TextureSourceOGL* source = aEffect->mTexture->AsSourceOGL();
     if (!source) {
         return;
     }
 
 #ifdef MOZ_WIDGET_GONK
     if (SendGraphicBuffer(aGLContext, aLayerRef, source, aEffect, false)) {
         return;
     }
 #endif
+
     // Fallback texture sending path.
-    // Render to texture and read pixels back.
-    SendTextureSource(aGLContext, aLayerRef, source, false, false);
+    SetAndSendTexture(aGLContext, aLayerRef, source, aEffect);
 }
 
 void
 SenderHelper::SendMaskEffect(GLContext* aGLContext,
                                  void* aLayerRef,
                                  const EffectMask* aEffect)
 {
     TextureSourceOGL* source = aEffect->mMaskTexture->AsSourceOGL();
     if (!source) {
         return;
     }
 
-    SendTextureSource(aGLContext, aLayerRef, source, false, true);
+    // Expose packet creation here, so we could dump secondary mask effect attributes.
+    auto packet = MakeUnique<layerscope::Packet>();
+    TexturePacket::EffectMask* mask = packet->mutable_texture()->mutable_mask();
+    mask->set_mis3d(aEffect->mIs3D);
+    mask->mutable_msize()->set_w(aEffect->mSize.width);
+    mask->mutable_msize()->set_h(aEffect->mSize.height);
+    auto element = reinterpret_cast<const Float *>(&(aEffect->mMaskTransform));
+    for (int i = 0; i < 16; i++) {
+        mask->mutable_mmasktransform()->add_m(*element++);
+    }
+
+    SendTextureSource(aGLContext, aLayerRef, source, false, true, Move(packet));
 }
 
 void
 SenderHelper::SendYCbCrEffect(GLContext* aGLContext,
                               void* aLayerRef,
                               const EffectYCbCr* aEffect)
 {
     TextureSource* sourceYCbCr = aEffect->mTexture;
     if (!sourceYCbCr)
         return;
 
     const int Y = 0, Cb = 1, Cr = 2;
-    TextureSourceOGL* sourceY =  sourceYCbCr->GetSubSource(Y)->AsSourceOGL();
-    TextureSourceOGL* sourceCb = sourceYCbCr->GetSubSource(Cb)->AsSourceOGL();
-    TextureSourceOGL* sourceCr = sourceYCbCr->GetSubSource(Cr)->AsSourceOGL();
+    TextureSourceOGL *sources[] = {
+        sourceYCbCr->GetSubSource(Y)->AsSourceOGL(),
+        sourceYCbCr->GetSubSource(Cb)->AsSourceOGL(),
+        sourceYCbCr->GetSubSource(Cr)->AsSourceOGL()
+    };
 
-    SendTextureSource(aGLContext, aLayerRef, sourceY, false, false);
-    SendTextureSource(aGLContext, aLayerRef, sourceCb, false, false);
-    SendTextureSource(aGLContext, aLayerRef, sourceCr, false, false);
+    for (auto source: sources) {
+        SetAndSendTexture(aGLContext, aLayerRef, source, aEffect);
+    }
 }
 
 void
 SenderHelper::SendEffectChain(GLContext* aGLContext,
                               const EffectChain& aEffectChain,
                               int aWidth,
                               int aHeight)
 {
--- a/gfx/layers/apz/src/TaskThrottler.cpp
+++ b/gfx/layers/apz/src/TaskThrottler.cpp
@@ -1,44 +1,39 @@
 /* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 8; -*- */
 /* vim: set sw=2 sts=2 ts=8 et tw=80 : */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "TaskThrottler.h"
 
-#include "mozilla/layers/APZThreadUtils.h"  // for NewTimerCallback
-#include "nsComponentManagerUtils.h"        // for do_CreateInstance
-#include "nsITimer.h"
+#include "base/message_loop.h"
 
 #define TASK_LOG(...)
 // #define TASK_LOG(...) printf_stderr("TASK: " __VA_ARGS__)
 
 namespace mozilla {
 namespace layers {
 
 TaskThrottler::TaskThrottler(const TimeStamp& aTimeStamp, const TimeDuration& aMaxWait)
   : mMonitor("TaskThrottler")
   , mOutstanding(false)
   , mQueuedTask(nullptr)
   , mStartTime(aTimeStamp)
   , mMaxWait(aMaxWait)
   , mMean(1)
-  , mTimer(do_CreateInstance(NS_TIMER_CONTRACTID))
+  , mTimeoutTask(nullptr)
 {
-  // The TaskThrottler must be created on the main thread (or some nsITimer-
-  // compatible thread) for the nsITimer to work properly. In particular,
-  // creating it on the Compositor thread doesn't work.
-  MOZ_ASSERT(NS_IsMainThread());
 }
 
 TaskThrottler::~TaskThrottler()
 {
-  mTimer->Cancel();
+  // The timeout task holds a strong reference to the TaskThrottler, so if the
+  // TaskThrottler is being destroyed, there's no need to cancel the task.
 }
 
 void
 TaskThrottler::PostTask(const tracked_objects::Location& aLocation,
                         UniquePtr<CancelableTask> aTask, const TimeStamp& aTimeStamp)
 {
   MonitorAutoLock lock(mMonitor);
 
@@ -48,52 +43,56 @@ TaskThrottler::PostTask(const tracked_ob
   if (mOutstanding) {
     CancelPendingTask(lock);
     if (TimeSinceLastRequest(aTimeStamp, lock) < mMaxWait) {
       mQueuedTask = Move(aTask);
       TASK_LOG("%p queued task %p\n", this, mQueuedTask.get());
       // Make sure the queued task is sent after mMaxWait time elapses,
       // even if we don't get a TaskComplete() until then.
       TimeDuration timeout = mMaxWait - TimeSinceLastRequest(aTimeStamp, lock);
-      TimeStamp timeoutTime = mStartTime + mMaxWait;
-      RefPtr<TaskThrottler> refPtrThis = this;
-      mTimer->InitWithCallback(NewTimerCallback(
-          [refPtrThis, timeoutTime]()
-          {
-            MonitorAutoLock lock(refPtrThis->mMonitor);
-            if (refPtrThis->mQueuedTask) {
-              refPtrThis->RunQueuedTask(timeoutTime, lock);
-            }
-          }),
-          timeout.ToMilliseconds(), nsITimer::TYPE_ONE_SHOT);
+      mTimeoutTask = NewRunnableMethod(this, &TaskThrottler::OnTimeout);
+      MessageLoop::current()->PostDelayedTask(FROM_HERE, mTimeoutTask,
+          timeout.ToMilliseconds());
       return;
     }
     // we've been waiting for more than the max-wait limit, so just fall through
     // and send the new task already.
   }
 
   mStartTime = aTimeStamp;
   aTask->Run();
   mOutstanding = true;
 }
 
 void
+TaskThrottler::OnTimeout()
+{
+  MonitorAutoLock lock(mMonitor);
+  if (mQueuedTask) {
+    RunQueuedTask(TimeStamp::Now(), lock);
+  }
+  // The message loop will delete the posted timeout task. Make sure we don't
+  // keep a dangling pointer to it.
+  mTimeoutTask = nullptr;
+}
+
+void
 TaskThrottler::TaskComplete(const TimeStamp& aTimeStamp)
 {
   MonitorAutoLock lock(mMonitor);
 
   if (!mOutstanding) {
     return;
   }
 
   mMean.insert(aTimeStamp - mStartTime);
 
   if (mQueuedTask) {
     RunQueuedTask(aTimeStamp, lock);
-    mTimer->Cancel();
+    CancelTimeoutTask(lock);
   } else {
     mOutstanding = false;
   }
 }
 
 TimeDuration
 TaskThrottler::AverageDuration()
 {
@@ -121,17 +120,26 @@ TaskThrottler::CancelPendingTask()
 
 void
 TaskThrottler::CancelPendingTask(const MonitorAutoLock& aProofOfLock)
 {
   if (mQueuedTask) {
     TASK_LOG("%p cancelling task %p\n", this, mQueuedTask.get());
     mQueuedTask->Cancel();
     mQueuedTask = nullptr;
-    mTimer->Cancel();
+    CancelTimeoutTask(aProofOfLock);
+  }
+}
+
+void
+TaskThrottler::CancelTimeoutTask(const MonitorAutoLock& aProofOfLock)
+{
+  if (mTimeoutTask) {
+    mTimeoutTask->Cancel();
+    mTimeoutTask = nullptr;  // the MessageLoop will destroy it
   }
 }
 
 TimeDuration
 TaskThrottler::TimeSinceLastRequest(const TimeStamp& aTimeStamp)
 {
   MonitorAutoLock lock(mMonitor);
   return TimeSinceLastRequest(aTimeStamp, lock);
--- a/gfx/layers/apz/src/TaskThrottler.h
+++ b/gfx/layers/apz/src/TaskThrottler.h
@@ -13,18 +13,16 @@
 #include "mozilla/mozalloc.h"           // for operator delete
 #include "mozilla/RollingMean.h"        // for RollingMean
 #include "mozilla/TimeStamp.h"          // for TimeDuration, TimeStamp
 #include "mozilla/UniquePtr.h"          // for UniquePtr
 #include "nsCOMPtr.h"                   // for nsCOMPtr
 #include "nsISupportsImpl.h"            // for NS_INLINE_DECL_THREADSAFE_REFCOUNTING
 #include "nsTArray.h"                   // for nsTArray
 
-class nsITimer;
-
 namespace tracked_objects {
 class Location;
 } // namespace tracked_objects
 
 namespace mozilla {
 namespace layers {
 
 /** The TaskThrottler prevents update event overruns. It is used in cases where
@@ -97,22 +95,25 @@ public:
 
 private:
   mutable Monitor mMonitor;
   bool mOutstanding;
   UniquePtr<CancelableTask> mQueuedTask;
   TimeStamp mStartTime;
   TimeDuration mMaxWait;
   RollingMean<TimeDuration, TimeDuration> mMean;
-  nsCOMPtr<nsITimer> mTimer;
+  CancelableTask* mTimeoutTask;  // not owned because it's posted to a MessageLoop
+                                 // which deletes it
 
   ~TaskThrottler();
   void RunQueuedTask(const TimeStamp& aTimeStamp,
                      const MonitorAutoLock& aProofOfLock);
   void CancelPendingTask(const MonitorAutoLock& aProofOfLock);
   TimeDuration TimeSinceLastRequest(const TimeStamp& aTimeStamp,
                                     const MonitorAutoLock& aProofOfLock);
+  void OnTimeout();
+  void CancelTimeoutTask(const MonitorAutoLock& aProofOfLock);
 };
 
 } // namespace layers
 } // namespace mozilla
 
 #endif // mozilla_dom_TaskThrottler_h
--- a/gfx/layers/apz/test/mochitest/mochitest.ini
+++ b/gfx/layers/apz/test/mochitest/mochitest.ini
@@ -24,8 +24,10 @@ skip-if = (os == 'android') || (os == 'b
 [test_layerization.html]
 skip-if = (os == 'android') || (os == 'b2g') # uses wheel events which are not supported on mobile
 [test_basic_pan.html]
 skip-if = toolkit != 'gonk'
 [test_scroll_inactive_flattened_frame.html]
 skip-if = (os == 'android') || (os == 'b2g') || (buildapp == 'mulet') # wheel events not supported on mobile; see bug 1164274 for mulet
 [test_scroll_inactive_bug1190112.html]
 skip-if = (os == 'android') || (os == 'b2g') || (buildapp == 'mulet') # wheel events not supported on mobile; see bug 1164274 for mulet
+[test_scroll_subframe_scrollbar.html]
+skip-if = (os == 'android') || (os == 'b2g') || (buildapp == 'mulet') # wheel events not supported on mobile; see bug 1164274 for mulet
new file mode 100644
--- /dev/null
+++ b/gfx/layers/apz/test/mochitest/test_scroll_subframe_scrollbar.html
@@ -0,0 +1,119 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test scrolling subframe scrollbars</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+<style>
+p {
+  width:200px;
+  height:200px;
+  border:solid 1px black;
+}
+</style>
+</head>
+<body>
+<p id="subframe">
+1	<br>
+2	<br>
+3	<br>
+4	<br>
+5	<br>
+6	<br>
+7	<br>
+8	<br>
+9	<br>
+10	<br>
+11	<br>
+12	<br>
+13	<br>
+14	<br>
+15	<br>
+16	<br>
+17	<br>
+18	<br>
+19	<br>
+20	<br>
+21	<br>
+22	<br>
+23	<br>
+24	<br>
+25	<br>
+26	<br>
+27	<br>
+28	<br>
+29	<br>
+30	<br>
+31	<br>
+32	<br>
+33	<br>
+34	<br>
+35	<br>
+36	<br>
+37	<br>
+38	<br>
+39	<br>
+40	<br>
+</p>
+<script clss="testbody" type="text/javascript;version=1.7">
+
+var DefaultEvent = {
+  deltaMode: WheelEvent.DOM_DELTA_LINE,
+  deltaX: 0, deltaY: 1,
+  lineOrPageDeltaX: 0, lineOrPageDeltaY: 1,
+};
+
+var ScrollbarWidth = 0;
+
+function test() {
+  var subframe = document.getElementById('subframe');
+  var oldClientWidth = subframe.clientWidth;
+
+  subframe.style.overflow = 'auto';
+  subframe.getBoundingClientRect();
+
+  waitForAllPaintsFlushed(function () {
+    ScrollbarWidth = oldClientWidth - subframe.clientWidth;
+    if (!ScrollbarWidth) {
+      // Probably we have overlay scrollbars - abort the test.
+      ok(true, "overlay scrollbars - skipping test");
+      SimpleTest.finish();
+      return;
+    }
+
+    ok(subframe.scrollHeight > subframe.clientHeight, "subframe should have scrollable content");
+    testScrolling(subframe);
+  });
+}
+
+function testScrolling(subframe) {
+  // Send a wheel event roughly to where we think the trackbar is. We pick a
+  // point at the bottom, in the middle of the trackbar, where the slider is
+  // unlikely to be (since it starts at the top).
+  var posX = subframe.clientWidth + (ScrollbarWidth / 2);
+  var posY = subframe.clientHeight - 20;
+
+  var oldScrollTop = subframe.scrollTop;
+
+  sendWheelAndPaint(subframe, posX, posY, DefaultEvent, function () {
+    ok(subframe.scrollTop > oldScrollTop, "subframe should have scrolled");
+    SimpleTest.finish();
+  });
+}
+
+window.onload = function() {
+  SpecialPowers.pushPrefEnv({
+    'set': [['general.smoothScroll', false],
+            ['mousewheel.transaction.timeout', 0],
+            ['mousewheel.transaction.ignoremovedelay', 0]]
+  }, function () {
+    SimpleTest.waitForFocus(test);
+  });
+}
+
+SimpleTest.waitForExplicitFinish();
+</script>
+</body>
+</html>
--- a/gfx/layers/composite/AsyncCompositionManager.cpp
+++ b/gfx/layers/composite/AsyncCompositionManager.cpp
@@ -812,16 +812,20 @@ AsyncCompositionManager::ApplyAsyncConte
               metrics.GetScrollableRect(), displayPort, geckoZoom, mLayersUpdated,
               mPaintSyncId, fixedLayerMargins);
         }
         mIsFirstPaint = false;
         mLayersUpdated = false;
         mPaintSyncId = 0;
       }
     }
+#else
+    // Non-Android platforms still care about this flag being cleared after
+    // the first call to TransformShadowTree().
+    mIsFirstPaint = false;
 #endif
 
     // Transform the current local clip by this APZC's async transform. If we're
     // using containerful scrolling, then the clip is not part of the scrolled
     // frame and should not be transformed.
     if (asyncClip && !metrics.UsesContainerScrolling()) {
       MOZ_ASSERT(asyncTransform.Is2D());
       asyncClip = Some(TransformTo<ParentLayerPixel>(asyncTransform, *asyncClip));
--- a/gfx/layers/protobuf/LayerScopePacket.pb.cc
+++ b/gfx/layers/protobuf/LayerScopePacket.pb.cc
@@ -16,16 +16,20 @@
 namespace mozilla {
 namespace layers {
 namespace layerscope {
 
 void protobuf_ShutdownFile_LayerScopePacket_2eproto() {
   delete FramePacket::default_instance_;
   delete ColorPacket::default_instance_;
   delete TexturePacket::default_instance_;
+  delete TexturePacket_Rect::default_instance_;
+  delete TexturePacket_Size::default_instance_;
+  delete TexturePacket_Matrix::default_instance_;
+  delete TexturePacket_EffectMask::default_instance_;
   delete LayersPacket::default_instance_;
   delete LayersPacket_Layer::default_instance_;
   delete LayersPacket_Layer_Size::default_instance_;
   delete LayersPacket_Layer_Rect::default_instance_;
   delete LayersPacket_Layer_Region::default_instance_;
   delete LayersPacket_Layer_Matrix::default_instance_;
   delete LayersPacket_Layer_Shadow::default_instance_;
   delete MetaPacket::default_instance_;
@@ -45,31 +49,39 @@ void protobuf_AddDesc_LayerScopePacket_2
   if (already_here) return;
   already_here = true;
   GOOGLE_PROTOBUF_VERIFY_VERSION;
 
 #endif
   FramePacket::default_instance_ = new FramePacket();
   ColorPacket::default_instance_ = new ColorPacket();
   TexturePacket::default_instance_ = new TexturePacket();
+  TexturePacket_Rect::default_instance_ = new TexturePacket_Rect();
+  TexturePacket_Size::default_instance_ = new TexturePacket_Size();
+  TexturePacket_Matrix::default_instance_ = new TexturePacket_Matrix();
+  TexturePacket_EffectMask::default_instance_ = new TexturePacket_EffectMask();
   LayersPacket::default_instance_ = new LayersPacket();
   LayersPacket_Layer::default_instance_ = new LayersPacket_Layer();
   LayersPacket_Layer_Size::default_instance_ = new LayersPacket_Layer_Size();
   LayersPacket_Layer_Rect::default_instance_ = new LayersPacket_Layer_Rect();
   LayersPacket_Layer_Region::default_instance_ = new LayersPacket_Layer_Region();
   LayersPacket_Layer_Matrix::default_instance_ = new LayersPacket_Layer_Matrix();
   LayersPacket_Layer_Shadow::default_instance_ = new LayersPacket_Layer_Shadow();
   MetaPacket::default_instance_ = new MetaPacket();
   DrawPacket::default_instance_ = new DrawPacket();
   DrawPacket_Rect::default_instance_ = new DrawPacket_Rect();
   Packet::default_instance_ = new Packet();
   CommandPacket::default_instance_ = new CommandPacket();
   FramePacket::default_instance_->InitAsDefaultInstance();
   ColorPacket::default_instance_->InitAsDefaultInstance();
   TexturePacket::default_instance_->InitAsDefaultInstance();
+  TexturePacket_Rect::default_instance_->InitAsDefaultInstance();
+  TexturePacket_Size::default_instance_->InitAsDefaultInstance();
+  TexturePacket_Matrix::default_instance_->InitAsDefaultInstance();
+  TexturePacket_EffectMask::default_instance_->InitAsDefaultInstance();
   LayersPacket::default_instance_->InitAsDefaultInstance();
   LayersPacket_Layer::default_instance_->InitAsDefaultInstance();
   LayersPacket_Layer_Size::default_instance_->InitAsDefaultInstance();
   LayersPacket_Layer_Rect::default_instance_->InitAsDefaultInstance();
   LayersPacket_Layer_Region::default_instance_->InitAsDefaultInstance();
   LayersPacket_Layer_Matrix::default_instance_->InitAsDefaultInstance();
   LayersPacket_Layer_Shadow::default_instance_->InitAsDefaultInstance();
   MetaPacket::default_instance_->InitAsDefaultInstance();
@@ -633,36 +645,1150 @@ void ColorPacket::Swap(ColorPacket* othe
 
 ::std::string ColorPacket::GetTypeName() const {
   return "mozilla.layers.layerscope.ColorPacket";
 }
 
 
 // ===================================================================
 
+bool TexturePacket_Filter_IsValid(int value) {
+  switch(value) {
+    case 0:
+    case 1:
+    case 2:
+      return true;
+    default:
+      return false;
+  }
+}
+
+#ifndef _MSC_VER
+const TexturePacket_Filter TexturePacket::GOOD;
+const TexturePacket_Filter TexturePacket::LINEAR;
+const TexturePacket_Filter TexturePacket::POINT;
+const TexturePacket_Filter TexturePacket::Filter_MIN;
+const TexturePacket_Filter TexturePacket::Filter_MAX;
+const int TexturePacket::Filter_ARRAYSIZE;
+#endif  // _MSC_VER
+#ifndef _MSC_VER
+const int TexturePacket_Rect::kXFieldNumber;
+const int TexturePacket_Rect::kYFieldNumber;
+const int TexturePacket_Rect::kWFieldNumber;
+const int TexturePacket_Rect::kHFieldNumber;
+#endif  // !_MSC_VER
+
+TexturePacket_Rect::TexturePacket_Rect()
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:mozilla.layers.layerscope.TexturePacket.Rect)
+}
+
+void TexturePacket_Rect::InitAsDefaultInstance() {
+}
+
+TexturePacket_Rect::TexturePacket_Rect(const TexturePacket_Rect& from)
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:mozilla.layers.layerscope.TexturePacket.Rect)
+}
+
+void TexturePacket_Rect::SharedCtor() {
+  _cached_size_ = 0;
+  x_ = 0;
+  y_ = 0;
+  w_ = 0;
+  h_ = 0;
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+TexturePacket_Rect::~TexturePacket_Rect() {
+  // @@protoc_insertion_point(destructor:mozilla.layers.layerscope.TexturePacket.Rect)
+  SharedDtor();
+}
+
+void TexturePacket_Rect::SharedDtor() {
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  if (this != &default_instance()) {
+  #else
+  if (this != default_instance_) {
+  #endif
+  }
+}
+
+void TexturePacket_Rect::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const TexturePacket_Rect& TexturePacket_Rect::default_instance() {
+#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  protobuf_AddDesc_LayerScopePacket_2eproto();
+#else
+  if (default_instance_ == NULL) protobuf_AddDesc_LayerScopePacket_2eproto();
+#endif
+  return *default_instance_;
+}
+
+TexturePacket_Rect* TexturePacket_Rect::default_instance_ = NULL;
+
+TexturePacket_Rect* TexturePacket_Rect::New() const {
+  return new TexturePacket_Rect;
+}
+
+void TexturePacket_Rect::Clear() {
+#define OFFSET_OF_FIELD_(f) (reinterpret_cast<char*>(      \
+  &reinterpret_cast<TexturePacket_Rect*>(16)->f) - \
+   reinterpret_cast<char*>(16))
+
+#define ZR_(first, last) do {                              \
+    size_t f = OFFSET_OF_FIELD_(first);                    \
+    size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last);  \
+    ::memset(&first, 0, n);                                \
+  } while (0)
+
+  ZR_(x_, h_);
+
+#undef OFFSET_OF_FIELD_
+#undef ZR_
+
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  mutable_unknown_fields()->clear();
+}
+
+bool TexturePacket_Rect::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::io::StringOutputStream unknown_fields_string(
+      mutable_unknown_fields());
+  ::google::protobuf::io::CodedOutputStream unknown_fields_stream(
+      &unknown_fields_string);
+  // @@protoc_insertion_point(parse_start:mozilla.layers.layerscope.TexturePacket.Rect)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // optional float x = 1;
+      case 1: {
+        if (tag == 13) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>(
+                 input, &x_)));
+          set_has_x();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(21)) goto parse_y;
+        break;
+      }
+
+      // optional float y = 2;
+      case 2: {
+        if (tag == 21) {
+         parse_y:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>(
+                 input, &y_)));
+          set_has_y();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(29)) goto parse_w;
+        break;
+      }
+
+      // optional float w = 3;
+      case 3: {
+        if (tag == 29) {
+         parse_w:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>(
+                 input, &w_)));
+          set_has_w();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(37)) goto parse_h;
+        break;
+      }
+
+      // optional float h = 4;
+      case 4: {
+        if (tag == 37) {
+         parse_h:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>(
+                 input, &h_)));
+          set_has_h();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+            input, tag, &unknown_fields_stream));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:mozilla.layers.layerscope.TexturePacket.Rect)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:mozilla.layers.layerscope.TexturePacket.Rect)
+  return false;
+#undef DO_
+}
+
+void TexturePacket_Rect::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:mozilla.layers.layerscope.TexturePacket.Rect)
+  // optional float x = 1;
+  if (has_x()) {
+    ::google::protobuf::internal::WireFormatLite::WriteFloat(1, this->x(), output);
+  }
+
+  // optional float y = 2;
+  if (has_y()) {
+    ::google::protobuf::internal::WireFormatLite::WriteFloat(2, this->y(), output);
+  }
+
+  // optional float w = 3;
+  if (has_w()) {
+    ::google::protobuf::internal::WireFormatLite::WriteFloat(3, this->w(), output);
+  }
+
+  // optional float h = 4;
+  if (has_h()) {
+    ::google::protobuf::internal::WireFormatLite::WriteFloat(4, this->h(), output);
+  }
+
+  output->WriteRaw(unknown_fields().data(),
+                   unknown_fields().size());
+  // @@protoc_insertion_point(serialize_end:mozilla.layers.layerscope.TexturePacket.Rect)
+}
+
+int TexturePacket_Rect::ByteSize() const {
+  int total_size = 0;
+
+  if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    // optional float x = 1;
+    if (has_x()) {
+      total_size += 1 + 4;
+    }
+
+    // optional float y = 2;
+    if (has_y()) {
+      total_size += 1 + 4;
+    }
+
+    // optional float w = 3;
+    if (has_w()) {
+      total_size += 1 + 4;
+    }
+
+    // optional float h = 4;
+    if (has_h()) {
+      total_size += 1 + 4;
+    }
+
+  }
+  total_size += unknown_fields().size();
+
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void TexturePacket_Rect::CheckTypeAndMergeFrom(
+    const ::google::protobuf::MessageLite& from) {
+  MergeFrom(*::google::protobuf::down_cast<const TexturePacket_Rect*>(&from));
+}
+
+void TexturePacket_Rect::MergeFrom(const TexturePacket_Rect& from) {
+  GOOGLE_CHECK_NE(&from, this);
+  if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    if (from.has_x()) {
+      set_x(from.x());
+    }
+    if (from.has_y()) {
+      set_y(from.y());
+    }
+    if (from.has_w()) {
+      set_w(from.w());
+    }
+    if (from.has_h()) {
+      set_h(from.h());
+    }
+  }
+  mutable_unknown_fields()->append(from.unknown_fields());
+}
+
+void TexturePacket_Rect::CopyFrom(const TexturePacket_Rect& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool TexturePacket_Rect::IsInitialized() const {
+
+  return true;
+}
+
+void TexturePacket_Rect::Swap(TexturePacket_Rect* other) {
+  if (other != this) {
+    std::swap(x_, other->x_);
+    std::swap(y_, other->y_);
+    std::swap(w_, other->w_);
+    std::swap(h_, other->h_);
+    std::swap(_has_bits_[0], other->_has_bits_[0]);
+    _unknown_fields_.swap(other->_unknown_fields_);
+    std::swap(_cached_size_, other->_cached_size_);
+  }
+}
+
+::std::string TexturePacket_Rect::GetTypeName() const {
+  return "mozilla.layers.layerscope.TexturePacket.Rect";
+}
+
+
+// -------------------------------------------------------------------
+
+#ifndef _MSC_VER
+const int TexturePacket_Size::kWFieldNumber;
+const int TexturePacket_Size::kHFieldNumber;
+#endif  // !_MSC_VER
+
+TexturePacket_Size::TexturePacket_Size()
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:mozilla.layers.layerscope.TexturePacket.Size)
+}
+
+void TexturePacket_Size::InitAsDefaultInstance() {
+}
+
+TexturePacket_Size::TexturePacket_Size(const TexturePacket_Size& from)
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:mozilla.layers.layerscope.TexturePacket.Size)
+}
+
+void TexturePacket_Size::SharedCtor() {
+  _cached_size_ = 0;
+  w_ = 0;
+  h_ = 0;
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+TexturePacket_Size::~TexturePacket_Size() {
+  // @@protoc_insertion_point(destructor:mozilla.layers.layerscope.TexturePacket.Size)
+  SharedDtor();
+}
+
+void TexturePacket_Size::SharedDtor() {
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  if (this != &default_instance()) {
+  #else
+  if (this != default_instance_) {
+  #endif
+  }
+}
+
+void TexturePacket_Size::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const TexturePacket_Size& TexturePacket_Size::default_instance() {
+#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  protobuf_AddDesc_LayerScopePacket_2eproto();
+#else
+  if (default_instance_ == NULL) protobuf_AddDesc_LayerScopePacket_2eproto();
+#endif
+  return *default_instance_;
+}
+
+TexturePacket_Size* TexturePacket_Size::default_instance_ = NULL;
+
+TexturePacket_Size* TexturePacket_Size::New() const {
+  return new TexturePacket_Size;
+}
+
+void TexturePacket_Size::Clear() {
+#define OFFSET_OF_FIELD_(f) (reinterpret_cast<char*>(      \
+  &reinterpret_cast<TexturePacket_Size*>(16)->f) - \
+   reinterpret_cast<char*>(16))
+
+#define ZR_(first, last) do {                              \
+    size_t f = OFFSET_OF_FIELD_(first);                    \
+    size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last);  \
+    ::memset(&first, 0, n);                                \
+  } while (0)
+
+  ZR_(w_, h_);
+
+#undef OFFSET_OF_FIELD_
+#undef ZR_
+
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  mutable_unknown_fields()->clear();
+}
+
+bool TexturePacket_Size::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::io::StringOutputStream unknown_fields_string(
+      mutable_unknown_fields());
+  ::google::protobuf::io::CodedOutputStream unknown_fields_stream(
+      &unknown_fields_string);
+  // @@protoc_insertion_point(parse_start:mozilla.layers.layerscope.TexturePacket.Size)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // optional int32 w = 1;
+      case 1: {
+        if (tag == 8) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &w_)));
+          set_has_w();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(16)) goto parse_h;
+        break;
+      }
+
+      // optional int32 h = 2;
+      case 2: {
+        if (tag == 16) {
+         parse_h:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &h_)));
+          set_has_h();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+            input, tag, &unknown_fields_stream));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:mozilla.layers.layerscope.TexturePacket.Size)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:mozilla.layers.layerscope.TexturePacket.Size)
+  return false;
+#undef DO_
+}
+
+void TexturePacket_Size::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:mozilla.layers.layerscope.TexturePacket.Size)
+  // optional int32 w = 1;
+  if (has_w()) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(1, this->w(), output);
+  }
+
+  // optional int32 h = 2;
+  if (has_h()) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(2, this->h(), output);
+  }
+
+  output->WriteRaw(unknown_fields().data(),
+                   unknown_fields().size());
+  // @@protoc_insertion_point(serialize_end:mozilla.layers.layerscope.TexturePacket.Size)
+}
+
+int TexturePacket_Size::ByteSize() const {
+  int total_size = 0;
+
+  if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    // optional int32 w = 1;
+    if (has_w()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
+          this->w());
+    }
+
+    // optional int32 h = 2;
+    if (has_h()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
+          this->h());
+    }
+
+  }
+  total_size += unknown_fields().size();
+
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void TexturePacket_Size::CheckTypeAndMergeFrom(
+    const ::google::protobuf::MessageLite& from) {
+  MergeFrom(*::google::protobuf::down_cast<const TexturePacket_Size*>(&from));
+}
+
+void TexturePacket_Size::MergeFrom(const TexturePacket_Size& from) {
+  GOOGLE_CHECK_NE(&from, this);
+  if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    if (from.has_w()) {
+      set_w(from.w());
+    }
+    if (from.has_h()) {
+      set_h(from.h());
+    }
+  }
+  mutable_unknown_fields()->append(from.unknown_fields());
+}
+
+void TexturePacket_Size::CopyFrom(const TexturePacket_Size& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool TexturePacket_Size::IsInitialized() const {
+
+  return true;
+}
+
+void TexturePacket_Size::Swap(TexturePacket_Size* other) {
+  if (other != this) {
+    std::swap(w_, other->w_);
+    std::swap(h_, other->h_);
+    std::swap(_has_bits_[0], other->_has_bits_[0]);
+    _unknown_fields_.swap(other->_unknown_fields_);
+    std::swap(_cached_size_, other->_cached_size_);
+  }
+}
+
+::std::string TexturePacket_Size::GetTypeName() const {
+  return "mozilla.layers.layerscope.TexturePacket.Size";
+}
+
+
+// -------------------------------------------------------------------
+
+#ifndef _MSC_VER
+const int TexturePacket_Matrix::kIs2DFieldNumber;
+const int TexturePacket_Matrix::kIsIdFieldNumber;
+const int TexturePacket_Matrix::kMFieldNumber;
+#endif  // !_MSC_VER
+
+TexturePacket_Matrix::TexturePacket_Matrix()
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:mozilla.layers.layerscope.TexturePacket.Matrix)
+}
+
+void TexturePacket_Matrix::InitAsDefaultInstance() {
+}
+
+TexturePacket_Matrix::TexturePacket_Matrix(const TexturePacket_Matrix& from)
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:mozilla.layers.layerscope.TexturePacket.Matrix)
+}
+
+void TexturePacket_Matrix::SharedCtor() {
+  _cached_size_ = 0;
+  is2d_ = false;
+  isid_ = false;
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+TexturePacket_Matrix::~TexturePacket_Matrix() {
+  // @@protoc_insertion_point(destructor:mozilla.layers.layerscope.TexturePacket.Matrix)
+  SharedDtor();
+}
+
+void TexturePacket_Matrix::SharedDtor() {
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  if (this != &default_instance()) {
+  #else
+  if (this != default_instance_) {
+  #endif
+  }
+}
+
+void TexturePacket_Matrix::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const TexturePacket_Matrix& TexturePacket_Matrix::default_instance() {
+#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  protobuf_AddDesc_LayerScopePacket_2eproto();
+#else
+  if (default_instance_ == NULL) protobuf_AddDesc_LayerScopePacket_2eproto();
+#endif
+  return *default_instance_;
+}
+
+TexturePacket_Matrix* TexturePacket_Matrix::default_instance_ = NULL;
+
+TexturePacket_Matrix* TexturePacket_Matrix::New() const {
+  return new TexturePacket_Matrix;
+}
+
+void TexturePacket_Matrix::Clear() {
+#define OFFSET_OF_FIELD_(f) (reinterpret_cast<char*>(      \
+  &reinterpret_cast<TexturePacket_Matrix*>(16)->f) - \
+   reinterpret_cast<char*>(16))
+
+#define ZR_(first, last) do {                              \
+    size_t f = OFFSET_OF_FIELD_(first);                    \
+    size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last);  \
+    ::memset(&first, 0, n);                                \
+  } while (0)
+
+  ZR_(is2d_, isid_);
+
+#undef OFFSET_OF_FIELD_
+#undef ZR_
+
+  m_.Clear();
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  mutable_unknown_fields()->clear();
+}
+
+bool TexturePacket_Matrix::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::io::StringOutputStream unknown_fields_string(
+      mutable_unknown_fields());
+  ::google::protobuf::io::CodedOutputStream unknown_fields_stream(
+      &unknown_fields_string);
+  // @@protoc_insertion_point(parse_start:mozilla.layers.layerscope.TexturePacket.Matrix)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // optional bool is2D = 1;
+      case 1: {
+        if (tag == 8) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+                 input, &is2d_)));
+          set_has_is2d();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(16)) goto parse_isId;
+        break;
+      }
+
+      // optional bool isId = 2;
+      case 2: {
+        if (tag == 16) {
+         parse_isId:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+                 input, &isid_)));
+          set_has_isid();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(29)) goto parse_m;
+        break;
+      }
+
+      // repeated float m = 3;
+      case 3: {
+        if (tag == 29) {
+         parse_m:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadRepeatedPrimitive<
+                   float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>(
+                 1, 29, input, this->mutable_m())));
+        } else if (tag == 26) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPackedPrimitiveNoInline<
+                   float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>(
+                 input, this->mutable_m())));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(29)) goto parse_m;
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+            input, tag, &unknown_fields_stream));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:mozilla.layers.layerscope.TexturePacket.Matrix)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:mozilla.layers.layerscope.TexturePacket.Matrix)
+  return false;
+#undef DO_
+}
+
+void TexturePacket_Matrix::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:mozilla.layers.layerscope.TexturePacket.Matrix)
+  // optional bool is2D = 1;
+  if (has_is2d()) {
+    ::google::protobuf::internal::WireFormatLite::WriteBool(1, this->is2d(), output);
+  }
+
+  // optional bool isId = 2;
+  if (has_isid()) {
+    ::google::protobuf::internal::WireFormatLite::WriteBool(2, this->isid(), output);
+  }
+
+  // repeated float m = 3;
+  for (int i = 0; i < this->m_size(); i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteFloat(
+      3, this->m(i), output);
+  }
+
+  output->WriteRaw(unknown_fields().data(),
+                   unknown_fields().size());
+  // @@protoc_insertion_point(serialize_end:mozilla.layers.layerscope.TexturePacket.Matrix)
+}
+
+int TexturePacket_Matrix::ByteSize() const {
+  int total_size = 0;
+
+  if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    // optional bool is2D = 1;
+    if (has_is2d()) {
+      total_size += 1 + 1;
+    }
+
+    // optional bool isId = 2;
+    if (has_isid()) {
+      total_size += 1 + 1;
+    }
+
+  }
+  // repeated float m = 3;
+  {
+    int data_size = 0;
+    data_size = 4 * this->m_size();
+    total_size += 1 * this->m_size() + data_size;
+  }
+
+  total_size += unknown_fields().size();
+
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void TexturePacket_Matrix::CheckTypeAndMergeFrom(
+    const ::google::protobuf::MessageLite& from) {
+  MergeFrom(*::google::protobuf::down_cast<const TexturePacket_Matrix*>(&from));
+}
+
+void TexturePacket_Matrix::MergeFrom(const TexturePacket_Matrix& from) {
+  GOOGLE_CHECK_NE(&from, this);
+  m_.MergeFrom(from.m_);
+  if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    if (from.has_is2d()) {
+      set_is2d(from.is2d());
+    }
+    if (from.has_isid()) {
+      set_isid(from.isid());
+    }
+  }
+  mutable_unknown_fields()->append(from.unknown_fields());
+}
+
+void TexturePacket_Matrix::CopyFrom(const TexturePacket_Matrix& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool TexturePacket_Matrix::IsInitialized() const {
+
+  return true;
+}
+
+void TexturePacket_Matrix::Swap(TexturePacket_Matrix* other) {
+  if (other != this) {
+    std::swap(is2d_, other->is2d_);
+    std::swap(isid_, other->isid_);
+    m_.Swap(&other->m_);
+    std::swap(_has_bits_[0], other->_has_bits_[0]);
+    _unknown_fields_.swap(other->_unknown_fields_);
+    std::swap(_cached_size_, other->_cached_size_);
+  }
+}
+
+::std::string TexturePacket_Matrix::GetTypeName() const {
+  return "mozilla.layers.layerscope.TexturePacket.Matrix";
+}
+
+
+// -------------------------------------------------------------------
+
+#ifndef _MSC_VER
+const int TexturePacket_EffectMask::kMIs3DFieldNumber;
+const int TexturePacket_EffectMask::kMSizeFieldNumber;
+const int TexturePacket_EffectMask::kMMaskTransformFieldNumber;
+#endif  // !_MSC_VER
+
+TexturePacket_EffectMask::TexturePacket_EffectMask()
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:mozilla.layers.layerscope.TexturePacket.EffectMask)
+}
+
+void TexturePacket_EffectMask::InitAsDefaultInstance() {
+#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  msize_ = const_cast< ::mozilla::layers::layerscope::TexturePacket_Size*>(
+      ::mozilla::layers::layerscope::TexturePacket_Size::internal_default_instance());
+#else
+  msize_ = const_cast< ::mozilla::layers::layerscope::TexturePacket_Size*>(&::mozilla::layers::layerscope::TexturePacket_Size::default_instance());
+#endif
+#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  mmasktransform_ = const_cast< ::mozilla::layers::layerscope::TexturePacket_Matrix*>(
+      ::mozilla::layers::layerscope::TexturePacket_Matrix::internal_default_instance());
+#else
+  mmasktransform_ = const_cast< ::mozilla::layers::layerscope::TexturePacket_Matrix*>(&::mozilla::layers::layerscope::TexturePacket_Matrix::default_instance());
+#endif
+}
+
+TexturePacket_EffectMask::TexturePacket_EffectMask(const TexturePacket_EffectMask& from)
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:mozilla.layers.layerscope.TexturePacket.EffectMask)
+}
+
+void TexturePacket_EffectMask::SharedCtor() {
+  _cached_size_ = 0;
+  mis3d_ = false;
+  msize_ = NULL;
+  mmasktransform_ = NULL;
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+TexturePacket_EffectMask::~TexturePacket_EffectMask() {
+  // @@protoc_insertion_point(destructor:mozilla.layers.layerscope.TexturePacket.EffectMask)
+  SharedDtor();
+}
+
+void TexturePacket_EffectMask::SharedDtor() {
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  if (this != &default_instance()) {
+  #else
+  if (this != default_instance_) {
+  #endif
+    delete msize_;
+    delete mmasktransform_;
+  }
+}
+
+void TexturePacket_EffectMask::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const TexturePacket_EffectMask& TexturePacket_EffectMask::default_instance() {
+#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  protobuf_AddDesc_LayerScopePacket_2eproto();
+#else
+  if (default_instance_ == NULL) protobuf_AddDesc_LayerScopePacket_2eproto();
+#endif
+  return *default_instance_;
+}
+
+TexturePacket_EffectMask* TexturePacket_EffectMask::default_instance_ = NULL;
+
+TexturePacket_EffectMask* TexturePacket_EffectMask::New() const {
+  return new TexturePacket_EffectMask;
+}
+
+void TexturePacket_EffectMask::Clear() {
+  if (_has_bits_[0 / 32] & 7) {
+    mis3d_ = false;
+    if (has_msize()) {
+      if (msize_ != NULL) msize_->::mozilla::layers::layerscope::TexturePacket_Size::Clear();
+    }
+    if (has_mmasktransform()) {
+      if (mmasktransform_ != NULL) mmasktransform_->::mozilla::layers::layerscope::TexturePacket_Matrix::Clear();
+    }
+  }
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  mutable_unknown_fields()->clear();
+}
+
+bool TexturePacket_EffectMask::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::io::StringOutputStream unknown_fields_string(
+      mutable_unknown_fields());
+  ::google::protobuf::io::CodedOutputStream unknown_fields_stream(
+      &unknown_fields_string);
+  // @@protoc_insertion_point(parse_start:mozilla.layers.layerscope.TexturePacket.EffectMask)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // optional bool mIs3D = 1;
+      case 1: {
+        if (tag == 8) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+                 input, &mis3d_)));
+          set_has_mis3d();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(18)) goto parse_mSize;
+        break;
+      }
+
+      // optional .mozilla.layers.layerscope.TexturePacket.Size mSize = 2;
+      case 2: {
+        if (tag == 18) {
+         parse_mSize:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+               input, mutable_msize()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(26)) goto parse_mMaskTransform;
+        break;
+      }
+
+      // optional .mozilla.layers.layerscope.TexturePacket.Matrix mMaskTransform = 3;
+      case 3: {
+        if (tag == 26) {
+         parse_mMaskTransform:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+               input, mutable_mmasktransform()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+            input, tag, &unknown_fields_stream));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:mozilla.layers.layerscope.TexturePacket.EffectMask)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:mozilla.layers.layerscope.TexturePacket.EffectMask)
+  return false;
+#undef DO_
+}
+
+void TexturePacket_EffectMask::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:mozilla.layers.layerscope.TexturePacket.EffectMask)
+  // optional bool mIs3D = 1;
+  if (has_mis3d()) {
+    ::google::protobuf::internal::WireFormatLite::WriteBool(1, this->mis3d(), output);
+  }
+
+  // optional .mozilla.layers.layerscope.TexturePacket.Size mSize = 2;
+  if (has_msize()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessage(
+      2, this->msize(), output);
+  }
+
+  // optional .mozilla.layers.layerscope.TexturePacket.Matrix mMaskTransform = 3;
+  if (has_mmasktransform()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessage(
+      3, this->mmasktransform(), output);
+  }
+
+  output->WriteRaw(unknown_fields().data(),
+                   unknown_fields().size());
+  // @@protoc_insertion_point(serialize_end:mozilla.layers.layerscope.TexturePacket.EffectMask)
+}
+
+int TexturePacket_EffectMask::ByteSize() const {
+  int total_size = 0;
+
+  if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    // optional bool mIs3D = 1;
+    if (has_mis3d()) {
+      total_size += 1 + 1;
+    }
+
+    // optional .mozilla.layers.layerscope.TexturePacket.Size mSize = 2;
+    if (has_msize()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+          this->msize());
+    }
+
+    // optional .mozilla.layers.layerscope.TexturePacket.Matrix mMaskTransform = 3;
+    if (has_mmasktransform()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+          this->mmasktransform());
+    }
+
+  }
+  total_size += unknown_fields().size();
+
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void TexturePacket_EffectMask::CheckTypeAndMergeFrom(
+    const ::google::protobuf::MessageLite& from) {
+  MergeFrom(*::google::protobuf::down_cast<const TexturePacket_EffectMask*>(&from));
+}
+
+void TexturePacket_EffectMask::MergeFrom(const TexturePacket_EffectMask& from) {
+  GOOGLE_CHECK_NE(&from, this);
+  if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    if (from.has_mis3d()) {
+      set_mis3d(from.mis3d());
+    }
+    if (from.has_msize()) {
+      mutable_msize()->::mozilla::layers::layerscope::TexturePacket_Size::MergeFrom(from.msize());
+    }
+    if (from.has_mmasktransform()) {
+      mutable_mmasktransform()->::mozilla::layers::layerscope::TexturePacket_Matrix::MergeFrom(from.mmasktransform());
+    }
+  }
+  mutable_unknown_fields()->append(from.unknown_fields());
+}
+
+void TexturePacket_EffectMask::CopyFrom(const TexturePacket_EffectMask& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool TexturePacket_EffectMask::IsInitialized() const {
+
+  return true;
+}
+
+void TexturePacket_EffectMask::Swap(TexturePacket_EffectMask* other) {
+  if (other != this) {
+    std::swap(mis3d_, other->mis3d_);
+    std::swap(msize_, other->msize_);
+    std::swap(mmasktransform_, other->mmasktransform_);
+    std::swap(_has_bits_[0], other->_has_bits_[0]);
+    _unknown_fields_.swap(other->_unknown_fields_);
+    std::swap(_cached_size_, other->_cached_size_);
+  }
+}
+
+::std::string TexturePacket_EffectMask::GetTypeName() const {
+  return "mozilla.layers.layerscope.TexturePacket.EffectMask";
+}
+
+
+// -------------------------------------------------------------------
+
 #ifndef _MSC_VER
 const int TexturePacket::kLayerrefFieldNumber;
 const int TexturePacket::kWidthFieldNumber;
 const int TexturePacket::kHeightFieldNumber;
 const int TexturePacket::kStrideFieldNumber;
 const int TexturePacket::kNameFieldNumber;
 const int TexturePacket::kTargetFieldNumber;
 const int TexturePacket::kDataformatFieldNumber;
 const int TexturePacket::kGlcontextFieldNumber;
 const int TexturePacket::kDataFieldNumber;
+const int TexturePacket::kMTextureCoordsFieldNumber;
+const int TexturePacket::kMPremultipliedFieldNumber;
+const int TexturePacket::kMFilterFieldNumber;
 const int TexturePacket::kIsMaskFieldNumber;
+const int TexturePacket::kMaskFieldNumber;
 #endif  // !_MSC_VER
 
 TexturePacket::TexturePacket()
   : ::google::protobuf::MessageLite() {
   SharedCtor();
   // @@protoc_insertion_point(constructor:mozilla.layers.layerscope.TexturePacket)
 }
 
 void TexturePacket::InitAsDefaultInstance() {
+#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  mtexturecoords_ = const_cast< ::mozilla::layers::layerscope::TexturePacket_Rect*>(
+      ::mozilla::layers::layerscope::TexturePacket_Rect::internal_default_instance());
+#else
+  mtexturecoords_ = const_cast< ::mozilla::layers::layerscope::TexturePacket_Rect*>(&::mozilla::layers::layerscope::TexturePacket_Rect::default_instance());
+#endif
+#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  mask_ = const_cast< ::mozilla::layers::layerscope::TexturePacket_EffectMask*>(
+      ::mozilla::layers::layerscope::TexturePacket_EffectMask::internal_default_instance());
+#else
+  mask_ = const_cast< ::mozilla::layers::layerscope::TexturePacket_EffectMask*>(&::mozilla::layers::layerscope::TexturePacket_EffectMask::default_instance());
+#endif
 }
 
 TexturePacket::TexturePacket(const TexturePacket& from)
   : ::google::protobuf::MessageLite() {
   SharedCtor();
   MergeFrom(from);
   // @@protoc_insertion_point(copy_constructor:mozilla.layers.layerscope.TexturePacket)
 }
@@ -674,17 +1800,21 @@ void TexturePacket::SharedCtor() {
   width_ = 0u;
   height_ = 0u;
   stride_ = 0u;
   name_ = 0u;
   target_ = 0u;
   dataformat_ = 0u;
   glcontext_ = GOOGLE_ULONGLONG(0);
   data_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  mtexturecoords_ = NULL;
+  mpremultiplied_ = false;
+  mfilter_ = 0;
   ismask_ = false;
+  mask_ = NULL;
   ::memset(_has_bits_, 0, sizeof(_has_bits_));
 }
 
 TexturePacket::~TexturePacket() {
   // @@protoc_insertion_point(destructor:mozilla.layers.layerscope.TexturePacket)
   SharedDtor();
 }
 
@@ -692,16 +1822,18 @@ void TexturePacket::SharedDtor() {
   if (data_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
     delete data_;
   }
   #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
   if (this != &default_instance()) {
   #else
   if (this != default_instance_) {
   #endif
+    delete mtexturecoords_;
+    delete mask_;
   }
 }
 
 void TexturePacket::SetCachedSize(int size) const {
   GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
   _cached_size_ = size;
   GOOGLE_SAFE_CONCURRENT_WRITES_END();
 }
@@ -729,23 +1861,29 @@ void TexturePacket::Clear() {
     size_t f = OFFSET_OF_FIELD_(first);                    \
     size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last);  \
     ::memset(&first, 0, n);                                \
   } while (0)
 
   if (_has_bits_[0 / 32] & 255) {
     ZR_(layerref_, glcontext_);
   }
-  if (_has_bits_[8 / 32] & 768) {
+  if (_has_bits_[8 / 32] & 16128) {
+    ZR_(mfilter_, ismask_);
     if (has_data()) {
       if (data_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
         data_->clear();
       }
     }
-    ismask_ = false;
+    if (has_mtexturecoords()) {
+      if (mtexturecoords_ != NULL) mtexturecoords_->::mozilla::layers::layerscope::TexturePacket_Rect::Clear();
+    }
+    if (has_mask()) {
+      if (mask_ != NULL) mask_->::mozilla::layers::layerscope::TexturePacket_EffectMask::Clear();
+    }
   }
 
 #undef OFFSET_OF_FIELD_
 #undef ZR_
 
   ::memset(_has_bits_, 0, sizeof(_has_bits_));
   mutable_unknown_fields()->clear();
 }
@@ -887,31 +2025,93 @@ bool TexturePacket::MergePartialFromCode
       case 9: {
         if (tag == 74) {
          parse_data:
           DO_(::google::protobuf::internal::WireFormatLite::ReadBytes(
                 input, this->mutable_data()));
         } else {
           goto handle_unusual;
         }
+        if (input->ExpectTag(82)) goto parse_mTextureCoords;
+        break;
+      }
+
+      // optional .mozilla.layers.layerscope.TexturePacket.Rect mTextureCoords = 10;
+      case 10: {
+        if (tag == 82) {
+         parse_mTextureCoords:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+               input, mutable_mtexturecoords()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(88)) goto parse_mPremultiplied;
+        break;
+      }
+
+      // optional bool mPremultiplied = 11;
+      case 11: {
+        if (tag == 88) {
+         parse_mPremultiplied:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+                 input, &mpremultiplied_)));
+          set_has_mpremultiplied();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(96)) goto parse_mFilter;
+        break;
+      }
+
+      // optional .mozilla.layers.layerscope.TexturePacket.Filter mFilter = 12;
+      case 12: {
+        if (tag == 96) {
+         parse_mFilter:
+          int value;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          if (::mozilla::layers::layerscope::TexturePacket_Filter_IsValid(value)) {
+            set_mfilter(static_cast< ::mozilla::layers::layerscope::TexturePacket_Filter >(value));
+          } else {
+            unknown_fields_stream.WriteVarint32(tag);
+            unknown_fields_stream.WriteVarint32(value);
+          }
+        } else {
+          goto handle_unusual;
+        }
         if (input->ExpectTag(160)) goto parse_isMask;
         break;
       }
 
       // optional bool isMask = 20;
       case 20: {
         if (tag == 160) {
          parse_isMask:
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
                  input, &ismask_)));
           set_has_ismask();
         } else {
           goto handle_unusual;
         }
+        if (input->ExpectTag(170)) goto parse_mask;
+        break;
+      }
+
+      // optional .mozilla.layers.layerscope.TexturePacket.EffectMask mask = 21;
+      case 21: {
+        if (tag == 170) {
+         parse_mask:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+               input, mutable_mask()));
+        } else {
+          goto handle_unusual;
+        }
         if (input->ExpectAtEnd()) goto success;
         break;
       }
 
       default: {
       handle_unusual:
         if (tag == 0 ||
             ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -977,21 +2177,44 @@ void TexturePacket::SerializeWithCachedS
   }
 
   // optional bytes data = 9;
   if (has_data()) {
     ::google::protobuf::internal::WireFormatLite::WriteBytesMaybeAliased(
       9, this->data(), output);
   }
 
+  // optional .mozilla.layers.layerscope.TexturePacket.Rect mTextureCoords = 10;
+  if (has_mtexturecoords()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessage(
+      10, this->mtexturecoords(), output);
+  }
+
+  // optional bool mPremultiplied = 11;
+  if (has_mpremultiplied()) {
+    ::google::protobuf::internal::WireFormatLite::WriteBool(11, this->mpremultiplied(), output);
+  }
+
+  // optional .mozilla.layers.layerscope.TexturePacket.Filter mFilter = 12;
+  if (has_mfilter()) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      12, this->mfilter(), output);
+  }
+
   // optional bool isMask = 20;
   if (has_ismask()) {
     ::google::protobuf::internal::WireFormatLite::WriteBool(20, this->ismask(), output);
   }
 
+  // optional .mozilla.layers.layerscope.TexturePacket.EffectMask mask = 21;
+  if (has_mask()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessage(
+      21, this->mask(), output);
+  }
+
   output->WriteRaw(unknown_fields().data(),
                    unknown_fields().size());
   // @@protoc_insertion_point(serialize_end:mozilla.layers.layerscope.TexturePacket)
 }
 
 int TexturePacket::ByteSize() const {
   int total_size = 0;
 
@@ -1056,21 +2279,46 @@ int TexturePacket::ByteSize() const {
   if (_has_bits_[8 / 32] & (0xffu << (8 % 32))) {
     // optional bytes data = 9;
     if (has_data()) {
       total_size += 1 +
         ::google::protobuf::internal::WireFormatLite::BytesSize(
           this->data());
     }
 
+    // optional .mozilla.layers.layerscope.TexturePacket.Rect mTextureCoords = 10;
+    if (has_mtexturecoords()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+          this->mtexturecoords());
+    }
+
+    // optional bool mPremultiplied = 11;
+    if (has_mpremultiplied()) {
+      total_size += 1 + 1;
+    }
+
+    // optional .mozilla.layers.layerscope.TexturePacket.Filter mFilter = 12;
+    if (has_mfilter()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::EnumSize(this->mfilter());
+    }
+
     // optional bool isMask = 20;
     if (has_ismask()) {
       total_size += 2 + 1;
     }
 
+    // optional .mozilla.layers.layerscope.TexturePacket.EffectMask mask = 21;
+    if (has_mask()) {
+      total_size += 2 +
+        ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+          this->mask());
+    }
+
   }
   total_size += unknown_fields().size();
 
   GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
   _cached_size_ = total_size;
   GOOGLE_SAFE_CONCURRENT_WRITES_END();
   return total_size;
 }
@@ -1107,19 +2355,31 @@ void TexturePacket::MergeFrom(const Text
     if (from.has_glcontext()) {
       set_glcontext(from.glcontext());
     }
   }
   if (from._has_bits_[8 / 32] & (0xffu << (8 % 32))) {
     if (from.has_data()) {
       set_data(from.data());
     }
+    if (from.has_mtexturecoords()) {
+      mutable_mtexturecoords()->::mozilla::layers::layerscope::TexturePacket_Rect::MergeFrom(from.mtexturecoords());
+    }
+    if (from.has_mpremultiplied()) {
+      set_mpremultiplied(from.mpremultiplied());
+    }
+    if (from.has_mfilter()) {
+      set_mfilter(from.mfilter());
+    }
     if (from.has_ismask()) {
       set_ismask(from.ismask());
     }
+    if (from.has_mask()) {
+      mutable_mask()->::mozilla::layers::layerscope::TexturePacket_EffectMask::MergeFrom(from.mask());
+    }
   }
   mutable_unknown_fields()->append(from.unknown_fields());
 }
 
 void TexturePacket::CopyFrom(const TexturePacket& from) {
   if (&from == this) return;
   Clear();
   MergeFrom(from);
@@ -1137,17 +2397,21 @@ void TexturePacket::Swap(TexturePacket* 
     std::swap(width_, other->width_);
     std::swap(height_, other->height_);
     std::swap(stride_, other->stride_);
     std::swap(name_, other->name_);
     std::swap(target_, other->target_);
     std::swap(dataformat_, other->dataformat_);
     std::swap(glcontext_, other->glcontext_);
     std::swap(data_, other->data_);
+    std::swap(mtexturecoords_, other->mtexturecoords_);
+    std::swap(mpremultiplied_, other->mpremultiplied_);
+    std::swap(mfilter_, other->mfilter_);
     std::swap(ismask_, other->ismask_);
+    std::swap(mask_, other->mask_);
     std::swap(_has_bits_[0], other->_has_bits_[0]);
     _unknown_fields_.swap(other->_unknown_fields_);
     std::swap(_cached_size_, other->_cached_size_);
   }
 }
 
 ::std::string TexturePacket::GetTypeName() const {
   return "mozilla.layers.layerscope.TexturePacket";
@@ -1208,27 +2472,37 @@ bool LayersPacket_Layer_Filter_IsValid(i
   switch(value) {
     case 0:
     case 1:
     case 2:
     case 3:
     case 4:
     case 5:
     case 6:
+    case 7:
+    case 8:
       return true;
     default:
       return false;
   }
 }
 
 #ifndef _MSC_VER
+const LayersPacket_Layer_Filter LayersPacket_Layer::FILTER_FAST;
 const LayersPacket_Layer_Filter LayersPacket_Layer::FILTER_GOOD;
+const LayersPacket_Layer_Filter LayersPacket_Layer::FILTER_BEST;
+const LayersPacket_Layer_Filter LayersPacket_Layer::FILTER_NEAREST;
+const LayersPacket_Layer_Filter LayersPacket_Layer::FILTER_BILINEAR;
+const LayersPacket_Layer_Filter LayersPacket_Layer::FILTER_GAUSSIAN;
+const LayersPacket_Layer_Filter LayersPacket_Layer::FILTER_SENTINEL;
 const LayersPacket_Layer_Filter LayersPacket_Layer::FILTER_LINEAR;
 const LayersPacket_Layer_Filter LayersPacket_Layer::FILTER_POINT;
-const LayersPacket_Layer_Filter LayersPacket_Layer::FILTER_SENTINEL;
+const LayersPacket_Layer_Filter LayersPacket_Layer::Filter_MIN;
+const LayersPacket_Layer_Filter LayersPacket_Layer::Filter_MAX;
+const int LayersPacket_Layer::Filter_ARRAYSIZE;
 #endif  // _MSC_VER
 #ifndef _MSC_VER
 const int LayersPacket_Layer_Size::kWFieldNumber;
 const int LayersPacket_Layer_Size::kHFieldNumber;
 #endif  // !_MSC_VER
 
 LayersPacket_Layer_Size::LayersPacket_Layer_Size()
   : ::google::protobuf::MessageLite() {
--- a/gfx/layers/protobuf/LayerScopePacket.pb.h
+++ b/gfx/layers/protobuf/LayerScopePacket.pb.h
@@ -32,29 +32,43 @@ namespace layerscope {
 // Internal implementation detail -- do not call these.
 void  protobuf_AddDesc_LayerScopePacket_2eproto();
 void protobuf_AssignDesc_LayerScopePacket_2eproto();
 void protobuf_ShutdownFile_LayerScopePacket_2eproto();
 
 class FramePacket;
 class ColorPacket;
 class TexturePacket;
+class TexturePacket_Rect;
+class TexturePacket_Size;
+class TexturePacket_Matrix;
+class TexturePacket_EffectMask;
 class LayersPacket;
 class LayersPacket_Layer;
 class LayersPacket_Layer_Size;
 class LayersPacket_Layer_Rect;
 class LayersPacket_Layer_Region;
 class LayersPacket_Layer_Matrix;
 class LayersPacket_Layer_Shadow;
 class MetaPacket;
 class DrawPacket;
 class DrawPacket_Rect;
 class Packet;
 class CommandPacket;
 
+enum TexturePacket_Filter {
+  TexturePacket_Filter_GOOD = 0,
+  TexturePacket_Filter_LINEAR = 1,
+  TexturePacket_Filter_POINT = 2
+};
+bool TexturePacket_Filter_IsValid(int value);
+const TexturePacket_Filter TexturePacket_Filter_Filter_MIN = TexturePacket_Filter_GOOD;
+const TexturePacket_Filter TexturePacket_Filter_Filter_MAX = TexturePacket_Filter_POINT;
+const int TexturePacket_Filter_Filter_ARRAYSIZE = TexturePacket_Filter_Filter_MAX + 1;
+
 enum LayersPacket_Layer_LayerType {
   LayersPacket_Layer_LayerType_UnknownLayer = 0,
   LayersPacket_Layer_LayerType_LayerManager = 1,
   LayersPacket_Layer_LayerType_ContainerLayer = 2,
   LayersPacket_Layer_LayerType_PaintedLayer = 3,
   LayersPacket_Layer_LayerType_CanvasLayer = 4,
   LayersPacket_Layer_LayerType_ImageLayer = 5,
   LayersPacket_Layer_LayerType_ColorLayer = 6,
@@ -71,22 +85,30 @@ enum LayersPacket_Layer_ScrollingDirect 
   LayersPacket_Layer_ScrollingDirect_HORIZONTAL = 2
 };
 bool LayersPacket_Layer_ScrollingDirect_IsValid(int value);
 const LayersPacket_Layer_ScrollingDirect LayersPacket_Layer_ScrollingDirect_ScrollingDirect_MIN = LayersPacket_Layer_ScrollingDirect_VERTICAL;
 const LayersPacket_Layer_ScrollingDirect LayersPacket_Layer_ScrollingDirect_ScrollingDirect_MAX = LayersPacket_Layer_ScrollingDirect_HORIZONTAL;
 const int LayersPacket_Layer_ScrollingDirect_ScrollingDirect_ARRAYSIZE = LayersPacket_Layer_ScrollingDirect_ScrollingDirect_MAX + 1;
 
 enum LayersPacket_Layer_Filter {
-  LayersPacket_Layer_Filter_FILTER_GOOD = 0,
-  LayersPacket_Layer_Filter_FILTER_LINEAR = 1,
-  LayersPacket_Layer_Filter_FILTER_POINT = 2,
-  LayersPacket_Layer_Filter_FILTER_SENTINEL = 3
+  LayersPacket_Layer_Filter_FILTER_FAST = 0,
+  LayersPacket_Layer_Filter_FILTER_GOOD = 1,
+  LayersPacket_Layer_Filter_FILTER_BEST = 2,
+  LayersPacket_Layer_Filter_FILTER_NEAREST = 3,
+  LayersPacket_Layer_Filter_FILTER_BILINEAR = 4,
+  LayersPacket_Layer_Filter_FILTER_GAUSSIAN = 5,
+  LayersPacket_Layer_Filter_FILTER_SENTINEL = 6,
+  LayersPacket_Layer_Filter_FILTER_LINEAR = 7,
+  LayersPacket_Layer_Filter_FILTER_POINT = 8
 };
 bool LayersPacket_Layer_Filter_IsValid(int value);
+const LayersPacket_Layer_Filter LayersPacket_Layer_Filter_Filter_MIN = LayersPacket_Layer_Filter_FILTER_FAST;
+const LayersPacket_Layer_Filter LayersPacket_Layer_Filter_Filter_MAX = LayersPacket_Layer_Filter_FILTER_POINT;
+const int LayersPacket_Layer_Filter_Filter_ARRAYSIZE = LayersPacket_Layer_Filter_Filter_MAX + 1;
 
 enum Packet_DataType {
   Packet_DataType_FRAMESTART = 1,
   Packet_DataType_FRAMEEND = 2,
   Packet_DataType_COLOR = 3,
   Packet_DataType_TEXTURE = 4,
   Packet_DataType_LAYERS = 5,
   Packet_DataType_META = 6,
@@ -326,16 +348,467 @@ class ColorPacket : public ::google::pro
   friend void protobuf_AssignDesc_LayerScopePacket_2eproto();
   friend void protobuf_ShutdownFile_LayerScopePacket_2eproto();
 
   void InitAsDefaultInstance();
   static ColorPacket* default_instance_;
 };
 // -------------------------------------------------------------------
 
+class TexturePacket_Rect : public ::google::protobuf::MessageLite {
+ public:
+  TexturePacket_Rect();
+  virtual ~TexturePacket_Rect();
+
+  TexturePacket_Rect(const TexturePacket_Rect& from);
+
+  inline TexturePacket_Rect& operator=(const TexturePacket_Rect& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline const ::std::string& unknown_fields() const {
+    return _unknown_fields_;
+  }
+
+  inline ::std::string* mutable_unknown_fields() {
+    return &_unknown_fields_;
+  }
+
+  static const TexturePacket_Rect& default_instance();
+
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  // Returns the internal default instance pointer. This function can
+  // return NULL thus should not be used by the user. This is intended
+  // for Protobuf internal code. Please use default_instance() declared
+  // above instead.
+  static inline const TexturePacket_Rect* internal_default_instance() {
+    return default_instance_;
+  }
+  #endif
+
+  void Swap(TexturePacket_Rect* other);
+
+  // implements Message ----------------------------------------------
+
+  TexturePacket_Rect* New() const;
+  void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from);
+  void CopyFrom(const TexturePacket_Rect& from);
+  void MergeFrom(const TexturePacket_Rect& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  void DiscardUnknownFields();
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  public:
+  ::std::string GetTypeName() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // optional float x = 1;
+  inline bool has_x() const;
+  inline void clear_x();
+  static const int kXFieldNumber = 1;
+  inline float x() const;
+  inline void set_x(float value);
+
+  // optional float y = 2;
+  inline bool has_y() const;
+  inline void clear_y();
+  static const int kYFieldNumber = 2;
+  inline float y() const;
+  inline void set_y(float value);
+
+  // optional float w = 3;
+  inline bool has_w() const;
+  inline void clear_w();
+  static const int kWFieldNumber = 3;
+  inline float w() const;
+  inline void set_w(float value);
+
+  // optional float h = 4;
+  inline bool has_h() const;
+  inline void clear_h();
+  static const int kHFieldNumber = 4;
+  inline float h() const;
+  inline void set_h(float value);
+
+  // @@protoc_insertion_point(class_scope:mozilla.layers.layerscope.TexturePacket.Rect)
+ private:
+  inline void set_has_x();
+  inline void clear_has_x();
+  inline void set_has_y();
+  inline void clear_has_y();
+  inline void set_has_w();
+  inline void clear_has_w();
+  inline void set_has_h();
+  inline void clear_has_h();
+
+  ::std::string _unknown_fields_;
+
+  ::google::protobuf::uint32 _has_bits_[1];
+  mutable int _cached_size_;
+  float x_;
+  float y_;
+  float w_;
+  float h_;
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  friend void  protobuf_AddDesc_LayerScopePacket_2eproto_impl();
+  #else
+  friend void  protobuf_AddDesc_LayerScopePacket_2eproto();
+  #endif
+  friend void protobuf_AssignDesc_LayerScopePacket_2eproto();
+  friend void protobuf_ShutdownFile_LayerScopePacket_2eproto();
+
+  void InitAsDefaultInstance();
+  static TexturePacket_Rect* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class TexturePacket_Size : public ::google::protobuf::MessageLite {
+ public:
+  TexturePacket_Size();
+  virtual ~TexturePacket_Size();
+
+  TexturePacket_Size(const TexturePacket_Size& from);
+
+  inline TexturePacket_Size& operator=(const TexturePacket_Size& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline const ::std::string& unknown_fields() const {
+    return _unknown_fields_;
+  }
+
+  inline ::std::string* mutable_unknown_fields() {
+    return &_unknown_fields_;
+  }
+
+  static const TexturePacket_Size& default_instance();
+
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  // Returns the internal default instance pointer. This function can
+  // return NULL thus should not be used by the user. This is intended
+  // for Protobuf internal code. Please use default_instance() declared
+  // above instead.
+  static inline const TexturePacket_Size* internal_default_instance() {
+    return default_instance_;
+  }
+  #endif
+
+  void Swap(TexturePacket_Size* other);
+
+  // implements Message ----------------------------------------------
+
+  TexturePacket_Size* New() const;
+  void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from);
+  void CopyFrom(const TexturePacket_Size& from);
+  void MergeFrom(const TexturePacket_Size& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  void DiscardUnknownFields();
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  public:
+  ::std::string GetTypeName() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // optional int32 w = 1;
+  inline bool has_w() const;
+  inline void clear_w();
+  static const int kWFieldNumber = 1;
+  inline ::google::protobuf::int32 w() const;
+  inline void set_w(::google::protobuf::int32 value);
+
+  // optional int32 h = 2;
+  inline bool has_h() const;
+  inline void clear_h();
+  static const int kHFieldNumber = 2;
+  inline ::google::protobuf::int32 h() const;
+  inline void set_h(::google::protobuf::int32 value);
+
+  // @@protoc_insertion_point(class_scope:mozilla.layers.layerscope.TexturePacket.Size)
+ private:
+  inline void set_has_w();
+  inline void clear_has_w();
+  inline void set_has_h();
+  inline void clear_has_h();
+
+  ::std::string _unknown_fields_;
+
+  ::google::protobuf::uint32 _has_bits_[1];
+  mutable int _cached_size_;
+  ::google::protobuf::int32 w_;
+  ::google::protobuf::int32 h_;
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  friend void  protobuf_AddDesc_LayerScopePacket_2eproto_impl();
+  #else
+  friend void  protobuf_AddDesc_LayerScopePacket_2eproto();
+  #endif
+  friend void protobuf_AssignDesc_LayerScopePacket_2eproto();
+  friend void protobuf_ShutdownFile_LayerScopePacket_2eproto();
+
+  void InitAsDefaultInstance();
+  static TexturePacket_Size* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class TexturePacket_Matrix : public ::google::protobuf::MessageLite {
+ public:
+  TexturePacket_Matrix();
+  virtual ~TexturePacket_Matrix();
+
+  TexturePacket_Matrix(const TexturePacket_Matrix& from);
+
+  inline TexturePacket_Matrix& operator=(const TexturePacket_Matrix& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline const ::std::string& unknown_fields() const {
+    return _unknown_fields_;
+  }
+
+  inline ::std::string* mutable_unknown_fields() {
+    return &_unknown_fields_;
+  }
+
+  static const TexturePacket_Matrix& default_instance();
+
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  // Returns the internal default instance pointer. This function can
+  // return NULL thus should not be used by the user. This is intended
+  // for Protobuf internal code. Please use default_instance() declared
+  // above instead.
+  static inline const TexturePacket_Matrix* internal_default_instance() {
+    return default_instance_;
+  }
+  #endif
+
+  void Swap(TexturePacket_Matrix* other);
+
+  // implements Message ----------------------------------------------
+
+  TexturePacket_Matrix* New() const;
+  void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from);
+  void CopyFrom(const TexturePacket_Matrix& from);
+  void MergeFrom(const TexturePacket_Matrix& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  void DiscardUnknownFields();
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  public:
+  ::std::string GetTypeName() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // optional bool is2D = 1;
+  inline bool has_is2d() const;
+  inline void clear_is2d();
+  static const int kIs2DFieldNumber = 1;
+  inline bool is2d() const;
+  inline void set_is2d(bool value);
+
+  // optional bool isId = 2;
+  inline bool has_isid() const;
+  inline void clear_isid();
+  static const int kIsIdFieldNumber = 2;
+  inline bool isid() const;
+  inline void set_isid(bool value);
+
+  // repeated float m = 3;
+  inline int m_size() const;
+  inline void clear_m();
+  static const int kMFieldNumber = 3;
+  inline float m(int index) const;
+  inline void set_m(int index, float value);
+  inline void add_m(float value);
+  inline const ::google::protobuf::RepeatedField< float >&
+      m() const;
+  inline ::google::protobuf::RepeatedField< float >*
+      mutable_m();
+
+  // @@protoc_insertion_point(class_scope:mozilla.layers.layerscope.TexturePacket.Matrix)
+ private:
+  inline void set_has_is2d();
+  inline void clear_has_is2d();
+  inline void set_has_isid();
+  inline void clear_has_isid();
+
+  ::std::string _unknown_fields_;
+
+  ::google::protobuf::uint32 _has_bits_[1];
+  mutable int _cached_size_;
+  ::google::protobuf::RepeatedField< float > m_;
+  bool is2d_;
+  bool isid_;
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  friend void  protobuf_AddDesc_LayerScopePacket_2eproto_impl();
+  #else
+  friend void  protobuf_AddDesc_LayerScopePacket_2eproto();
+  #endif
+  friend void protobuf_AssignDesc_LayerScopePacket_2eproto();
+  friend void protobuf_ShutdownFile_LayerScopePacket_2eproto();
+
+  void InitAsDefaultInstance();
+  static TexturePacket_Matrix* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class TexturePacket_EffectMask : public ::google::protobuf::MessageLite {
+ public:
+  TexturePacket_EffectMask();
+  virtual ~TexturePacket_EffectMask();
+
+  TexturePacket_EffectMask(const TexturePacket_EffectMask& from);
+
+  inline TexturePacket_EffectMask& operator=(const TexturePacket_EffectMask& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline const ::std::string& unknown_fields() const {
+    return _unknown_fields_;
+  }
+
+  inline ::std::string* mutable_unknown_fields() {
+    return &_unknown_fields_;
+  }
+
+  static const TexturePacket_EffectMask& default_instance();
+
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  // Returns the internal default instance pointer. This function can
+  // return NULL thus should not be used by the user. This is intended
+  // for Protobuf internal code. Please use default_instance() declared
+  // above instead.
+  static inline const TexturePacket_EffectMask* internal_default_instance() {
+    return default_instance_;
+  }
+  #endif
+
+  void Swap(TexturePacket_EffectMask* other);
+
+  // implements Message ----------------------------------------------
+
+  TexturePacket_EffectMask* New() const;
+  void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from);
+  void CopyFrom(const TexturePacket_EffectMask& from);
+  void MergeFrom(const TexturePacket_EffectMask& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  void DiscardUnknownFields();
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  public:
+  ::std::string GetTypeName() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // optional bool mIs3D = 1;
+  inline bool has_mis3d() const;
+  inline void clear_mis3d();
+  static const int kMIs3DFieldNumber = 1;
+  inline bool mis3d() const;
+  inline void set_mis3d(bool value);
+
+  // optional .mozilla.layers.layerscope.TexturePacket.Size mSize = 2;
+  inline bool has_msize() const;
+  inline void clear_msize();
+  static const int kMSizeFieldNumber = 2;
+  inline const ::mozilla::layers::layerscope::TexturePacket_Size& msize() const;
+  inline ::mozilla::layers::layerscope::TexturePacket_Size* mutable_msize();
+  inline ::mozilla::layers::layerscope::TexturePacket_Size* release_msize();
+  inline void set_allocated_msize(::mozilla::layers::layerscope::TexturePacket_Size* msize);
+
+  // optional .mozilla.layers.layerscope.TexturePacket.Matrix mMaskTransform = 3;
+  inline bool has_mmasktransform() const;
+  inline void clear_mmasktransform();
+  static const int kMMaskTransformFieldNumber = 3;
+  inline const ::mozilla::layers::layerscope::TexturePacket_Matrix& mmasktransform() const;
+  inline ::mozilla::layers::layerscope::TexturePacket_Matrix* mutable_mmasktransform();
+  inline ::mozilla::layers::layerscope::TexturePacket_Matrix* release_mmasktransform();
+  inline void set_allocated_mmasktransform(::mozilla::layers::layerscope::TexturePacket_Matrix* mmasktransform);
+
+  // @@protoc_insertion_point(class_scope:mozilla.layers.layerscope.TexturePacket.EffectMask)
+ private:
+  inline void set_has_mis3d();
+  inline void clear_has_mis3d();
+  inline void set_has_msize();
+  inline void clear_has_msize();
+  inline void set_has_mmasktransform();
+  inline void clear_has_mmasktransform();
+
+  ::std::string _unknown_fields_;
+
+  ::google::protobuf::uint32 _has_bits_[1];
+  mutable int _cached_size_;
+  ::mozilla::layers::layerscope::TexturePacket_Size* msize_;
+  ::mozilla::layers::layerscope::TexturePacket_Matrix* mmasktransform_;
+  bool mis3d_;
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  friend void  protobuf_AddDesc_LayerScopePacket_2eproto_impl();
+  #else
+  friend void  protobuf_AddDesc_LayerScopePacket_2eproto();
+  #endif
+  friend void protobuf_AssignDesc_LayerScopePacket_2eproto();
+  friend void protobuf_ShutdownFile_LayerScopePacket_2eproto();
+
+  void InitAsDefaultInstance();
+  static TexturePacket_EffectMask* default_instance_;
+};
+// -------------------------------------------------------------------
+
 class TexturePacket : public ::google::protobuf::MessageLite {
  public:
   TexturePacket();
   virtual ~TexturePacket();
 
   TexturePacket(const TexturePacket& from);
 
   inline TexturePacket& operator=(const TexturePacket& from) {
@@ -385,16 +858,35 @@ class TexturePacket : public ::google::p
   void SharedCtor();
   void SharedDtor();
   void SetCachedSize(int size) const;
   public:
   ::std::string GetTypeName() const;
 
   // nested types ----------------------------------------------------
 
+  typedef TexturePacket_Rect Rect;
+  typedef TexturePacket_Size Size;
+  typedef TexturePacket_Matrix Matrix;
+  typedef TexturePacket_EffectMask EffectMask;
+
+  typedef TexturePacket_Filter Filter;
+  static const Filter GOOD = TexturePacket_Filter_GOOD;
+  static const Filter LINEAR = TexturePacket_Filter_LINEAR;
+  static const Filter POINT = TexturePacket_Filter_POINT;
+  static inline bool Filter_IsValid(int value) {
+    return TexturePacket_Filter_IsValid(value);
+  }
+  static const Filter Filter_MIN =
+    TexturePacket_Filter_Filter_MIN;
+  static const Filter Filter_MAX =
+    TexturePacket_Filter_Filter_MAX;
+  static const int Filter_ARRAYSIZE =
+    TexturePacket_Filter_Filter_ARRAYSIZE;
+
   // accessors -------------------------------------------------------
 
   // required uint64 layerref = 1;
   inline bool has_layerref() const;
   inline void clear_layerref();
   static const int kLayerrefFieldNumber = 1;
   inline ::google::protobuf::uint64 layerref() const;
   inline void set_layerref(::google::protobuf::uint64 value);
@@ -455,23 +947,55 @@ class TexturePacket : public ::google::p
   inline const ::std::string& data() const;
   inline void set_data(const ::std::string& value);
   inline void set_data(const char* value);
   inline void set_data(const void* value, size_t size);
   inline ::std::string* mutable_data();
   inline ::std::string* release_data();
   inline void set_allocated_data(::std::string* data);
 
+  // optional .mozilla.layers.layerscope.TexturePacket.Rect mTextureCoords = 10;
+  inline bool has_mtexturecoords() const;
+  inline void clear_mtexturecoords();
+  static const int kMTextureCoordsFieldNumber = 10;
+  inline const ::mozilla::layers::layerscope::TexturePacket_Rect& mtexturecoords() const;
+  inline ::mozilla::layers::layerscope::TexturePacket_Rect* mutable_mtexturecoords();
+  inline ::mozilla::layers::layerscope::TexturePacket_Rect* release_mtexturecoords();
+  inline void set_allocated_mtexturecoords(::mozilla::layers::layerscope::TexturePacket_Rect* mtexturecoords);
+
+  // optional bool mPremultiplied = 11;
+  inline bool has_mpremultiplied() const;
+  inline void clear_mpremultiplied();
+  static const int kMPremultipliedFieldNumber = 11;
+  inline bool mpremultiplied() const;
+  inline void set_mpremultiplied(bool value);
+
+  // optional .mozilla.layers.layerscope.TexturePacket.Filter mFilter = 12;
+  inline bool has_mfilter() const;
+  inline void clear_mfilter();
+  static const int kMFilterFieldNumber = 12;
+  inline ::mozilla::layers::layerscope::TexturePacket_Filter mfilter() const;
+  inline void set_mfilter(::mozilla::layers::layerscope::TexturePacket_Filter value);
+
   // optional bool isMask = 20;
   inline bool has_ismask() const;
   inline void clear_ismask();
   static const int kIsMaskFieldNumber = 20;
   inline bool ismask() const;
   inline void set_ismask(bool value);
 
+  // optional .mozilla.layers.layerscope.TexturePacket.EffectMask mask = 21;
+  inline bool has_mask() const;
+  inline void clear_mask();
+  static const int kMaskFieldNumber = 21;
+  inline const ::mozilla::layers::layerscope::TexturePacket_EffectMask& mask() const;
+  inline ::mozilla::layers::layerscope::TexturePacket_EffectMask* mutable_mask();
+  inline ::mozilla::layers::layerscope::TexturePacket_EffectMask* release_mask();
+  inline void set_allocated_mask(::mozilla::layers::layerscope::TexturePacket_EffectMask* mask);
+
   // @@protoc_insertion_point(class_scope:mozilla.layers.layerscope.TexturePacket)
  private:
   inline void set_has_layerref();
   inline void clear_has_layerref();
   inline void set_has_width();
   inline void clear_has_width();
   inline void set_has_height();
   inline void clear_has_height();
@@ -482,33 +1006,45 @@ class TexturePacket : public ::google::p
   inline void set_has_target();
   inline void clear_has_target();
   inline void set_has_dataformat();
   inline void clear_has_dataformat();
   inline void set_has_glcontext();
   inline void clear_has_glcontext();
   inline void set_has_data();
   inline void clear_has_data();
+  inline void set_has_mtexturecoords();
+  inline void clear_has_mtexturecoords();
+  inline void set_has_mpremultiplied();
+  inline void clear_has_mpremultiplied();
+  inline void set_has_mfilter();
+  inline void clear_has_mfilter();
   inline void set_has_ismask();
   inline void clear_has_ismask();
+  inline void set_has_mask();
+  inline void clear_has_mask();
 
   ::std::string _unknown_fields_;
 
   ::google::protobuf::uint32 _has_bits_[1];
   mutable int _cached_size_;
   ::google::protobuf::uint64 layerref_;
   ::google::protobuf::uint32 width_;
   ::google::protobuf::uint32 height_;
   ::google::protobuf::uint32 stride_;
   ::google::protobuf::uint32 name_;
   ::google::protobuf::uint32 target_;
   ::google::protobuf::uint32 dataformat_;
   ::google::protobuf::uint64 glcontext_;
   ::std::string* data_;
+  ::mozilla::layers::layerscope::TexturePacket_Rect* mtexturecoords_;
+  int mfilter_;
+  bool mpremultiplied_;
   bool ismask_;
+  ::mozilla::layers::layerscope::TexturePacket_EffectMask* mask_;
   #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
   friend void  protobuf_AddDesc_LayerScopePacket_2eproto_impl();
   #else
   friend void  protobuf_AddDesc_LayerScopePacket_2eproto();
   #endif
   friend void protobuf_AssignDesc_LayerScopePacket_2eproto();
   friend void protobuf_ShutdownFile_LayerScopePacket_2eproto();
 
@@ -1158,23 +1694,34 @@ class LayersPacket_Layer : public ::goog
   static const ScrollingDirect ScrollingDirect_MIN =
     LayersPacket_Layer_ScrollingDirect_ScrollingDirect_MIN;
   static const ScrollingDirect ScrollingDirect_MAX =
     LayersPacket_Layer_ScrollingDirect_ScrollingDirect_MAX;
   static const int ScrollingDirect_ARRAYSIZE =
     LayersPacket_Layer_ScrollingDirect_ScrollingDirect_ARRAYSIZE;
 
   typedef LayersPacket_Layer_Filter Filter;
+  static const Filter FILTER_FAST = LayersPacket_Layer_Filter_FILTER_FAST;
   static const Filter FILTER_GOOD = LayersPacket_Layer_Filter_FILTER_GOOD;
+  static const Filter FILTER_BEST = LayersPacket_Layer_Filter_FILTER_BEST;
+  static const Filter FILTER_NEAREST = LayersPacket_Layer_Filter_FILTER_NEAREST;
+  static const Filter FILTER_BILINEAR = LayersPacket_Layer_Filter_FILTER_BILINEAR;
+  static const Filter FILTER_GAUSSIAN = LayersPacket_Layer_Filter_FILTER_GAUSSIAN;
+  static const Filter FILTER_SENTINEL = LayersPacket_Layer_Filter_FILTER_SENTINEL;
   static const Filter FILTER_LINEAR = LayersPacket_Layer_Filter_FILTER_LINEAR;
   static const Filter FILTER_POINT = LayersPacket_Layer_Filter_FILTER_POINT;
-  static const Filter FILTER_SENTINEL = LayersPacket_Layer_Filter_FILTER_SENTINEL;
   static inline bool Filter_IsValid(int value) {
     return LayersPacket_Layer_Filter_IsValid(value);
   }
+  static const Filter Filter_MIN =
+    LayersPacket_Layer_Filter_Filter_MIN;
+  static const Filter Filter_MAX =
+    LayersPacket_Layer_Filter_Filter_MAX;
+  static const int Filter_ARRAYSIZE =
+    LayersPacket_Layer_Filter_Filter_ARRAYSIZE;
 
   // accessors -------------------------------------------------------
 
   // required .mozilla.layers.layerscope.LayersPacket.Layer.LayerType type = 1;
   inline bool has_type() const;
   inline void clear_type();
   static const int kTypeFieldNumber = 1;
   inline ::mozilla::layers::layerscope::LayersPacket_Layer_LayerType type() const;
@@ -2399,16 +2946,368 @@ inline ::google::protobuf::uint32 ColorP
 inline void ColorPacket::set_color(::google::protobuf::uint32 value) {
   set_has_color();
   color_ = value;
   // @@protoc_insertion_point(field_set:mozilla.layers.layerscope.ColorPacket.color)
 }
 
 // -------------------------------------------------------------------
 
+// TexturePacket_Rect
+
+// optional float x = 1;
+inline bool TexturePacket_Rect::has_x() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void TexturePacket_Rect::set_has_x() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void TexturePacket_Rect::clear_has_x() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+inline void TexturePacket_Rect::clear_x() {
+  x_ = 0;
+  clear_has_x();
+}
+inline float TexturePacket_Rect::x() const {
+  // @@protoc_insertion_point(field_get:mozilla.layers.layerscope.TexturePacket.Rect.x)
+  return x_;
+}
+inline void TexturePacket_Rect::set_x(float value) {
+  set_has_x();
+  x_ = value;
+  // @@protoc_insertion_point(field_set:mozilla.layers.layerscope.TexturePacket.Rect.x)
+}
+
+// optional float y = 2;
+inline bool TexturePacket_Rect::has_y() const {
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+inline void TexturePacket_Rect::set_has_y() {
+  _has_bits_[0] |= 0x00000002u;
+}
+inline void TexturePacket_Rect::clear_has_y() {
+  _has_bits_[0] &= ~0x00000002u;
+}
+inline void TexturePacket_Rect::clear_y() {
+  y_ = 0;
+  clear_has_y();
+}
+inline float TexturePacket_Rect::y() const {
+  // @@protoc_insertion_point(field_get:mozilla.layers.layerscope.TexturePacket.Rect.y)
+  return y_;
+}
+inline void TexturePacket_Rect::set_y(float value) {
+  set_has_y();
+  y_ = value;
+  // @@protoc_insertion_point(field_set:mozilla.layers.layerscope.TexturePacket.Rect.y)
+}
+
+// optional float w = 3;
+inline bool TexturePacket_Rect::has_w() const {
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+inline void TexturePacket_Rect::set_has_w() {
+  _has_bits_[0] |= 0x00000004u;
+}
+inline void TexturePacket_Rect::clear_has_w() {
+  _has_bits_[0] &= ~0x00000004u;
+}
+inline void TexturePacket_Rect::clear_w() {
+  w_ = 0;
+  clear_has_w();
+}
+inline float TexturePacket_Rect::w() const {
+  // @@protoc_insertion_point(field_get:mozilla.layers.layerscope.TexturePacket.Rect.w)
+  return w_;
+}
+inline void TexturePacket_Rect::set_w(float value) {
+  set_has_w();
+  w_ = value;
+  // @@protoc_insertion_point(field_set:mozilla.layers.layerscope.TexturePacket.Rect.w)
+}
+
+// optional float h = 4;
+inline bool TexturePacket_Rect::has_h() const {
+  return (_has_bits_[0] & 0x00000008u) != 0;
+}
+inline void TexturePacket_Rect::set_has_h() {
+  _has_bits_[0] |= 0x00000008u;
+}
+inline void TexturePacket_Rect::clear_has_h() {
+  _has_bits_[0] &= ~0x00000008u;
+}
+inline void TexturePacket_Rect::clear_h() {
+  h_ = 0;
+  clear_has_h();
+}
+inline float TexturePacket_Rect::h() const {
+  // @@protoc_insertion_point(field_get:mozilla.layers.layerscope.TexturePacket.Rect.h)
+  return h_;
+}
+inline void TexturePacket_Rect::set_h(float value) {
+  set_has_h();
+  h_ = value;
+  // @@protoc_insertion_point(field_set:mozilla.layers.layerscope.TexturePacket.Rect.h)
+}
+
+// -------------------------------------------------------------------
+
+// TexturePacket_Size
+
+// optional int32 w = 1;
+inline bool TexturePacket_Size::has_w() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void TexturePacket_Size::set_has_w() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void TexturePacket_Size::clear_has_w() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+inline void TexturePacket_Size::clear_w() {
+  w_ = 0;
+  clear_has_w();
+}
+inline ::google::protobuf::int32 TexturePacket_Size::w() const {
+  // @@protoc_insertion_point(field_get:mozilla.layers.layerscope.TexturePacket.Size.w)
+  return w_;
+}
+inline void TexturePacket_Size::set_w(::google::protobuf::int32 value) {
+  set_has_w();
+  w_ = value;
+  // @@protoc_insertion_point(field_set:mozilla.layers.layerscope.TexturePacket.Size.w)
+}
+
+// optional int32 h = 2;
+inline bool TexturePacket_Size::has_h() const {
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+inline void TexturePacket_Size::set_has_h() {
+  _has_bits_[0] |= 0x00000002u;
+}
+inline void TexturePacket_Size::clear_has_h() {
+  _has_bits_[0] &= ~0x00000002u;
+}
+inline void TexturePacket_Size::clear_h() {
+  h_ = 0;
+  clear_has_h();
+}
+inline ::google::protobuf::int32 TexturePacket_Size::h() const {
+  // @@protoc_insertion_point(field_get:mozilla.layers.layerscope.TexturePacket.Size.h)
+  return h_;
+}
+inline void TexturePacket_Size::set_h(::google::protobuf::int32 value) {
+  set_has_h();
+  h_ = value;
+  // @@protoc_insertion_point(field_set:mozilla.layers.layerscope.TexturePacket.Size.h)
+}
+
+// -------------------------------------------------------------------
+
+// TexturePacket_Matrix
+
+// optional bool is2D = 1;
+inline bool TexturePacket_Matrix::has_is2d() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void TexturePacket_Matrix::set_has_is2d() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void TexturePacket_Matrix::clear_has_is2d() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+inline void TexturePacket_Matrix::clear_is2d() {
+  is2d_ = false;
+  clear_has_is2d();
+}
+inline bool TexturePacket_Matrix::is2d() const {
+  // @@protoc_insertion_point(field_get:mozilla.layers.layerscope.TexturePacket.Matrix.is2D)
+  return is2d_;
+}
+inline void TexturePacket_Matrix::set_is2d(bool value) {
+  set_has_is2d();
+  is2d_ = value;
+  // @@protoc_insertion_point(field_set:mozilla.layers.layerscope.TexturePacket.Matrix.is2D)
+}
+
+// optional bool isId = 2;
+inline bool TexturePacket_Matrix::has_isid() const {
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+inline void TexturePacket_Matrix::set_has_isid() {
+  _has_bits_[0] |= 0x00000002u;
+}
+inline void TexturePacket_Matrix::clear_has_isid() {
+  _has_bits_[0] &= ~0x00000002u;
+}
+inline void TexturePacket_Matrix::clear_isid() {
+  isid_ = false;
+  clear_has_isid();
+}
+inline bool TexturePacket_Matrix::isid() const {
+  // @@protoc_insertion_point(field_get:mozilla.layers.layerscope.TexturePacket.Matrix.isId)
+  return isid_;
+}
+inline void TexturePacket_Matrix::set_isid(bool value) {
+  set_has_isid();
+  isid_ = value;
+  // @@protoc_insertion_point(field_set:mozilla.layers.layerscope.TexturePacket.Matrix.isId)
+}
+
+// repeated float m = 3;
+inline int TexturePacket_Matrix::m_size() const {
+  return m_.size();
+}
+inline void TexturePacket_Matrix::clear_m() {
+  m_.Clear();
+}
+inline float TexturePacket_Matrix::m(int index) const {
+  // @@protoc_insertion_point(field_get:mozilla.layers.layerscope.TexturePacket.Matrix.m)
+  return m_.Get(index);
+}
+inline void TexturePacket_Matrix::set_m(int index, float value) {
+  m_.Set(index, value);
+  // @@protoc_insertion_point(field_set:mozilla.layers.layerscope.TexturePacket.Matrix.m)
+}
+inline void TexturePacket_Matrix::add_m(float value) {
+  m_.Add(value);
+  // @@protoc_insertion_point(field_add:mozilla.layers.layerscope.TexturePacket.Matrix.m)
+}
+inline const ::google::protobuf::RepeatedField< float >&
+TexturePacket_Matrix::m() const {
+  // @@protoc_insertion_point(field_list:mozilla.layers.layerscope.TexturePacket.Matrix.m)
+  return m_;
+}
+inline ::google::protobuf::RepeatedField< float >*
+TexturePacket_Matrix::mutable_m() {
+  // @@protoc_insertion_point(field_mutable_list:mozilla.layers.layerscope.TexturePacket.Matrix.m)
+  return &m_;
+}
+
+// -------------------------------------------------------------------
+
+// TexturePacket_EffectMask
+
+// optional bool mIs3D = 1;
+inline bool TexturePacket_EffectMask::has_mis3d() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void TexturePacket_EffectMask::set_has_mis3d() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void TexturePacket_EffectMask::clear_has_mis3d() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+inline void TexturePacket_EffectMask::clear_mis3d() {
+  mis3d_ = false;
+  clear_has_mis3d();
+}
+inline bool TexturePacket_EffectMask::mis3d() const {
+  // @@protoc_insertion_point(field_get:mozilla.layers.layerscope.TexturePacket.EffectMask.mIs3D)
+  return mis3d_;
+}
+inline void TexturePacket_EffectMask::set_mis3d(bool value) {
+  set_has_mis3d();
+  mis3d_ = value;
+  // @@protoc_insertion_point(field_set:mozilla.layers.layerscope.TexturePacket.EffectMask.mIs3D)
+}
+
+// optional .mozilla.layers.layerscope.TexturePacket.Size mSize = 2;
+inline bool TexturePacket_EffectMask::has_msize() const {
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+inline void TexturePacket_EffectMask::set_has_msize() {
+  _has_bits_[0] |= 0x00000002u;
+}
+inline void TexturePacket_EffectMask::clear_has_msize() {
+  _has_bits_[0] &= ~0x00000002u;
+}
+inline void TexturePacket_EffectMask::clear_msize() {
+  if (msize_ != NULL) msize_->::mozilla::layers::layerscope::TexturePacket_Size::Clear();
+  clear_has_msize();
+}
+inline const ::mozilla::layers::layerscope::TexturePacket_Size& TexturePacket_EffectMask::msize() const {
+  // @@protoc_insertion_point(field_get:mozilla.layers.layerscope.TexturePacket.EffectMask.mSize)
+#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  return msize_ != NULL ? *msize_ : *default_instance().msize_;
+#else
+  return msize_ != NULL ? *msize_ : *default_instance_->msize_;
+#endif
+}
+inline ::mozilla::layers::layerscope::TexturePacket_Size* TexturePacket_EffectMask::mutable_msize() {
+  set_has_msize();
+  if (msize_ == NULL) msize_ = new ::mozilla::layers::layerscope::TexturePacket_Size;
+  // @@protoc_insertion_point(field_mutable:mozilla.layers.layerscope.TexturePacket.EffectMask.mSize)
+  return msize_;
+}
+inline ::mozilla::layers::layerscope::TexturePacket_Size* TexturePacket_EffectMask::release_msize() {
+  clear_has_msize();
+  ::mozilla::layers::layerscope::TexturePacket_Size* temp = msize_;
+  msize_ = NULL;
+  return temp;
+}
+inline void TexturePacket_EffectMask::set_allocated_msize(::mozilla::layers::layerscope::TexturePacket_Size* msize) {
+  delete msize_;
+  msize_ = msize;
+  if (msize) {
+    set_has_msize();
+  } else {
+    clear_has_msize();
+  }
+  // @@protoc_insertion_point(field_set_allocated:mozilla.layers.layerscope.TexturePacket.EffectMask.mSize)
+}
+
+// optional .mozilla.layers.layerscope.TexturePacket.Matrix mMaskTransform = 3;
+inline bool TexturePacket_EffectMask::has_mmasktransform() const {
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+inline void TexturePacket_EffectMask::set_has_mmasktransform() {
+  _has_bits_[0] |= 0x00000004u;
+}
+inline void TexturePacket_EffectMask::clear_has_mmasktransform() {
+  _has_bits_[0] &= ~0x00000004u;
+}
+inline void TexturePacket_EffectMask::clear_mmasktransform() {
+  if (mmasktransform_ != NULL) mmasktransform_->::mozilla::layers::layerscope::TexturePacket_Matrix::Clear();
+  clear_has_mmasktransform();
+}
+inline const ::mozilla::layers::layerscope::TexturePacket_Matrix& TexturePacket_EffectMask::mmasktransform() const {
+  // @@protoc_insertion_point(field_get:mozilla.layers.layerscope.TexturePacket.EffectMask.mMaskTransform)
+#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  return mmasktransform_ != NULL ? *mmasktransform_ : *default_instance().mmasktransform_;
+#else
+  return mmasktransform_ != NULL ? *mmasktransform_ : *default_instance_->mmasktransform_;
+#endif
+}
+inline ::mozilla::layers::layerscope::TexturePacket_Matrix* TexturePacket_EffectMask::mutable_mmasktransform() {
+  set_has_mmasktransform();
+  if (mmasktransform_ == NULL) mmasktransform_ = new ::mozilla::layers::layerscope::TexturePacket_Matrix;
+  // @@protoc_insertion_point(field_mutable:mozilla.layers.layerscope.TexturePacket.EffectMask.mMaskTransform)
+  return mmasktransform_;
+}
+inline ::mozilla::layers::layerscope::TexturePacket_Matrix* TexturePacket_EffectMask::release_mmasktransform() {
+  clear_has_mmasktransform();
+  ::mozilla::layers::layerscope::TexturePacket_Matrix* temp = mmasktransform_;
+  mmasktransform_ = NULL;
+  return temp;
+}
+inline void TexturePacket_EffectMask::set_allocated_mmasktransform(::mozilla::layers::layerscope::TexturePacket_Matrix* mmasktransform) {
+  delete mmasktransform_;
+  mmasktransform_ = mmasktransform;
+  if (mmasktransform) {
+    set_has_mmasktransform();
+  } else {
+    clear_has_mmasktransform();
+  }
+  // @@protoc_insertion_point(field_set_allocated:mozilla.layers.layerscope.TexturePacket.EffectMask.mMaskTransform)
+}
+
+// -------------------------------------------------------------------
+
 // TexturePacket
 
 // required uint64 layerref = 1;
 inline bool TexturePacket::has_layerref() const {
   return (_has_bits_[0] & 0x00000001u) != 0;
 }
 inline void TexturePacket::set_has_layerref() {
   _has_bits_[0] |= 0x00000001u;
@@ -2669,40 +3568,179 @@ inline void TexturePacket::set_allocated
     data_ = data;
   } else {
     clear_has_data();
     data_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
   }
   // @@protoc_insertion_point(field_set_allocated:mozilla.layers.layerscope.TexturePacket.data)
 }
 
+// optional .mozilla.layers.layerscope.TexturePacket.Rect mTextureCoords = 10;
+inline bool TexturePacket::has_mtexturecoords() const {
+  return (_has_bits_[0] & 0x00000200u) != 0;
+}
+inline void TexturePacket::set_has_mtexturecoords() {
+  _has_bits_[0] |= 0x00000200u;
+}
+inline void TexturePacket::clear_has_mtexturecoords() {
+  _has_bits_[0] &= ~0x00000200u;
+}
+inline void TexturePacket::clear_mtexturecoords() {
+  if (mtexturecoords_ != NULL) mtexturecoords_->::mozilla::layers::layerscope::TexturePacket_Rect::Clear();
+  clear_has_mtexturecoords();
+}
+inline const ::mozilla::layers::layerscope::TexturePacket_Rect& TexturePacket::mtexturecoords() const {
+  // @@protoc_insertion_point(field_get:mozilla.layers.layerscope.TexturePacket.mTextureCoords)
+#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  return mtexturecoords_ != NULL ? *mtexturecoords_ : *default_instance().mtexturecoords_;
+#else
+  return mtexturecoords_ != NULL ? *mtexturecoords_ : *default_instance_->mtexturecoords_;
+#endif
+}
+inline ::mozilla::layers::layerscope::TexturePacket_Rect* TexturePacket::mutable_mtexturecoords() {
+  set_has_mtexturecoords();
+  if (mtexturecoords_ == NULL) mtexturecoords_ = new ::mozilla::layers::layerscope::TexturePacket_Rect;
+  // @@protoc_insertion_point(field_mutable:mozilla.layers.layerscope.TexturePacket.mTextureCoords)
+  return mtexturecoords_;
+}
+inline ::mozilla::layers::layerscope::TexturePacket_Rect* TexturePacket::release_mtexturecoords() {
+  clear_has_mtexturecoords();
+  ::mozilla::layers::layerscope::TexturePacket_Rect* temp = mtexturecoords_;
+  mtexturecoords_ = NULL;
+  return temp;
+}
+inline void TexturePacket::set_allocated_mtexturecoords(::mozilla::layers::layerscope::TexturePacket_Rect* mtexturecoords) {
+  delete mtexturecoords_;
+  mtexturecoords_ = mtexturecoords;
+  if (mtexturecoords) {
+    set_has_mtexturecoords();
+  } else {
+    clear_has_mtexturecoords();
+  }
+  // @@protoc_insertion_point(field_set_allocated:mozilla.layers.layerscope.TexturePacket.mTextureCoords)
+}
+
+// optional bool mPremultiplied = 11;
+inline bool TexturePacket::has_mpremultiplied() const {
+  return (_has_bits_[0] & 0x00000400u) != 0;
+}
+inline void TexturePacket::set_has_mpremultiplied() {
+  _has_bits_[0] |= 0x00000400u;
+}
+inline void TexturePacket::clear_has_mpremultiplied() {
+  _has_bits_[0] &= ~0x00000400u;
+}
+inline void TexturePacket::clear_mpremultiplied() {
+  mpremultiplied_ = false;
+  clear_has_mpremultiplied();
+}
+inline bool TexturePacket::mpremultiplied() const {
+  // @@protoc_insertion_point(field_get:mozilla.layers.layerscope.TexturePacket.mPremultiplied)
+  return mpremultiplied_;
+}
+inline void TexturePacket::set_mpremultiplied(bool value) {
+  set_has_mpremultiplied();
+  mpremultiplied_ = value;
+  // @@protoc_insertion_point(field_set:mozilla.layers.layerscope.TexturePacket.mPremultiplied)
+}
+
+// optional .mozilla.layers.layerscope.TexturePacket.Filter mFilter = 12;
+inline bool TexturePacket::has_mfilter() const {
+  return (_has_bits_[0] & 0x00000800u) != 0;
+}
+inline void TexturePacket::set_has_mfilter() {
+  _has_bits_[0] |= 0x00000800u;
+}
+inline void TexturePacket::clear_has_mfilter() {
+  _has_bits_[0] &= ~0x00000800u;
+}
+inline void TexturePacket::clear_mfilter() {
+  mfilter_ = 0;
+  clear_has_mfilter();
+}
+inline ::mozilla::layers::layerscope::TexturePacket_Filter TexturePacket::mfilter() const {
+  // @@protoc_insertion_point(field_get:mozilla.layers.layerscope.TexturePacket.mFilter)
+  return static_cast< ::mozilla::layers::layerscope::TexturePacket_Filter >(mfilter_);
+}
+inline void TexturePacket::set_mfilter(::mozilla::layers::layerscope::TexturePacket_Filter value) {
+  assert(::mozilla::layers::layerscope::TexturePacket_Filter_IsValid(value));
+  set_has_mfilter();
+  mfilter_ = value;
+  // @@protoc_insertion_point(field_set:mozilla.layers.layerscope.TexturePacket.mFilter)
+}
+
 // optional bool isMask = 20;
 inline bool TexturePacket::has_ismask() const {
-  return (_has_bits_[0] & 0x00000200u) != 0;
+  return (_has_bits_[0] & 0x00001000u) != 0;
 }
 inline void TexturePacket::set_has_ismask() {
-  _has_bits_[0] |= 0x00000200u;
+  _has_bits_[0] |= 0x00001000u;
 }
 inline void TexturePacket::clear_has_ismask() {
-  _has_bits_[0] &= ~0x00000200u;
+  _has_bits_[0] &= ~0x00001000u;
 }
 inline void TexturePacket::clear_ismask() {
   ismask_ = false;
   clear_has_ismask();
 }
 inline bool TexturePacket::ismask() const {
   // @@protoc_insertion_point(field_get:mozilla.layers.layerscope.TexturePacket.isMask)
   return ismask_;
 }
 inline void TexturePacket::set_ismask(bool value) {
   set_has_ismask();
   ismask_ = value;
   // @@protoc_insertion_point(field_set:mozilla.layers.layerscope.TexturePacket.isMask)
 }
 
+// optional .mozilla.layers.layerscope.TexturePacket.EffectMask mask = 21;
+inline bool TexturePacket::has_mask() const {
+  return (_has_bits_[0] & 0x00002000u) != 0;
+}
+inline void TexturePacket::set_has_mask() {
+  _has_bits_[0] |= 0x00002000u;
+}
+inline void TexturePacket::clear_has_mask() {
+  _has_bits_[0] &= ~0x00002000u;
+}
+inline void TexturePacket::clear_mask() {
+  if (mask_ != NULL) mask_->::mozilla::layers::layerscope::TexturePacket_EffectMask::Clear();
+  clear_has_mask();
+}
+inline const ::mozilla::layers::layerscope::TexturePacket_EffectMask& TexturePacket::mask() const {
+  // @@protoc_insertion_point(field_get:mozilla.layers.layerscope.TexturePacket.mask)
+#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  return mask_ != NULL ? *mask_ : *default_instance().mask_;
+#else
+  return mask_ != NULL ? *mask_ : *default_instance_->mask_;
+#endif
+}
+inline ::mozilla::layers::layerscope::TexturePacket_EffectMask* TexturePacket::mutable_mask() {
+  set_has_mask();
+  if (mask_ == NULL) mask_ = new ::mozilla::layers::layerscope::TexturePacket_EffectMask;
+  // @@protoc_insertion_point(field_mutable:mozilla.layers.layerscope.TexturePacket.mask)
+  return mask_;
+}
+inline ::mozilla::layers::layerscope::TexturePacket_EffectMask* TexturePacket::release_mask() {
+  clear_has_mask();
+  ::mozilla::layers::layerscope::TexturePacket_EffectMask* temp = mask_;
+  mask_ = NULL;
+  return temp;
+}
+inline void TexturePacket::set_allocated_mask(::mozilla::layers::layerscope::TexturePacket_EffectMask* mask) {
+  delete mask_;
+  mask_ = mask;
+  if (mask) {
+    set_has_mask();
+  } else {
+    clear_has_mask();
+  }
+  // @@protoc_insertion_point(field_set_allocated:mozilla.layers.layerscope.TexturePacket.mask)
+}
+
 // -------------------------------------------------------------------
 
 // LayersPacket_Layer_Size
 
 // optional int32 w = 1;
 inline bool LayersPacket_Layer_Size::has_w() const {
   return (_has_bits_[0] & 0x00000001u) != 0;
 }
--- a/gfx/layers/protobuf/LayerScopePacket.proto
+++ b/gfx/layers/protobuf/LayerScopePacket.proto
@@ -15,33 +15,61 @@ message FramePacket {
 message ColorPacket {
   required uint64 layerref = 1;
   optional uint32 width = 2;
   optional uint32 height = 3;
   optional uint32 color = 4;
 }
 
 message TexturePacket {
+  enum Filter {
+    GOOD = 0;
+    LINEAR = 1;
+    POINT = 2;
+  }
+  message Rect {
+    optional float x = 1;
+    optional float y = 2;
+    optional float w = 3;
+    optional float h = 4;
+  }
+  message Size {
+    optional int32 w = 1;
+    optional int32 h = 2;
+  }
+  message Matrix {
+    optional bool is2D = 1;
+    optional bool isId = 2;
+    repeated float m = 3;
+  }
+  message EffectMask {
+    optional bool mIs3D = 1;
+    optional Size mSize = 2;
+    optional Matrix mMaskTransform = 3;
+  }
+
   // Basic info
   required uint64 layerref = 1;
   optional uint32 width = 2;
   optional uint32 height = 3;
   optional uint32 stride = 4;
   optional uint32 name = 5;
   optional uint32 target = 6;
   optional uint32 dataformat = 7;
   optional uint64 glcontext = 8;
   optional bytes data = 9;
 
-  // Texture effect attributes (10 to 19)
-  // TODO: reserved for primary textured effect attributes, see Bug 1205521
+  // TextureEffect attributes
+  optional Rect mTextureCoords = 10;
+  optional bool mPremultiplied = 11;
+  optional Filter mFilter = 12;
 
-  // Mask effect attributes (20 to 29)
+  // Mask attributes
   optional bool isMask = 20;
-  // TODO: reserved for secondary mask effect attributes, see Bug 1205521
+  optional EffectMask mask = 21;
 }
 
 message LayersPacket {
   message Layer {
     enum LayerType {
       UnknownLayer = 0;
       LayerManager = 1;
       ContainerLayer = 2;
@@ -52,23 +80,25 @@ message LayersPacket {
       RefLayer = 7;
       ReadbackLayer = 8;
     }
     enum ScrollingDirect {
       VERTICAL = 1;
       HORIZONTAL = 2;
     }
     enum Filter {
-      FILTER_FAST = 0;
+      FILTER_FAST = 0; // deprecated
       FILTER_GOOD = 1;
-      FILTER_BEST = 2;
-      FILTER_NEAREST = 3;
-      FILTER_BILINEAR = 4;
-      FILTER_GAUSSIAN = 5;
-      FILTER_SENTINEL = 6;
+      FILTER_BEST = 2; // deprecated
+      FILTER_NEAREST = 3; //deprecated
+      FILTER_BILINEAR = 4; //deprecated
+      FILTER_GAUSSIAN = 5; //deprecated
+      FILTER_SENTINEL = 6; //deprecated
+      FILTER_LINEAR = 7;
+      FILTER_POINT = 8;
     }
     message Size {
       optional int32 w = 1;
       optional int32 h = 2;
     }
     message Rect {
       optional int32 x = 1;
       optional int32 y = 2;
--- a/gfx/tests/crashtests/crashtests.list
+++ b/gfx/tests/crashtests/crashtests.list
@@ -98,17 +98,17 @@ load 665218.html
 load 686190-1.html
 load 693143-1.html
 load 768079-1.html
 load 783041-1.html
 load 783041-2.html
 load 783041-3.html
 load 783041-4.html
 asserts-if(gtkWidget,0-1) load 798853.html # bug 868792
-asserts-if(winWidget,0-1) skip-if(B2G) load 815489.html
+asserts-if(winWidget,0-1) skip-if(B2G||Android) load 815489.html # bug 871763, 1216304
 load 836225-1.html
 load 839745-1.html
 load 856784-1.html
 load 893572-1.html
 load 893572-2.html
 load 893572-3.html
 load 893572-4.html
 pref(layers.force-active,true) load 914457-1.html
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/gc/bug-1215363-1.js
@@ -0,0 +1,4 @@
+if (!('oomTest' in this))
+    quit();
+
+oomTest(() => parseModule(10));
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/gc/bug-1215363-2.js
@@ -0,0 +1,7 @@
+if (!('oomTest' in this))
+    quit();
+
+var lfcode = new Array();
+oomTest((function(x) {
+    assertEq(...Object);
+}));
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/gc/bug-1215363-3.js
@@ -0,0 +1,5 @@
+if (!('oomTest' in this))
+    quit();
+
+var lfcode = new Array();
+oomTest(() => getBacktrace({}));
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/gc/oomInOffTheadCompile.js
@@ -0,0 +1,15 @@
+if (!('oomTest' in this) || helperThreadCount() === 0)
+    quit();
+
+oomTest(() => {
+    offThreadCompileScript(
+        `
+        function f(x) {
+            if (x == 0)
+                return "foobar";
+            return 1 + f(x - 1);
+        }
+        f(5);
+        `);
+    runOffThreadScript();
+});
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -8003,17 +8003,21 @@ CodeGenerator::link(JSContext* cx, Compi
 
     if (!linkSharedStubs(cx))
         return false;
 
     // Check to make sure we didn't have a mid-build invalidation. If so, we
     // will trickle to jit::Compile() and return Method_Skipped.
     uint32_t warmUpCount = script->getWarmUpCount();
     RecompileInfo recompileInfo;
-    if (!FinishCompilation(cx, script, constraints, &recompileInfo))
+    bool isValid;
+    if (!FinishCompilation(cx, script, constraints, &recompileInfo, &isValid))
+        return false;
+
+    if (!isValid)
         return true;
 
     // IonMonkey could have inferred better type information during
     // compilation. Since adding the new information to the actual type
     // information can reset the usecount, increase it back to what it was
     // before.
     if (warmUpCount > script->getWarmUpCount())
         script->incWarmUpCounter(warmUpCount - script->getWarmUpCount());
--- a/js/src/jit/CompactBuffer.h
+++ b/js/src/jit/CompactBuffer.h
@@ -120,17 +120,18 @@ class CompactBufferWriter
     // Note: writeByte() takes uint32 to catch implicit casts with a runtime
     // assert.
     void writeByte(uint32_t byte) {
         MOZ_ASSERT(byte <= 0xFF);
         enoughMemory_ &= buffer_.append(byte);
     }
     void writeByteAt(uint32_t pos, uint32_t byte) {
         MOZ_ASSERT(byte <= 0xFF);
-        buffer_[pos] = byte;
+        if (!oom())
+            buffer_[pos] = byte;
     }
     void writeUnsigned(uint32_t value) {
         do {
             uint8_t byte = ((value & 0x7F) << 1) | (value > 0x7F);
             writeByte(byte);
             value >>= 7;
         } while (value);
     }
@@ -173,19 +174,21 @@ class CompactBufferWriter
             return;
         uint8_t* endPtr = buffer() + length();
         reinterpret_cast<uint32_t*>(endPtr)[-1] = value;
     }
     size_t length() const {
         return buffer_.length();
     }
     uint8_t* buffer() {
+        MOZ_ASSERT(!oom());
         return &buffer_[0];
     }
     const uint8_t* buffer() const {
+        MOZ_ASSERT(!oom());
         return &buffer_[0];
     }
     bool oom() const {
         return !enoughMemory_;
     }
 };
 
 CompactBufferReader::CompactBufferReader(const CompactBufferWriter& writer)
--- a/js/src/jit/JitFrameIterator.h
+++ b/js/src/jit/JitFrameIterator.h
@@ -333,16 +333,19 @@ class RInstructionResults
     RInstructionResults(RInstructionResults&& src);
 
     RInstructionResults& operator=(RInstructionResults&& rhs);
 
     ~RInstructionResults();
 
     bool init(JSContext* cx, uint32_t numResults);
     bool isInitialized() const;
+#ifdef DEBUG
+    size_t length() const;
+#endif
 
     JitFrameLayout* frame() const;
 
     RelocatableValue& operator[](size_t index);
 
     void trace(JSTracer* trc);
 };
 
--- a/js/src/jit/JitFrames.cpp
+++ b/js/src/jit/JitFrames.cpp
@@ -1745,16 +1745,24 @@ RInstructionResults::init(JSContext* cx,
 }
 
 bool
 RInstructionResults::isInitialized() const
 {
     return initialized_;
 }
 
+#ifdef DEBUG
+size_t
+RInstructionResults::length() const
+{
+    return results_->length();
+}
+#endif
+
 JitFrameLayout*
 RInstructionResults::frame() const
 {
     MOZ_ASSERT(fp_);
     return fp_;
 }
 
 RelocatableValue&
@@ -2211,16 +2219,17 @@ SnapshotIterator::initInstructionResults
             // If the evaluation failed because of OOMs, then we discard the
             // current set of result that we collected so far.
             fallback.activation->removeIonFrameRecovery(fp);
             return false;
         }
     }
 
     MOZ_ASSERT(results->isInitialized());
+    MOZ_ASSERT(results->length() == recover_.numInstructions() - 1);
     instructionResults_ = results;
     return true;
 }
 
 bool
 SnapshotIterator::computeInstructionResults(JSContext* cx, RInstructionResults* results) const
 {
     MOZ_ASSERT(!results->isInitialized());
--- a/js/src/jit/Snapshots.cpp
+++ b/js/src/jit/Snapshots.cpp
@@ -309,27 +309,26 @@ RValueAllocation::readPayload(CompactBuf
         break;
     }
 }
 
 RValueAllocation
 RValueAllocation::read(CompactBufferReader& reader)
 {
     uint8_t mode = reader.readByte();
-    const Layout& layout = layoutFromMode(Mode(mode & MODE_MASK));
+    const Layout& layout = layoutFromMode(Mode(mode & MODE_BITS_MASK));
     Payload arg1, arg2;
 
     readPayload(reader, layout.type1, &mode, &arg1);
     readPayload(reader, layout.type2, &mode, &arg2);
     return RValueAllocation(Mode(mode), arg1, arg2);
 }
 
 void
-RValueAllocation::writePayload(CompactBufferWriter& writer, PayloadType type,
-                               Payload p)
+RValueAllocation::writePayload(CompactBufferWriter& writer, PayloadType type, Payload p)
 {
     switch (type) {
       case PAYLOAD_NONE:
         break;
       case PAYLOAD_INDEX:
         writer.writeUnsigned(p.index);
         break;
       case PAYLOAD_STACK_OFFSET:
@@ -343,20 +342,22 @@ RValueAllocation::writePayload(CompactBu
       case PAYLOAD_FPU:
         static_assert(FloatRegisters::Total <= 0x100,
                       "Not enough bytes to encode all float registers.");
         writer.writeByte(p.fpu.code());
         break;
       case PAYLOAD_PACKED_TAG: {
         // This code assumes that the PACKED_TAG payload is following the
         // writeByte of the mode.
-        MOZ_ASSERT(writer.length());
-        uint8_t* mode = writer.buffer() + (writer.length() - 1);
-        MOZ_ASSERT((*mode & PACKED_TAG_MASK) == 0 && (p.type & ~PACKED_TAG_MASK) == 0);
-        *mode = *mode | p.type;
+        if (!writer.oom()) {
+            MOZ_ASSERT(writer.length());
+            uint8_t* mode = writer.buffer() + (writer.length() - 1);
+            MOZ_ASSERT((*mode & PACKED_TAG_MASK) == 0 && (p.type & ~PACKED_TAG_MASK) == 0);
+            *mode = *mode | p.type;
+        }
         break;
       }
     }
 }
 
 void
 RValueAllocation::writePadding(CompactBufferWriter& writer)
 {
--- a/js/src/jit/Snapshots.h
+++ b/js/src/jit/Snapshots.h
@@ -75,17 +75,17 @@ class RValueAllocation
         // set on the mode, this inform the snapshot iterator that even if the
         // allocation is readable, the content of if might be incomplete unless
         // all side-effects are executed.
         RECOVER_SIDE_EFFECT_MASK = 0x80,
 
         // This mask represents the set of bits which can be used to encode a
         // value in a snapshot. The mode is used to determine how to interpret
         // the union of values and how to pack the value in memory.
-        MODE_MASK           = 0x17f,
+        MODE_BITS_MASK           = 0x17f,
 
         INVALID = 0x100,
     };
 
     enum { PACKED_TAG_MASK = 0x0f };
 
     // See Payload encoding in Snapshots.cpp
     enum PayloadType {
@@ -289,17 +289,17 @@ class RValueAllocation
 
     void writeHeader(CompactBufferWriter& writer, JSValueType type, uint32_t regCode) const;
   public:
     static RValueAllocation read(CompactBufferReader& reader);
     void write(CompactBufferWriter& writer) const;
 
   public:
     Mode mode() const {
-        return Mode(mode_ & MODE_MASK);
+        return Mode(mode_ & MODE_BITS_MASK);
     }
     bool needSideEffect() const {
         return mode_ & RECOVER_SIDE_EFFECT_MASK;
     }
 
     uint32_t index() const {
         MOZ_ASSERT(layoutFromMode(mode()).type1 == PAYLOAD_INDEX);
         return arg1_.index;
--- a/js/src/jit/arm/CodeGenerator-arm.cpp
+++ b/js/src/jit/arm/CodeGenerator-arm.cpp
@@ -155,18 +155,18 @@ CodeGeneratorARM::bailoutIf(Assembler::C
 }
 
 void
 CodeGeneratorARM::bailoutFrom(Label* label, LSnapshot* snapshot)
 {
     if (masm.bailed())
         return;
 
-    MOZ_ASSERT(label->used());
-    MOZ_ASSERT(!label->bound());
+    MOZ_ASSERT_IF(!masm.oom(), label->used());
+    MOZ_ASSERT_IF(!masm.oom(), !label->bound());
 
     encode(snapshot);
 
     // Though the assembler doesn't track all frame pushes, at least make sure
     // the known value makes sense. We can't use bailout tables if the stack
     // isn't properly aligned to the static frame size.
     MOZ_ASSERT_IF(frameClass_ != FrameSizeClass::None(),
                   frameClass_.frameSize() == masm.framePushed());
--- a/js/src/jit/mips-shared/CodeGenerator-mips-shared.cpp
+++ b/js/src/jit/mips-shared/CodeGenerator-mips-shared.cpp
@@ -166,18 +166,18 @@ CodeGeneratorMIPSShared::generateOutOfLi
 }
 
 void
 CodeGeneratorMIPSShared::bailoutFrom(Label* label, LSnapshot* snapshot)
 {
     if (masm.bailed())
         return;
 
-    MOZ_ASSERT(label->used());
-    MOZ_ASSERT(!label->bound());
+    MOZ_ASSERT_IF(!masm.oom(), label->used());
+    MOZ_ASSERT_IF(!masm.oom(), !label->bound());
 
     encode(snapshot);
 
     // Though the assembler doesn't track all frame pushes, at least make sure
     // the known value makes sense. We can't use bailout tables if the stack
     // isn't properly aligned to the static frame size.
     MOZ_ASSERT_IF(frameClass_ != FrameSizeClass::None(),
                   frameClass_.frameSize() == masm.framePushed());
--- a/js/src/jit/shared/IonAssemblerBufferWithConstantPools.h
+++ b/js/src/jit/shared/IonAssemblerBufferWithConstantPools.h
@@ -513,17 +513,17 @@ struct AssemblerBufferWithConstantPools 
         PoolInfo pi = getLastPoolInfo();
         return codeEnd + (pi.finalPos - pi.offset);
     }
 
   public:
     size_t size() const {
         // Return the current actual size of the buffer. This is only accurate
         // if there are no pending pool entries to dump, check.
-        MOZ_ASSERT(pool_.numEntries() == 0);
+        MOZ_ASSERT_IF(!this->oom(), pool_.numEntries() == 0);
         return sizeExcludingCurrentPool();
     }
 
   private:
     void insertNopFill() {
         // Insert fill for testing.
         if (nopFill_ > 0 && !inhibitNops_ && !canNotPlacePool_) {
             inhibitNops_ = true;
@@ -766,17 +766,17 @@ struct AssemblerBufferWithConstantPools 
         MOZ_ASSERT(numDumps_ < poolInfoSize_);
         poolInfo_[numDumps_] = newPoolInfo;
         numDumps_++;
 
         // Bind the current pool to the perforation point, copying the pool
         // state into the BufferSlice.
         Pool** tmp = &perforatedSlice->pool;
         *tmp = static_cast<Pool*>(this->lifoAlloc_.alloc(sizeof(Pool)));
-        if (tmp == nullptr) {
+        if (!*tmp) {
             this->fail_oom();
             return;
         }
         mozilla::PodCopy(*tmp, &pool_, 1);
 
         // Reset everything to the state that it was in when we started.
         if (!pool_.reset(this->lifoAlloc_)) {
             this->fail_oom();
--- a/js/src/jscntxt.cpp
+++ b/js/src/jscntxt.cpp
@@ -427,18 +427,20 @@ js::ReportErrorVA(JSContext* cx, unsigne
     size_t messagelen;
     JSErrorReport report;
     bool warning;
 
     if (checkReportFlags(cx, &flags))
         return true;
 
     message = JS_vsmprintf(format, ap);
-    if (!message)
+    if (!message) {
+        ReportOutOfMemory(cx);
         return false;
+    }
     messagelen = strlen(message);
 
     report.flags = flags;
     report.errorNumber = JSMSG_USER_DEFINED_ERROR;
     report.ucmessage = ucmessage = InflateString(cx, message, &messagelen);
     PopulateReportBlame(cx, &report);
 
     warning = JSREPORT_IS_WARNING(report.flags);
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -3506,18 +3506,25 @@ js::DumpBacktrace(JSContext* cx)
 {
     Sprinter sprinter(cx);
     sprinter.init();
     size_t depth = 0;
     for (AllFramesIter i(cx); !i.done(); ++i, ++depth) {
         const char* filename = JS_GetScriptFilename(i.script());
         unsigned line = PCToLineNumber(i.script(), i.pc());
         JSScript* script = i.script();
-        sprinter.printf("#%d %14p   %s:%d (%p @ %d)\n",
-                        depth, (i.isJit() ? 0 : i.interpFrame()), filename, line,
+        char frameType =
+            i.isInterp() ? 'i' :
+            i.isBaseline() ? 'b' :
+            i.isIon() ? 'I' :
+            i.isAsmJS() ? 'A' :
+            '?';
+
+        sprinter.printf("#%d %14p %c   %s:%d (%p @ %d)\n",
+                        depth, i.rawFramePtr(), frameType, filename, line,
                         script, script->pcToOffset(i.pc()));
     }
     fprintf(stdout, "%s", sprinter.string());
 #ifdef XP_WIN32
     if (IsDebuggerPresent()) {
         OutputDebugStringA(sprinter.string());
     }
 #endif
--- a/js/src/jsprf.cpp
+++ b/js/src/jsprf.cpp
@@ -370,21 +370,21 @@ BuildArgArray(const char* fmt, va_list a
             continue;
         if ((c = *p++) == '%')          // skip %% case
             continue;
 
         while (c != 0) {
             if (c > '9' || c < '0') {
                 if (c == '$') {         // numbered argument case
                     if (i > 0)
-                        return false;
+                        MOZ_CRASH("Bad format string");
                     number++;
                 } else {                // non-numbered argument case
                     if (number > 0)
-                        return false;
+                        MOZ_CRASH("Bad format string");
                     i = 1;
                 }
                 break;
             }
 
             c = *p++;
         }
     }
@@ -412,41 +412,41 @@ BuildArgArray(const char* fmt, va_list a
 
         cn = 0;
         while (c && c != '$') {     // should improve error check later
             cn = cn*10 + c - '0';
             c = *p++;
         }
 
         if (!c || cn < 1 || cn > number)
-            return false;
+            MOZ_CRASH("Bad format string");
 
         // nas[cn] starts from 0, and make sure nas[cn].type is not assigned.
         cn--;
         if (nas[cn].type != TYPE_UNKNOWN)
             continue;
 
         c = *p++;
 
         // width
         if (c == '*') {
             // not supported feature, for the argument is not numbered
-            return false;
+            MOZ_CRASH("Bad format string");
         }
 
         while ((c >= '0') && (c <= '9')) {
             c = *p++;
         }
 
         // precision
         if (c == '.') {
             c = *p++;
             if (c == '*') {
                 // not supported feature, for the argument is not numbered
-                return false;
+                MOZ_CRASH("Bad format string");
             }
 
             while ((c >= '0') && (c <= '9')) {
                 c = *p++;
             }
         }
 
         // size
@@ -522,17 +522,17 @@ BuildArgArray(const char* fmt, va_list a
         default:
             MOZ_ASSERT(0);
             nas[cn].type = TYPE_UNKNOWN;
             break;
         }
 
         // get a legal para.
         if (nas[cn].type == TYPE_UNKNOWN)
-            return false;
+            MOZ_CRASH("Bad format string");
     }
 
 
     // Third pass:
     // Fill nas[].ap.
 
     cn = 0;
     while (cn < number) {
@@ -552,17 +552,17 @@ BuildArgArray(const char* fmt, va_list a
         case TYPE_UINT32:       (void) va_arg(ap, uint32_t);    break;
         case TYPE_INT64:        (void) va_arg(ap, int64_t);     break;
         case TYPE_UINT64:       (void) va_arg(ap, uint64_t);    break;
         case TYPE_STRING:       (void) va_arg(ap, char*);       break;
         case TYPE_WSTRING:      (void) va_arg(ap, char16_t*);   break;
         case TYPE_INTSTR:       (void) va_arg(ap, int*);        break;
         case TYPE_DOUBLE:       (void) va_arg(ap, double);      break;
 
-        default: return false;
+        default: MOZ_CRASH();
         }
 
         cn++;
     }
 
     return true;
 }
 
@@ -594,18 +594,17 @@ dosprintf(SprintfState* ss, const char* 
     const char* dolPt = nullptr;  // in "%4$.2f", dolPt will point to '.'
 
     // Build an argument array, IF the fmt is numbered argument
     // list style, to contain the Numbered Argument list pointers.
 
     NumArgStateVector nas;
     if (!BuildArgArray(fmt, ap, nas)) {
         // the fmt contains error Numbered Argument format, jliu@netscape.com
-        MOZ_ASSERT(0);
-        return false;
+        MOZ_CRASH("Bad format string");
     }
 
     while ((c = *fmt++) != 0) {
         if (c != '%') {
             if (!(*ss->stuff)(ss, fmt - 1, 1))
                 return false;
 
             continue;
@@ -628,17 +627,17 @@ dosprintf(SprintfState* ss, const char* 
             // the fmt contains the Numbered Arguments feature
             i = 0;
             while (c && c != '$') {         // should improve error check later
                 i = (i * 10) + (c - '0');
                 c = *fmt++;
             }
 
             if (nas[i - 1].type == TYPE_UNKNOWN)
-                return false;
+                MOZ_CRASH("Bad format string");
 
             ap = nas[i - 1].ap;
             dolPt = fmt;
             c = *fmt++;
         }
 
         // Examine optional flags.  Note that we do not implement the
         // '#' flag of sprintf().  The ANSI C spec. of the '#' flag is
--- a/js/src/vm/HelperThreads.cpp
+++ b/js/src/vm/HelperThreads.cpp
@@ -399,26 +399,28 @@ js::StartOffThreadParseScript(JSContext*
 
     helpercx.forget();
 
     if (!task->init(cx, options))
         return false;
 
     if (OffThreadParsingMustWaitForGC(cx->runtime())) {
         AutoLockHelperThreadState lock;
-        if (!HelperThreadState().parseWaitingOnGC().append(task.get()))
+        if (!HelperThreadState().parseWaitingOnGC().append(task.get())) {
+            ReportOutOfMemory(cx);
             return false;
+        }
     } else {
-        task->activate(cx->runtime());
+        AutoLockHelperThreadState lock;
+        if (!HelperThreadState().parseWorklist().append(task.get())) {
+            ReportOutOfMemory(cx);
+            return false;
+        }
 
-        AutoLockHelperThreadState lock;
-
-        if (!HelperThreadState().parseWorklist().append(task.get()))
-            return false;
-
+        task->activate(cx->runtime());
         HelperThreadState().notifyOne(GlobalHelperThreadState::PRODUCER);
     }
 
     task.forget();
 
     return true;
 }
 
@@ -1061,25 +1063,30 @@ GlobalHelperThreadState::finishParseTask
     // debugger about the compiled scripts.
     for (size_t i = 0; i < parseTask->errors.length(); i++)
         parseTask->errors[i]->throwError(cx);
     if (parseTask->overRecursed)
         ReportOverRecursed(cx);
     if (cx->isExceptionPending())
         return nullptr;
 
-    if (script) {
-        // The Debugger only needs to be told about the topmost script that was compiled.
-        Debugger::onNewScript(cx, script);
+    if (!script) {
+        // No error was reported, but no script produced. Assume we hit out of
+        // memory.
+        ReportOutOfMemory(cx);
+        return nullptr;
+    }
 
-        // Update the compressed source table with the result. This is normally
-        // called by setCompressedSource when compilation occurs on the main thread.
-        if (script->scriptSource()->hasCompressedSource())
-            script->scriptSource()->updateCompressedSourceSet(rt);
-    }
+    // The Debugger only needs to be told about the topmost script that was compiled.
+    Debugger::onNewScript(cx, script);
+
+    // Update the compressed source table with the result. This is normally
+    // called by setCompressedSource when compilation occurs on the main thread.
+    if (script->scriptSource()->hasCompressedSource())
+        script->scriptSource()->updateCompressedSourceSet(rt);
 
     return script;
 }
 
 JSObject*
 GlobalObject::getStarGeneratorFunctionPrototype()
 {
     const Value& v = getReservedSlot(STAR_GENERATOR_FUNCTION_PROTO);
--- a/js/src/vm/ObjectGroup.cpp
+++ b/js/src/vm/ObjectGroup.cpp
@@ -1442,18 +1442,20 @@ ObjectGroup::allocationSiteGroup(JSConte
         PreliminaryObjectArrayWithTemplate* preliminaryObjects =
             cx->new_<PreliminaryObjectArrayWithTemplate>(nullptr);
         if (preliminaryObjects)
             res->setPreliminaryObjects(preliminaryObjects);
         else
             cx->recoverFromOutOfMemory();
     }
 
-    if (!table->add(p, key, res))
+    if (!table->add(p, key, res)) {
+        ReportOutOfMemory(cx);
         return nullptr;
+    }
 
     return res;
 }
 
 void
 ObjectGroupCompartment::replaceAllocationSiteGroup(JSScript* script, jsbytecode* pc,
                                                    JSProtoKey kind, ObjectGroup* group)
 {
--- a/js/src/vm/Stack.cpp
+++ b/js/src/vm/Stack.cpp
@@ -848,16 +848,31 @@ AbstractFramePtr
 FrameIter::copyDataAsAbstractFramePtr() const
 {
     AbstractFramePtr frame;
     if (Data* data = copyData())
         frame.ptr_ = uintptr_t(data);
     return frame;
 }
 
+void*
+FrameIter::rawFramePtr() const
+{
+    switch (data_.state_) {
+      case DONE:
+      case ASMJS:
+        return nullptr;
+      case JIT:
+        return data_.jitFrames_.fp();
+      case INTERP:
+        return interpFrame();
+    }
+    MOZ_CRASH("Unexpected state");
+}
+
 JSCompartment*
 FrameIter::compartment() const
 {
     switch (data_.state_) {
       case DONE:
         break;
       case INTERP:
       case JIT:
--- a/js/src/vm/Stack.h
+++ b/js/src/vm/Stack.h
@@ -2035,16 +2035,19 @@ class FrameIter
     Data* copyData() const;
 
     // This can only be called when isInterp():
     inline InterpreterFrame* interpFrame() const;
 
     // This can only be called when isPhysicalIonFrame():
     inline jit::CommonFrameLayout* physicalIonFrame() const;
 
+    // This is used to provide a raw interface for debugging.
+    void* rawFramePtr() const;
+
   private:
     Data data_;
     jit::InlineFrameIterator ionInlineFrames_;
 
     void popActivation();
     void popInterpreterFrame();
     void nextJitFrame();
     void popJitFrame();
--- a/js/src/vm/TypeInference.cpp
+++ b/js/src/vm/TypeInference.cpp
@@ -1363,17 +1363,17 @@ class TypeConstraintFreezeStack : public
         return true;
     }
 };
 
 } /* anonymous namespace */
 
 bool
 js::FinishCompilation(JSContext* cx, HandleScript script, CompilerConstraintList* constraints,
-                      RecompileInfo* precompileInfo)
+                      RecompileInfo* precompileInfo, bool* isValidOut)
 {
     if (constraints->failed())
         return false;
 
     CompilerOutput co(script);
 
     TypeZone& types = cx->zone()->types;
     if (!types.compilerOutputs) {
@@ -1447,19 +1447,21 @@ js::FinishCompilation(JSContext* cx, Han
             if (!array[i].addConstraint(cx, cx->typeLifoAlloc().new_<TypeConstraintFreezeStack>(entry.script), false))
                 succeeded = false;
         }
     }
 
     if (!succeeded || types.compilerOutputs->back().pendingInvalidation()) {
         types.compilerOutputs->back().invalidate();
         script->resetWarmUpCounter();
-        return false;
+        *isValidOut = false;
+        return true;
     }
 
+    *isValidOut = true;
     return true;
 }
 
 void
 js::InvalidateCompilerOutputsForScript(JSContext* cx, HandleScript script)
 {
     TypeZone& types = cx->zone()->types;
     if (types.compilerOutputs) {
--- a/js/src/vm/TypeInference.h
+++ b/js/src/vm/TypeInference.h
@@ -1059,21 +1059,21 @@ class TypeScript
 };