Merge m-c to m-i
authorPhil Ringnalda <philringnalda@gmail.com>
Sun, 31 Aug 2014 18:41:31 -0700
changeset 202774 9fa8a667258f08c823c8e726d0b8eec5ea620c7a
parent 202753 da622497067d12187ac1fdec4c132faf5092bfee (current diff)
parent 202773 738469449872ffc1d278c33fc900af5348fa57fb (diff)
child 202775 a7eaac164c36c9a23df61c91bf3359ee0c296071
push id48479
push userphilringnalda@gmail.com
push dateMon, 01 Sep 2014 01:42:19 +0000
treeherdermozilla-inbound@9fa8a667258f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone34.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 m-i
dom/settings/SettingsQueue.jsm
--- 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="4b4336c73c081b39776d399835ce4853aee5cc1c">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="2be78d83a760fa3b9638fe51c266b442d14597f1"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="e7d31f0e9b6b19d9b484eeec8fb980718bc40d79"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3bb61a27cd2941b2ba9b616a11aaa44269210396"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="320650844ec7cba40a70317b761b88b47a8dca0e"/>
--- 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="0d616942c300d9fb142483210f1dda9096c9a9fc">
     <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="2be78d83a760fa3b9638fe51c266b442d14597f1"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="e7d31f0e9b6b19d9b484eeec8fb980718bc40d79"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3bb61a27cd2941b2ba9b616a11aaa44269210396"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="c058843242068d0df7c107e09da31b53d2e08fa6"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="320650844ec7cba40a70317b761b88b47a8dca0e"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/emulator-jb/sources.xml
+++ b/b2g/config/emulator-jb/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="74465af039d2809454afdfef285285bb63146e1b">
     <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="2be78d83a760fa3b9638fe51c266b442d14597f1"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="e7d31f0e9b6b19d9b484eeec8fb980718bc40d79"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3bb61a27cd2941b2ba9b616a11aaa44269210396"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="320650844ec7cba40a70317b761b88b47a8dca0e"/>
   <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="4b4336c73c081b39776d399835ce4853aee5cc1c">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="2be78d83a760fa3b9638fe51c266b442d14597f1"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="e7d31f0e9b6b19d9b484eeec8fb980718bc40d79"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3bb61a27cd2941b2ba9b616a11aaa44269210396"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="320650844ec7cba40a70317b761b88b47a8dca0e"/>
--- 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="0d616942c300d9fb142483210f1dda9096c9a9fc">
     <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="2be78d83a760fa3b9638fe51c266b442d14597f1"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="e7d31f0e9b6b19d9b484eeec8fb980718bc40d79"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3bb61a27cd2941b2ba9b616a11aaa44269210396"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="c058843242068d0df7c107e09da31b53d2e08fa6"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="320650844ec7cba40a70317b761b88b47a8dca0e"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/flame-kk/sources.xml
+++ b/b2g/config/flame-kk/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="4b4336c73c081b39776d399835ce4853aee5cc1c">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="2be78d83a760fa3b9638fe51c266b442d14597f1"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="e7d31f0e9b6b19d9b484eeec8fb980718bc40d79"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3bb61a27cd2941b2ba9b616a11aaa44269210396"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="320650844ec7cba40a70317b761b88b47a8dca0e"/>
--- 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="74465af039d2809454afdfef285285bb63146e1b">
     <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="2be78d83a760fa3b9638fe51c266b442d14597f1"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="e7d31f0e9b6b19d9b484eeec8fb980718bc40d79"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3bb61a27cd2941b2ba9b616a11aaa44269210396"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="320650844ec7cba40a70317b761b88b47a8dca0e"/>
   <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": "f990b157724a819b6899089d01472aa0230e3104", 
+    "revision": "bce92f813f48346b36ce9dffc16b0c93d0ac8330", 
     "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="0d616942c300d9fb142483210f1dda9096c9a9fc">
     <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="2be78d83a760fa3b9638fe51c266b442d14597f1"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="e7d31f0e9b6b19d9b484eeec8fb980718bc40d79"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3bb61a27cd2941b2ba9b616a11aaa44269210396"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="320650844ec7cba40a70317b761b88b47a8dca0e"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
--- a/b2g/config/helix/sources.xml
+++ b/b2g/config/helix/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="0d616942c300d9fb142483210f1dda9096c9a9fc">
     <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="2be78d83a760fa3b9638fe51c266b442d14597f1"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="e7d31f0e9b6b19d9b484eeec8fb980718bc40d79"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3bb61a27cd2941b2ba9b616a11aaa44269210396"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
--- a/b2g/config/nexus-4/sources.xml
+++ b/b2g/config/nexus-4/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="74465af039d2809454afdfef285285bb63146e1b">
     <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="2be78d83a760fa3b9638fe51c266b442d14597f1"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="e7d31f0e9b6b19d9b484eeec8fb980718bc40d79"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3bb61a27cd2941b2ba9b616a11aaa44269210396"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="320650844ec7cba40a70317b761b88b47a8dca0e"/>
   <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="0d616942c300d9fb142483210f1dda9096c9a9fc">
     <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="2be78d83a760fa3b9638fe51c266b442d14597f1"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="e7d31f0e9b6b19d9b484eeec8fb980718bc40d79"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3bb61a27cd2941b2ba9b616a11aaa44269210396"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="320650844ec7cba40a70317b761b88b47a8dca0e"/>
   <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/main.js
+++ b/browser/devtools/main.js
@@ -316,26 +316,28 @@ Tools.netMonitor = {
   build: function(iframeWindow, toolbox) {
     let panel = new NetMonitorPanel(iframeWindow, toolbox);
     return panel.open();
   }
 };
 
 Tools.storage = {
   id: "storage",
-  key: l10n("open.commandkey", storageStrings),
+  key: l10n("storage.commandkey", storageStrings),
   ordinal: 9,
-  accesskey: l10n("open.accesskey", storageStrings),
+  accesskey: l10n("storage.accesskey", storageStrings),
   modifiers: "shift",
   visibilityswitch: "devtools.storage.enabled",
   icon: "chrome://browser/skin/devtools/tool-storage.svg",
   invertIconForLightTheme: true,
   url: "chrome://browser/content/devtools/storage.xul",
   label: l10n("storage.label", storageStrings),
-  tooltip: l10n("storage.tooltip", storageStrings),
+  menuLabel: l10n("storage.menuLabel", storageStrings),
+  panelLabel: l10n("storage.panelLabel", storageStrings),
+  tooltip: l10n("storage.tooltip2", storageStrings),
   inMenu: true,
 
   isTargetSupported: function(target) {
     return target.isLocalTab ||
            (target.client.traits.storageInspector && !target.isAddon);
   },
 
   build: function(iframeWindow, toolbox) {
--- a/browser/locales/en-US/chrome/browser/devtools/storage.properties
+++ b/browser/locales/en-US/chrome/browser/devtools/storage.properties
@@ -4,39 +4,42 @@
 
 # LOCALIZATION NOTE These strings are used inside the Storage Editor tool.
 # LOCALIZATION NOTE The correct localization of this file might be to keep it
 # in English, or another language commonly spoken among web developers.
 # You want to make that choice consistent across the developer tools.
 # A good criteria is the language in which you'd find the best documentation
 # on web development on the web.
 
-# LOCALIZATION NOTE  (chromeWindowTitle): This is the title of the Storage
-# 'chrome' window. That is, the main window with all the cookies, etc.
-# The argument is either the content document's title or its href if no title
-# is available.
-chromeWindowTitle=Storage [%S]
+# LOCALIZATION NOTE  (storage.commandkey): This the key to use in
+# conjunction with shift to open the storage editor
+storage.commandkey=VK_F9
 
-# LOCALIZATION NOTE  (open.commandkey): This the key to use in
-# conjunction with shift to open the storage editor
-open.commandkey=VK_F9
-
-# LOCALIZATION NOTE (open.accesskey): The access key used to open the storage
+# LOCALIZATION NOTE (storage.accesskey): The access key used to open the storage
 # editor.
-open.accesskey=d
+storage.accesskey=a
 
 # LOCALIZATION NOTE (storage.label):
-# This string is displayed in the title of the tab when the storage editor is
-# displayed inside the developer tools window and in the Developer Tools Menu.
+# This string is displayed as the label of the tab in the developer tools window
 storage.label=Storage
 
+# LOCALIZATION NOTE (storage.menuLabel):
+# This string is displayed in the Tools menu as a shortcut to open the devtools
+# with the Storage Inspector tab selected.
+storage.menuLabel=Storage Inspector
+
+# LOCALIZATION NOTE (storage.panelLabel):
+# This string is used as the aria-label for the iframe of the Storage Inspector
+# tool in developer tools toolbox.
+storage.panelLabel=Storage Panel
+
 # LOCALIZATION NOTE (storage.tooltip):
 # This string is displayed in the tooltip of the tab when the storage editor is
 # displayed inside the developer tools window.
-storage.tooltip=Storage Inspector (Cookies, Local Storage ...)
+storage.tooltip2=Storage Inspector (Cookies, Local Storage …)
 
 # LOCALIZATION NOTE (tree.emptyText):
 # This string is displayed when the Storage Tree is empty. This can happen when
 # there are no websites on the current page (about:blank)
 tree.emptyText=No hosts on the page
 
 # LOCALIZATION NOTE (table.emptyText):
 # This string is displayed when there are no rows in the Storage Table for the
@@ -54,21 +57,30 @@ tree.labels.indexedDB=Indexed DB
 # LOCALIZATION NOTE (table.headers.*.*):
 # These strings are the header names of the columns in the Storage Table for
 # each type of storage available through the Storage Tree to the side.
 table.headers.cookies.name=Name
 table.headers.cookies.path=Path
 table.headers.cookies.host=Domain
 table.headers.cookies.expires=Expires on
 table.headers.cookies.value=Value
-table.headers.cookies.lastAccessed:Last accessed on
-table.headers.cookies.creationTime:Created on
-table.headers.cookies.isHttpOnly:isHttpOnly
-table.headers.cookies.isSecure:isSecure
-table.headers.cookies.isDomain:isDomain
+table.headers.cookies.lastAccessed=Last accessed on
+table.headers.cookies.creationTime=Created on
+# LOCALIZATION NOTE (table.headers.cookies.isHttpOnly):
+# This string is used in the header for the column which denotes whether a
+# cookie is HTTP only or not.
+table.headers.cookies.isHttpOnly=isHttpOnly
+# LOCALIZATION NOTE (table.headers.cookies.isSecure):
+# This string is used in the header for the column which denotes whether a
+# cookie can be accessed via a secure channel only or not.
+table.headers.cookies.isSecure=isSecure
+# LOCALIZATION NOTE (table.headers.cookies.isDomain):
+# This string is used in the header for the column which denotes whether a
+# cookie is a domain cookie only or not.
+table.headers.cookies.isDomain=isDomain
 
 table.headers.localStorage.name=Key
 table.headers.localStorage.value=Value
 
 table.headers.sessionStorage.name=Key
 table.headers.sessionStorage.value=Value
 
 table.headers.indexedDB.name=Key
deleted file mode 100644
--- a/dom/settings/SettingsQueue.jsm
+++ /dev/null
@@ -1,30 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-this.EXPORTED_SYMBOLS = ["Queue"];
-
-this.Queue = function Queue() {
-  this._queue = [];
-  this._index = 0;
-}
-
-Queue.prototype = {
-  getLength: function() { return (this._queue.length - this._index); },
-
-  isEmpty: function() { return (this._queue.length == 0); },
-
-  enqueue: function(item) { this._queue.push(item); },
-
-  dequeue: function() {
-    if(this.isEmpty())
-      return undefined;
-
-    var item = this._queue[this._index];
-    if (++this._index * 2 >= this._queue.length){
-      this._queue  = this._queue.slice(this._index);
-      this._index = 0;
-    }
-    return item;
-  }
-}
--- a/gfx/thebes/gfxPrefs.h
+++ b/gfx/thebes/gfxPrefs.h
@@ -191,16 +191,21 @@ private:
   DECL_GFX_PREF(Live, "gfx.layerscope.port",                   LayerScopePort, int32_t, 23456);
   DECL_GFX_PREF(Live, "gfx.perf-warnings.enabled",             PerfWarnings, bool, false);
   DECL_GFX_PREF(Once, "gfx.work-around-driver-bugs",           WorkAroundDriverBugs, bool, true);
 
   DECL_GFX_PREF(Live, "gfx.draw-color-bars",                   CompositorDrawColorBars, bool, false);
 
   // Use vsync events generated by hardware
   DECL_GFX_PREF(Once, "gfx.frameuniformity.hw-vsync",          FrameUniformityHWVsyncEnabled, bool, false);
+  DECL_GFX_PREF(Once, "gfx.touch.resample",                    TouchResampling, bool, false);
+  // These times should be in nanoseconds
+  DECL_GFX_PREF(Once, "gfx.touch.resample.max-predict",        TouchResampleMaxPredict, int32_t, 8000000);
+  DECL_GFX_PREF(Once, "gfx.touch.resample.vsync-adjust",       TouchVsyncSampleAdjust, int32_t, 5000000);
+  DECL_GFX_PREF(Once, "gfx.touch.resample.min-resample",       TouchResampleMinTime, int32_t, 2000000);
 
   DECL_GFX_PREF(Live, "gl.msaa-level",                         MSAALevel, uint32_t, 2);
 
   DECL_GFX_PREF(Once, "layers.acceleration.disabled",          LayersAccelerationDisabled, bool, false);
   DECL_GFX_PREF(Live, "layers.acceleration.draw-fps",          LayersDrawFPS, bool, false);
   DECL_GFX_PREF(Live, "layers.acceleration.draw-fps.print-histogram",  FPSPrintHistogram, bool, false);
   DECL_GFX_PREF(Live, "layers.acceleration.draw-fps.write-to-file", WriteFPSToFile, bool, false);
   DECL_GFX_PREF(Once, "layers.acceleration.force-enabled",     LayersAccelerationForceEnabled, bool, false);
--- a/toolkit/components/places/tests/bookmarks/test_bookmarks.js
+++ b/toolkit/components/places/tests/bookmarks/test_bookmarks.js
@@ -21,19 +21,19 @@ let bookmarksObserver = {
     this._itemAddedId = id;
     this._itemAddedParent = folder;
     this._itemAddedIndex = index;
     this._itemAddedURI = uri;
     this._itemAddedTitle = title;
 
     // Ensure that we've created a guid for this item.
     let stmt = DBConn().createStatement(
-      "SELECT guid "
-    + "FROM moz_bookmarks "
-    + "WHERE id = :item_id "
+      `SELECT guid
+       FROM moz_bookmarks
+       WHERE id = :item_id`
     );
     stmt.params.item_id = id;
     do_check_true(stmt.executeStep());
     do_check_false(stmt.getIsNull(0));
     do_check_valid_places_guid(stmt.row.guid);
     do_check_eq(stmt.row.guid, guid);
     stmt.finalize();
   },
--- a/toolkit/components/places/tests/bookmarks/test_keywords.js
+++ b/toolkit/components/places/tests/bookmarks/test_keywords.js
@@ -23,31 +23,31 @@ function check_uri_keyword(aURI, aKeywor
     url = PlacesUtils.bookmarks.getURIForKeyword(aKeyword.toUpperCase()).spec
     do_check_true(re.test(url));
   }
 }
 
 function check_orphans()
 {
   stmt = DBConn().createStatement(
-    "SELECT id FROM moz_keywords k WHERE NOT EXISTS ("
-  +    "SELECT id FROM moz_bookmarks WHERE keyword_id = k.id "
-  + ")"
+    `SELECT id FROM moz_keywords k WHERE NOT EXISTS (
+        SELECT id FROM moz_bookmarks WHERE keyword_id = k.id
+     )`
   );
   try {
     do_check_false(stmt.executeStep());
   } finally {
     stmt.finalize();
   }
 
   print("Check there are no orphan database entries");
   let stmt = DBConn().createStatement(
-    "SELECT b.id FROM moz_bookmarks b "
-  + "LEFT JOIN moz_keywords k ON b.keyword_id = k.id "
-  + "WHERE keyword_id NOTNULL AND k.id ISNULL"
+    `SELECT b.id FROM moz_bookmarks b
+     LEFT JOIN moz_keywords k ON b.keyword_id = k.id
+     WHERE keyword_id NOTNULL AND k.id ISNULL`
   );
   try {
     do_check_false(stmt.executeStep());
   } finally {
     stmt.finalize();
   }
 }
 
--- a/toolkit/components/places/tests/browser/browser_settitle.js
+++ b/toolkit/components/places/tests/browser/browser_settitle.js
@@ -29,18 +29,18 @@ function load(href, callback)
 var conn = PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase).DBConnection;
 
 /**
  * Gets a single column value from either the places or historyvisits table.
  */
 function getColumn(table, column, fromColumnName, fromColumnValue)
 {
   var stmt = conn.createStatement(
-    "SELECT " + column + " FROM " + table + " WHERE " + fromColumnName + "=:val " +
-    "LIMIT 1");
+    `SELECT ${column} FROM ${table} WHERE ${fromColumnName} = :val
+     LIMIT 1`);
   try {
     stmt.params.val = fromColumnValue;
     stmt.executeStep();
     return stmt.row[column];
   }
   finally {
     stmt.finalize();
   }
--- a/toolkit/components/places/tests/browser/browser_visituri.js
+++ b/toolkit/components/places/tests/browser/browser_visituri.js
@@ -43,20 +43,20 @@ function waitForLoad(callback)
 
 var conn = PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase).DBConnection;
 
 /**
  * Gets a single column value from either the places or historyvisits table.
  */
 function getColumn(table, column, fromColumnName, fromColumnValue)
 {
-  let sql = "SELECT " + column + " " +
-            "FROM " + table + " " +
-            "WHERE " + fromColumnName + " = :val " +
-            "LIMIT 1";
+  let sql = `SELECT ${column}
+             FROM ${table}
+             WHERE ${fromColumnName} = :val
+             LIMIT 1`;
   let stmt = conn.createStatement(sql);
   try {
     stmt.params.val = fromColumnValue;
     ok(stmt.executeStep(), "Expect to get a row");
     return stmt.row[column];
   }
   finally {
     stmt.reset();
--- a/toolkit/components/places/tests/browser/head.js
+++ b/toolkit/components/places/tests/browser/head.js
@@ -97,17 +97,17 @@ function promiseAsyncUpdates()
  * param aCallback
  *        Callback function that will get the property value.
  */
 function fieldForUrl(aURI, aFieldName, aCallback)
 {
   let url = aURI instanceof Ci.nsIURI ? aURI.spec : aURI;
   let stmt = PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase)
                                 .DBConnection.createAsyncStatement(
-    "SELECT " + aFieldName + " FROM moz_places WHERE url = :page_url"
+    `SELECT ${aFieldName} FROM moz_places WHERE url = :page_url`
   );
   stmt.params.page_url = url;
   stmt.executeAsync({
     _value: -1,
     handleResult: function(aResultSet) {
       let row = aResultSet.getNextRow();
       if (!row)
         ok(false, "The page should exist in the database");
@@ -346,19 +346,19 @@ function checkGuidForURI(aURI, aGUID) {
  * Retrieves the guid for a given uri.
  *
  * @param aURI
  *        The uri to check.
  * @return the associated the guid.
  */
 function doGetGuidForURI(aURI) {
   let stmt = DBConn().createStatement(
-    "SELECT guid "
-    + "FROM moz_places "
-    + "WHERE url = :url "
+    `SELECT guid
+       FROM moz_places
+       WHERE url = :url`
   );
   stmt.params.url = aURI.spec;
   ok(stmt.executeStep(), "Check get guid for uri from moz_places");
   let guid = stmt.row.guid;
   stmt.finalize();
   doCheckValidPlacesGuid(guid);
   return guid;
 }
--- a/toolkit/components/places/tests/expiration/test_annos_expire_session.js
+++ b/toolkit/components/places/tests/expiration/test_annos_expire_session.js
@@ -49,19 +49,19 @@ add_task(function test_annos_expire_sess
   let items = as.getItemsWithAnnotation("test1");
   do_check_eq(items.length, 10);
   items = as.getItemsWithAnnotation("test2");
   do_check_eq(items.length, 10);
 
   let deferred = Promise.defer();
   waitForConnectionClosed(function() {
     let stmt = DBConn(true).createAsyncStatement(
-      "SELECT id FROM moz_annos "
-    + "UNION ALL "
-    + "SELECT id FROM moz_items_annos "
+      `SELECT id FROM moz_annos
+       UNION ALL
+       SELECT id FROM moz_items_annos`
     );
     stmt.executeAsync({
       handleResult: function(aResultSet) {
         dump_table("moz_annos");
         dump_table("moz_items_annos");
         do_throw("Should not find any leftover session annotations");
       },
       handleError: function(aError) {
--- a/toolkit/components/places/tests/head_common.js
+++ b/toolkit/components/places/tests/head_common.js
@@ -307,19 +307,19 @@ function page_in_database(aURI)
  * @param aURI
  *        nsIURI or address to look for.
  * @return number of visits found.
  */
 function visits_in_database(aURI)
 {
   let url = aURI instanceof Ci.nsIURI ? aURI.spec : aURI;
   let stmt = DBConn().createStatement(
-    "SELECT count(*) FROM moz_historyvisits v "
-  + "JOIN moz_places h ON h.id = v.place_id "
-  + "WHERE url = :url"
+    `SELECT count(*) FROM moz_historyvisits v
+     JOIN moz_places h ON h.id = v.place_id
+     WHERE url = :url`
   );
   stmt.params.url = url;
   try {
     if (!stmt.executeStep())
       return 0;
     return stmt.getInt64(0);
   }
   finally {
@@ -684,19 +684,19 @@ function do_check_valid_places_guid(aGui
  */
 function do_get_guid_for_uri(aURI,
                              aStack)
 {
   if (!aStack) {
     aStack = Components.stack.caller;
   }
   let stmt = DBConn().createStatement(
-    "SELECT guid "
-  + "FROM moz_places "
-  + "WHERE url = :url "
+    `SELECT guid
+     FROM moz_places
+     WHERE url = :url`
   );
   stmt.params.url = aURI.spec;
   do_check_true(stmt.executeStep(), aStack);
   let guid = stmt.row.guid;
   stmt.finalize();
   do_check_valid_places_guid(guid, aStack);
   return guid;
 }
@@ -731,19 +731,19 @@ function do_check_guid_for_uri(aURI,
  */
 function do_get_guid_for_bookmark(aId,
                                   aStack)
 {
   if (!aStack) {
     aStack = Components.stack.caller;
   }
   let stmt = DBConn().createStatement(
-    "SELECT guid "
-  + "FROM moz_bookmarks "
-  + "WHERE id = :item_id "
+    `SELECT guid
+     FROM moz_bookmarks
+     WHERE id = :item_id`
   );
   stmt.params.item_id = aId;
   do_check_true(stmt.executeStep(), aStack);
   let guid = stmt.row.guid;
   stmt.finalize();
   do_check_valid_places_guid(guid, aStack);
   return guid;
 }
--- a/toolkit/components/places/tests/migration/test_current_from_v10.js
+++ b/toolkit/components/places/tests/migration/test_current_from_v10.js
@@ -52,42 +52,42 @@ function test_initial_state()
   do_check_neq(stmt.getString(0).toLowerCase(), "wal");
   stmt.finalize();
 
   do_check_false(db.indexExists("moz_bookmarks_guid_uniqueindex"));
   do_check_false(db.indexExists("moz_places_guid_uniqueindex"));
 
   // There should be five item annotations for a bookmark guid.
   stmt = db.createStatement(
-    "SELECT content AS guid, item_id "
-  + "FROM moz_items_annos "
-  + "WHERE anno_attribute_id = ( "
-  +   "SELECT id "
-  +   "FROM moz_anno_attributes "
-  +   "WHERE name = :attr_name "
-  + ") "
+    `SELECT content AS guid, item_id
+     FROM moz_items_annos
+     WHERE anno_attribute_id = (
+       SELECT id
+       FROM moz_anno_attributes
+       WHERE name = :attr_name
+     )`
   );
   stmt.params.attr_name = kGuidAnnotationName;
   while (stmt.executeStep()) {
     gItemGuid.push(stmt.row.guid);
     gItemId.push(stmt.row.item_id)
   }
   do_check_eq(gItemGuid.length, gItemId.length);
   do_check_eq(gItemGuid.length, kExpectedAnnotations);
   stmt.finalize();
 
   // There should be five item annotations for a place guid.
   stmt = db.createStatement(
-    "SELECT content AS guid, place_id "
-  + "FROM moz_annos "
-  + "WHERE anno_attribute_id = ( "
-  +   "SELECT id "
-  +   "FROM moz_anno_attributes "
-  +   "WHERE name = :attr_name "
-  + ") "
+    `SELECT content AS guid, place_id
+     FROM moz_annos
+     WHERE anno_attribute_id = (
+       SELECT id
+       FROM moz_anno_attributes
+       WHERE name = :attr_name
+     )`
   );
   stmt.params.attr_name = kGuidAnnotationName;
   while (stmt.executeStep()) {
     gPlaceGuid.push(stmt.row.guid);
     gPlaceId.push(stmt.row.place_id)
   }
   do_check_eq(gPlaceGuid.length, gPlaceId.length);
   do_check_eq(gPlaceGuid.length, kExpectedAnnotations);
@@ -99,54 +99,54 @@ function test_initial_state()
   db.close();
   run_next_test();
 }
 
 function test_moz_bookmarks_guid_exists()
 {
   // This will throw if the column does not exist
   let stmt = DBConn().createStatement(
-    "SELECT guid "
-  + "FROM moz_bookmarks "
+    `SELECT guid
+     FROM moz_bookmarks`
   );
   stmt.finalize();
 
   run_next_test();
 }
 
 function test_bookmark_guids_non_null()
 {
   // First, sanity check that we have a non-zero amount of bookmarks.
   let stmt = DBConn().createStatement(
-    "SELECT COUNT(1) "
-  + "FROM moz_bookmarks "
+    `SELECT COUNT(1)
+     FROM moz_bookmarks`
   );
   do_check_true(stmt.executeStep());
   do_check_neq(stmt.getInt32(0), 0);
   stmt.finalize();
 
   // Now, make sure we have no NULL guid entry.
   stmt = DBConn().createStatement(
-    "SELECT guid "
-  + "FROM moz_bookmarks "
-  + "WHERE guid IS NULL "
+    `SELECT guid
+     FROM moz_bookmarks
+     WHERE guid IS NULL`
   );
   do_check_false(stmt.executeStep());
   stmt.finalize();
   run_next_test();
 }
 
 function test_bookmark_guid_annotation_imported()
 {
   // Make sure we have the imported guid; not a newly generated one.
   let stmt = DBConn().createStatement(
-    "SELECT id "
-  + "FROM moz_bookmarks "
-  + "WHERE guid = :guid "
-  + "AND id = :item_id "
+    `SELECT id
+     FROM moz_bookmarks
+     WHERE guid = :guid
+     AND id = :item_id`
   );
   let validGuids = 0;
   let seenGuids = [];
   for (let i = 0; i < gItemGuid.length; i++) {
     let guid = gItemGuid[i];
     stmt.params.guid = guid;
     stmt.params.item_id = gItemId[i];
 
@@ -168,74 +168,74 @@ function test_bookmark_guid_annotation_i
   stmt.finalize();
 
   run_next_test();
 }
 
 function test_bookmark_guid_annotation_removed()
 {
   let stmt = DBConn().createStatement(
-    "SELECT COUNT(1) "
-  + "FROM moz_items_annos "
-  + "WHERE anno_attribute_id = ( "
-  +   "SELECT id "
-  +   "FROM moz_anno_attributes "
-  +   "WHERE name = :attr_name "
-  + ") "
+    `SELECT COUNT(1)
+     FROM moz_items_annos
+     WHERE anno_attribute_id = (
+       SELECT id
+       FROM moz_anno_attributes
+       WHERE name = :attr_name
+     )`
   );
   stmt.params.attr_name = kGuidAnnotationName;
   do_check_true(stmt.executeStep());
   do_check_eq(stmt.getInt32(0), 0);
   stmt.finalize();
 
   run_next_test();
 }
 
 function test_moz_places_guid_exists()
 {
   // This will throw if the column does not exist
   let stmt = DBConn().createStatement(
-    "SELECT guid "
-  + "FROM moz_places "
+    `SELECT guid
+     FROM moz_places`
   );
   stmt.finalize();
 
   run_next_test();
 }
 
 function test_place_guids_non_null()
 {
   // First, sanity check that we have a non-zero amount of places.
   let stmt = DBConn().createStatement(
-    "SELECT COUNT(1) "
-  + "FROM moz_places "
+    `SELECT COUNT(1)
+     FROM moz_places`
   );
   do_check_true(stmt.executeStep());
   do_check_neq(stmt.getInt32(0), 0);
   stmt.finalize();
 
   // Now, make sure we have no NULL guid entry.
   stmt = DBConn().createStatement(
-    "SELECT guid "
-  + "FROM moz_places "
-  + "WHERE guid IS NULL "
+    `SELECT guid
+     FROM moz_places
+     WHERE guid IS NULL`
   );
   do_check_false(stmt.executeStep());
   stmt.finalize();
   run_next_test();
 }
 
 function test_place_guid_annotation_imported()
 {
   // Make sure we have the imported guid; not a newly generated one.
   let stmt = DBConn().createStatement(
-    "SELECT id "
-  + "FROM moz_places "
-  + "WHERE guid = :guid "
-  + "AND id = :item_id "
+    `SELECT id
+     FROM moz_places
+     WHERE guid = :guid
+     AND id = :item_id`
   );
   let validGuids = 0;
   let seenGuids = [];
   for (let i = 0; i < gPlaceGuid.length; i++) {
     let guid = gPlaceGuid[i];
     stmt.params.guid = guid;
     stmt.params.item_id = gPlaceId[i];
 
@@ -257,50 +257,50 @@ function test_place_guid_annotation_impo
   stmt.finalize();
 
   run_next_test();
 }
 
 function test_place_guid_annotation_removed()
 {
   let stmt = DBConn().createStatement(
-    "SELECT COUNT(1) "
-  + "FROM moz_annos "
-  + "WHERE anno_attribute_id = ( "
-  +   "SELECT id "
-  +   "FROM moz_anno_attributes "
-  +   "WHERE name = :attr_name "
-  + ") "
+    `SELECT COUNT(1)
+     FROM moz_annos
+     WHERE anno_attribute_id = (
+       SELECT id
+       FROM moz_anno_attributes
+       WHERE name = :attr_name
+     )`
   );
   stmt.params.attr_name = kGuidAnnotationName;
   do_check_true(stmt.executeStep());
   do_check_eq(stmt.getInt32(0), 0);
   stmt.finalize();
 
   run_next_test();
 }
 
 function test_moz_hosts()
 {
   // This will throw if the column does not exist
   let stmt = DBConn().createStatement(
-    "SELECT host, frecency, typed, prefix "
-  + "FROM moz_hosts "
+    `SELECT host, frecency, typed, prefix
+     FROM moz_hosts`
   );
   stmt.finalize();
 
   // moz_hosts is populated asynchronously, so query asynchronously to serialize
   // to that.
   // check the number of entries in moz_hosts equals the number of
   // unique rev_host in moz_places
   stmt = DBConn().createAsyncStatement(
-    "SELECT (SELECT COUNT(host) FROM moz_hosts), " +
-           "(SELECT COUNT(DISTINCT rev_host) " +
-            "FROM moz_places " +
-            "WHERE LENGTH(rev_host) > 1)");
+    `SELECT (SELECT COUNT(host) FROM moz_hosts),
+            (SELECT COUNT(DISTINCT rev_host)
+             FROM moz_places
+             WHERE LENGTH(rev_host) > 1)`);
   try {
     stmt.executeAsync({
       handleResult: function (aResult) {
         this._hasResults = true;
         let row = aResult.getNextRow();
         let mozHostsCount = row.getResultByIndex(0);
         let mozPlacesCount = row.getResultByIndex(1);
         do_check_true(mozPlacesCount > 0);
--- a/toolkit/components/places/tests/migration/test_current_from_v10_migrated_from_v14.js
+++ b/toolkit/components/places/tests/migration/test_current_from_v10_migrated_from_v14.js
@@ -25,29 +25,29 @@ function test_initial_state()
   do_check_neq(stmt.getString(0).toLowerCase(), "wal");
   stmt.finalize();
 
   do_check_true(db.indexExists("moz_bookmarks_guid_uniqueindex"));
   do_check_true(db.indexExists("moz_places_guid_uniqueindex"));
 
   // There should be a non-zero amount of bookmarks without a guid.
   stmt = db.createStatement(
-    "SELECT COUNT(1) "
-  + "FROM moz_bookmarks "
-  + "WHERE guid IS NULL "
+    `SELECT COUNT(1)
+     FROM moz_bookmarks
+     WHERE guid IS NULL`
   );
   do_check_true(stmt.executeStep());
   do_check_neq(stmt.getInt32(0), 0);
   stmt.finalize();
 
   // There should be a non-zero amount of places without a guid.
   stmt = db.createStatement(
-    "SELECT COUNT(1) "
-  + "FROM moz_places "
-  + "WHERE guid IS NULL "
+    `SELECT COUNT(1)
+     FROM moz_places
+     WHERE guid IS NULL`
   );
   do_check_true(stmt.executeStep());
   do_check_neq(stmt.getInt32(0), 0);
   stmt.finalize();
 
   // Check our schema version to make sure it is actually at 10.
   do_check_eq(db.schemaVersion, 10);
 
@@ -55,51 +55,51 @@ function test_initial_state()
   run_next_test();
 }
 
 function test_bookmark_guids_non_null()
 {
   // First, sanity check that we have a non-zero amount of bookmarks.  If
   // migration failed, we would have zero.
   let stmt = DBConn().createStatement(
-    "SELECT COUNT(1) "
-  + "FROM moz_bookmarks "
+    `SELECT COUNT(1)
+     FROM moz_bookmarks`
   );
   do_check_true(stmt.executeStep());
   do_check_neq(stmt.getInt32(0), 0);
   stmt.finalize();
 
   // Now, make sure we have no NULL guid entries.
   stmt = DBConn().createStatement(
-    "SELECT guid "
-  + "FROM moz_bookmarks "
-  + "WHERE guid IS NULL "
+    `SELECT guid
+     FROM moz_bookmarks
+     WHERE guid IS NULL`
   );
   do_check_false(stmt.executeStep());
   stmt.finalize();
   run_next_test();
 }
 
 function test_place_guids_non_null()
 {
   // First, sanity check that we have a non-zero amount of places.  If migration
   // failed, we would have zero.
   let stmt = DBConn().createStatement(
-    "SELECT COUNT(1) "
-  + "FROM moz_places "
+    `SELECT COUNT(1)
+     FROM moz_places`
   );
   do_check_true(stmt.executeStep());
   do_check_neq(stmt.getInt32(0), 0);
   stmt.finalize();
 
   // Now, make sure we have no NULL guid entry.
   stmt = DBConn().createStatement(
-    "SELECT guid "
-  + "FROM moz_places "
-  + "WHERE guid IS NULL "
+    `SELECT guid
+     FROM moz_places
+     WHERE guid IS NULL`
   );
   do_check_false(stmt.executeStep());
   stmt.finalize();
   run_next_test();
 }
 
 function test_final_state()
 {
--- a/toolkit/components/places/tests/migration/test_current_from_v19.js
+++ b/toolkit/components/places/tests/migration/test_current_from_v19.js
@@ -8,20 +8,20 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 //// Globals
 
 const kGuidAnnotationName = "placesInternal/GUID";
 
 function getTotalGuidAnnotationsCount(aStorageConnection) {
   stmt = aStorageConnection.createStatement(
-    "SELECT count(*) "
-  + "FROM moz_items_annos a "
-  + "JOIN moz_anno_attributes b ON a.anno_attribute_id = b.id "
-  + "WHERE b.name = :attr_name"
+    `SELECT count(*)
+     FROM moz_items_annos a
+     JOIN moz_anno_attributes b ON a.anno_attribute_id = b.id
+     WHERE b.name = :attr_name`
   );
   try {
     stmt.params.attr_name = kGuidAnnotationName;
     do_check_true(stmt.executeStep());
     return stmt.getInt32(0);
   } finally {
     stmt.finalize();
   }
--- a/toolkit/components/places/tests/mochitest/bug_411966/redirect.js
+++ b/toolkit/components/places/tests/mochitest/bug_411966/redirect.js
@@ -112,22 +112,22 @@ function checkDB(data){
   var referrer = this.mChannel.QueryInterface(Ci.nsIHttpChannel).referrer;
 
   addVisits(
     {uri: this.mChannel.URI,
       transition: Ci.nsINavHistoryService.TRANSITION_REDIRECT_PERMANENT,
       referrer: referrer},
     function() {
       // Get all pages visited from the original typed one
-      var sql = "SELECT url FROM moz_historyvisits " +
-                "JOIN moz_places h ON h.id = place_id " +
-                "WHERE from_visit IN " +
-                   "(SELECT v.id FROM moz_historyvisits v " +
-                   "JOIN moz_places p ON p.id = v.place_id " +
-                   "WHERE p.url = ?1)";
+      var sql = `SELECT url FROM moz_historyvisits
+                 JOIN moz_places h ON h.id = place_id
+                 WHERE from_visit IN
+                    (SELECT v.id FROM moz_historyvisits v
+                    JOIN moz_places p ON p.id = v.place_id
+                    WHERE p.url = ?1)`;
       var stmt = mDBConn.createStatement(sql);
       stmt.bindByIndex(0, typedURI.spec);
 
       var empty = true;
       while (stmt.executeStep()) {
         empty = false;
         var visitedURI = stmt.getUTF8String(0);
         // Check that redirect from_visit is not from the original typed one
--- a/toolkit/components/places/tests/unit/test_async_history_api.js
+++ b/toolkit/components/places/tests/unit/test_async_history_api.js
@@ -130,19 +130,19 @@ VisitObserver.prototype = {
  * @param aTitle
  *        The expected title in the database.
  */
 function do_check_title_for_uri(aURI,
                                 aTitle)
 {
   let stack = Components.stack.caller;
   let stmt = DBConn().createStatement(
-    "SELECT title " +
-    "FROM moz_places " +
-    "WHERE url = :url "
+    `SELECT title
+     FROM moz_places
+     WHERE url = :url`
   );
   stmt.params.url = aURI.spec;
   do_check_true(stmt.executeStep(), stack);
   do_check_eq(stmt.row.title, aTitle, stack);
   stmt.finalize();
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -465,19 +465,19 @@ function test_invalid_referrerURI_ignore
   let placeInfo = placesResult.results[0];
   do_check_true(yield promiseIsURIVisited(placeInfo.uri));
 
   // Check to make sure we do not visit the invalid referrer.
   do_check_false(yield promiseIsURIVisited(place.visits[0].referrerURI));
 
   // Check to make sure from_visit is zero in database.
   let stmt = DBConn().createStatement(
-    "SELECT from_visit " +
-    "FROM moz_historyvisits " +
-    "WHERE id = :visit_id"
+    `SELECT from_visit
+     FROM moz_historyvisits
+     WHERE id = :visit_id`
   );
   stmt.params.visit_id = placeInfo.visits[0].visitId;
   do_check_true(stmt.executeStep());
   do_check_eq(stmt.row.from_visit, 0);
   stmt.finalize();
 
   yield promiseAsyncUpdates();
 }
@@ -498,19 +498,19 @@ function test_nonnsIURI_referrerURI_igno
   if (placesResult.errors.length > 0) {
     do_throw("Unexpected error.");
   }
   let placeInfo = placesResult.results[0];
   do_check_true(yield promiseIsURIVisited(placeInfo.uri));
 
   // Check to make sure from_visit is zero in database.
   let stmt = DBConn().createStatement(
-    "SELECT from_visit " +
-    "FROM moz_historyvisits " +
-    "WHERE id = :visit_id"
+    `SELECT from_visit
+     FROM moz_historyvisits
+     WHERE id = :visit_id`
   );
   stmt.params.visit_id = placeInfo.visits[0].visitId;
   do_check_true(stmt.executeStep());
   do_check_eq(stmt.row.from_visit, 0);
   stmt.finalize();
 
   yield promiseAsyncUpdates();
 }
@@ -557,20 +557,20 @@ function test_old_referrer_ignored()
   }
   let placeInfo = placesResult.results[0];
   do_check_true(yield promiseIsURIVisited(place.uri));
 
   // Though the visit will not contain the referrer, we must examine the
   // database to be sure.
   do_check_eq(placeInfo.visits[0].referrerURI, null);
   let stmt = DBConn().createStatement(
-    "SELECT COUNT(1) AS count " +
-    "FROM moz_historyvisits " +
-    "WHERE place_id = (SELECT id FROM moz_places WHERE url = :page_url) " +
-    "AND from_visit = 0 "
+    `SELECT COUNT(1) AS count
+     FROM moz_historyvisits
+     WHERE place_id = (SELECT id FROM moz_places WHERE url = :page_url)
+     AND from_visit = 0`
   );
   stmt.params.page_url = place.uri.spec;
   do_check_true(stmt.executeStep());
   do_check_eq(stmt.row.count, 1);
   stmt.finalize();
 
   yield promiseAsyncUpdates();
 }
@@ -753,50 +753,50 @@ function test_properties_saved()
     print("TEST-INFO | test_properties_saved | updatePlaces callback for " +
           "transition type " + visit.transitionType);
 
     // Note that TRANSITION_EMBED should not be in the database.
     const EXPECTED_COUNT = visit.transitionType == TRANSITION_EMBED ? 0 : 1;
 
     // mozIVisitInfo::date
     let stmt = DBConn().createStatement(
-      "SELECT COUNT(1) AS count " +
-      "FROM moz_places h " +
-      "JOIN moz_historyvisits v " +
-      "ON h.id = v.place_id " +
-      "WHERE h.url = :page_url " +
-      "AND v.visit_date = :visit_date "
+      `SELECT COUNT(1) AS count
+       FROM moz_places h
+       JOIN moz_historyvisits v
+       ON h.id = v.place_id
+       WHERE h.url = :page_url
+       AND v.visit_date = :visit_date`
     );
     stmt.params.page_url = uri.spec;
     stmt.params.visit_date = visit.visitDate;
     do_check_true(stmt.executeStep());
     do_check_eq(stmt.row.count, EXPECTED_COUNT);
     stmt.finalize();
 
     // mozIVisitInfo::transitionType
     stmt = DBConn().createStatement(
-      "SELECT COUNT(1) AS count " +
-      "FROM moz_places h " +
-      "JOIN moz_historyvisits v " +
-      "ON h.id = v.place_id " +
-      "WHERE h.url = :page_url " +
-      "AND v.visit_type = :transition_type "
+      `SELECT COUNT(1) AS count
+       FROM moz_places h
+       JOIN moz_historyvisits v
+       ON h.id = v.place_id
+       WHERE h.url = :page_url
+       AND v.visit_type = :transition_type`
     );
     stmt.params.page_url = uri.spec;
     stmt.params.transition_type = visit.transitionType;
     do_check_true(stmt.executeStep());
     do_check_eq(stmt.row.count, EXPECTED_COUNT);
     stmt.finalize();
 
     // mozIPlaceInfo::title
     stmt = DBConn().createStatement(
-      "SELECT COUNT(1) AS count " +
-      "FROM moz_places h " +
-      "WHERE h.url = :page_url " +
-      "AND h.title = :title "
+      `SELECT COUNT(1) AS count
+       FROM moz_places h
+       WHERE h.url = :page_url
+       AND h.title = :title`
     );
     stmt.params.page_url = uri.spec;
     stmt.params.title = placeInfo.title;
     do_check_true(stmt.executeStep());
     do_check_eq(stmt.row.count, EXPECTED_COUNT);
     stmt.finalize();
 
     // If we have had all of our callbacks, continue running tests.
@@ -858,24 +858,24 @@ function test_referrer_saved()
     do_check_true(yield promiseIsURIVisited(uri));
     let visit = placeInfo.visits[0];
 
     // We need to insert all of our visits before we can test conditions.
     if (++resultCount == places.length) {
       do_check_true(places[0].uri.equals(visit.referrerURI));
 
       let stmt = DBConn().createStatement(
-        "SELECT COUNT(1) AS count " +
-        "FROM moz_historyvisits " +
-        "WHERE place_id = (SELECT id FROM moz_places WHERE url = :page_url) " +
-        "AND from_visit = ( " +
-          "SELECT id " +
-          "FROM moz_historyvisits " +
-          "WHERE place_id = (SELECT id FROM moz_places WHERE url = :referrer) " +
-        ") "
+        `SELECT COUNT(1) AS count
+         FROM moz_historyvisits
+         WHERE place_id = (SELECT id FROM moz_places WHERE url = :page_url)
+         AND from_visit = (
+           SELECT id
+           FROM moz_historyvisits
+           WHERE place_id = (SELECT id FROM moz_places WHERE url = :referrer)
+         )`
       );
       stmt.params.page_url = uri.spec;
       stmt.params.referrer = visit.referrerURI.spec;
       do_check_true(stmt.executeStep());
       do_check_eq(stmt.row.count, 1);
       stmt.finalize();
 
       yield promiseAsyncUpdates();
--- a/toolkit/components/places/tests/unit/test_history_removeAllPages.js
+++ b/toolkit/components/places/tests/unit/test_history_removeAllPages.js
@@ -108,18 +108,18 @@ add_task(function test_history_removeAll
   // to -MAX(visit_count, 1), so we will be able to recalculate frecency
   // starting from most frecent bookmarks.
   stmt = mDBConn.createStatement(
     "SELECT h.id FROM moz_places h WHERE h.frecency > 0 ");
   do_check_false(stmt.executeStep());
   stmt.finalize();
 
   stmt = mDBConn.createStatement(
-    "SELECT h.id FROM moz_places h WHERE h.frecency < 0 " +
-      "AND EXISTS (SELECT id FROM moz_bookmarks WHERE fk = h.id) LIMIT 1");
+    `SELECT h.id FROM moz_places h WHERE h.frecency < 0
+       AND EXISTS (SELECT id FROM moz_bookmarks WHERE fk = h.id) LIMIT 1`);
   do_check_true(stmt.executeStep());
   stmt.finalize();
 
   // Check that all visit_counts have been brought to 0
   stmt = mDBConn.createStatement(
     "SELECT id FROM moz_places WHERE visit_count <> 0 LIMIT 1");
   do_check_false(stmt.executeStep());
   stmt.finalize();
@@ -127,41 +127,41 @@ add_task(function test_history_removeAll
   // Check that history tables are empty
   stmt = mDBConn.createStatement(
     "SELECT * FROM (SELECT id FROM moz_historyvisits LIMIT 1)");
   do_check_false(stmt.executeStep());
   stmt.finalize();
 
   // Check that all moz_places entries except bookmarks and place: have been removed
   stmt = mDBConn.createStatement(
-    "SELECT h.id FROM moz_places h WHERE SUBSTR(h.url, 1, 6) <> 'place:' "+
-      "AND NOT EXISTS (SELECT id FROM moz_bookmarks WHERE fk = h.id) LIMIT 1");
+    `SELECT h.id FROM moz_places h WHERE SUBSTR(h.url, 1, 6) <> 'place:'
+       AND NOT EXISTS (SELECT id FROM moz_bookmarks WHERE fk = h.id) LIMIT 1`);
   do_check_false(stmt.executeStep());
   stmt.finalize();
 
   // Check that we only have favicons for retained places
   stmt = mDBConn.createStatement(
-    "SELECT f.id FROM moz_favicons f WHERE NOT EXISTS " +
-      "(SELECT id FROM moz_places WHERE favicon_id = f.id) LIMIT 1");
+    `SELECT f.id FROM moz_favicons f WHERE NOT EXISTS
+       (SELECT id FROM moz_places WHERE favicon_id = f.id) LIMIT 1`);
   do_check_false(stmt.executeStep());
   stmt.finalize();
 
   // Check that we only have annotations for retained places
   stmt = mDBConn.createStatement(
-    "SELECT a.id FROM moz_annos a WHERE NOT EXISTS " +
-      "(SELECT id FROM moz_places WHERE id = a.place_id) LIMIT 1");
+    `SELECT a.id FROM moz_annos a WHERE NOT EXISTS
+       (SELECT id FROM moz_places WHERE id = a.place_id) LIMIT 1`);
   do_check_false(stmt.executeStep());
   stmt.finalize();
 
   // Check that we only have inputhistory for retained places
   stmt = mDBConn.createStatement(
-    "SELECT i.place_id FROM moz_inputhistory i WHERE NOT EXISTS " +
-      "(SELECT id FROM moz_places WHERE id = i.place_id) LIMIT 1");
+    `SELECT i.place_id FROM moz_inputhistory i WHERE NOT EXISTS
+       (SELECT id FROM moz_places WHERE id = i.place_id) LIMIT 1`);
   do_check_false(stmt.executeStep());
   stmt.finalize();
 
   // Check that place:uris have frecency 0
   stmt = mDBConn.createStatement(
-    "SELECT h.id FROM moz_places h " +
-    "WHERE SUBSTR(h.url, 1, 6) = 'place:' AND h.frecency <> 0 LIMIT 1");
+    `SELECT h.id FROM moz_places h
+     WHERE SUBSTR(h.url, 1, 6) = 'place:' AND h.frecency <> 0 LIMIT 1`);
   do_check_false(stmt.executeStep());
   stmt.finalize();
 });
--- a/toolkit/components/places/tests/unit/test_hosts_triggers.js
+++ b/toolkit/components/places/tests/unit/test_hosts_triggers.js
@@ -11,39 +11,39 @@ XPCOMUtils.defineLazyServiceGetter(this,
 
 // add some visits and remove them, add a bookmark,
 // change its uri, then remove it, and
 // for each change check that moz_hosts has correctly been updated.
 
 function isHostInMozPlaces(aURI)
 {
   let stmt = DBConn().createStatement(
-    "SELECT url "
-    + "FROM moz_places "
-    + "WHERE url = :host"
+    `SELECT url
+       FROM moz_places
+       WHERE url = :host`
   );
   let result = false;
   stmt.params.host = aURI.spec;
   while(stmt.executeStep()) {
     if (stmt.row.url == aURI.spec) {
       result = true;
       break;
     }
   }
   stmt.finalize();
   return result;
 }
 
 function isHostInMozHosts(aURI, aTyped, aPrefix)
 {
   let stmt = DBConn().createStatement(
-    "SELECT host, typed, prefix "
-    + "FROM moz_hosts "
-    + "WHERE host = fixup_url(:host) "
-    + "AND frecency NOTNULL "
+    `SELECT host, typed, prefix
+       FROM moz_hosts
+       WHERE host = fixup_url(:host)
+       AND frecency NOTNULL`
   );
   let result = false;
   stmt.params.host = aURI.host;
   if (stmt.executeStep()) {
     result = aTyped == stmt.row.typed && aPrefix == stmt.row.prefix;
   }
   stmt.finalize();
   return result;
--- a/toolkit/components/places/tests/unit/test_preventive_maintenance.js
+++ b/toolkit/components/places/tests/unit/test_preventive_maintenance.js
@@ -47,20 +47,20 @@ function addPlace(aUrl, aFavicon) {
   stmt.params["favicon"] = aFavicon || null;
   stmt.execute();
   stmt.finalize();
   return mDBConn.lastInsertRowID;
 }
 
 function addBookmark(aPlaceId, aType, aParent, aKeywordId, aFolderType, aTitle) {
   let stmt = mDBConn.createStatement(
-    "INSERT INTO moz_bookmarks (fk, type, parent, keyword_id, folder_type, "
-  +                            "title, guid) "
-  + "VALUES (:place_id, :type, :parent, :keyword_id, :folder_type, :title, "
-  +         "GENERATE_GUID())");
+    `INSERT INTO moz_bookmarks (fk, type, parent, keyword_id, folder_type,
+                                title, guid)
+     VALUES (:place_id, :type, :parent, :keyword_id, :folder_type, :title,
+             GENERATE_GUID())`);
   stmt.params["place_id"] = aPlaceId || null;
   stmt.params["type"] = aType || bs.TYPE_BOOKMARK;
   stmt.params["parent"] = aParent || bs.unfiledBookmarksFolder;
   stmt.params["keyword_id"] = aKeywordId || null;
   stmt.params["folder_type"] = aFolderType || null;
   stmt.params["title"] = typeof(aTitle) == "string" ? aTitle : null;
   stmt.execute();
   stmt.finalize();
@@ -87,20 +87,20 @@ tests.push({
     // Add an obsolete attribute.
     let stmt = mDBConn.createStatement(
       "INSERT INTO moz_anno_attributes (name) VALUES (:anno)"
     );
     stmt.params['anno'] = this._obsoleteWeaveAttribute;
     stmt.execute();
     stmt.finalize();
     stmt = mDBConn.createStatement(
-      "INSERT INTO moz_annos (place_id, anno_attribute_id) "
-    + "VALUES (:place_id, "
-    +   "(SELECT id FROM moz_anno_attributes WHERE name = :anno)"
-    + ")"
+      `INSERT INTO moz_annos (place_id, anno_attribute_id)
+       VALUES (:place_id,
+         (SELECT id FROM moz_anno_attributes WHERE name = :anno)
+       )`
     );
     stmt.params['place_id'] = this._placeId;
     stmt.params['anno'] = this._obsoleteWeaveAttribute;
     stmt.execute();
     stmt.finalize();
   },
 
   check: function() {
@@ -126,43 +126,43 @@ tests.push({
 
   setup: function() {
     // Add a place to ensure place_id = 1 is valid.
     this._placeId = addPlace();
     // Add a bookmark.
     this._bookmarkId = addBookmark(this._placeId);
     // Add an obsolete attribute.
     let stmt = mDBConn.createStatement(
-      "INSERT INTO moz_anno_attributes (name) "
-    + "VALUES (:anno1), (:anno2), (:anno3)"
+      `INSERT INTO moz_anno_attributes (name)
+       VALUES (:anno1), (:anno2), (:anno3)`
     );
     stmt.params['anno1'] = this._obsoleteSyncAttribute;
     stmt.params['anno2'] = this._obsoleteGuidAttribute;
     stmt.params['anno3'] = this._obsoleteWeaveAttribute;
     stmt.execute();
     stmt.finalize();
     stmt = mDBConn.createStatement(
-      "INSERT INTO moz_items_annos (item_id, anno_attribute_id) "
-    + "SELECT :item_id, id "
-    + "FROM moz_anno_attributes "
-    + "WHERE name IN (:anno1, :anno2, :anno3)"
+      `INSERT INTO moz_items_annos (item_id, anno_attribute_id)
+       SELECT :item_id, id
+       FROM moz_anno_attributes
+       WHERE name IN (:anno1, :anno2, :anno3)`
     );
     stmt.params['item_id'] = this._bookmarkId;
     stmt.params['anno1'] = this._obsoleteSyncAttribute;
     stmt.params['anno2'] = this._obsoleteGuidAttribute;
     stmt.params['anno3'] = this._obsoleteWeaveAttribute;
     stmt.execute();
     stmt.finalize();
   },
 
   check: function() {
     // Check that the obsolete annotations have been removed.
     let stmt = mDBConn.createStatement(
-      "SELECT id FROM moz_anno_attributes "
-    + "WHERE name IN (:anno1, :anno2, :anno3)"
+      `SELECT id FROM moz_anno_attributes
+       WHERE name IN (:anno1, :anno2, :anno3)`
     );
     stmt.params['anno1'] = this._obsoleteSyncAttribute;
     stmt.params['anno2'] = this._obsoleteGuidAttribute;
     stmt.params['anno3'] = this._obsoleteWeaveAttribute;
     do_check_false(stmt.executeStep());
     stmt.finalize();
   }
 });
@@ -718,35 +718,35 @@ tests.push({
                             NetUtil.newURI("http://example.com/"),
                             bs.DEFAULT_INDEX, "testbookmark");
         }
       }
     }, null);
 
     function randomize_positions(aParent, aResultArray) {
       let stmt = mDBConn.createStatement(
-        "UPDATE moz_bookmarks SET position = :rand " +
-        "WHERE id IN ( " +
-          "SELECT id FROM moz_bookmarks WHERE parent = :parent " +
-          "ORDER BY RANDOM() LIMIT 1 " +
-        ") "
+        `UPDATE moz_bookmarks SET position = :rand
+         WHERE id IN (
+           SELECT id FROM moz_bookmarks WHERE parent = :parent
+           ORDER BY RANDOM() LIMIT 1
+         )`
       );
       for (let i = 0; i < (NUM_BOOKMARKS / 2); i++) {
         stmt.params["parent"] = aParent;
         stmt.params["rand"] = Math.round(Math.random() * (NUM_BOOKMARKS - 1));
         stmt.execute();
         stmt.reset();
       }
       stmt.finalize();
 
       // Build the expected ordered list of bookmarks.
       stmt = mDBConn.createStatement(
-        "SELECT id, position " +
-        "FROM moz_bookmarks WHERE parent = :parent " +
-        "ORDER BY position ASC, ROWID ASC "
+        `SELECT id, position
+         FROM moz_bookmarks WHERE parent = :parent
+         ORDER BY position ASC, ROWID ASC`
       );
       stmt.params["parent"] = aParent;
       while (stmt.executeStep()) {
         aResultArray.push(stmt.row.id);
         print(stmt.row.id + "\t" + stmt.row.position + "\t" +
               (aResultArray.length - 1));
       }
       stmt.finalize();
@@ -757,18 +757,18 @@ tests.push({
                         this._unfiledBookmarks);
     randomize_positions(PlacesUtils.toolbarFolderId, this._toolbarBookmarks);
   },
 
   check: function() {
     function check_order(aParent, aResultArray) {
       // Build the expected ordered list of bookmarks.
       let stmt = mDBConn.createStatement(
-        "SELECT id, position FROM moz_bookmarks WHERE parent = :parent " +
-        "ORDER BY position ASC"
+        `SELECT id, position FROM moz_bookmarks WHERE parent = :parent
+         ORDER BY position ASC`
       );
       stmt.params["parent"] = aParent;
       let pass = true;
       while (stmt.executeStep()) {
         print(stmt.row.id + "\t" + stmt.row.position);
         if (aResultArray.indexOf(stmt.row.id) != stmt.row.position) {
           pass = false;
         }
@@ -1184,23 +1184,23 @@ tests.push({
     url = "http://8.moz.org/";
     addPlace(url);
     setVisitCount(url, 10);
     setLastVisitDate(url, now++);
   },
 
   check: function() {
     let stmt = mDBConn.createStatement(
-      "SELECT h.id FROM moz_places h " +
-      "JOIN moz_historyvisits v ON v.place_id = h.id AND visit_type NOT IN (0,4,7,8) " +
-      "GROUP BY h.id HAVING h.visit_count <> count(*) " +
-      "UNION ALL " +
-      "SELECT h.id FROM moz_places h " +
-      "JOIN moz_historyvisits v ON v.place_id = h.id " +
-      "GROUP BY h.id HAVING h.last_visit_date <> MAX(v.visit_date) "
+      `SELECT h.id FROM moz_places h
+       JOIN moz_historyvisits v ON v.place_id = h.id AND visit_type NOT IN (0,4,7,8)
+       GROUP BY h.id HAVING h.visit_count <> count(*)
+       UNION ALL
+       SELECT h.id FROM moz_places h
+       JOIN moz_historyvisits v ON v.place_id = h.id
+       GROUP BY h.id HAVING h.last_visit_date <> MAX(v.visit_date)`
     );
     do_check_false(stmt.executeStep());
     stmt.finalize();
   }
 });
 
 //------------------------------------------------------------------------------
 
new file mode 100644
--- /dev/null
+++ b/widget/gonk/GeckoTouchDispatcher.cpp
@@ -0,0 +1,453 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 sts=2 et sw=2 tw=80: */
+/* Copyright 2014 Mozilla Foundation and Mozilla contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "FrameMetrics.h"
+#include "GeckoProfiler.h"
+#include "GeckoTouchDispatcher.h"
+#include "InputData.h"
+#include "base/basictypes.h"
+#include "gfxPrefs.h"
+#include "libui/Input.h"
+#include "mozilla/ClearOnShutdown.h"
+#include "mozilla/MouseEvents.h"
+#include "mozilla/Mutex.h"
+#include "mozilla/TimeStamp.h"
+#include "mozilla/TouchEvents.h"
+#include "mozilla/dom/Touch.h"
+#include "nsAppShell.h"
+#include "nsDebug.h"
+#include "nsThreadUtils.h"
+#include "nsWindow.h"
+#include <sys/types.h>
+#include <unistd.h>
+#include <utils/Timers.h>
+
+#define LOG(args...)                                            \
+  __android_log_print(ANDROID_LOG_INFO, "Gonk" , ## args)
+
+// uncomment to print log resample data
+// #define LOG_RESAMPLE_DATA 1
+
+namespace mozilla {
+
+// Amount of time in MS before an input is considered expired.
+static const uint64_t kInputExpirationThresholdMs = 1000;
+static int32_t nanosecToMillisec(int64_t nanosec) { return nanosec / 1000000; }
+
+static StaticRefPtr<GeckoTouchDispatcher> sTouchDispatcher;
+
+GeckoTouchDispatcher::GeckoTouchDispatcher()
+  : mTouchQueueLock("GeckoTouchDispatcher::mTouchQueueLock")
+  , mTouchEventsFiltered(false)
+  , mTouchDownCount(0)
+  , mTouchTimeDiff(0)
+  , mLastTouchTime(0)
+{
+  // Since GeckoTouchDispatcher is initialized when input is initialized
+  // and reads gfxPrefs, it is the first thing to touch gfxPrefs.
+  // The first thing to touch gfxPrefs MUST occur on the main thread and init
+  // the singleton
+  MOZ_ASSERT(sTouchDispatcher == nullptr);
+  MOZ_ASSERT(NS_IsMainThread());
+  gfxPrefs::GetSingleton();
+
+  mEnabledUniformityInfo = gfxPrefs::UniformityInfo();
+  mResamplingEnabled = gfxPrefs::TouchResampling() &&
+                       gfxPrefs::FrameUniformityHWVsyncEnabled();
+  mVsyncAdjust = gfxPrefs::TouchVsyncSampleAdjust();
+  mMaxPredict = gfxPrefs::TouchResampleMaxPredict();
+  mMinResampleTime = gfxPrefs::TouchResampleMinTime();
+  sTouchDispatcher = this;
+  ClearOnShutdown(&sTouchDispatcher);
+}
+
+class DispatchTouchEventsMainThread : public nsRunnable
+{
+public:
+  DispatchTouchEventsMainThread(GeckoTouchDispatcher* aTouchDispatcher,
+                                uint64_t aVsyncTime)
+    : mTouchDispatcher(aTouchDispatcher)
+    , mVsyncTime(aVsyncTime)
+  {
+  }
+
+  NS_IMETHOD Run()
+  {
+    mTouchDispatcher->DispatchTouchMoveEvents(mVsyncTime);
+    return NS_OK;
+  }
+
+private:
+  nsRefPtr<GeckoTouchDispatcher> mTouchDispatcher;
+  uint64_t mVsyncTime;
+};
+
+class DispatchSingleTouchMainThread : public nsRunnable
+{
+public:
+  DispatchSingleTouchMainThread(GeckoTouchDispatcher* aTouchDispatcher,
+                                MultiTouchInput& aTouch)
+    : mTouchDispatcher(aTouchDispatcher)
+    , mTouch(aTouch)
+  {
+  }
+
+  NS_IMETHOD Run()
+  {
+    mTouchDispatcher->DispatchTouchEvent(mTouch);
+    return NS_OK;
+  }
+
+private:
+  nsRefPtr<GeckoTouchDispatcher> mTouchDispatcher;
+  MultiTouchInput mTouch;
+};
+
+// Timestamp is in nanoseconds
+/* static */ bool
+GeckoTouchDispatcher::NotifyVsync(uint64_t aVsyncTimestamp)
+{
+  if (sTouchDispatcher == nullptr) {
+    return false;
+  }
+
+  MOZ_ASSERT(sTouchDispatcher->mResamplingEnabled);
+  bool haveTouchData = false;
+  {
+    MutexAutoLock lock(sTouchDispatcher->mTouchQueueLock);
+    haveTouchData = !sTouchDispatcher->mTouchMoveEvents.empty();
+  }
+
+  if (haveTouchData) {
+    NS_DispatchToMainThread(new DispatchTouchEventsMainThread(sTouchDispatcher, aVsyncTimestamp));
+  }
+
+  return haveTouchData;
+}
+
+// Touch data timestamps are in milliseconds, aEventTime is in nanoseconds
+void
+GeckoTouchDispatcher::NotifyTouch(MultiTouchInput& aData, uint64_t aEventTime)
+{
+  if (mResamplingEnabled) {
+    switch (aData.mType) {
+      case MultiTouchInput::MULTITOUCH_MOVE:
+      {
+        MutexAutoLock lock(mTouchQueueLock);
+        mTouchMoveEvents.push_back(aData);
+        mTouchTimeDiff = aEventTime - mLastTouchTime;
+        mLastTouchTime = aEventTime;
+        return;
+      }
+      default:
+        break;
+    }
+  }
+
+  NS_DispatchToMainThread(new DispatchSingleTouchMainThread(this, aData));
+}
+
+void
+GeckoTouchDispatcher::DispatchTouchMoveEvents(uint64_t aVsyncTime)
+{
+  MultiTouchInput touchMove;
+
+  {
+    MutexAutoLock lock(mTouchQueueLock);
+    if (mTouchMoveEvents.empty()) {
+      return;
+    }
+
+    int touchCount = mTouchMoveEvents.size();
+    // Both aVsynctime and mLastTouchTime are uint64_t
+    // Need to store as a signed int.
+    int64_t vsyncTouchDiff = aVsyncTime - mLastTouchTime;
+    bool resample = (touchCount > 1) &&
+                    (vsyncTouchDiff > mMinResampleTime);
+
+    if (!resample) {
+      touchMove = mTouchMoveEvents.back();
+      mTouchMoveEvents.clear();
+      mTouchMoveEvents.push_back(touchMove);
+    } else {
+      ResampleTouchMoves(touchMove, aVsyncTime);
+    }
+  }
+
+  DispatchTouchEvent(touchMove);
+}
+
+static int
+Interpolate(int start, int end, int64_t aFrameDiff, int64_t aTouchDiff)
+{
+  return start + (((end - start) * aFrameDiff) / aTouchDiff);
+}
+
+static const SingleTouchData&
+GetTouchByID(const SingleTouchData& aCurrentTouch, MultiTouchInput& aOtherTouch)
+{
+  int32_t id = aCurrentTouch.mIdentifier;
+  for (size_t i = 0; i < aOtherTouch.mTouches.Length(); i++) {
+    SingleTouchData& touch = aOtherTouch.mTouches[i];
+    if (touch.mIdentifier == id) {
+      return touch;
+    }
+  }
+
+  // We can have situations where a previous touch event had 2 fingers
+  // and we lift 1 finger off. In those cases, we won't find the touch event
+  // with given id, so just return the current touch, which will be resampled
+  // without modification and dispatched.
+  return aCurrentTouch;
+}
+
+static void
+ResampleTouch(MultiTouchInput& aOutTouch, MultiTouchInput& aCurrent,
+              MultiTouchInput& aOther, int64_t aFrameDiff,
+              int64_t aTouchDiff, bool aInterpolate)
+{
+  aOutTouch = aCurrent;
+
+  // Make sure we only resample the correct finger.
+  for (size_t i = 0; i < aOutTouch.mTouches.Length(); i++) {
+    const SingleTouchData& current = aCurrent.mTouches[i];
+    const SingleTouchData& other = GetTouchByID(current, aOther);
+
+    const ScreenIntPoint& currentTouchPoint = current.mScreenPoint;
+    const ScreenIntPoint& otherTouchPoint = other.mScreenPoint;
+
+    ScreenIntPoint newSamplePoint;
+    newSamplePoint.x = Interpolate(currentTouchPoint.x, otherTouchPoint.x, aFrameDiff, aTouchDiff);
+    newSamplePoint.y = Interpolate(currentTouchPoint.y, otherTouchPoint.y, aFrameDiff, aTouchDiff);
+
+    aOutTouch.mTouches[i].mScreenPoint = newSamplePoint;
+
+#ifdef LOG_RESAMPLE_DATA
+    const char* type = "extrapolate";
+    if (aInterpolate) {
+      type = "interpolate";
+    }
+
+    float alpha = (double) aFrameDiff / (double) aTouchDiff;
+    LOG("%s current (%d, %d), other (%d, %d) to (%d, %d) alpha %f, touch diff %llu, frame diff %lld\n",
+        type,
+        currentTouchPoint.x, currentTouchPoint.y,
+        otherTouchPoint.x, otherTouchPoint.y,
+        newSamplePoint.x, newSamplePoint.y,
+        alpha, aTouchDiff, aFrameDiff);
+#endif
+  }
+}
+
+// Interpolates with the touch event prior to SampleTime
+// and with the future touch event past sample time
+int32_t
+GeckoTouchDispatcher::InterpolateTouch(MultiTouchInput& aOutTouch, uint64_t aSampleTime)
+{
+  MOZ_RELEASE_ASSERT(mTouchMoveEvents.size() >= 2);
+  mTouchQueueLock.AssertCurrentThreadOwns();
+
+  // currentTouch < SampleTime < futureTouch
+  MultiTouchInput futureTouch = mTouchMoveEvents.back();
+  mTouchMoveEvents.pop_back();
+  MultiTouchInput currentTouch = mTouchMoveEvents.back();
+
+  mTouchMoveEvents.clear();
+  mTouchMoveEvents.push_back(futureTouch);
+
+  uint64_t currentTouchTime = mLastTouchTime - mTouchTimeDiff;
+  int64_t frameDiff = aSampleTime - currentTouchTime;
+  ResampleTouch(aOutTouch, currentTouch, futureTouch, frameDiff, mTouchTimeDiff, true);
+
+  return nanosecToMillisec(frameDiff);
+}
+
+// Extrapolates from the previous two touch events before sample time
+// and extrapolates them to sample time.
+int32_t
+GeckoTouchDispatcher::ExtrapolateTouch(MultiTouchInput& aOutTouch, uint64_t aSampleTime)
+{
+  MOZ_RELEASE_ASSERT(mTouchMoveEvents.size() >= 2);
+  mTouchQueueLock.AssertCurrentThreadOwns();
+
+  // prevTouch < currentTouch < SampleTime
+  MultiTouchInput currentTouch = mTouchMoveEvents.back();
+  mTouchMoveEvents.pop_back();
+  MultiTouchInput prevTouch = mTouchMoveEvents.back();
+  mTouchMoveEvents.clear();
+  mTouchMoveEvents.push_back(currentTouch);
+
+  uint64_t currentTouchTime = mLastTouchTime;
+  int64_t maxResampleTime = std::min(mTouchTimeDiff / 2, (int64_t) mMaxPredict);
+  uint64_t maxTimestamp = currentTouchTime + maxResampleTime;
+
+  if (aSampleTime > maxTimestamp) {
+    aSampleTime = maxTimestamp;
+    #ifdef LOG_RESAMPLE_DATA
+    LOG("Overshot extrapolation time, adjusting sample time\n");
+    #endif
+  }
+
+  // This has to be signed int since it is negative
+  int64_t frameDiff = currentTouchTime - aSampleTime;
+  ResampleTouch(aOutTouch, currentTouch, prevTouch, frameDiff, mTouchTimeDiff, false);
+  return -nanosecToMillisec(frameDiff);
+}
+
+void
+GeckoTouchDispatcher::ResampleTouchMoves(MultiTouchInput& aOutTouch, uint64_t aVsyncTime)
+{
+  uint64_t sampleTime = aVsyncTime - mVsyncAdjust;
+  int32_t touchTimeAdjust = 0;
+
+  if (mLastTouchTime > sampleTime) {
+    touchTimeAdjust = InterpolateTouch(aOutTouch, sampleTime);
+  } else {
+    touchTimeAdjust = ExtrapolateTouch(aOutTouch, sampleTime);
+  }
+
+  aOutTouch.mTimeStamp += TimeDuration::FromMilliseconds(touchTimeAdjust);
+  aOutTouch.mTime += touchTimeAdjust;
+}
+
+// Some touch events get sent as mouse events. If APZ doesn't capture the event
+// and if a touch only has 1 touch input, we can send a mouse event.
+void
+GeckoTouchDispatcher::DispatchMouseEvent(MultiTouchInput& aMultiTouch,
+                                         bool aForwardToChildren)
+{
+  WidgetMouseEvent mouseEvent = ToWidgetMouseEvent(aMultiTouch, nullptr);
+  if (mouseEvent.message == NS_EVENT_NULL) {
+    return;
+  }
+
+  mouseEvent.mFlags.mNoCrossProcessBoundaryForwarding = !aForwardToChildren;
+  nsWindow::DispatchInputEvent(mouseEvent);
+}
+
+static bool
+IsExpired(const MultiTouchInput& aTouch)
+{
+  // No pending events, the filter state can be updated.
+  uint64_t timeNowMs = systemTime(SYSTEM_TIME_MONOTONIC) / 1000000;
+  return (timeNowMs - aTouch.mTime) > kInputExpirationThresholdMs;
+}
+void
+GeckoTouchDispatcher::DispatchTouchEvent(MultiTouchInput& aMultiTouch)
+{
+  if (!mTouchDownCount) {
+    mTouchEventsFiltered = IsExpired(aMultiTouch);
+  }
+
+  switch (aMultiTouch.mType) {
+    case MultiTouchInput::MULTITOUCH_START:
+      mTouchDownCount++;
+      break;
+    case MultiTouchInput::MULTITOUCH_MOVE:
+      break;
+    case MultiTouchInput::MULTITOUCH_END:
+    case MultiTouchInput::MULTITOUCH_CANCEL:
+      mTouchDownCount--;
+      if (mTouchDownCount == 0) {
+        MutexAutoLock lock(mTouchQueueLock);
+        mTouchMoveEvents.clear();
+      }
+      break;
+    default:
+      break;
+  }
+
+  if (mTouchEventsFiltered) {
+    return;
+  }
+
+  bool captured = false;
+  WidgetTouchEvent event = aMultiTouch.ToWidgetTouchEvent(nullptr);
+  nsEventStatus status = nsWindow::DispatchInputEvent(event, &captured);
+
+  if (mEnabledUniformityInfo) {
+    const char* touchAction = "Invalid";
+    switch (aMultiTouch.mType) {
+      case MultiTouchInput::MULTITOUCH_START:
+        touchAction = "Touch_Event_Down";
+        break;
+      case MultiTouchInput::MULTITOUCH_MOVE:
+        touchAction = "Touch_Event_Move";
+        break;
+      case MultiTouchInput::MULTITOUCH_END:
+      case MultiTouchInput::MULTITOUCH_CANCEL:
+        touchAction = "Touch_Event_Up";
+        break;
+    }
+
+    const SingleTouchData& firstTouch = aMultiTouch.mTouches[0];
+    const ScreenIntPoint& touchPoint = firstTouch.mScreenPoint;
+
+    LOG("UniformityInfo %s %llu %d %d", touchAction, systemTime(SYSTEM_TIME_MONOTONIC),
+        touchPoint.x, touchPoint.y);
+  }
+
+  if (!captured && (aMultiTouch.mTouches.Length() == 1)) {
+    bool forwardToChildren = status != nsEventStatus_eConsumeNoDefault;
+    DispatchMouseEvent(aMultiTouch, forwardToChildren);
+  }
+}
+
+WidgetMouseEvent
+GeckoTouchDispatcher::ToWidgetMouseEvent(const MultiTouchInput& aMultiTouch,
+                                         nsIWidget* aWidget) const
+{
+  NS_ABORT_IF_FALSE(NS_IsMainThread(),
+                    "Can only convert To WidgetMouseEvent on main thread");
+
+  uint32_t mouseEventType = NS_EVENT_NULL;
+  switch (aMultiTouch.mType) {
+    case MultiTouchInput::MULTITOUCH_START:
+      mouseEventType = NS_MOUSE_BUTTON_DOWN;
+      break;
+    case MultiTouchInput::MULTITOUCH_MOVE:
+      mouseEventType = NS_MOUSE_MOVE;
+      break;
+    case MultiTouchInput::MULTITOUCH_CANCEL:
+    case MultiTouchInput::MULTITOUCH_END:
+      mouseEventType = NS_MOUSE_BUTTON_UP;
+      break;
+    default:
+      MOZ_ASSERT_UNREACHABLE("Did not assign a type to WidgetMouseEvent");
+      break;
+  }
+
+  WidgetMouseEvent event(true, mouseEventType, aWidget,
+                         WidgetMouseEvent::eReal, WidgetMouseEvent::eNormal);
+
+  const SingleTouchData& firstTouch = aMultiTouch.mTouches[0];
+  event.refPoint.x = firstTouch.mScreenPoint.x;
+  event.refPoint.y = firstTouch.mScreenPoint.y;
+
+  event.time = aMultiTouch.mTime;
+  event.button = WidgetMouseEvent::eLeftButton;
+  event.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH;
+  event.modifiers = aMultiTouch.modifiers;
+
+  if (mouseEventType != NS_MOUSE_MOVE) {
+    event.clickCount = 1;
+  }
+
+  return event;
+}
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/widget/gonk/GeckoTouchDispatcher.h
@@ -0,0 +1,87 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 sts=2 et sw=2 tw=80: */
+/* Copyright 2014 Mozilla Foundation and Mozilla contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef GECKO_TOUCH_INPUT_DISPATCHER_h
+#define GECKO_TOUCH_INPUT_DISPATCHER_h
+
+#include "InputData.h"
+#include "Units.h"
+#include "mozilla/Mutex.h"
+#include <vector>
+
+class nsIWidget;
+
+namespace mozilla {
+class WidgetMouseEvent;
+
+// Used to resample touch events whenever a vsync event occurs. It batches
+// touch moves and on every vsync, resamples the touch position to create smooth
+// scrolls. We use the Android touch resample algorithm. It uses a combination of
+// extrapolation and interpolation. The algorithm takes the vsync time and
+// subtracts mVsyncAdjust time in ms and creates a sample time. All touch events are
+// relative to this sample time. If the last touch event occurs AFTER this
+// sample time, interpolate the last two touch events. If the last touch event occurs BEFORE
+// this sample time, we extrapolate the last two touch events to the sample
+// time. The magic numbers defined as constants are taken from android
+// InputTransport.cpp.
+class GeckoTouchDispatcher
+{
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GeckoTouchDispatcher)
+
+public:
+  GeckoTouchDispatcher();
+  void NotifyTouch(MultiTouchInput& aData, uint64_t aEventTime);
+  void DispatchTouchEvent(MultiTouchInput& aMultiTouch);
+  void DispatchTouchMoveEvents(uint64_t aVsyncTime);
+  static bool NotifyVsync(uint64_t aVsyncTimestamp);
+
+private:
+  int32_t InterpolateTouch(MultiTouchInput& aOutTouch, uint64_t aSampleTime);
+  int32_t ExtrapolateTouch(MultiTouchInput& aOutTouch, uint64_t aSampleTime);
+  void ResampleTouchMoves(MultiTouchInput& aOutTouch, uint64_t vsyncTime);
+  void SendTouchEvent(MultiTouchInput& aData);
+  void DispatchMouseEvent(MultiTouchInput& aMultiTouch,
+                          bool aForwardToChildren);
+  WidgetMouseEvent ToWidgetMouseEvent(const MultiTouchInput& aData, nsIWidget* aWidget) const;
+
+  // mTouchQueueLock are used to protect the vector below
+  // as it is accessed on the vsync thread and main thread
+  Mutex mTouchQueueLock;
+  std::vector<MultiTouchInput> mTouchMoveEvents;
+
+  bool mResamplingEnabled;
+  bool mTouchEventsFiltered;
+  bool mEnabledUniformityInfo;
+  int mTouchDownCount;
+
+  // All times below are in nanoseconds
+  int32_t mVsyncAdjust;     // Time from vsync we create sample times from
+  int32_t mMaxPredict;      // How far into the future we're allowed to extrapolate
+
+  // Amount of time between vsync and the last event that is required before we
+  // resample
+  int32_t mMinResampleTime;
+
+  // The time difference between the last two touch move events
+  int64_t mTouchTimeDiff;
+
+  // The system time at which the last touch event occured
+  uint64_t mLastTouchTime;
+};
+
+} // namespace mozilla
+#endif // GECKO_TOUCH_INPUT_DISPATCHER_h
--- a/widget/gonk/HwcComposer2D.cpp
+++ b/widget/gonk/HwcComposer2D.cpp
@@ -23,16 +23,17 @@
 #include "LayerScope.h"
 #include "mozilla/layers/LayerManagerComposite.h"
 #include "mozilla/layers/PLayerTransaction.h"
 #include "mozilla/layers/ShadowLayerUtilsGralloc.h"
 #include "mozilla/layers/TextureHostOGL.h"  // for TextureHostOGL
 #include "mozilla/StaticPtr.h"
 #include "cutils/properties.h"
 #include "gfx2DGlue.h"
+#include "GeckoTouchDispatcher.h"
 
 #if ANDROID_VERSION >= 17
 #include "libdisplay/FramebufferSurface.h"
 #include "gfxPrefs.h"
 #include "nsThreadUtils.h"
 
 #ifndef HWC_BLIT
 #define HWC_BLIT (HWC_FRAMEBUFFER_TARGET + 1)
@@ -144,16 +145,20 @@ HwcComposer2D::Init(hwc_display_t dpy, h
         }
         if (mHwc->query(mHwc, HwcUtils::HWC_FORMAT_RB_SWAP, &supported) == NO_ERROR) {
             mRBSwapSupport = !!supported;
         }
     } else {
         mColorFill = false;
         mRBSwapSupport = false;
     }
+
+    if (RegisterHwcEventCallback()) {
+        EnableVsync(true);
+    }
 #else
     char propValue[PROPERTY_VALUE_MAX];
     property_get("ro.display.colorfill", propValue, "0");
     mColorFill = (atoi(propValue) == 1) ? true : false;
     mRBSwapSupport = true;
 #endif
 
     mDpy = dpy;
@@ -218,17 +223,17 @@ HwcComposer2D::RunVsyncEventControl(bool
             device->eventControl(device, HWC_DISPLAY_PRIMARY, HWC_EVENT_VSYNC, aEnable);
         }
     }
 }
 
 void
 HwcComposer2D::Vsync(int aDisplay, int64_t aTimestamp)
 {
-    // TODO: Handle Vsync event here
+    GeckoTouchDispatcher::NotifyVsync(aTimestamp);
 }
 #endif
 
 bool
 HwcComposer2D::ReallocLayerList()
 {
     int size = sizeof(HwcList) +
         ((mMaxLayerCount + LAYER_COUNT_INCREMENTS) * sizeof(HwcLayer));
--- a/widget/gonk/moz.build
+++ b/widget/gonk/moz.build
@@ -39,16 +39,17 @@ SOURCES += ['libui/' + src for src in [
     'SpriteController.cpp',
     'Tokenizer.cpp',
     'VelocityControl.cpp',
     'VelocityTracker.cpp',
     'VirtualKeyMap.cpp',
 ]]
 
 SOURCES += [
+    'GeckoTouchDispatcher.cpp',
     'GfxInfo.cpp',
     'GonkMemoryPressureMonitoring.cpp',
     'GonkPermission.cpp',
     'HwcComposer2D.cpp',
     'HwcUtils.cpp',
     'nsAppShell.cpp',
     'nsClipboard.cpp',
     'nsIdleServiceGonk.cpp',
--- a/widget/gonk/nsAppShell.cpp
+++ b/widget/gonk/nsAppShell.cpp
@@ -67,16 +67,17 @@
 #include "ipc/Nuwa.h"
 #endif
 
 #include "mozilla/Preferences.h"
 #include "GeckoProfiler.h"
 
 // Defines kKeyMapping and GetKeyNameIndex()
 #include "GonkKeyMapping.h"
+#include "GeckoTouchDispatcher.h"
 
 #define LOG(args...)                                            \
     __android_log_print(ANDROID_LOG_INFO, "Gonk" , ## args)
 #ifdef VERBOSE_LOG_ENABLED
 # define VERBOSE_LOG(args...)                           \
     __android_log_print(ANDROID_LOG_INFO, "Gonk" , ## args)
 #else
 # define VERBOSE_LOG(args...)                   \
@@ -152,24 +153,22 @@ struct UserInputData {
             int32_t keyCode;
             int32_t scanCode;
         } key;
         struct {
             int32_t touchCount;
             ::Touch touches[MAX_POINTERS];
         } motion;
     };
-
-    Modifiers DOMModifiers() const;
 };
 
-Modifiers
-UserInputData::DOMModifiers() const
+static mozilla::Modifiers
+getDOMModifiers(int32_t metaState)
 {
-    Modifiers result = 0;
+    mozilla::Modifiers result = 0;
     if (metaState & (AMETA_ALT_ON | AMETA_ALT_LEFT_ON | AMETA_ALT_RIGHT_ON)) {
         result |= MODIFIER_ALT;
     }
     if (metaState & (AMETA_SHIFT_ON |
                      AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_RIGHT_ON)) {
         result |= MODIFIER_SHIFT;
     }
     if (metaState & AMETA_FUNCTION_ON) {
@@ -190,116 +189,16 @@ UserInputData::DOMModifiers() const
         result |= MODIFIER_NUMLOCK;
     }
     if (metaState & AMETA_SCROLL_LOCK_ON) {
         result |= MODIFIER_SCROLLLOCK;
     }
     return result;
 }
 
-static void
-sendMouseEvent(uint32_t msg, UserInputData& data, bool forwardToChildren)
-{
-    WidgetMouseEvent event(true, msg, nullptr,
-                           WidgetMouseEvent::eReal, WidgetMouseEvent::eNormal);
-
-    event.refPoint.x = data.motion.touches[0].coords.getX();
-    event.refPoint.y = data.motion.touches[0].coords.getY();
-    event.time = data.timeMs;
-    event.button = WidgetMouseEvent::eLeftButton;
-    event.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH;
-    if (msg != NS_MOUSE_MOVE)
-        event.clickCount = 1;
-    event.modifiers = data.DOMModifiers();
-
-    event.mFlags.mNoCrossProcessBoundaryForwarding = !forwardToChildren;
-
-    nsWindow::DispatchInputEvent(event);
-}
-
-static void
-addDOMTouch(UserInputData& data, WidgetTouchEvent& event, int i)
-{
-    const ::Touch& touch = data.motion.touches[i];
-    event.touches.AppendElement(
-        new dom::Touch(touch.id,
-                       nsIntPoint(floor(touch.coords.getX() + 0.5), floor(touch.coords.getY() + 0.5)),
-                       nsIntPoint(touch.coords.getAxisValue(AMOTION_EVENT_AXIS_SIZE),
-                                  touch.coords.getAxisValue(AMOTION_EVENT_AXIS_SIZE)),
-                       0,
-                       touch.coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE))
-    );
-}
-
-static void
-printUniformityInfo(UserInputData& aData)
-{
-    char* touchAction;
-    const ::Touch& touch = aData.motion.touches[0];
-    int32_t action = aData.action & AMOTION_EVENT_ACTION_MASK;
-    switch (action) {
-    case AMOTION_EVENT_ACTION_DOWN:
-         touchAction = "Touch_Event_Down";
-         break;
-    case AMOTION_EVENT_ACTION_MOVE:
-         touchAction = "Touch_Event_Move";
-          break;
-    case AMOTION_EVENT_ACTION_UP:
-         touchAction = "Touch_Event_Up";
-         break;
-    default :
-         return;
-    }
-    LOG("UniformityInfo %s %llu %f %f", touchAction, systemTime(SYSTEM_TIME_MONOTONIC),
-        touch.coords.getX(),  touch.coords.getY() );
-}
-
-static nsEventStatus
-sendTouchEvent(UserInputData& data, bool* captured)
-{
-    uint32_t msg;
-    int32_t action = data.action & AMOTION_EVENT_ACTION_MASK;
-    switch (action) {
-    case AMOTION_EVENT_ACTION_DOWN:
-    case AMOTION_EVENT_ACTION_POINTER_DOWN:
-        msg = NS_TOUCH_START;
-        break;
-    case AMOTION_EVENT_ACTION_MOVE:
-        msg = NS_TOUCH_MOVE;
-        break;
-    case AMOTION_EVENT_ACTION_UP:
-    case AMOTION_EVENT_ACTION_POINTER_UP:
-        msg = NS_TOUCH_END;
-        break;
-    case AMOTION_EVENT_ACTION_OUTSIDE:
-    case AMOTION_EVENT_ACTION_CANCEL:
-        msg = NS_TOUCH_CANCEL;
-        break;
-    default:
-        return nsEventStatus_eIgnore;
-    }
-
-    WidgetTouchEvent event(true, msg, nullptr);
-
-    event.time = data.timeMs;
-    event.modifiers = data.DOMModifiers();
-
-    int32_t i;
-    if (msg == NS_TOUCH_END) {
-        i = data.action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK;
-        i >>= AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
-        addDOMTouch(data, event, i);
-    } else {
-        for (i = 0; i < data.motion.touchCount; ++i)
-            addDOMTouch(data, event, i);
-    }
-
-    return nsWindow::DispatchInputEvent(event, captured);
-}
-
 class MOZ_STACK_CLASS KeyEventDispatcher
 {
 public:
     KeyEventDispatcher(const UserInputData& aData,
                        KeyCharacterMap* aKeyCharMap);
     void Dispatch();
 
 private:
@@ -400,17 +299,17 @@ KeyEventDispatcher::DispatchKeyEventInte
     }
     event.isChar = !!event.charCode;
     event.mIsRepeat = IsRepeat();
     event.mKeyNameIndex = mDOMKeyNameIndex;
     if (mDOMPrintableKeyValue) {
         event.mKeyValue = mDOMPrintableKeyValue;
     }
     event.mCodeNameIndex = mDOMCodeNameIndex;
-    event.modifiers = mData.DOMModifiers();
+    event.modifiers = getDOMModifiers(mData.metaState);
     event.location = nsIDOMKeyEvent::DOM_KEY_LOCATION_MOBILE;
     event.time = mData.timeMs;
     return nsWindow::DispatchInputEvent(event);
 }
 
 void
 KeyEventDispatcher::Dispatch()
 {
@@ -589,22 +488,20 @@ protected:
     virtual ~GeckoInputReaderPolicy() {}
 };
 
 class GeckoInputDispatcher : public InputDispatcherInterface {
 public:
     GeckoInputDispatcher(sp<EventHub> &aEventHub)
         : mQueueLock("GeckoInputDispatcher::mQueueMutex")
         , mEventHub(aEventHub)
-        , mTouchDownCount(0)
         , mKeyDownCount(0)
-        , mTouchEventsFiltered(false)
         , mKeyEventsFiltered(false)
     {
-      mEnabledUniformityInfo = Preferences::GetBool("layers.uniformity-info", false);
+        mTouchDispatcher = new GeckoTouchDispatcher();
     }
 
     virtual void dump(String8& dump);
 
     virtual void monitor() {}
 
     // Called on the main thread
     virtual void dispatchOnce();
@@ -630,32 +527,29 @@ public:
 
     virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel,
             const sp<InputWindowHandle>& inputWindowHandle, bool monitor);
     virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel);
 
 
 
 protected:
-    virtual ~GeckoInputDispatcher() {}
+    virtual ~GeckoInputDispatcher() { }
 
 private:
     // mQueueLock should generally be locked while using mEventQueue.
     // UserInputData is pushed on on the InputReaderThread and
     // popped and dispatched on the main thread.
     mozilla::Mutex mQueueLock;
     std::queue<UserInputData> mEventQueue;
     sp<EventHub> mEventHub;
+    nsRefPtr<GeckoTouchDispatcher> mTouchDispatcher;
 
-    int mTouchDownCount;
     int mKeyDownCount;
-    bool mTouchEventsFiltered;
     bool mKeyEventsFiltered;
-    BitSet32 mTouchDown;
-    bool mEnabledUniformityInfo;
 };
 
 // GeckoInputReaderPolicy
 void
 GeckoInputReaderPolicy::setDisplayInfo()
 {
     static_assert(nsIScreen::ROTATION_0_DEG ==
                   DISPLAY_ORIENTATION_0,
@@ -717,90 +611,17 @@ GeckoInputDispatcher::dispatchOnce()
         data = mEventQueue.front();
         mEventQueue.pop();
         if (!mEventQueue.empty())
             gAppShell->NotifyNativeEvent();
     }
 
     switch (data.type) {
     case UserInputData::MOTION_DATA: {
-        if (!mTouchDownCount) {
-            // No pending events, the filter state can be updated.
-            mTouchEventsFiltered = isExpired(data);
-        }
-
-        int32_t action = data.action & AMOTION_EVENT_ACTION_MASK;
-        int32_t index = data.action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK;
-        index >>= AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
-        int32_t id = data.motion.touches[index].id;
-        switch (action) {
-        case AMOTION_EVENT_ACTION_DOWN:
-        case AMOTION_EVENT_ACTION_POINTER_DOWN:
-            if (!mTouchDown.hasBit(id)) {
-                mTouchDown.markBit(id);
-                mTouchDownCount++;
-            }
-            break;
-        case AMOTION_EVENT_ACTION_MOVE:
-        case AMOTION_EVENT_ACTION_HOVER_MOVE:
-            // No need to update the count on move.
-            break;
-        case AMOTION_EVENT_ACTION_UP:
-        case AMOTION_EVENT_ACTION_POINTER_UP:
-        case AMOTION_EVENT_ACTION_OUTSIDE:
-        case AMOTION_EVENT_ACTION_CANCEL:
-            if (mTouchDown.hasBit(id)) {
-                mTouchDown.clearBit(id);
-                mTouchDownCount--;
-            }
-            break;
-        default:
-            break;
-        }
-
-        if (mTouchEventsFiltered) {
-            return;
-        }
-
-        nsEventStatus status = nsEventStatus_eIgnore;
-        if (action != AMOTION_EVENT_ACTION_HOVER_MOVE) {
-            bool captured;
-            status = sendTouchEvent(data, &captured);
-            if (mEnabledUniformityInfo) {
-                printUniformityInfo(data);
-            }
-            if (captured) {
-                return;
-            }
-        }
-
-        uint32_t msg;
-        switch (action) {
-        case AMOTION_EVENT_ACTION_DOWN:
-            msg = NS_MOUSE_BUTTON_DOWN;
-            break;
-        case AMOTION_EVENT_ACTION_POINTER_DOWN:
-        case AMOTION_EVENT_ACTION_POINTER_UP:
-        case AMOTION_EVENT_ACTION_MOVE:
-        case AMOTION_EVENT_ACTION_HOVER_MOVE:
-            msg = NS_MOUSE_MOVE;
-            break;
-        case AMOTION_EVENT_ACTION_OUTSIDE:
-        case AMOTION_EVENT_ACTION_CANCEL:
-        case AMOTION_EVENT_ACTION_UP:
-            msg = NS_MOUSE_BUTTON_UP;
-            break;
-        default:
-            msg = NS_EVENT_NULL;
-            break;
-        }
-        if (msg != NS_EVENT_NULL) {
-            sendMouseEvent(msg, data, 
-                           status != nsEventStatus_eConsumeNoDefault);
-        }
+        MOZ_ASSERT_UNREACHABLE("Should not dispatch touch events here anymore");
         break;
     }
     case UserInputData::KEY_DATA: {
         if (!mKeyDownCount) {
             // No pending events, the filter state can be updated.
             mKeyEventsFiltered = isExpired(data);
         }
 
@@ -836,51 +657,82 @@ GeckoInputDispatcher::notifyKey(const No
     data.key.scanCode = args->scanCode;
     {
         MutexAutoLock lock(mQueueLock);
         mEventQueue.push(data);
     }
     gAppShell->NotifyNativeEvent();
 }
 
+static void
+addMultiTouch(MultiTouchInput& aMultiTouch,
+                                    const NotifyMotionArgs* args, int aIndex)
+{
+    int32_t id = args->pointerProperties[aIndex].id;
+    PointerCoords coords = args->pointerCoords[aIndex];
+    float force = coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE);
+    ScreenIntPoint point(floor(coords.getX() + 0.5),
+                         floor(coords.getY() + 0.5));
+
+    SingleTouchData touchData(id, point, ScreenSize(0, 0),
+                              0, force);
+
+    aMultiTouch.mTouches.AppendElement(touchData);
+}
 
 void
 GeckoInputDispatcher::notifyMotion(const NotifyMotionArgs* args)
 {
-    UserInputData data;
-    data.timeMs = nanosecsToMillisecs(args->eventTime);
-    data.type = UserInputData::MOTION_DATA;
-    data.action = args->action;
-    data.flags = args->flags;
-    data.metaState = args->metaState;
-    data.deviceId = args->deviceId;
-    MOZ_ASSERT(args->pointerCount <= MAX_POINTERS);
-    data.motion.touchCount = args->pointerCount;
-    for (uint32_t i = 0; i < args->pointerCount; ++i) {
-        ::Touch& touch = data.motion.touches[i];
-        touch.id = args->pointerProperties[i].id;
-        memcpy(&touch.coords, &args->pointerCoords[i], sizeof(*args->pointerCoords));
+    uint32_t time = nanosecsToMillisecs(args->eventTime);
+    int32_t action = args->action & AMOTION_EVENT_ACTION_MASK;
+    int touchCount = args->pointerCount;
+    MOZ_ASSERT(touchCount <= MAX_POINTERS);
+    TimeStamp timestamp = TimeStamp::Now();
+    Modifiers modifiers = getDOMModifiers(args->metaState);
+
+    MultiTouchInput::MultiTouchType touchType = MultiTouchInput::MULTITOUCH_CANCEL;
+    switch (action) {
+    case AMOTION_EVENT_ACTION_DOWN:
+    case AMOTION_EVENT_ACTION_POINTER_DOWN:
+        touchType = MultiTouchInput::MULTITOUCH_START;
+        break;
+    case AMOTION_EVENT_ACTION_MOVE:
+        touchType = MultiTouchInput::MULTITOUCH_MOVE;
+        break;
+    case AMOTION_EVENT_ACTION_UP:
+    case AMOTION_EVENT_ACTION_POINTER_UP:
+        touchType = MultiTouchInput::MULTITOUCH_END;
+        break;
+    case AMOTION_EVENT_ACTION_OUTSIDE:
+    case AMOTION_EVENT_ACTION_CANCEL:
+        touchType = MultiTouchInput::MULTITOUCH_CANCEL;
+        break;
+    default:
+        MOZ_ASSERT_UNREACHABLE("Could not assign a touch type");
+        break;
     }
-    {
-        MutexAutoLock lock(mQueueLock);
-        if (!mEventQueue.empty() &&
-             mEventQueue.back().type == UserInputData::MOTION_DATA &&
-           ((mEventQueue.back().action & AMOTION_EVENT_ACTION_MASK) ==
-             AMOTION_EVENT_ACTION_MOVE ||
-            (mEventQueue.back().action & AMOTION_EVENT_ACTION_MASK) ==
-             AMOTION_EVENT_ACTION_HOVER_MOVE))
-            mEventQueue.back() = data;
-        else
-            mEventQueue.push(data);
+
+    MultiTouchInput touchData(touchType, time, timestamp, modifiers);
+
+    // For touch ends, we have to filter out which finger is actually
+    // the touch end since the touch array has all fingers, not just the touch
+    // that we want to end
+    if (touchType == MultiTouchInput::MULTITOUCH_END) {
+        int touchIndex = args->action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK;
+        touchIndex >>= AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
+        addMultiTouch(touchData, args, touchIndex);
+    } else {
+        for (int32_t i = 0; i < touchCount; ++i) {
+            addMultiTouch(touchData, args, i);
+        }
     }
-    gAppShell->NotifyNativeEvent();
+
+    mTouchDispatcher->NotifyTouch(touchData, args->eventTime);
 }
 
-
-
 void GeckoInputDispatcher::notifySwitch(const NotifySwitchArgs* args)
 {
     if (!sDevInputAudioJack)
         return;
 
     bool needSwitchUpdate = false;
 
     if (args->switchMask & (1 << SW_HEADPHONE_INSERT)) {