Merge b2g-inbound to m-c. a=merge
authorRyan VanderMeulen <ryanvm@gmail.com>
Wed, 26 Nov 2014 21:39:08 -0500
changeset 217745 cef590a6f94681064fa954890bae6014db819158
parent 217700 c63e741bca2e3d27d57609fcc59ab474eacb6066 (current diff)
parent 217744 bd5c9c856409bf9e1a2f7baf4d59da8fe4f11ad1 (diff)
child 217746 8e0783737421f308b8d818796e220d27c897a223
child 217814 abb313cc25acf0f08d2cdf02aa9069841fb08653
child 217825 679466398b30c66fc38b12d031ea184ee42c3db6
push id27888
push userryanvm@gmail.com
push dateThu, 27 Nov 2014 02:38:47 +0000
treeherdermozilla-central@cef590a6f946 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone36.0a1
first release with
nightly linux32
cef590a6f946 / 36.0a1 / 20141127030208 / files
nightly linux64
cef590a6f946 / 36.0a1 / 20141127030208 / files
nightly mac
cef590a6f946 / 36.0a1 / 20141127030208 / files
nightly win32
cef590a6f946 / 36.0a1 / 20141127030208 / files
nightly win64
cef590a6f946 / 36.0a1 / 20141127030208 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge b2g-inbound to m-c. a=merge
dom/icc/tests/marionette/test_icc_card_lock.js
--- a/b2g/components/SystemAppProxy.jsm
+++ b/b2g/components/SystemAppProxy.jsm
@@ -84,20 +84,26 @@ let SystemAppProxy = {
 
     event.initCustomEvent(type, true, false, payload);
     (target || content).dispatchEvent(event);
 
     return event;
   },
 
   // Now deprecated, use sendCustomEvent with a custom event name
-  dispatchEvent: function systemApp_sendChromeEvent(details, target) {
+  dispatchEvent: function systemApp_dispatchEvent(details, target) {
     return this._sendCustomEvent('mozChromeEvent', details, false, target);
   },
 
+  dispatchKeyboardEvent: function systemApp_dispatchKeyboardEvent(type, details) {
+    let content = this._frame ? this._frame.contentWindow : null;
+    let e = new content.KeyboardEvent(type, details);
+    content.dispatchEvent(e);
+  },
+
   // Listen for dom events on the system app
   addEventListener: function systemApp_addEventListener() {
     let content = this._frame ? this._frame.contentWindow : null;
     if (!content) {
       this._pendingListeners.push(arguments);
       return false;
     }
 
--- 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="3ab0d9c70f0b2e1ededc679112c392303f037361">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="41b7be7c67167f367c3c4982ff08651d55455373"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="76e1789f081a811416c95e25213ca63976486af6"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="6499615ecece69e726657dc5caaeefa05fbb66bf"/>
--- a/b2g/config/emulator-ics/sources.xml
+++ b/b2g/config/emulator-ics/sources.xml
@@ -14,21 +14,21 @@
   <!--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="df362ace56338da8173d30d3e09e08c42c1accfa">
     <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="41b7be7c67167f367c3c4982ff08651d55455373"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="76e1789f081a811416c95e25213ca63976486af6"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d5d3f93914558b6f168447b805cd799c8233e300"/>
-  <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="a47dd04f8f66e42fd331711140f2c3e2fed0767d"/>
+  <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="8b13bfc1d7d25cee4de55f332654fdba25b8460b"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="6499615ecece69e726657dc5caaeefa05fbb66bf"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
   <project name="platform/bionic" path="bionic" revision="c72b8f6359de7ed17c11ddc9dfdde3f615d188a9"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="425f8b5fadf5889834c5acd27d23c9e0b2129c28"/>
   <project name="device/common" path="device/common" revision="42b808b7e93d0619286ae8e59110b176b7732389"/>
   <project name="device/sample" path="device/sample" revision="237bd668d0f114d801a8d6455ef5e02cc3577587"/>
--- 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="0e94c080bee081a50aa2097527b0b40852f9143f">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="41b7be7c67167f367c3c4982ff08651d55455373"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="76e1789f081a811416c95e25213ca63976486af6"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="6499615ecece69e726657dc5caaeefa05fbb66bf"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
--- a/b2g/config/emulator-kk/sources.xml
+++ b/b2g/config/emulator-kk/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="3ab0d9c70f0b2e1ededc679112c392303f037361">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="41b7be7c67167f367c3c4982ff08651d55455373"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="76e1789f081a811416c95e25213ca63976486af6"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="6499615ecece69e726657dc5caaeefa05fbb66bf"/>
--- a/b2g/config/emulator/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -14,21 +14,21 @@
   <!--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="df362ace56338da8173d30d3e09e08c42c1accfa">
     <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="41b7be7c67167f367c3c4982ff08651d55455373"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="76e1789f081a811416c95e25213ca63976486af6"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d5d3f93914558b6f168447b805cd799c8233e300"/>
-  <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="a47dd04f8f66e42fd331711140f2c3e2fed0767d"/>
+  <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="8b13bfc1d7d25cee4de55f332654fdba25b8460b"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="6499615ecece69e726657dc5caaeefa05fbb66bf"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
   <project name="platform/bionic" path="bionic" revision="c72b8f6359de7ed17c11ddc9dfdde3f615d188a9"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="425f8b5fadf5889834c5acd27d23c9e0b2129c28"/>
   <project name="device/common" path="device/common" revision="42b808b7e93d0619286ae8e59110b176b7732389"/>
   <project name="device/sample" path="device/sample" revision="237bd668d0f114d801a8d6455ef5e02cc3577587"/>
--- 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="3ab0d9c70f0b2e1ededc679112c392303f037361">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="41b7be7c67167f367c3c4982ff08651d55455373"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="76e1789f081a811416c95e25213ca63976486af6"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="6499615ecece69e726657dc5caaeefa05fbb66bf"/>
--- a/b2g/config/flame/sources.xml
+++ b/b2g/config/flame/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="0e94c080bee081a50aa2097527b0b40852f9143f">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="41b7be7c67167f367c3c4982ff08651d55455373"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="76e1789f081a811416c95e25213ca63976486af6"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="6499615ecece69e726657dc5caaeefa05fbb66bf"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="e95b4ce22c825da44d14299e1190ea39a5260bde"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="471afab478649078ad7c75ec6b252481a59e19b8"/>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,9 +1,9 @@
 {
     "git": {
         "git_revision": "", 
         "remote": "", 
         "branch": ""
     }, 
-    "revision": "769491b138582de92f5636413928de13268e1a63", 
+    "revision": "05f40074f94c58315e6c353089d31e8e20ea3c1a", 
     "repo_path": "integration/gaia-central"
 }
--- a/b2g/config/hamachi/sources.xml
+++ b/b2g/config/hamachi/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="df362ace56338da8173d30d3e09e08c42c1accfa">
     <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="41b7be7c67167f367c3c4982ff08651d55455373"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="76e1789f081a811416c95e25213ca63976486af6"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="6499615ecece69e726657dc5caaeefa05fbb66bf"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="746bc48f34f5060f90801925dcdd964030c1ab6d"/>
--- a/b2g/config/helix/sources.xml
+++ b/b2g/config/helix/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="df362ace56338da8173d30d3e09e08c42c1accfa">
     <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="41b7be7c67167f367c3c4982ff08651d55455373"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="76e1789f081a811416c95e25213ca63976486af6"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
--- a/b2g/config/nexus-4/sources.xml
+++ b/b2g/config/nexus-4/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="0e94c080bee081a50aa2097527b0b40852f9143f">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="41b7be7c67167f367c3c4982ff08651d55455373"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="76e1789f081a811416c95e25213ca63976486af6"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="6499615ecece69e726657dc5caaeefa05fbb66bf"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
--- a/b2g/config/wasabi/sources.xml
+++ b/b2g/config/wasabi/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="ics_chocolate_rb4.2" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="df362ace56338da8173d30d3e09e08c42c1accfa">
     <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="41b7be7c67167f367c3c4982ff08651d55455373"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="76e1789f081a811416c95e25213ca63976486af6"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="6499615ecece69e726657dc5caaeefa05fbb66bf"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
--- a/browser/devtools/responsivedesign/responsivedesign.jsm
+++ b/browser/devtools/responsivedesign/responsivedesign.jsm
@@ -477,63 +477,63 @@ ResponsiveUI.prototype = {
   // FxOS custom controls
   buildPhoneUI: function () {
     this.stack.classList.add("fxos-mode");
 
     let sleepButton = this.chromeDoc.createElement("button");
     sleepButton.className = "devtools-responsiveui-sleep-button";
     sleepButton.setAttribute("top", 0);
     sleepButton.setAttribute("right", 0);
-    sleepButton.addEventListener("mousedown", function() {
-      SystemAppProxy.dispatchEvent({type: "sleep-button-press"});
+    sleepButton.addEventListener("mousedown", () => {
+      SystemAppProxy.dispatchKeyboardEvent("keydown", {key: "Power"});
     });
-    sleepButton.addEventListener("mouseup", function() {
-      SystemAppProxy.dispatchEvent({type: "sleep-button-release"});
+    sleepButton.addEventListener("mouseup", () => {
+      SystemAppProxy.dispatchKeyboardEvent("keyup", {key: "Power"});
     });
     this.stack.appendChild(sleepButton);
 
     let volumeButtons = this.chromeDoc.createElement("vbox");
     volumeButtons.className = "devtools-responsiveui-volume-buttons";
     volumeButtons.setAttribute("top", 0);
     volumeButtons.setAttribute("left", 0);
 
     let volumeUp = this.chromeDoc.createElement("button");
     volumeUp.className = "devtools-responsiveui-volume-up-button";
-    volumeUp.addEventListener("mousedown", function() {
-      SystemAppProxy.dispatchEvent({type: "volume-up-button-press"});
+    volumeUp.addEventListener("mousedown", () => {
+      SystemAppProxy.dispatchKeyboardEvent("keydown", {key: "VolumeUp"});
     });
-    volumeUp.addEventListener("mouseup", function() {
-      SystemAppProxy.dispatchEvent({type: "volume-up-button-release"});
+    volumeUp.addEventListener("mouseup", () => {
+      SystemAppProxy.dispatchKeyboardEvent("keyup", {key: "VolumeUp"});
     });
 
     let volumeDown = this.chromeDoc.createElement("button");
     volumeDown.className = "devtools-responsiveui-volume-down-button";
-    volumeDown.addEventListener("mousedown", function() {
-      SystemAppProxy.dispatchEvent({type: "volume-down-button-press"});
+    volumeDown.addEventListener("mousedown", () => {
+      SystemAppProxy.dispatchKeyboardEvent("keydown", {key: "VolumeDown"});
     });
-    volumeDown.addEventListener("mouseup", function() {
-      SystemAppProxy.dispatchEvent({type: "volume-down-button-release"});
+    volumeDown.addEventListener("mouseup", () => {
+      SystemAppProxy.dispatchKeyboardEvent("keyup", {key: "VolumeDown"});
     });
 
     volumeButtons.appendChild(volumeUp);
     volumeButtons.appendChild(volumeDown);
     this.stack.appendChild(volumeButtons);
 
     let bottomToolbar = this.chromeDoc.createElement("toolbar");
     bottomToolbar.className = "devtools-responsiveui-hardware-buttons";
     bottomToolbar.setAttribute("align", "center");
     bottomToolbar.setAttribute("pack", "center");
 
     let homeButton = this.chromeDoc.createElement("toolbarbutton");
     homeButton.className = "devtools-responsiveui-toolbarbutton devtools-responsiveui-home-button";
-    homeButton.addEventListener("mousedown", function() {
-      SystemAppProxy.dispatchEvent({type: "home-button-press"});
+    homeButton.addEventListener("mousedown", () => {
+      SystemAppProxy.dispatchKeyboardEvent("keydown", {key: "Home"});
     });
-    homeButton.addEventListener("mouseup", function() {
-      SystemAppProxy.dispatchEvent({type: "home-button-release"});
+    homeButton.addEventListener("mouseup", () => {
+      SystemAppProxy.dispatchKeyboardEvent("keyup", {key: "Home"});
     });
     bottomToolbar.appendChild(homeButton);
     this.bottomToolbar = bottomToolbar;
     this.container.appendChild(bottomToolbar);
   },
 
   /**
    * Validate and apply any user input on the editable menulist
--- a/dom/camera/CameraPreviewMediaStream.cpp
+++ b/dom/camera/CameraPreviewMediaStream.cpp
@@ -14,29 +14,32 @@
  */
 #define MAX_INVALIDATE_PENDING 4
 
 using namespace mozilla::layers;
 using namespace mozilla::dom;
 
 namespace mozilla {
 
+static const TrackID TRACK_VIDEO = 2;
+
 void
 FakeMediaStreamGraph::DispatchToMainThreadAfterStreamStateUpdate(already_AddRefed<nsIRunnable> aRunnable)
 {
   nsRefPtr<nsIRunnable> task = aRunnable;
   NS_DispatchToMainThread(task);
 }
 
 CameraPreviewMediaStream::CameraPreviewMediaStream(DOMMediaStream* aWrapper)
   : MediaStream(aWrapper)
   , mMutex("mozilla::camera::CameraPreviewMediaStream")
   , mInvalidatePending(0)
   , mDiscardedFrames(0)
   , mRateLimit(false)
+  , mTrackCreated(false)
 {
   SetGraphImpl(MediaStreamGraph::GetInstance());
   mFakeMediaStreamGraph = new FakeMediaStreamGraph();
   mIsConsumed = false;
 }
 
 void
 CameraPreviewMediaStream::AddAudioOutput(void* aKey)
@@ -107,16 +110,34 @@ CameraPreviewMediaStream::RemoveListener
   MutexAutoLock lock(mMutex);
 
   nsRefPtr<MediaStreamListener> listener(aListener);
   mListeners.RemoveElement(aListener);
   listener->NotifyEvent(mFakeMediaStreamGraph, MediaStreamListener::EVENT_REMOVED);
 }
 
 void
+CameraPreviewMediaStream::OnPreviewStateChange(bool aActive)
+{
+  if (aActive) {
+    MutexAutoLock lock(mMutex);
+    if (!mTrackCreated) {
+      mTrackCreated = true;
+      VideoSegment tmpSegment;
+      for (uint32_t j = 0; j < mListeners.Length(); ++j) {
+        MediaStreamListener* l = mListeners[j];
+        l->NotifyQueuedTrackChanges(mFakeMediaStreamGraph, TRACK_VIDEO, 0,
+                                    MediaStreamListener::TRACK_EVENT_CREATED,
+                                    tmpSegment);
+      }
+    }
+  }
+}
+
+void
 CameraPreviewMediaStream::Destroy()
 {
   MutexAutoLock lock(mMutex);
   DestroyImpl();
 }
 
 void
 CameraPreviewMediaStream::Invalidate()
--- a/dom/camera/CameraPreviewMediaStream.h
+++ b/dom/camera/CameraPreviewMediaStream.h
@@ -46,30 +46,32 @@ public:
   virtual void SetAudioOutputVolume(void* aKey, float aVolume) MOZ_OVERRIDE;
   virtual void RemoveAudioOutput(void* aKey) MOZ_OVERRIDE;
   virtual void AddVideoOutput(VideoFrameContainer* aContainer) MOZ_OVERRIDE;
   virtual void RemoveVideoOutput(VideoFrameContainer* aContainer) MOZ_OVERRIDE;
   virtual void ChangeExplicitBlockerCount(int32_t aDelta) MOZ_OVERRIDE;
   virtual void AddListener(MediaStreamListener* aListener) MOZ_OVERRIDE;
   virtual void RemoveListener(MediaStreamListener* aListener) MOZ_OVERRIDE;
   virtual void Destroy();
+  void OnPreviewStateChange(bool aActive);
 
   void Invalidate();
 
   // Call these on any thread.
   void SetCurrentFrame(const gfxIntSize& aIntrinsicSize, Image* aImage);
   void ClearCurrentFrame();
   void RateLimit(bool aLimit);
 
 protected:
   // mMutex protects all the class' fields.
   // This class is not registered to MediaStreamGraph.
   // It needs to protect all the fields.
   Mutex mMutex;
   int32_t mInvalidatePending;
   uint32_t mDiscardedFrames;
   bool mRateLimit;
+  bool mTrackCreated;
   nsRefPtr<FakeMediaStreamGraph> mFakeMediaStreamGraph;
 };
 
 }
 
 #endif // DOM_CAMERA_CAMERAPREVIEWMEDIASTREAM_H
--- a/dom/camera/DOMCameraControl.cpp
+++ b/dom/camera/DOMCameraControl.cpp
@@ -286,17 +286,18 @@ nsDOMCameraControl::nsDOMCameraControl(u
 #endif
     mCameraControl = ICameraControl::Create(aCameraId);
 #ifdef MOZ_WIDGET_GONK
   }
 #endif
   mCurrentConfiguration = initialConfig.forget();
 
   // Attach our DOM-facing media stream to our viewfinder stream.
-  mStream = mInput;
+  SetHintContents(HINT_CONTENTS_VIDEO);
+  InitStreamCommon(mInput);
   MOZ_ASSERT(mWindow, "Shouldn't be created with a null window!");
   if (mWindow->GetExtantDoc()) {
     CombineWithPrincipal(mWindow->GetExtantDoc()->NodePrincipal());
   }
 
   // Register a listener for camera events.
   mListener = new DOMCameraControlListener(this, mInput);
   mCameraControl->AddListener(mListener);
--- a/dom/camera/DOMCameraControlListener.cpp
+++ b/dom/camera/DOMCameraControlListener.cpp
@@ -135,16 +135,17 @@ DOMCameraControlListener::OnPreviewState
       DOM_CAMERA_LOGI("Preview started\n");
       break;
 
     default:
       DOM_CAMERA_LOGE("Unknown preview state %d\n", aState);
       MOZ_ASSERT_UNREACHABLE("Invalid preview state");
       return;
   }
+  mStream->OnPreviewStateChange(aState == kPreviewStarted);
   NS_DispatchToMainThread(new Callback(mDOMCameraControl, aState));
 }
 
 void
 DOMCameraControlListener::OnRecorderStateChange(RecorderState aState,
                                                 int32_t aStatus, int32_t aTrackNum)
 {
   class Callback : public DOMCallback
--- a/dom/camera/test/test_camera.html
+++ b/dom/camera/test/test_camera.html
@@ -104,28 +104,36 @@ var Camera = {
   takePictureSuccess: function taken_foto(blob) {
     ok(blob.size > 100 , "Blob Size Gathered = " + blob.size);
     ok("image/" + test.fileFormat ==  blob.type, "Blob Type = " + blob.type);
   },
   takePictureEvent: function taken_foto_evt(e) {
     var blob = e.data;
     var img = new Image();
     var test = this._currentTest;
+    var onPreviewStateChange = function(e) {
+      if (e.newState === 'started') {
+        ok(true, "viewfinder is ready and playing after resume");
+        Camera.cameraObj.removeEventListener('previewstatechange', onPreviewStateChange);
+        Camera._testsCompleted++;
+        if(Camera._testsCompleted == Camera._tests.length) {
+          ok(true, "test finishing");
+          SimpleTest.finish();
+        } else {
+          Camera.runTests();
+        }
+      }
+    }
+    Camera.cameraObj.addEventListener('previewstatechange', onPreviewStateChange);
     img.onload = function Imgsize() {
       ok(this.width == test.pictureSize.width, "The image taken has the width " +
                                               this.width + " pictureSize width = " + test.pictureSize.width);
       ok(this.height == test.pictureSize.height, "The image taken has the height " +
                                               this.height + " picturesize height = " + test.pictureSize.height);
-      Camera._testsCompleted++;
-      if(Camera._testsCompleted == Camera._tests.length) {
-        ok(true, "test finishing");
-        SimpleTest.finish();
-      } else {
-        Camera.runTests();
-      }
+      Camera.cameraObj.resumePreview();
     }
     ok(blob.size > 100 , "Blob Size Gathered = " + blob.size);
     ok("image/" + test.fileFormat ==  blob.type, "Blob Type = " + blob.type);
     img.src = window.URL.createObjectURL(blob);
   },
   shutter: function onShutter () {
     Camera._shutter++;
     
new file mode 100644
--- /dev/null
+++ b/dom/icc/tests/marionette/head.js
@@ -0,0 +1,348 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+const {Cc: Cc, Ci: Ci, Cr: Cr, Cu: Cu} = SpecialPowers;
+
+const PREF_KEY_RIL_DEBUGGING_ENABLED = "ril.debugging.enabled";
+
+// The pin code hard coded in emulator is "0000".
+const DEFAULT_PIN = "0000";
+// The puk code hard coded in emulator is "12345678".
+const DEFAULT_PUK = "12345678";
+
+// Emulate Promise.jsm semantics.
+Promise.defer = function() { return new Deferred(); }
+function Deferred() {
+  this.promise = new Promise(function(resolve, reject) {
+    this.resolve = resolve;
+    this.reject = reject;
+  }.bind(this));
+  Object.freeze(this);
+}
+
+let _pendingEmulatorCmdCount = 0;
+
+/**
+ * Send emulator command with safe guard.
+ *
+ * We should only call |finish()| after all emulator command transactions
+ * end, so here comes with the pending counter.  Resolve when the emulator
+ * gives positive response, and reject otherwise.
+ *
+ * Fulfill params:
+ *   result -- an array of emulator response lines.
+ * Reject params:
+ *   result -- an array of emulator response lines.
+ *
+ * @param aCommand
+ *        A string command to be passed to emulator through its telnet console.
+ *
+ * @return A deferred promise.
+ */
+function runEmulatorCmdSafe(aCommand) {
+  let deferred = Promise.defer();
+
+  ++_pendingEmulatorCmdCount;
+  runEmulatorCmd(aCommand, function(aResult) {
+    --_pendingEmulatorCmdCount;
+
+    ok(true, "Emulator response: " + JSON.stringify(aResult));
+    if (Array.isArray(aResult) &&
+        aResult[aResult.length - 1] === "OK") {
+      deferred.resolve(aResult);
+    } else {
+      deferred.reject(aResult);
+    }
+  });
+
+  return deferred.promise;
+}
+
+let workingFrame;
+let iccManager;
+
+/**
+ * Push required permissions and test if
+ * |navigator.mozIccManager| exists. Resolve if it does,
+ * reject otherwise.
+ *
+ * Fulfill params:
+ *   iccManager -- an reference to navigator.mozIccManager.
+ *
+ * Reject params: (none)
+ *
+ * @param aAdditonalPermissions [optional]
+ *        An array of permission strings other than "mobileconnection" to be
+ *        pushed. Default: empty string.
+ *
+ * @return A deferred promise.
+ */
+function ensureIccManager(aAdditionalPermissions) {
+  let deferred = Promise.defer();
+
+  aAdditionalPermissions = aAdditionalPermissions || [];
+
+  if (aAdditionalPermissions.indexOf("mobileconnection") < 0) {
+    aAdditionalPermissions.push("mobileconnection");
+  }
+  let permissions = [];
+  for (let perm of aAdditionalPermissions) {
+    permissions.push({ "type": perm, "allow": 1, "context": document });
+  }
+
+  SpecialPowers.pushPermissions(permissions, function() {
+    ok(true, "permissions pushed: " + JSON.stringify(permissions));
+
+    // Permission changes can't change existing Navigator.prototype
+    // objects, so grab our objects from a new Navigator.
+    workingFrame = document.createElement("iframe");
+    workingFrame.addEventListener("load", function load() {
+      workingFrame.removeEventListener("load", load);
+
+      iccManager = workingFrame.contentWindow.navigator.mozIccManager;
+
+      if (iccManager) {
+        ok(true, "navigator.mozIccManager is instance of " + iccManager.constructor);
+      } else {
+        ok(true, "navigator.mozIccManager is undefined");
+      }
+
+      if (iccManager instanceof MozIccManager) {
+        deferred.resolve(iccManager);
+      } else {
+        deferred.reject();
+      }
+    });
+
+    document.body.appendChild(workingFrame);
+  });
+
+  return deferred.promise;
+}
+
+/**
+ * Get MozIcc by IccId
+ *
+ * @param aIccId [optional]
+ *        Default: The first item of |aIccManager.iccIds|.
+ *
+ * @return A MozIcc.
+ */
+function getMozIcc(aIccId) {
+  aIccId = aIccId || iccManager.iccIds[0];
+
+  if (!aIccId) {
+    ok(true, "iccManager.iccIds[0] is undefined");
+    return null;
+  }
+
+  return iccManager.getIccById(aIccId);
+}
+
+/**
+ * Get MozMobileConnection by ServiceId
+ *
+ * @param aServiceId [optional]
+ *        A numeric DSDS service id. Default: 0 if not indicated.
+ *
+ * @return A MozMobileConnection.
+ */
+function getMozMobileConnectionByServiceId(aServiceId) {
+  aServiceId = aServiceId || 0;
+  return workingFrame.contentWindow.navigator.mozMobileConnections[aServiceId];
+}
+
+/**
+ * Set radio enabling state.
+ *
+ * Resolve no matter the request succeeds or fails. Never reject.
+ *
+ * Fulfill params: (none)
+ *
+ * @param aEnabled
+ *        A boolean state.
+ * @param aServiceId [optional]
+ *        A numeric DSDS service id.
+ *
+ * @return A deferred promise.
+ */
+function setRadioEnabled(aEnabled, aServiceId) {
+  return getMozMobileConnectionByServiceId(aServiceId).setRadioEnabled(aEnabled)
+    .then(() => {
+      ok(true, "setRadioEnabled " + aEnabled + " on " + aServiceId + " success.");
+    }, (aError) => {
+      ok(false, "setRadioEnabled " + aEnabled + " on " + aServiceId + " " +
+         aError.name);
+    });
+}
+
+/**
+ * Wait for one named event.
+ *
+ * Resolve if that named event occurs.  Never reject.
+ *
+ * Fulfill params: the DOMEvent passed.
+ *
+ * @param aEventTarget
+ *        An EventTarget object.
+ * @param aEventName
+ *        A string event name.
+ * @param aMatchFun [optional]
+ *        A matching function returns true or false to filter the event.
+ *
+ * @return A deferred promise.
+ */
+function waitForTargetEvent(aEventTarget, aEventName, aMatchFun) {
+  let deferred = Promise.defer();
+
+  aEventTarget.addEventListener(aEventName, function onevent(aEvent) {
+    if (!aMatchFun || aMatchFun(aEvent)) {
+      aEventTarget.removeEventListener(aEventName, onevent);
+      ok(true, "Event '" + aEventName + "' got.");
+      deferred.resolve(aEvent);
+    }
+  });
+
+  return deferred.promise;
+}
+
+/**
+ * Set radio enabling state and wait for "radiostatechange" event.
+ *
+ * Resolve if radio state changed to the expected one. Never reject.
+ *
+ * Fulfill params: (none)
+ *
+ * @param aEnabled
+ *        A boolean state.
+ * @param aServiceId [optional]
+ *        A numeric DSDS service id. Default: the one indicated in
+ *        start*TestCommon() or 0 if not indicated.
+ *
+ * @return A deferred promise.
+ */
+function setRadioEnabledAndWait(aEnabled, aServiceId) {
+  let mobileConn = getMozMobileConnectionByServiceId(aServiceId);
+  let promises = [];
+
+  promises.push(waitForTargetEvent(mobileConn, "radiostatechange", function() {
+    // To ignore some transient states, we only resolve that deferred promise
+    // when |radioState| equals to the expected one.
+    return mobileConn.radioState === (aEnabled ? "enabled" : "disabled");
+  }));
+  promises.push(setRadioEnabled(aEnabled, aServiceId));
+
+  return Promise.all(promises);
+}
+
+/**
+ * Restart radio and wait card state changes to expected one.
+ *
+ * Resolve if card state changed to the expected one. Never reject.
+ *
+ * Fulfill params: (none)
+ *
+ * @param aCardState
+ *        Expected card state.
+ *
+ * @return A deferred promise.
+ */
+function restartRadioAndWait(aCardState) {
+  return setRadioEnabledAndWait(false).then(() => {
+    let promises = [];
+
+    promises.push(waitForTargetEvent(iccManager, "iccdetected")
+      .then((aEvent) => {
+        let icc = getMozIcc(aEvent.iccId);
+        if (icc.cardState !== aCardState) {
+          return waitForTargetEvent(icc, "cardstatechange", function() {
+            return icc.cardState === aCardState;
+          });
+        }
+      }));
+    promises.push(setRadioEnabledAndWait(true));
+
+    return Promise.all(promises);
+  });
+}
+
+/**
+ * Enable/Disable PIN-lock.
+ *
+ * Fulfill params: (none)
+ * Reject params:
+ *   An object contains error name and remaining retry count.
+ *   @see IccCardLockError
+ *
+ * @param aIcc
+ *        A MozIcc object.
+ * @param aEnabled
+ *        A boolean state.
+ *
+ * @return A deferred promise.
+ */
+function setPinLockEnabled(aIcc, aEnabled) {
+  let options = {
+    lockType: "pin",
+    enabled: aEnabled,
+    pin: DEFAULT_PIN
+  };
+
+  return aIcc.setCardLock(options);
+}
+
+/**
+ * Wait for pending emulator transactions and call |finish()|.
+ */
+function cleanUp() {
+  // Use ok here so that we have at least one test run.
+  ok(true, ":: CLEANING UP ::");
+
+  waitFor(finish, function() {
+    return _pendingEmulatorCmdCount === 0;
+  });
+}
+
+/**
+ * Basic test routine helper for icc tests.
+ *
+ * This helper does nothing but clean-ups.
+ *
+ * @param aTestCaseMain
+ *        A function that takes no parameter.
+ */
+function startTestBase(aTestCaseMain) {
+  // Turn on debugging pref.
+  let debugPref = SpecialPowers.getBoolPref(PREF_KEY_RIL_DEBUGGING_ENABLED);
+  SpecialPowers.setBoolPref(PREF_KEY_RIL_DEBUGGING_ENABLED, true);
+
+  Promise.resolve()
+    .then(aTestCaseMain)
+    .catch((aError) => {
+      ok(false, "promise rejects during test: " + aError);
+    })
+    .then(() => {
+      // Restore debugging pref.
+      SpecialPowers.setBoolPref(PREF_KEY_RIL_DEBUGGING_ENABLED, debugPref);
+      cleanUp();
+    });
+}
+
+/**
+ * Common test routine helper for icc tests.
+ *
+ * This function ensures global variable |iccManager| and |icc| is available
+ * during the process and performs clean-ups as well.
+ *
+ * @param aTestCaseMain
+ *        A function that takes one parameter -- icc.
+ * @param aAdditonalPermissions [optional]
+ *        An array of permission strings other than "mobileconnection" to be
+ *        pushed. Default: empty string..
+ */
+function startTestCommon(aTestCaseMain, aAdditionalPermissions) {
+  startTestBase(function() {
+    return ensureIccManager(aAdditionalPermissions)
+      .then(aTestCaseMain);
+  });
+}
--- a/dom/icc/tests/marionette/manifest.ini
+++ b/dom/icc/tests/marionette/manifest.ini
@@ -1,16 +1,20 @@
 [DEFAULT]
 b2g = true
 browser = false
 qemu = true
 
 [test_stk_proactive_command.js]
 [test_icc_contact.js]
-[test_icc_card_lock.js]
+[test_icc_card_lock_get_retry_count.js]
+[test_icc_card_lock_change_pin.js]
+[test_icc_card_lock_enable_pin.js]
+[test_icc_card_lock_unlock_pin.js]
+[test_icc_card_lock_unlock_puk.js]
 [test_icc_card_state.js]
 [test_icc_info.js]
 [test_stk_refresh.js]
 [test_stk_poll_off.js]
 [test_stk_setup_event_list.js]
 [test_stk_setup_call.js]
 [test_stk_send_ss.js]
 [test_stk_send_ussd.js]
rename from dom/icc/tests/marionette/test_icc_card_lock.js
rename to dom/icc/tests/marionette/test_icc_card_lock_change_pin.js
--- a/dom/icc/tests/marionette/test_icc_card_lock.js
+++ b/dom/icc/tests/marionette/test_icc_card_lock_change_pin.js
@@ -1,126 +1,45 @@
 /* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-MARIONETTE_TIMEOUT = 30000;
-MARIONETTE_HEAD_JS = "icc_header.js";
-
-/* Test PIN code changes fail */
-taskHelper.push(function testPinChangeFailed() {
-  // The default pin is '0000' in emulator
-  let request = icc.setCardLock(
-    {lockType: "pin",
-     pin: "1111",
-     newPin: "0000"});
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
 
-  ok(request instanceof DOMRequest,
-     "request instanceof " + request.constructor);
+MARIONETTE_TIMEOUT = 60000;
+MARIONETTE_HEAD_JS = "head.js";
 
-  request.onerror = function onerror() {
-    is(request.error.name, "IncorrectPassword");
-    // The default pin retries is 3, failed once becomes to 2
-    is(request.error.retryCount, 2);
-
-    // Reset pin retries by passing correct pin code.
-    let resetRequest = icc.setCardLock(
-      {lockType: "pin",
-       pin: "0000",
-       newPin: "0000"});
+const LOCK_TYPE = "pin";
 
-    resetRequest.onsuccess = function onsuccess() {
-      taskHelper.runNext();
-    };
-
-    resetRequest.onerror = function onerror() {
-      ok(false, "Reset pin retries got error: " + request.error.name);
-      taskHelper.runNext();
-    };
-  };
-});
-
-/* Test PIN code changes success */
-taskHelper.push(function testPinChangeSuccess() {
-  // The default pin is '0000' in emulator
-  let request = icc.setCardLock(
-    {lockType: "pin",
-     pin: "0000",
-     newPin: "0000"});
-
-  ok(request instanceof DOMRequest,
-     "request instanceof " + request.constructor);
-
-  request.onerror = function onerror() {
-    ok(false, "Should not fail, got error: " + request.error.name);
-
-    taskHelper.runNext();
-  };
-
-  request.onsuccess = function onsuccess() {
-    taskHelper.runNext();
-  };
-});
+function testChangePin(aIcc, aPin, aNewPin, aErrorName, aRetryCount) {
+  log("testChangePin for pin=" + aPin + " and newPin=" + aNewPin);
+  return aIcc.setCardLock({ lockType: LOCK_TYPE, pin: aPin, newPin: aNewPin })
+    .then((aResult) => {
+      if (aErrorName) {
+        ok(false, "changing pin should not success");
+      }
+    }, (aError) => {
+      if (!aErrorName) {
+        ok(false, "changing pin should not fail");
+        return;
+      }
 
-/* Read PIN-lock retry count */
-taskHelper.push(function testPinCardLockRetryCount() {
-  let request = icc.getCardLockRetryCount('pin');
-
-  ok(request instanceof DOMRequest,
-     'request instanceof ' + request.constructor);
+      // check the request error.
+      is(aError.name, aErrorName, "error.name");
+      is(aError.retryCount, aRetryCount, "error.retryCount");
+    });
+}
 
-  request.onsuccess = function onsuccess() {
-    ok(request.result.retryCount >= 0,
-        'retryCount is ' + request.result.retryCount);
-    taskHelper.runNext();
-  };
-  request.onerror = function onerror() {
-    // The operation is optional any might not be supported for all
-    // all locks. In this case, we generate 'NotSupportedError' for
-    // the valid lock types.
-    is(request.error.name, 'RequestNotSupported',
-        'error name is ' + request.error.name);
-    taskHelper.runNext();
-  };
-});
-
-/* Read PUK-lock retry count */
-taskHelper.push(function testPukCardLockRetryCount() {
-  let request = icc.getCardLockRetryCount('puk');
-
-  ok(request instanceof DOMRequest,
-     'request instanceof ' + request.constructor);
+// Start tests
+startTestCommon(function() {
+  let icc = getMozIcc();
+  let retryCount;
 
-  request.onsuccess = function onsuccess() {
-    ok(request.result.retryCount >= 0,
-        'retryCount is ' + request.result.retryCount);
-    taskHelper.runNext();
-  };
-  request.onerror = function onerror() {
-    // The operation is optional any might not be supported for all
-    // all locks. In this case, we generate 'NotSupportedError' for
-    // the valid lock types.
-    is(request.error.name, 'RequestNotSupported',
-        'error name is ' + request.error.name);
-    taskHelper.runNext();
-  };
+  return icc.getCardLockRetryCount(LOCK_TYPE)
+    // Get current PIN-lock retry count.
+    .then((aResult) => {
+      retryCount = aResult.retryCount;
+      ok(true, LOCK_TYPE + " retryCount is " + retryCount);
+    })
+    // Test PIN code changes fail.
+    // The retry count should be decreased by 1.
+    .then(() => testChangePin(icc, "1111", DEFAULT_PIN, "IncorrectPassword",
+                              retryCount - 1))
+    // Test PIN code changes success. This will reset the retry count.
+    .then(() => testChangePin(icc, DEFAULT_PIN, DEFAULT_PIN));
 });
-
-/* Read lock retry count for an invalid entries  */
-taskHelper.push(function testInvalidCardLockRetryCount() {
-  let request = icc.getCardLockRetryCount('invalid-lock-type');
-
-  ok(request instanceof DOMRequest,
-     'request instanceof ' + request.constructor);
-
-  request.onsuccess = function onsuccess() {
-    ok(false,
-        'request should never return success for an invalid lock type');
-    taskHelper.runNext();
-  };
-  request.onerror = function onerror() {
-    is(request.error.name, 'GenericFailure',
-        'error name is ' + request.error.name);
-    taskHelper.runNext();
-  };
-});
-
-// Start test
-taskHelper.runNext();
new file mode 100644
--- /dev/null
+++ b/dom/icc/tests/marionette/test_icc_card_lock_enable_pin.js
@@ -0,0 +1,59 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+MARIONETTE_TIMEOUT = 60000;
+MARIONETTE_HEAD_JS = "head.js";
+
+function setCardLockAndCheck(aIcc, aLockType, aPin, aEnabled, aErrorName,
+                             aRetryCount) {
+  let options = {
+    lockType: aLockType,
+    enabled: aEnabled,
+    pin: aPin
+  };
+
+  return aIcc.setCardLock(options)
+    .then((aResult) => {
+      if (aErrorName) {
+        ok(false, "setting pin should not success");
+        return;
+      }
+
+      // Check lock state.
+      return aIcc.getCardLock(aLockType)
+        .then((aResult) => {
+          is(aResult.enabled, aEnabled, "result.enabled");
+        });
+    }, (aError) => {
+      if (!aErrorName) {
+        ok(false, "setting pin should not fail");
+        return;
+      }
+
+      // Check the request error.
+      is(aError.name, aErrorName, "error.name");
+      is(aError.retryCount, aRetryCount, "error.retryCount");
+    });
+}
+
+// Start tests
+startTestCommon(function() {
+  let icc = getMozIcc();
+  let lockType = "pin";
+  let retryCount;
+
+  return icc.getCardLockRetryCount(lockType)
+    // Get current PIN-lock retry count.
+    .then((aResult) => {
+      retryCount = aResult.retryCount;
+      ok(true, lockType + " retryCount is " + retryCount);
+    })
+    // Test fail to enable PIN-lock by passing wrong pin.
+    // The retry count should be decreased by 1.
+    .then(() => setCardLockAndCheck(icc, lockType, "1111", true,
+                                    "IncorrectPassword", retryCount -1))
+    // Test enabling PIN-lock.
+    .then(() => setCardLockAndCheck(icc, lockType, DEFAULT_PIN, true))
+    // Restore pin state.
+    .then(() => setCardLockAndCheck(icc, lockType, DEFAULT_PIN, false));
+});
new file mode 100644
--- /dev/null
+++ b/dom/icc/tests/marionette/test_icc_card_lock_get_retry_count.js
@@ -0,0 +1,41 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+MARIONETTE_TIMEOUT = 60000;
+MARIONETTE_HEAD_JS = "head.js";
+
+function testGetCardLockRetryCount(aIcc, aLockType, aRetryCount) {
+  log("testGetCardLockRetryCount for " + aLockType);
+  return aIcc.getCardLockRetryCount(aLockType)
+    .then((aResult) => {
+      if (!aRetryCount) {
+        ok(false, "getCardLockRetryCount(" + aLockType + ") should not success");
+        return;
+      }
+
+      // Check the request result.
+      is(aResult.retryCount, aRetryCount, "result.retryCount");
+    }, (aError) => {
+      if (aRetryCount) {
+        ok(false, "getCardLockRetryCount(" + aLockType + ") should not fail");
+        return;
+      }
+
+      // Check the error.
+      is(aError.name, "GenericFailure", "error.name");
+    });
+}
+
+// Start tests
+startTestCommon(function() {
+  let icc = getMozIcc();
+
+  // Read PIN-lock retry count.
+  // The default PIN-lock retry count hard coded in emulator is 3.
+  return testGetCardLockRetryCount(icc, "pin", 3)
+    // Read PUK-lock retry count.
+    // The default PUK-lock retry count hard coded in emulator is 6.
+    .then(() => testGetCardLockRetryCount(icc, "puk", 6))
+    // Read lock retry count for an invalid entries.
+    .then(() => testGetCardLockRetryCount(icc, "invalid-lock-type"));
+});
new file mode 100644
--- /dev/null
+++ b/dom/icc/tests/marionette/test_icc_card_lock_unlock_pin.js
@@ -0,0 +1,68 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+MARIONETTE_TIMEOUT = 60000;
+MARIONETTE_HEAD_JS = "head.js";
+
+function testUnlockPin(aIcc, aPin, aErrorName, aRetryCount) {
+  log("testUnlockPin with pin=" + aPin);
+
+  return aIcc.unlockCardLock({ lockType: "pin", pin: aPin })
+    .then((aResult) => {
+      if (aErrorName) {
+        ok(false, "unlocking pin should not success");
+      }
+    }, (aError) => {
+      if (!aErrorName) {
+        ok(false, "unlocking pin should not fail");
+        return;
+      }
+
+      // Check the request error.
+      is(aError.name, aErrorName, "error.name");
+      is(aError.retryCount, aRetryCount, "error.retryCount");
+    });
+}
+
+function testUnlockPinAndWait(aIcc, aPin, aCardState) {
+  log("testUnlockPin with pin=" + aPin + ", and wait cardState changes to '" +
+      aCardState + "'");
+
+  let promises = [];
+
+  promises.push(waitForTargetEvent(aIcc, "cardstatechange", function() {
+    return aIcc.cardState === aCardState;
+  }));
+  promises.push(testUnlockPin(aIcc, aPin));
+
+  return Promise.all(promises);
+}
+
+// Start tests
+startTestCommon(function() {
+  let icc = getMozIcc();
+  let retryCount;
+
+  // Enable PIN-lock.
+  return setPinLockEnabled(icc, true)
+    // Reset card state to "pinRequired" by restarting radio
+    .then(() => restartRadioAndWait("pinRequired"))
+    .then(() => { icc = getMozIcc(); })
+
+    // Get current PIN-lock retry count.
+    .then(() => icc.getCardLockRetryCount("pin"))
+    .then((aResult) => {
+      retryCount = aResult.retryCount;
+      ok(true, "pin retryCount is " + retryCount);
+    })
+
+    // Test fail to unlock PIN-lock.
+    // The retry count should be decreased by 1.
+    .then(() => testUnlockPin(icc, "1111", "IncorrectPassword", retryCount - 1))
+
+    // Test success to unlock PIN-lock.
+    .then(() => testUnlockPinAndWait(icc, DEFAULT_PIN, "ready"))
+
+    // Restore pin state.
+    .then(() => setPinLockEnabled(icc, false));
+});
new file mode 100644
--- /dev/null
+++ b/dom/icc/tests/marionette/test_icc_card_lock_unlock_puk.js
@@ -0,0 +1,97 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+MARIONETTE_TIMEOUT = 60000;
+MARIONETTE_HEAD_JS = "head.js";
+
+function passingWrongPinAndWait(aIcc) {
+  return aIcc.getCardLockRetryCount("pin").then((aResult) => {
+    let promises = [];
+    let retryCount = aResult.retryCount;
+
+    ok(true, "pin retryCount is " + retryCount);
+
+    promises.push(waitForTargetEvent(aIcc, "cardstatechange", function() {
+      return aIcc.cardState === "pukRequired";
+    }));
+
+    for (let i = 0; i < retryCount; i++) {
+      promises.push(aIcc.unlockCardLock({ lockType: "pin", pin: "1111" })
+        .then(() => {
+          ok(false, "unlocking pin should not success");
+        }, function reject(aRetryCount, aError) {
+          // check the request error.
+          is(aError.name, "IncorrectPassword", "error.name");
+          is(aError.retryCount, aRetryCount, "error.retryCount");
+        }.bind(null, retryCount - i - 1)));
+    }
+
+    return Promise.all(promises);
+  });
+}
+
+function testUnlockPuk(aIcc, aPuk, aNewPin, aErrorName, aRetryCount) {
+  log("testUnlockPuk with puk=" + aPuk + " and newPin=" + aNewPin);
+
+  return aIcc.unlockCardLock({ lockType: "puk", puk: aPuk, newPin: aNewPin })
+    .then((aResult) => {
+      if (aErrorName) {
+        ok(false, "unlocking puk should not success");
+      }
+    }, (aError) => {
+      if (!aErrorName) {
+        ok(false, "unlocking puk should not fail");
+        return;
+      }
+
+      // Check the request error.
+      is(aError.name, aErrorName, "error.name");
+      is(aError.retryCount, aRetryCount, "error.retryCount");
+    });
+}
+
+function testUnlockPukAndWait(aIcc, aPuk, aNewPin, aCardState) {
+  log("testUnlockPuk with puk=" + aPuk + "/newPin=" + aNewPin +
+      ", and wait card state changes to '" + aCardState + "'");
+
+  let promises = [];
+
+  promises.push(waitForTargetEvent(aIcc, "cardstatechange", function() {
+    return aIcc.cardState === aCardState;
+  }));
+  promises.push(testUnlockPuk(aIcc, aPuk, aNewPin));
+
+  return Promise.all(promises);
+}
+
+// Start tests
+startTestCommon(function() {
+  let icc = getMozIcc();
+  let retryCount;
+
+  // Enable pin lock.
+  return setPinLockEnabled(icc, true)
+    // Reset card state to "pinRequired" by restarting radio
+    .then(() => restartRadioAndWait("pinRequired"))
+    .then(() => { icc = getMozIcc() })
+    // Switch cardState to "pukRequired" by entering wrong pin code.
+    .then(() => passingWrongPinAndWait(icc))
+
+    // Get current PUK-lock retry count.
+    .then(() => icc.getCardLockRetryCount("puk"))
+    .then((aResult) => {
+      retryCount = aResult.retryCount;
+      ok(true, "puk retryCount is " + retryCount);
+    })
+
+    // Test unlock PUK code fail.
+    // The retry count should be decreased by 1.
+    .then(() => testUnlockPuk(icc, "11111111", DEFAULT_PIN, "IncorrectPassword",
+                              retryCount - 1))
+
+    // Test unlock PUK code success.
+    .then(() => testUnlockPukAndWait(icc, DEFAULT_PUK, DEFAULT_PIN, "ready"))
+
+    // Restore pin state.
+    .then(() => setPinLockEnabled(icc, false));
+});
--- a/dom/network/NetUtils.cpp
+++ b/dom/network/NetUtils.cpp
@@ -23,18 +23,16 @@ InitNetUtilsLib()
 
 static void*
 GetNetUtilsLibHandle()
 {
   PR_CallOnce(&sInitNetUtilsLib, InitNetUtilsLib);
   return sNetUtilsLib;
 }
 
-mozilla::Mutex NetUtils::sIfcMutex("NetUtils::sIfcMutex");
-
 // static
 void*
 NetUtils::GetSharedLibrary()
 {
   void* netLib = GetNetUtilsLibHandle();
   if (!netLib) {
     NS_WARNING("No /system/lib/libnetutils.so");
   }
@@ -65,87 +63,78 @@ DEFINE_DLFUNC(dhcp_stop, int32_t, const 
 
 NetUtils::NetUtils()
 {
 }
 
 int32_t NetUtils::do_ifc_enable(const char *ifname)
 {
   USE_DLFUNC(ifc_enable)
-  mozilla::MutexAutoLock lock(sIfcMutex);
   return ifc_enable(ifname);
 }
 
 int32_t NetUtils::do_ifc_disable(const char *ifname)
 {
   USE_DLFUNC(ifc_disable)
-  mozilla::MutexAutoLock lock(sIfcMutex);
   return ifc_disable(ifname);
 }
 
 int32_t NetUtils::do_ifc_configure(const char *ifname,
                                        in_addr_t address,
                                        uint32_t prefixLength,
                                        in_addr_t gateway,
                                        in_addr_t dns1,
                                        in_addr_t dns2)
 {
   USE_DLFUNC(ifc_configure)
-  mozilla::MutexAutoLock lock(sIfcMutex);
   int32_t ret = ifc_configure(ifname, address, prefixLength, gateway, dns1, dns2);
   return ret;
 }
 
 int32_t NetUtils::do_ifc_reset_connections(const char *ifname,
                                                const int32_t resetMask)
 {
   USE_DLFUNC(ifc_reset_connections)
-  mozilla::MutexAutoLock lock(sIfcMutex);
   return ifc_reset_connections(ifname, resetMask);
 }
 
 int32_t NetUtils::do_ifc_set_default_route(const char *ifname,
                                            in_addr_t gateway)
 {
   USE_DLFUNC(ifc_set_default_route)
-  mozilla::MutexAutoLock lock(sIfcMutex);
   return ifc_set_default_route(ifname, gateway);
 }
 
 int32_t NetUtils::do_ifc_add_route(const char *ifname,
                                    const char *dst,
                                    uint32_t prefixLength,
                                    const char *gateway)
 {
   USE_DLFUNC(ifc_add_route)
-  mozilla::MutexAutoLock lock(sIfcMutex);
   return ifc_add_route(ifname, dst, prefixLength, gateway);
 }
 
 int32_t NetUtils::do_ifc_remove_route(const char *ifname,
                                       const char *dst,
                                       uint32_t prefixLength,
                                       const char *gateway)
 {
   USE_DLFUNC(ifc_remove_route)
-  mozilla::MutexAutoLock lock(sIfcMutex);
   return ifc_remove_route(ifname, dst, prefixLength, gateway);
 }
 
 int32_t NetUtils::do_ifc_remove_host_routes(const char *ifname)
 {
   USE_DLFUNC(ifc_remove_host_routes)
-  mozilla::MutexAutoLock lock(sIfcMutex);
   return ifc_remove_host_routes(ifname);
 }
 
 int32_t NetUtils::do_ifc_remove_default_route(const char *ifname)
 {
   USE_DLFUNC(ifc_remove_default_route)
-  mozilla::MutexAutoLock lock(sIfcMutex);
   return ifc_remove_default_route(ifname);
 }
 
 int32_t NetUtils::do_dhcp_stop(const char *ifname)
 {
   USE_DLFUNC(dhcp_stop)
   return dhcp_stop(ifname);
 }
--- a/dom/network/NetUtils.h
+++ b/dom/network/NetUtils.h
@@ -6,17 +6,16 @@
  * Abstraction on top of the network support from libnetutils that we
  * use to set up network connections.
  */
 
 #ifndef NetUtils_h
 #define NetUtils_h
 
 #include "arpa/inet.h"
-#include "mozilla/Mutex.h"
 
 // Copied from ifc.h
 #define RESET_IPV4_ADDRESSES 0x01
 #define RESET_IPV6_ADDRESSES 0x02
 #define RESET_ALL_ADDRESSES  (RESET_IPV4_ADDRESSES | RESET_IPV6_ADDRESSES)
 
 // Implements netutils functions. No need for an abstract class here since we
 // only have a one sdk specific method (dhcp_do_request)
@@ -54,19 +53,16 @@ public:
                              uint32_t *prefixLength,
                              char *dns1,
                              char *dns2,
                              char *server,
                              uint32_t  *lease,
                              char* vendorinfo);
 
   static int32_t SdkVersion();
-
-private:
-  static mozilla::Mutex sIfcMutex;
 };
 
 // Defines a function type with the right arguments and return type.
 #define DEFINE_DLFUNC(name, ret, args...) typedef ret (*FUNC##name)(args);
 
 // Set up a dlsymed function ready to use.
 #define USE_DLFUNC(name)                                                      \
   FUNC##name name = (FUNC##name) dlsym(GetSharedLibrary(), #name);            \
--- a/dom/notification/ChromeNotifications.js
+++ b/dom/notification/ChromeNotifications.js
@@ -49,16 +49,21 @@ ChromeNotifications.prototype = {
 
     notifications.forEach(function(notification) {
       let behavior;
       try {
         behavior = JSON.parse(notification.mozbehavior);
       } catch(e) {
         behavior = undefined;
       }
+
+      if (behavior && behavior.showOnlyOnce === true) {
+        return;
+      }
+
       appNotifier.showAppNotification(
         notification.icon,
         notification.title,
         notification.body,
         null,
         {
           manifestURL: notification.origin,
           id: notification.alertName,
--- a/dom/tests/mochitest/notification/test_notification_resend.html
+++ b/dom/tests/mochitest/notification/test_notification_resend.html
@@ -82,16 +82,45 @@
 
       navigator.mozChromeNotifications.mozResendAllNotifications(function(number) {
         is(number, 1, "One notification resent");
         notif.close();
       });
     },
 
     function (done) {
+      info("Sending one non-resendable notification");
+      var behavior = {
+        showOnlyOnce: true
+      };
+      var notif = new Notification("title", { mozbehavior: behavior });
+      ok(notif, "Notification object is valid");
+      notifications.push(notif);
+
+      var promise = Notification.get();
+      promise.then(function (notifications) {
+        is(notifications.length, 1, "one notification has been sent");
+        done();
+      });
+    },
+
+    function (done) {
+      info("Trying to resend non-resendable notification");
+      var notif = notifications.pop();
+      notif.onclose = function() {
+        done();
+      };
+
+      navigator.mozChromeNotifications.mozResendAllNotifications(function(number) {
+        is(number, 0, "One notification not resent");
+        notif.close();
+      });
+    },
+
+    function (done) {
       info("Sending two notifications, closing one");
       var notif1 = new Notification("title1");
       ok(notif1, "Notification object is valid");
       notif1.onclose = function() {
         done();
       };
 
       var payload = NotificationTest.payload;
--- a/dom/webidl/Notification.webidl
+++ b/dom/webidl/Notification.webidl
@@ -67,16 +67,17 @@ dictionary NotificationOptions {
 
 dictionary GetNotificationOptions {
   DOMString tag;
 };
 
 dictionary NotificationBehavior {
   boolean noscreen = false;
   boolean noclear = false;
+  boolean showOnlyOnce = false;
   DOMString soundFile = "";
   sequence<unsigned long> vibrationPattern;
 };
 
 enum NotificationPermission {
   "default",
   "denied",
   "granted"
--- a/gfx/layers/apz/src/APZCTreeManager.cpp
+++ b/gfx/layers/apz/src/APZCTreeManager.cpp
@@ -241,16 +241,19 @@ APZCTreeManager::PrepareAPZCForLayer(con
                                      const nsIntRegion& aObscured,
                                      AsyncPanZoomController* aParent,
                                      AsyncPanZoomController* aNextSibling,
                                      TreeBuildingState& aState)
 {
   if (!aMetrics.IsScrollable()) {
     return nullptr;
   }
+  if (gfxPrefs::LayoutEventRegionsEnabled() && aLayer.IsScrollInfoLayer()) {
+    return nullptr;
+  }
 
   const CompositorParent::LayerTreeState* state = CompositorParent::GetIndirectShadowTree(aLayersId);
   if (!(state && state->mController.get())) {
     return nullptr;
   }
 
   AsyncPanZoomController* apzc = nullptr;
   // If we get here, aLayer is a scrollable layer and somebody
--- a/gfx/layers/apz/src/APZCTreeManager.h
+++ b/gfx/layers/apz/src/APZCTreeManager.h
@@ -138,20 +138,21 @@ public:
    * This function transforms |aEvent| to have its coordinates in DOM space.
    * This is so that the event can be passed through the DOM and content can
    * handle them. The event may need to be converted to a WidgetInputEvent
    * by the caller if it wants to do this.
    *
    * The following values may be returned by this function:
    * nsEventStatus_eConsumeNoDefault is returned to indicate the
    *   caller should discard the event with extreme prejudice.
-   *   Currently this is only returned if the APZ determines that
-   *   something is in overscroll and the event should be ignored entirely.
-   *   There may be other scenarios where this return code might be used in
-   *   the future.
+   *   Currently this is only returned if the APZ determines that something is
+   *   in overscroll and the event should be ignored entirely, or if the input
+   *   event is part of a extended gesture like flywheel scrolling, and gets
+   *   consumed within the APZ code. There may be other scenarios where this
+   *   return code might be used in the future.
    * nsEventStatus_eIgnore is returned to indicate that the APZ code didn't
    *   use this event. This might be because it was directed at a point on
    *   the screen where there was no APZ, or because the thing the user was
    *   trying to do was not allowed. (For example, attempting to pan a
    *   non-pannable document).
    * nsEventStatus_eConsumeDoDefault is returned to indicate that the APZ
    *   code may have used this event to do some user-visible thing. Note that
    *   in some cases CONSUMED is returned even if the event was NOT used. This
--- a/gfx/layers/apz/src/InputBlockState.cpp
+++ b/gfx/layers/apz/src/InputBlockState.cpp
@@ -79,17 +79,17 @@ InputBlockState::IsTargetConfirmed() con
 
 TouchBlockState::TouchBlockState(const nsRefPtr<AsyncPanZoomController>& aTargetApzc,
                                  bool aTargetConfirmed)
   : InputBlockState(aTargetApzc, aTargetConfirmed)
   , mAllowedTouchBehaviorSet(false)
   , mPreventDefault(false)
   , mContentResponded(false)
   , mContentResponseTimerExpired(false)
-  , mSingleTapDisallowed(false)
+  , mDuringFastMotion(false)
   , mSingleTapOccurred(false)
 {
   TBS_LOG("Creating %p\n", this);
 }
 
 bool
 TouchBlockState::SetContentResponse(bool aPreventDefault)
 {
@@ -159,27 +159,34 @@ TouchBlockState::IsReadyForHandling() co
 bool
 TouchBlockState::IsDefaultPrevented() const
 {
   MOZ_ASSERT(mContentResponded || mContentResponseTimerExpired);
   return mPreventDefault;
 }
 
 void
-TouchBlockState::DisallowSingleTap()
+TouchBlockState::SetDuringFastMotion()
 {
-  TBS_LOG("%p disallowing single-tap\n", this);
-  mSingleTapDisallowed = true;
+  TBS_LOG("%p setting fast-motion flag\n", this);
+  mDuringFastMotion = true;
+}
+
+bool
+TouchBlockState::IsDuringFastMotion() const
+{
+  return mDuringFastMotion;
 }
 
 bool
 TouchBlockState::SetSingleTapOccurred()
 {
-  TBS_LOG("%p attempting to set single-tap occurred; disallowed=%d\n", this, mSingleTapDisallowed);
-  if (!mSingleTapDisallowed) {
+  TBS_LOG("%p attempting to set single-tap occurred; disallowed=%d\n",
+    this, mDuringFastMotion);
+  if (!mDuringFastMotion) {
     mSingleTapOccurred = true;
     return true;
   }
   return false;
 }
 
 bool
 TouchBlockState::SingleTapOccurred() const
--- a/gfx/layers/apz/src/InputBlockState.h
+++ b/gfx/layers/apz/src/InputBlockState.h
@@ -111,26 +111,34 @@ public:
    */
   bool IsReadyForHandling() const;
   /**
    * @return true iff web content cancelled this block of events.
    */
   bool IsDefaultPrevented() const;
 
   /**
-   * Set a flag that disables setting the single-tap flag on this block.
+   * Sets a flag that indicates this input block occurred while the APZ was
+   * in a state of fast motion. This affects gestures that may be produced
+   * from input events in this block.
    */
-  void DisallowSingleTap();
+  void SetDuringFastMotion();
   /**
-   * Set a flag that indicates that this touch block triggered a single tap event.
-   * @return true iff DisallowSingleTap was not previously called.
+   * @return true iff SetDuringFastMotion was called on this block.
+   */
+  bool IsDuringFastMotion() const;
+  /**
+   * Set the single-tap-occurred flag that indicates that this touch block
+   * triggered a single tap event.
+   * @return true if the flag was set. This may not happen if, for example,
+   *         SetDuringFastMotion was previously called.
    */
   bool SetSingleTapOccurred();
   /**
-   * @return true iff SetSingleTapOccurred was previously called on this block.
+   * @return true iff the single-tap-occurred flag is set on this block.
    */
   bool SingleTapOccurred() const;
 
   /**
    * @return true iff there are pending events in this touch block.
    */
   bool HasEvents() const;
   /**
@@ -166,17 +174,17 @@ public:
   bool TouchActionAllowsPanningXY() const;
 
 private:
   nsTArray<TouchBehaviorFlags> mAllowedTouchBehaviors;
   bool mAllowedTouchBehaviorSet;
   bool mPreventDefault;
   bool mContentResponded;
   bool mContentResponseTimerExpired;
-  bool mSingleTapDisallowed;
+  bool mDuringFastMotion;
   bool mSingleTapOccurred;
   nsTArray<MultiTouchInput> mEvents;
 };
 
 } // namespace layers
 } // namespace mozilla
 
 #endif // mozilla_layers_InputBlockState_h
--- a/gfx/layers/apz/src/InputQueue.cpp
+++ b/gfx/layers/apz/src/InputQueue.cpp
@@ -54,25 +54,28 @@ InputQueue::ReceiveInputEvent(const nsRe
     // touch blocks still in the queue.
     if (block == CurrentTouchBlock()) {
       // XXX using the chain from |block| here may be wrong in cases where the
       // target isn't confirmed and the real target turns out to be something
       // else. For now assume this is rare enough that it's not an issue.
       if (block->GetOverscrollHandoffChain()->HasFastMovingApzc()) {
         // If we're already in a fast fling, then we want the touch event to stop the fling
         // and to disallow the touch event from being used as part of a fling.
-        block->DisallowSingleTap();
+        block->SetDuringFastMotion();
       }
       block->GetOverscrollHandoffChain()->CancelAnimations();
     }
 
     bool waitForMainThread = !aTargetConfirmed;
     if (!gfxPrefs::LayoutEventRegionsEnabled()) {
       waitForMainThread |= aTarget->NeedToWaitForContent();
     }
+    if (block->IsDuringFastMotion()) {
+      waitForMainThread = false;
+    }
     if (waitForMainThread) {
       // We either don't know for sure if aTarget is the right APZC, or we may
       // need to wait to give content the opportunity to prevent-default the
       // touch events. Either way we schedule a timeout so the main thread stuff
       // can run.
       ScheduleMainThreadTimeout(aTarget, block->GetBlockId());
     } else {
       // Content won't prevent-default this, so we can just pretend like we scheduled
@@ -101,17 +104,19 @@ InputQueue::ReceiveInputEvent(const nsRe
   // null) should take priority. This is equivalent to just always using the
   // target (confirmed or not) from the block.
   nsRefPtr<AsyncPanZoomController> target = block->GetTargetApzc();
 
   nsEventStatus result = nsEventStatus_eIgnore;
   // XXX calling ArePointerEventsConsumable on |target| may be wrong here if
   // the target isn't confirmed and the real target turns out to be something
   // else. For now assume this is rare enough that it's not an issue.
-  if (target && target->ArePointerEventsConsumable(block, aEvent.AsMultiTouchInput().mTouches.Length())) {
+  if (block->IsDuringFastMotion()) {
+    result = nsEventStatus_eConsumeNoDefault;
+  } else if (target && target->ArePointerEventsConsumable(block, aEvent.AsMultiTouchInput().mTouches.Length())) {
     result = nsEventStatus_eConsumeDoDefault;
   }
 
   if (block == CurrentTouchBlock() && block->IsReadyForHandling()) {
     INPQ_LOG("current touch block is ready with target %p preventdefault %d\n",
         target.get(), block->IsDefaultPrevented());
     if (!target || block->IsDefaultPrevented()) {
       return result;
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -270,19 +270,19 @@ public:
   {}
 
 #ifdef MOZ_DUMP_PAINTING
   /**
    * Keep track of important decisions for debugging.
    */
   nsAutoCString mLog;
 
-  #define FLB_LOG_PAINTED_LAYER_DECISION(tld, ...) \
-          tld->mLog.AppendPrintf("\t\t\t\t"); \
-          tld->mLog.AppendPrintf(__VA_ARGS__);
+  #define FLB_LOG_PAINTED_LAYER_DECISION(pld, ...) \
+          pld->mLog.AppendPrintf("\t\t\t\t"); \
+          pld->mLog.AppendPrintf(__VA_ARGS__);
 #else
   #define FLB_LOG_PAINTED_LAYER_DECISION(...)
 #endif
 
   /**
    * Record that an item has been added to the PaintedLayer, so we
    * need to update our regions.
    * @param aVisibleRect the area of the item that's visible
@@ -304,17 +304,17 @@ public:
   const nsIFrame* GetAnimatedGeometryRoot() { return mAnimatedGeometryRoot; }
 
   /**
    * Add the given hit regions to the hit regions to the hit retions for this
    * PaintedLayer.
    */
   void AccumulateEventRegions(nsDisplayLayerEventRegions* aEventRegions)
   {
-    FLB_LOG_PAINTED_LAYER_DECISION(this, "Accumulating event regions %p against tld=%p\n", aEventRegions, this);
+    FLB_LOG_PAINTED_LAYER_DECISION(this, "Accumulating event regions %p against pld=%p\n", aEventRegions, this);
 
     mHitRegion.Or(mHitRegion, aEventRegions->HitRegion());
     mMaybeHitRegion.Or(mMaybeHitRegion, aEventRegions->MaybeHitRegion());
     mDispatchToContentHitRegion.Or(mDispatchToContentHitRegion, aEventRegions->DispatchToContentHitRegion());
   }
 
   /**
    * If this represents only a nsDisplayImage, and the image type
@@ -2101,17 +2101,17 @@ ContainerState::PopPaintedLayerData()
                                      data->mDrawRegion,
                                      &data->mVisibleRegion,
                                      &data->mIsSolidColorInVisibleRegion);
 
   NewLayerEntry* newLayerEntry = &mNewChildLayers[data->mNewChildLayersIndex];
   nsRefPtr<Layer> layer;
   nsRefPtr<ImageContainer> imageContainer = data->CanOptimizeImageLayer(mBuilder);
 
-  FLB_LOG_PAINTED_LAYER_DECISION(data, "Selecting layer for tld=%p\n", data);
+  FLB_LOG_PAINTED_LAYER_DECISION(data, "Selecting layer for pld=%p\n", data);
   FLB_LOG_PAINTED_LAYER_DECISION(data, "  Solid=%i, hasImage=%i, canOptimizeAwayPaintedLayer=%i\n",
           data->mIsSolidColorInVisibleRegion, !!imageContainer,
           CanOptimizeAwayPaintedLayer(data, mLayerBuilder));
 
   if ((data->mIsSolidColorInVisibleRegion || imageContainer) &&
       CanOptimizeAwayPaintedLayer(data, mLayerBuilder)) {
     NS_ASSERTION(!(data->mIsSolidColorInVisibleRegion && imageContainer),
                  "Can't be a solid color as well as an image!");
@@ -2342,17 +2342,17 @@ IsItemAreaInWindowOpaqueRegion(nsDisplay
 void
 PaintedLayerData::Accumulate(ContainerState* aState,
                             nsDisplayItem* aItem,
                             const nsIntRegion& aClippedOpaqueRegion,
                             const nsIntRect& aVisibleRect,
                             const nsIntRect& aDrawRect,
                             const DisplayItemClip& aClip)
 {
-  FLB_LOG_PAINTED_LAYER_DECISION(this, "Accumulating dp=%s(%p), f=%p against tld=%p\n", aItem->Name(), aItem, aItem->Frame(), this);
+  FLB_LOG_PAINTED_LAYER_DECISION(this, "Accumulating dp=%s(%p), f=%p against pld=%p\n", aItem->Name(), aItem, aItem->Frame(), this);
 
   bool snap;
   nsRect itemBounds = aItem->GetBounds(aState->mBuilder, &snap);
   mBounds.OrWith(aState->ScaleToOutsidePixels(itemBounds, snap));
 
   if (aState->mBuilder->NeedToForceTransparentSurfaceForItem(aItem)) {
     mForceTransparentSurface = true;
   }