Merge m-c to inbound. a=merge
authorRyan VanderMeulen <ryanvm@gmail.com>
Thu, 16 Oct 2014 14:58:03 -0400
changeset 210802 63241287b1741a9fa2913b41740b8e5321f8f007
parent 210801 fe2216810527aad5233efbabd28006c3e0273ab2 (current diff)
parent 210767 cc7fc5918561b47d77404e4beffa31ede57a9522 (diff)
child 210803 7e905781c7152f82c6e1c6c52e12133278d1720f
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersmerge
milestone36.0a1
Merge m-c to inbound. a=merge
--- 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="3a2947df41a480de1457a6dcdbf46ad0af70d8e0">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="5c636a7a54b2c86d8ff6bc1aa1e5f9594c7bc586"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="abef62c0623e5504a97b4fd411e879a67b285b52"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
   <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="9f6b7471c881ee689183d681658cf2ba3dfc5610"/>
--- 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="84923f1940625c47ff4c1fdf01b10fde3b7d909e">
     <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="5c636a7a54b2c86d8ff6bc1aa1e5f9594c7bc586"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="abef62c0623e5504a97b4fd411e879a67b285b52"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
   <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="9f6b7471c881ee689183d681658cf2ba3dfc5610"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/emulator-jb/sources.xml
+++ b/b2g/config/emulator-jb/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="8986df0f82e15ac2798df0b6c2ee3435400677ac">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="5c636a7a54b2c86d8ff6bc1aa1e5f9594c7bc586"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="abef62c0623e5504a97b4fd411e879a67b285b52"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="9f6b7471c881ee689183d681658cf2ba3dfc5610"/>
   <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"/>
@@ -129,12 +129,12 @@
   <project name="android-development" path="development" remote="b2g" revision="dab55669da8f48b6e57df95d5af9f16b4a87b0b1"/>
   <project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="3a9a17613cc685aa232432566ad6cc607eab4ec1"/>
   <project name="device_generic_goldfish" path="device/generic/goldfish" remote="b2g" revision="197cd9492b9fadaa915c5daf36ff557f8f4a8d1c"/>
   <project name="platform/external/libnfc-nci" path="external/libnfc-nci" revision="7d33aaf740bbf6c7c6e9c34a92b371eda311b66b"/>
   <project name="libnfcemu" path="external/libnfcemu" remote="b2g" revision="125ccf9bd5986c7728ea44508b3e1d1185ac028b"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="d259117b4976decbe2f76eeed85218bf0109190f"/>
   <project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="0e56e450367cd802241b27164a2979188242b95f"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="9f28c4faea3b2f01db227b2467b08aeba96d9bec"/>
-  <project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="85e864c4abc80e08bc82f0ac53c042e0d27839b0"/>
+  <project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="7047fcaa8bb55888ec7b84997e1bab41185ba3a3"/>
   <project name="android-sdk" path="sdk" remote="b2g" revision="8b1365af38c9a653df97349ee53a3f5d64fd590a"/>
   <project name="darwinstreamingserver" path="system/darwinstreamingserver" remote="b2g" revision="cf85968c7f85e0ec36e72c87ceb4837a943b8af6"/>
 </manifest>
--- 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="3a2947df41a480de1457a6dcdbf46ad0af70d8e0">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="5c636a7a54b2c86d8ff6bc1aa1e5f9594c7bc586"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="abef62c0623e5504a97b4fd411e879a67b285b52"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
   <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="9f6b7471c881ee689183d681658cf2ba3dfc5610"/>
--- 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="84923f1940625c47ff4c1fdf01b10fde3b7d909e">
     <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="5c636a7a54b2c86d8ff6bc1aa1e5f9594c7bc586"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="abef62c0623e5504a97b4fd411e879a67b285b52"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
   <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="9f6b7471c881ee689183d681658cf2ba3dfc5610"/>
   <!-- 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="3a2947df41a480de1457a6dcdbf46ad0af70d8e0">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="5c636a7a54b2c86d8ff6bc1aa1e5f9594c7bc586"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="abef62c0623e5504a97b4fd411e879a67b285b52"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
   <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="9f6b7471c881ee689183d681658cf2ba3dfc5610"/>
@@ -127,17 +127,17 @@
   <remove-project name="platform/hardware/libhardware"/>
   <remove-project name="platform/external/bluetooth/bluedroid"/>
   <!--original fetch url was git://github.com/t2m-foxfone/-->
   <remote fetch="https://git.mozilla.org/external/t2m-foxfone" name="t2m"/>
   <default remote="caf" revision="LNX.LA.3.5.2.1.1" sync-j="4"/>
   <!-- Flame specific things -->
   <project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="1bb28abbc215f45220620af5cd60a8ac1be93722"/>
   <project name="device/qcom/common" path="device/qcom/common" revision="54c32c2ddef066fbdf611d29e4b7c47e0363599e"/>
-  <project name="device-flame" path="device/t2m/flame" remote="b2g" revision="52c909e821d107d414f851e267dedcd7aae2cebf"/>
+  <project name="device-flame" path="device/t2m/flame" remote="b2g" revision="05aa7b98d3f891b334031dc710d48d0d6b82ec1d"/>
   <project name="codeaurora_kernel_msm" path="kernel" remote="b2g" revision="7731d63c809dbca4da408e1de0c1a044f0765e52"/>
   <project name="kernel_lk" path="bootable/bootloader/lk" remote="b2g" revision="fda40423ffa573dc6cafd3780515010cb2a086be"/>
   <project name="platform/external/bluetooth/bluedroid" path="external/bluetooth/bluedroid" revision="30b96dfca99cb384bf520a16b81f3aba56f09907"/>
   <project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="5b71e40213f650459e95d35b6f14af7e88d8ab62"/>
   <project name="platform_external_libnfc-nci" path="external/libnfc-nci" remote="t2m" revision="4186bdecb4dae911b39a8202252cc2310d91b0be"/>
   <project name="platform/frameworks/av" path="frameworks/av" revision="ea2f399b3ca0a23524d2828f85f69902caefc22e"/>
   <project name="platform/frameworks/base" path="frameworks/base" revision="6b58ab45e3e56c1fc20708cc39fa2264c52558df"/>
   <project name="platform/frameworks/native" path="frameworks/native" revision="a46a9f1ac0ed5662d614c277cbb14eb3f332f365"/>
@@ -146,13 +146,13 @@
   <project name="platform/hardware/qcom/camera" path="hardware/qcom/camera" revision="2a1ded216a91bf62a72b1640cf01ab4998f37028"/>
   <project name="platform/hardware/qcom/display" path="hardware/qcom/display" revision="e5a971282719907f73fb1da964ca40aad67a3be0"/>
   <project name="platform/hardware/qcom/gps" path="hardware/qcom/gps" revision="9883ea57b0668d8f60dba025d4522dfa69a1fbfa"/>
   <project name="platform/hardware/qcom/media" path="hardware/qcom/media" revision="a558dc844bf5144fc38603fd8f4df8d9557052a5"/>
   <project name="platform/hardware/qcom/wlan" path="hardware/qcom/wlan" revision="57ee1320ed7b4a1a1274d8f3f6c177cd6b9becb2"/>
   <project name="platform/hardware/ril" path="hardware/ril" revision="12b1977cc704b35f2e9db2bb423fa405348bc2f3"/>
   <project name="platform/system/bluetooth" path="system/bluetooth" revision="985bf15264d865fe7b9c5b45f61c451cbaafa43d"/>
   <project name="platform/system/core" path="system/core" revision="350eac5403124dacb2a5fd9e28ac290a59fc3b8e"/>
-  <project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="85e864c4abc80e08bc82f0ac53c042e0d27839b0"/>
+  <project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="7047fcaa8bb55888ec7b84997e1bab41185ba3a3"/>
   <project name="platform/system/qcom" path="system/qcom" revision="63e3f6f176caad587d42bba4c16b66d953fb23c2"/>
   <project name="platform/vendor/qcom-opensource/wlan/prima" path="vendor/qcom/opensource/wlan/prima" revision="d8952a42771045fca73ec600e2b42a4c7129d723"/>
   <project name="platform/vendor/qcom/msm8610" path="device/qcom/msm8610" revision="7704e16da545f4207812e593743d6743e1afb9c5"/>
 </manifest>
--- a/b2g/config/flame/sources.xml
+++ b/b2g/config/flame/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="8986df0f82e15ac2798df0b6c2ee3435400677ac">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="5c636a7a54b2c86d8ff6bc1aa1e5f9594c7bc586"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="abef62c0623e5504a97b4fd411e879a67b285b52"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="9f6b7471c881ee689183d681658cf2ba3dfc5610"/>
   <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"/>
@@ -140,13 +140,13 @@
   <project name="platform/hardware/qcom/camera" path="hardware/qcom/camera" revision="5e110615212302c5d798a3c223dcee458817651c"/>
   <project name="platform/hardware/qcom/display" path="hardware/qcom/display" revision="fa9ffd47948eb24466de227e48fe9c4a7c5e7711"/>
   <project name="platform/hardware/qcom/gps" path="hardware/qcom/gps" revision="cd76b19aafd4229ccf83853d02faef8c51ca8b34"/>
   <project name="platform/hardware/qcom/media" path="hardware/qcom/media" revision="8a0d0b0d9889ef99c4c6317c810db4c09295f15a"/>
   <project name="platform/hardware/qcom/wlan" path="hardware/qcom/wlan" revision="2208fa3537ace873b8f9ec2355055761c79dfd5f"/>
   <project name="platform/hardware/ril" path="hardware/ril" revision="c4e2ac95907a5519a0e09f01a0d8e27fec101af0"/>
   <project name="platform/system/bluetooth" path="system/bluetooth" revision="e1eb226fa3ad3874ea7b63c56a9dc7012d7ff3c2"/>
   <project name="platform/system/core" path="system/core" revision="adc485d8755af6a61641d197de7cfef667722580"/>
-  <project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="85e864c4abc80e08bc82f0ac53c042e0d27839b0"/>
+  <project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="7047fcaa8bb55888ec7b84997e1bab41185ba3a3"/>
   <project name="platform/system/qcom" path="system/qcom" revision="1cdab258b15258b7f9657da70e6f06ebd5a2fc25"/>
   <project name="platform/vendor/qcom/msm8610" path="device/qcom/msm8610" revision="4ae5df252123591d5b941191790e7abed1bce5a4"/>
   <project name="platform/vendor/qcom-opensource/wlan/prima" path="vendor/qcom/opensource/wlan/prima" revision="ce18b47b4a4f93a581d672bbd5cb6d12fe796ca9"/>
 </manifest>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,9 +1,9 @@
 {
     "git": {
         "git_revision": "", 
         "remote": "", 
         "branch": ""
     }, 
-    "revision": "8017299c3eb7b82bdaee1334994f546c11eb16ab", 
+    "revision": "63436aa17e7fa3ad521fdeffdc22b81c36e5d69b", 
     "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="84923f1940625c47ff4c1fdf01b10fde3b7d909e">
     <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="5c636a7a54b2c86d8ff6bc1aa1e5f9594c7bc586"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="abef62c0623e5504a97b4fd411e879a67b285b52"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
   <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="9f6b7471c881ee689183d681658cf2ba3dfc5610"/>
   <!-- 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="84923f1940625c47ff4c1fdf01b10fde3b7d909e">
     <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="5c636a7a54b2c86d8ff6bc1aa1e5f9594c7bc586"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="abef62c0623e5504a97b4fd411e879a67b285b52"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
--- a/b2g/config/nexus-4/sources.xml
+++ b/b2g/config/nexus-4/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="8986df0f82e15ac2798df0b6c2ee3435400677ac">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="5c636a7a54b2c86d8ff6bc1aa1e5f9594c7bc586"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="abef62c0623e5504a97b4fd411e879a67b285b52"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="9f6b7471c881ee689183d681658cf2ba3dfc5610"/>
   <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"/>
@@ -124,17 +124,17 @@
   <project name="platform/system/netd" path="system/netd" revision="56112dd7b811301b718d0643a82fd5cac9522073"/>
   <project name="platform/system/security" path="system/security" revision="f48ff68fedbcdc12b570b7699745abb6e7574907"/>
   <project name="platform/system/vold" path="system/vold" revision="8de05d4a52b5a91e7336e6baa4592f945a6ddbea"/>
   <default remote="caf" revision="refs/tags/android-4.3_r2.1" sync-j="4"/>
   <!-- Nexus 4 specific things -->
   <project name="device-mako" path="device/lge/mako" remote="b2g" revision="78d17f0c117f0c66dd55ee8d5c5dde8ccc93ecba"/>
   <project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="3a9a17613cc685aa232432566ad6cc607eab4ec1"/>
   <project name="device/lge/mako-kernel" path="device/lge/mako-kernel" revision="d1729e53d71d711c8fde25eab8728ff2b9b4df0e"/>
-  <project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="85e864c4abc80e08bc82f0ac53c042e0d27839b0"/>
+  <project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="7047fcaa8bb55888ec7b84997e1bab41185ba3a3"/>
   <project name="platform/external/libnfc-nci" path="external/libnfc-nci" revision="7d33aaf740bbf6c7c6e9c34a92b371eda311b66b"/>
   <project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="0e56e450367cd802241b27164a2979188242b95f"/>
   <project name="platform/hardware/broadcom/wlan" path="hardware/broadcom/wlan" revision="0e1929fa3aa38bf9d40e9e953d619fab8164c82e"/>
   <project name="platform/hardware/qcom/audio" path="hardware/qcom/audio" revision="b0a528d839cfd9d170d092fe3743b5252b4243a6"/>
   <project name="platform/hardware/qcom/bt" path="hardware/qcom/bt" revision="380945eaa249a2dbdde0daa4c8adb8ca325edba6"/>
   <project name="platform/hardware/qcom/display" path="hardware/qcom/display" revision="6f3b0272cefaffeaed2a7d2bb8f633059f163ddc"/>
   <project name="platform/hardware/qcom/keymaster" path="hardware/qcom/keymaster" revision="16da8262c997a5a0d797885788a64a0771b26910"/>
   <project name="platform/hardware/qcom/media" path="hardware/qcom/media" revision="689b476ba3eb46c34b81343295fe144a0e81a18e"/>
--- 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="84923f1940625c47ff4c1fdf01b10fde3b7d909e">
     <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="5c636a7a54b2c86d8ff6bc1aa1e5f9594c7bc586"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="abef62c0623e5504a97b4fd411e879a67b285b52"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
   <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="9f6b7471c881ee689183d681658cf2ba3dfc5610"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
--- a/dom/base/test/test_window_enumeration.html
+++ b/dom/base/test/test_window_enumeration.html
@@ -8,27 +8,24 @@ https://bugzilla.mozilla.org/show_bug.cg
   <title>Test for Bug 807222</title>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
 </head>
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=807222">Mozilla Bug 807222</a>
 <p id="display"></p>
 <div id="content" style="display: none">
-  
+
 </div>
 <pre id="test">
 <script type="application/javascript">
 
 /** Test for Bug 807222 **/
 var expectedProps = [ "Image", "Audio", "Option",
                       "PerformanceTiming", "CSS2Properties", "SVGElement" ];
-if (navigator.mozTelephony) {
-  expectedProps.push("USSDReceivedEvent");
-}
 var actualProps = Object.getOwnPropertyNames(window);
 
 for (var i = 0; i < expectedProps.length; ++i) {
   isnot(actualProps.indexOf(expectedProps[i]), -1,
         "getOwnPropertyNames should include " + expectedProps[i]);
 }
 </script>
 </pre>
--- a/dom/bluetooth/bluedroid/BluetoothA2dpManager.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothA2dpManager.cpp
@@ -188,31 +188,71 @@ public:
     BluetoothA2dpManager* a2dpManager = BluetoothA2dpManager::Get();
     sBtAvrcpInterface->Init(a2dpManager, new InitAvrcpResultHandler(mRes));
   }
 
 private:
   nsRefPtr<BluetoothProfileResultHandler> mRes;
 };
 
+class OnErrorProfileResultHandlerRunnable MOZ_FINAL : public nsRunnable
+{
+public:
+  OnErrorProfileResultHandlerRunnable(BluetoothProfileResultHandler* aRes,
+                                      nsresult aRv)
+  : mRes(aRes)
+  , mRv(aRv)
+  {
+    MOZ_ASSERT(mRes);
+  }
+
+  NS_IMETHOD Run() MOZ_OVERRIDE
+  {
+    mRes->OnError(mRv);
+    return NS_OK;
+  }
+
+private:
+  nsRefPtr<BluetoothProfileResultHandler> mRes;
+  nsresult mRv;
+};
+
 /*
  * This function will be only called when Bluetooth is turning on.
  * It is important to register a2dp callbacks before enable() gets called.
  * It is required to register a2dp callbacks before a2dp media task
  * starts up.
  */
 // static
 void
 BluetoothA2dpManager::InitA2dpInterface(BluetoothProfileResultHandler* aRes)
 {
   BluetoothInterface* btInf = BluetoothInterface::GetInstance();
-  NS_ENSURE_TRUE_VOID(btInf);
+  if (NS_WARN_IF(!btInf)) {
+    // If there's no HFP interface, we dispatch a runnable
+    // that calls the profile result handler.
+    nsRefPtr<nsRunnable> r =
+      new OnErrorProfileResultHandlerRunnable(aRes, NS_ERROR_FAILURE);
+    if (NS_FAILED(NS_DispatchToMainThread(r))) {
+      BT_LOGR("Failed to dispatch HFP OnError runnable");
+    }
+    return;
+  }
 
   sBtA2dpInterface = btInf->GetBluetoothA2dpInterface();
-  NS_ENSURE_TRUE_VOID(sBtA2dpInterface);
+  if (NS_WARN_IF(!sBtA2dpInterface)) {
+    // If there's no HFP interface, we dispatch a runnable
+    // that calls the profile result handler.
+    nsRefPtr<nsRunnable> r =
+      new OnErrorProfileResultHandlerRunnable(aRes, NS_ERROR_FAILURE);
+    if (NS_FAILED(NS_DispatchToMainThread(r))) {
+      BT_LOGR("Failed to dispatch HFP OnError runnable");
+    }
+    return;
+  }
 
   BluetoothA2dpManager* a2dpManager = BluetoothA2dpManager::Get();
   sBtA2dpInterface->Init(a2dpManager, new InitA2dpResultHandler(aRes));
 }
 
 BluetoothA2dpManager::~BluetoothA2dpManager()
 {
   nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
@@ -336,16 +376,21 @@ public:
     }
   }
 
   void Cleanup() MOZ_OVERRIDE
   {
     sBtA2dpInterface = nullptr;
     if (sBtAvrcpInterface) {
       sBtAvrcpInterface->Cleanup(new CleanupAvrcpResultHandler(mRes));
+    } else if (mRes) {
+      /* Not all backends support AVRCP. If it's not available
+       * we signal success from here.
+       */
+      mRes->Deinit();
     }
   }
 
 private:
   nsRefPtr<BluetoothProfileResultHandler> mRes;
 };
 
 class CleanupA2dpResultHandlerRunnable MOZ_FINAL : public nsRunnable
@@ -355,16 +400,21 @@ public:
   : mRes(aRes)
   { }
 
   NS_IMETHOD Run() MOZ_OVERRIDE
   {
     sBtA2dpInterface = nullptr;
     if (sBtAvrcpInterface) {
       sBtAvrcpInterface->Cleanup(new CleanupAvrcpResultHandler(mRes));
+    } else if (mRes) {
+      /* Not all backends support AVRCP. If it's not available
+       * we signal success from here.
+       */
+      mRes->Deinit();
     }
 
     return NS_OK;
   }
 
 private:
   nsRefPtr<BluetoothProfileResultHandler> mRes;
 };
--- a/dom/bluetooth/bluedroid/hfp/BluetoothHfpManager.cpp
+++ b/dom/bluetooth/bluedroid/hfp/BluetoothHfpManager.cpp
@@ -324,26 +324,66 @@ public:
     mRes->RunInit();
     return NS_OK;
   }
 
 private:
   nsRefPtr<CleanupInitResultHandler> mRes;
 };
 
+class OnErrorProfileResultHandlerRunnable MOZ_FINAL : public nsRunnable
+{
+public:
+  OnErrorProfileResultHandlerRunnable(BluetoothProfileResultHandler* aRes,
+                                      nsresult aRv)
+  : mRes(aRes)
+  , mRv(aRv)
+  {
+    MOZ_ASSERT(mRes);
+  }
+
+  NS_IMETHOD Run() MOZ_OVERRIDE
+  {
+    mRes->OnError(mRv);
+    return NS_OK;
+  }
+
+private:
+  nsRefPtr<BluetoothProfileResultHandler> mRes;
+  nsresult mRv;
+};
+
 // static
 void
 BluetoothHfpManager::InitHfpInterface(BluetoothProfileResultHandler* aRes)
 {
   BluetoothInterface* btInf = BluetoothInterface::GetInstance();
-  NS_ENSURE_TRUE_VOID(btInf);
+  if (NS_WARN_IF(!btInf)) {
+    // If there's no backend interface, we dispatch a runnable
+    // that calls the profile result handler.
+    nsRefPtr<nsRunnable> r =
+      new OnErrorProfileResultHandlerRunnable(aRes, NS_ERROR_FAILURE);
+    if (NS_FAILED(NS_DispatchToMainThread(r))) {
+      BT_LOGR("Failed to dispatch HFP OnError runnable");
+    }
+    return;
+  }
 
   BluetoothHandsfreeInterface *interface =
     btInf->GetBluetoothHandsfreeInterface();
-  NS_ENSURE_TRUE_VOID(interface);
+  if (NS_WARN_IF(!interface)) {
+    // If there's no HFP interface, we dispatch a runnable
+    // that calls the profile result handler.
+    nsRefPtr<nsRunnable> r =
+      new OnErrorProfileResultHandlerRunnable(aRes, NS_ERROR_FAILURE);
+    if (NS_FAILED(NS_DispatchToMainThread(r))) {
+      BT_LOGR("Failed to dispatch HFP OnError runnable");
+    }
+    return;
+  }
 
   nsRefPtr<CleanupInitResultHandler> res =
     new CleanupInitResultHandler(interface, aRes);
 
   if (sBluetoothHfpInterface) {
     // Cleanup an initialized HFP before initializing again.
     sBluetoothHfpInterface->Cleanup(res);
   } else {
--- a/dom/bluetooth2/bluedroid/BluetoothA2dpManager.cpp
+++ b/dom/bluetooth2/bluedroid/BluetoothA2dpManager.cpp
@@ -192,40 +192,68 @@ public:
     BluetoothA2dpManager* a2dpManager = BluetoothA2dpManager::Get();
     sBtAvrcpInterface->Init(a2dpManager, new InitAvrcpResultHandler(mRes));
   }
 
 private:
   nsRefPtr<BluetoothProfileResultHandler> mRes;
 };
 
+class OnErrorProfileResultHandlerRunnable MOZ_FINAL : public nsRunnable
+{
+public:
+  OnErrorProfileResultHandlerRunnable(BluetoothProfileResultHandler* aRes,
+                                      nsresult aRv)
+  : mRes(aRes)
+  , mRv(aRv)
+  {
+    MOZ_ASSERT(mRes);
+  }
+
+  NS_IMETHOD Run() MOZ_OVERRIDE
+  {
+    mRes->OnError(mRv);
+    return NS_OK;
+  }
+
+private:
+  nsRefPtr<BluetoothProfileResultHandler> mRes;
+  nsresult mRv;
+};
+
 /*
  * This function will be only called when Bluetooth is turning on.
  * It is important to register a2dp callbacks before enable() gets called.
  * It is required to register a2dp callbacks before a2dp media task
  * starts up.
  */
 // static
 void
 BluetoothA2dpManager::InitA2dpInterface(BluetoothProfileResultHandler* aRes)
 {
   BluetoothInterface* btInf = BluetoothInterface::GetInstance();
-  if (!btInf) {
-    BT_LOGR("Error: Bluetooth interface not available");
-    if (aRes) {
-      aRes->OnError(NS_ERROR_FAILURE);
+  if (NS_WARN_IF(!btInf)) {
+    // If there's no backend interface, we dispatch a runnable
+    // that calls the profile result handler.
+    nsRefPtr<nsRunnable> r =
+      new OnErrorProfileResultHandlerRunnable(aRes, NS_ERROR_FAILURE);
+    if (NS_FAILED(NS_DispatchToMainThread(r))) {
+      BT_LOGR("Failed to dispatch HFP OnError runnable");
     }
     return;
   }
 
   sBtA2dpInterface = btInf->GetBluetoothA2dpInterface();
-  if (!sBtA2dpInterface) {
-    BT_LOGR("Error: Bluetooth A2DP interface not available");
-    if (aRes) {
-      aRes->OnError(NS_ERROR_FAILURE);
+  if (NS_WARN_IF(!sBtA2dpInterface)) {
+    // If there's no A2DP interface, we dispatch a runnable
+    // that calls the profile result handler.
+    nsRefPtr<nsRunnable> r =
+      new OnErrorProfileResultHandlerRunnable(aRes, NS_ERROR_FAILURE);
+    if (NS_FAILED(NS_DispatchToMainThread(r))) {
+      BT_LOGR("Failed to dispatch HFP OnError runnable");
     }
     return;
   }
 
   BluetoothA2dpManager* a2dpManager = BluetoothA2dpManager::Get();
   sBtA2dpInterface->Init(a2dpManager, new InitA2dpResultHandler(aRes));
 }
 
@@ -352,16 +380,21 @@ public:
     }
   }
 
   void Cleanup() MOZ_OVERRIDE
   {
     sBtA2dpInterface = nullptr;
     if (sBtAvrcpInterface) {
       sBtAvrcpInterface->Cleanup(new CleanupAvrcpResultHandler(mRes));
+    } else if (mRes) {
+      /* Not all backends support AVRCP. If it's not available
+       * we signal success from here.
+       */
+      mRes->Deinit();
     }
   }
 
 private:
   nsRefPtr<BluetoothProfileResultHandler> mRes;
 };
 
 class CleanupA2dpResultHandlerRunnable MOZ_FINAL : public nsRunnable
@@ -371,16 +404,21 @@ public:
   : mRes(aRes)
   { }
 
   NS_IMETHOD Run() MOZ_OVERRIDE
   {
     sBtA2dpInterface = nullptr;
     if (sBtAvrcpInterface) {
       sBtAvrcpInterface->Cleanup(new CleanupAvrcpResultHandler(mRes));
+    } else if (mRes) {
+      /* Not all backends support AVRCP. If it's not available
+       * we signal success from here.
+       */
+      mRes->Deinit();
     }
 
     return NS_OK;
   }
 
 private:
   nsRefPtr<BluetoothProfileResultHandler> mRes;
 };
--- a/dom/bluetooth2/bluedroid/hfp/BluetoothHfpManager.cpp
+++ b/dom/bluetooth2/bluedroid/hfp/BluetoothHfpManager.cpp
@@ -315,35 +315,63 @@ public:
     mRes->RunInit();
     return NS_OK;
   }
 
 private:
   nsRefPtr<CleanupInitResultHandler> mRes;
 };
 
+class OnErrorProfileResultHandlerRunnable MOZ_FINAL : public nsRunnable
+{
+public:
+  OnErrorProfileResultHandlerRunnable(BluetoothProfileResultHandler* aRes,
+                                      nsresult aRv)
+  : mRes(aRes)
+  , mRv(aRv)
+  {
+    MOZ_ASSERT(mRes);
+  }
+
+  NS_IMETHOD Run() MOZ_OVERRIDE
+  {
+    mRes->OnError(mRv);
+    return NS_OK;
+  }
+
+private:
+  nsRefPtr<BluetoothProfileResultHandler> mRes;
+  nsresult mRv;
+};
+
 // static
 void
 BluetoothHfpManager::InitHfpInterface(BluetoothProfileResultHandler* aRes)
 {
   BluetoothInterface* btInf = BluetoothInterface::GetInstance();
-  if (!btInf) {
-    BT_LOGR("Error: Bluetooth interface not available");
-    if (aRes) {
-      aRes->OnError(NS_ERROR_FAILURE);
+  if (NS_WARN_IF(!btInf)) {
+    // If there's no backend interface, we dispatch a runnable
+    // that calls the profile result handler.
+    nsRefPtr<nsRunnable> r =
+      new OnErrorProfileResultHandlerRunnable(aRes, NS_ERROR_FAILURE);
+    if (NS_FAILED(NS_DispatchToMainThread(r))) {
+      BT_LOGR("Failed to dispatch HFP OnError runnable");
     }
     return;
   }
 
   BluetoothHandsfreeInterface *interface =
     btInf->GetBluetoothHandsfreeInterface();
-  if (!interface) {
-    BT_LOGR("Error: Bluetooth Handsfree interface not available");
-    if (aRes) {
-      aRes->OnError(NS_ERROR_FAILURE);
+  if (NS_WARN_IF(!interface)) {
+    // If there's no HFP interface, we dispatch a runnable
+    // that calls the profile result handler.
+    nsRefPtr<nsRunnable> r =
+      new OnErrorProfileResultHandlerRunnable(aRes, NS_ERROR_FAILURE);
+    if (NS_FAILED(NS_DispatchToMainThread(r))) {
+      BT_LOGR("Failed to dispatch HFP OnError runnable");
     }
     return;
   }
 
   nsRefPtr<CleanupInitResultHandler> res =
     new CleanupInitResultHandler(interface, aRes);
 
   if (sBluetoothHfpInterface) {
--- a/dom/mobileconnection/gonk/MobileConnectionService.js
+++ b/dom/mobileconnection/gonk/MobileConnectionService.js
@@ -22,18 +22,18 @@ const GONK_MOBILECONNECTIONSERVICE_CID =
 const MOBILECONNECTIONINFO_CID =
   Components.ID("{8162b3c0-664b-45f6-96cd-f07b4e193b0e}");
 const MOBILENETWORKINFO_CID =
   Components.ID("{a6c8416c-09b4-46d1-bf29-6520d677d085}");
 const MOBILECELLINFO_CID =
   Components.ID("{0635d9ab-997e-4cdf-84e7-c1883752dff3}");
 const MOBILECALLFORWARDINGOPTIONS_CID =
   Components.ID("{e0cf4463-ee63-4b05-ab2e-d94bf764836c}");
-const TELEPHONYCALLBACK_CID =
-  Components.ID("{6e1af17e-37f3-11e4-aed3-60a44c237d2b}");
+const TELEPHONYDIALCALLBACK_CID =
+  Components.ID("{c2af1a5d-3649-44ef-a1ff-18e9ac1dec51}");
 
 const NS_XPCOM_SHUTDOWN_OBSERVER_ID      = "xpcom-shutdown";
 const NS_PREFBRANCH_PREFCHANGE_TOPIC_ID  = "nsPref:changed";
 const NS_NETWORK_ACTIVE_CHANGED_TOPIC_ID = "network-active-changed";
 
 const kPrefRilDebuggingEnabled = "ril.debugging.enabled";
 
 XPCOMUtils.defineLazyServiceGetter(this, "gSystemMessenger",
@@ -134,24 +134,24 @@ MobileCallForwardingOptions.prototype = 
   action: Ci.nsIMobileConnection.CALL_FORWARD_ACTION_UNKNOWN,
   reason: Ci.nsIMobileConnection.CALL_FORWARD_REASON_UNKNOWN,
   number: null,
   timeSeconds: -1,
   serviceClass: Ci.nsIMobileConnection.ICC_SERVICE_CLASS_NONE
 }
 
 /**
- * Wrap a MobileConnectionCallback to a TelephonyCallback.
+ * Wrap a MobileConnectionCallback to a TelephonyDialCallback.
  */
-function TelephonyCallback(aCallback) {
+function TelephonyDialCallback(aCallback) {
   this.callback = aCallback;
 }
-TelephonyCallback.prototype = {
-  QueryInterface:   XPCOMUtils.generateQI([Ci.nsITelephonyCallback]),
-  classID:          TELEPHONYCALLBACK_CID,
+TelephonyDialCallback.prototype = {
+  QueryInterface:   XPCOMUtils.generateQI([Ci.nsITelephonyDialCallback]),
+  classID:          TELEPHONYDIALCALLBACK_CID,
 
   _notifySendCancelMmiSuccess: function(aResult) {
     // No additional information.
     if (aResult.additionalInformation === undefined) {
       this.callback.notifySendCancelMmiSuccess(aResult.serviceCode,
                                                aResult.statusMessage);
       return;
     }
@@ -687,18 +687,18 @@ MobileConnectionProvider.prototype = {
       }
 
       aCallback.notifySuccessWithBoolean(aResponse.enabled);
       return false;
     }).bind(this));
   },
 
   sendMMI: function(aMmi, aCallback) {
-    let telephonyCallback = new TelephonyCallback(aCallback);
-    gGonkTelephonyService.dialMMI(this._clientId, aMmi, telephonyCallback);
+    let callback = new TelephonyDialCallback(aCallback);
+    gGonkTelephonyService.dialMMI(this._clientId, aMmi, callback);
   },
 
   cancelMMI: function(aCallback) {
     this._radioInterface.sendWorkerMessage("cancelUSSD", null,
                                            (function(aResponse) {
       if (aResponse.errorMsg) {
         aCallback.notifyError(aResponse.errorMsg);
         return false;
@@ -995,24 +995,16 @@ MobileConnectionService.prototype = {
   notifyUssdReceived: function(aClientId, aMessage, aSessionEnded) {
     if (DEBUG) {
       debug("notifyUssdReceived for " + aClientId + ": " +
             aMessage + " (sessionEnded : " + aSessionEnded + ")");
     }
 
     this.getItemByServiceId(aClientId)
         .deliverListenerEvent("notifyUssdReceived", [aMessage, aSessionEnded]);
-
-    let info = {
-      message: aMessage,
-      sessionEnded: aSessionEnded,
-      serviceId: aClientId
-    };
-
-    gSystemMessenger.broadcastMessage("ussd-received", info);
   },
 
   notifyDataError: function(aClientId, aMessage) {
     if (DEBUG) {
       debug("notifyDataError for " + aClientId + ": " + aMessage);
     }
 
     this.getItemByServiceId(aClientId)
--- a/dom/nfc/gonk/Nfc.js
+++ b/dom/nfc/gonk/Nfc.js
@@ -625,16 +625,17 @@ Nfc.prototype = {
       case "NFC:PowerOff":
         this.setConfig({powerLevel: NFC.NFC_POWER_LEVEL_DISABLED,
                         requestId: message.data.requestId});
         break;
       case "NFC:ReadNDEF":
         this.sendToNfcService("readNDEF", message.data);
         break;
       case "NFC:WriteNDEF":
+        message.data.isP2P = SessionHelper.isP2PSession(message.data.sessionId);
         this.sendToNfcService("writeNDEF", message.data);
         break;
       case "NFC:MakeReadOnlyNDEF":
         this.sendToNfcService("makeReadOnlyNDEF", message.data);
         break;
       case "NFC:Connect":
         this.sendToNfcService("connect", message.data);
         break;
--- a/dom/nfc/gonk/NfcGonkMessage.h
+++ b/dom/nfc/gonk/NfcGonkMessage.h
@@ -3,17 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef NfcGonkMessage_h
 #define NfcGonkMessage_h
 
 namespace mozilla {
 
 #define NFCD_MAJOR_VERSION 1
-#define NFCD_MINOR_VERSION 10
+#define NFCD_MINOR_VERSION 12
 
 enum NfcRequest {
   ConfigReq = 0,
   ConnectReq,
   CloseReq,
   ReadNDEFReq,
   WriteNDEFReq,
   MakeReadOnlyNDEFReq,
--- a/dom/nfc/gonk/NfcMessageHandler.cpp
+++ b/dom/nfc/gonk/NfcMessageHandler.cpp
@@ -191,16 +191,17 @@ NfcMessageHandler::ReadNDEFResponse(cons
   return true;
 }
 
 bool
 NfcMessageHandler::WriteNDEFRequest(Parcel& aParcel, const CommandOptions& aOptions)
 {
   aParcel.writeInt32(NfcRequest::WriteNDEFReq);
   aParcel.writeInt32(aOptions.mSessionId);
+  aParcel.writeInt32(aOptions.mIsP2P);
   WriteNDEFMessage(aParcel, aOptions);
   mRequestIdQueue.AppendElement(aOptions.mRequestId);
   return true;
 }
 
 bool
 NfcMessageHandler::MakeReadOnlyNDEFRequest(Parcel& aParcel, const CommandOptions& aOptions)
 {
--- a/dom/nfc/gonk/NfcOptions.h
+++ b/dom/nfc/gonk/NfcOptions.h
@@ -31,16 +31,17 @@ struct CommandOptions
     prop = defaultValue;                              \
   }
 
     COPY_FIELD(mType)
     COPY_FIELD(mRequestId)
     COPY_OPT_FIELD(mSessionId, 0)
     COPY_OPT_FIELD(mPowerLevel, 0)
     COPY_OPT_FIELD(mTechType, 0)
+    COPY_OPT_FIELD(mIsP2P, false)
 
     if (!aOther.mRecords.WasPassed()) {
       return;
     }
 
     mozilla::dom::Sequence<mozilla::dom::MozNDEFRecordOptions> const & currentValue = aOther.mRecords.InternalValue();
     int count = currentValue.Length();
     for (int32_t i = 0; i < count; i++) {
@@ -72,16 +73,17 @@ struct CommandOptions
 #undef COPY_OPT_FIELD
   }
 
   nsString mType;
   int32_t mSessionId;
   nsString mRequestId;
   int32_t mPowerLevel;
   int32_t mTechType;
+  bool mIsP2P;
   nsTArray<NDEFRecordStruct> mRecords;
 };
 
 struct EventOptions
 {
   EventOptions()
     : mType(EmptyString()), mStatus(-1), mSessionId(-1), mRequestId(EmptyString()), mMajorVersion(-1), mMinorVersion(-1),
       mIsReadOnly(-1), mCanBeMadeReadOnly(-1), mMaxSupportedLength(-1), mPowerLevel(-1),
--- a/dom/nfc/nsNfc.js
+++ b/dom/nfc/nsNfc.js
@@ -26,42 +26,26 @@ XPCOMUtils.defineLazyServiceGetter(this,
 /**
  * NFCTag
  */
 function MozNFCTag() {
   debug("In MozNFCTag Constructor");
   this._nfcContentHelper = Cc["@mozilla.org/nfc/content-helper;1"]
                              .getService(Ci.nsINfcContentHelper);
   this.session = null;
-
-  // Map WebIDL declared enum map names to integer
-  this._techTypesMap = [];
-  this._techTypesMap['NFC_A'] = 0;
-  this._techTypesMap['NFC_B'] = 1;
-  this._techTypesMap['NFC_ISO_DEP'] = 2;
-  this._techTypesMap['NFC_F'] = 3;
-  this._techTypesMap['NFC_V'] = 4;
-  this._techTypesMap['NDEF'] = 5;
-  this._techTypesMap['NDEF_FORMATABLE'] = 6;
-  this._techTypesMap['MIFARE_CLASSIC'] = 7;
-  this._techTypesMap['MIFARE_ULTRALIGHT'] = 8;
-  this._techTypesMap['NFC_BARCODE'] = 9;
-  this._techTypesMap['P2P'] = 10;
 }
 MozNFCTag.prototype = {
   _nfcContentHelper: null,
   _window: null,
 
   initialize: function(aWindow, aSessionToken) {
     this._window = aWindow;
     this.session = aSessionToken;
   },
 
-  _techTypesMap: null,
-
   // NFCTag interface:
   readNDEF: function readNDEF() {
     return this._nfcContentHelper.readNDEF(this._window, this.session);
   },
   writeNDEF: function writeNDEF(records) {
     return this._nfcContentHelper.writeNDEF(this._window, records, this.session);
   },
   makeReadOnlyNDEF: function makeReadOnlyNDEF() {
--- a/dom/system/gonk/RadioInterfaceLayer.js
+++ b/dom/system/gonk/RadioInterfaceLayer.js
@@ -1980,23 +1980,28 @@ RadioInterface.prototype = {
         break;
       case "callDisconnected":
         gTelephonyService.notifyCallDisconnected(this.clientId, message.call);
         break;
       case "conferenceCallStateChanged":
         gTelephonyService.notifyConferenceCallStateChanged(message.state);
         break;
       case "cdmaCallWaiting":
-        gTelephonyService.notifyCdmaCallWaiting(this.clientId, message.waitingCall);
+        gTelephonyService.notifyCdmaCallWaiting(this.clientId,
+                                                message.waitingCall);
         break;
       case "suppSvcNotification":
         gTelephonyService.notifySupplementaryService(this.clientId,
                                                      message.callIndex,
                                                      message.notification);
         break;
+      case "ussdreceived":
+        gTelephonyService.notifyUssdReceived(this.clientId, message.message,
+                                             message.sessionEnded);
+        break;
       case "datacallerror":
         connHandler.handleDataCallError(message);
         break;
       case "datacallstatechange":
         let addresses = [];
         for (let i = 0; i < message.addresses.length; i++) {
           let [address, prefixLength] = message.addresses[i].split("/");
           // From AOSP hardware/ril/include/telephony/ril.h, that address prefix
@@ -2040,21 +2045,16 @@ RadioInterface.prototype = {
         gMobileConnectionService.notifyOtaStatusChanged(this.clientId, message.status);
         break;
       case "radiostatechange":
         // gRadioEnabledController should know the radio state for each client,
         // so notify gRadioEnabledController here.
         gRadioEnabledController.notifyRadioStateChanged(this.clientId,
                                                         message.radioState);
         break;
-      case "ussdreceived":
-        gMobileConnectionService.notifyUssdReceived(this.clientId,
-                                                    message.message,
-                                                    message.sessionEnded);
-        break;
       case "cardstatechange":
         this.rilContext.cardState = message.cardState;
         gRadioEnabledController.receiveCardState(this.clientId);
         gMessageManager.sendIccMessage("RIL:CardStateChanged",
                                        this.clientId, message);
         break;
       case "sms-received":
         this.handleSmsMultipart(message);
--- a/dom/system/gonk/ril_worker.js
+++ b/dom/system/gonk/ril_worker.js
@@ -2636,32 +2636,58 @@ RilObject.prototype = {
     }
 
     // If the MMI code is not a known code, it is treated as an ussd.
     if (!_isRadioAvailable()) {
       return;
     }
 
     options.ussd = mmi.fullMMI;
+
+    if (options.startNewSession && this._ussdSession) {
+      if (DEBUG) this.context.debug("Cancel existing ussd session.");
+      this.cachedUSSDRequest = options;
+      this.cancelUSSD({});
+      return;
+    }
+
     this.sendUSSD(options);
   },
 
   /**
+   * Cache the request for send out a new ussd when there is an existing
+   * session. We should do cancelUSSD first.
+   */
+  cachedUSSDRequest : null,
+
+  /**
    * Send USSD.
    *
    * @param ussd
    *        String containing the USSD code.
-   *
-   */
-   sendUSSD: function(options) {
-     let Buf = this.context.Buf;
-     Buf.newParcel(REQUEST_SEND_USSD, options);
-     Buf.writeString(options.ussd);
-     Buf.sendParcel();
-   },
+   * @param checkSession
+   *        True if an existing session should be there.
+   */
+  sendUSSD: function(options) {
+    if (options.checkSession && !this._ussdSession) {
+      options.success = false;
+      options.errorMsg = GECKO_ERROR_GENERIC_FAILURE;
+      this.sendChromeMessage(options);
+      return;
+    }
+
+    this.sendRilRequestSendUSSD(options);
+  },
+
+  sendRilRequestSendUSSD: function(options) {
+    let Buf = this.context.Buf;
+    Buf.newParcel(REQUEST_SEND_USSD, options);
+    Buf.writeString(options.ussd);
+    Buf.sendParcel();
+  },
 
   /**
    * Cancel pending USSD.
    */
    cancelUSSD: function(options) {
      this.context.Buf.simpleRequest(REQUEST_CANCEL_USSD, options);
    },
 
@@ -5674,19 +5700,29 @@ RilObject.prototype[REQUEST_SEND_USSD] =
   options.success = (this._ussdSession = options.rilRequestError === 0);
   options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
   this.sendChromeMessage(options);
 };
 RilObject.prototype[REQUEST_CANCEL_USSD] = function REQUEST_CANCEL_USSD(length, options) {
   if (DEBUG) {
     this.context.debug("REQUEST_CANCEL_USSD" + JSON.stringify(options));
   }
+
   options.success = (options.rilRequestError === 0);
   this._ussdSession = !options.success;
   options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
+
+  // The cancelUSSD is triggered by ril_worker itself.
+  if (this.cachedUSSDRequest) {
+    if (DEBUG) this.context.debug("Send out the cached ussd request");
+    this.sendUSSD(this.cachedUSSDRequest);
+    this.cachedUSSDRequest = null;
+    return;
+  }
+
   this.sendChromeMessage(options);
 };
 RilObject.prototype[REQUEST_GET_CLIR] = function REQUEST_GET_CLIR(length, options) {
   options.success = (options.rilRequestError === 0);
   if (!options.success) {
     options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
     this.sendChromeMessage(options);
     return;
--- a/dom/telephony/Telephony.cpp
+++ b/dom/telephony/Telephony.cpp
@@ -21,17 +21,17 @@
 #include "nsPIDOMWindow.h"
 #include "nsServiceManagerUtils.h"
 #include "nsThreadUtils.h"
 
 #include "CallsList.h"
 #include "TelephonyCall.h"
 #include "TelephonyCallGroup.h"
 #include "TelephonyCallId.h"
-#include "TelephonyCallback.h"
+#include "TelephonyDialCallback.h"
 
 // Service instantiation
 #include "ipc/TelephonyIPCService.h"
 #if defined(MOZ_WIDGET_GONK) && defined(MOZ_B2G_RIL)
 #include "nsIGonkTelephonyService.h"
 #endif
 #include "nsXULAppAPI.h" // For XRE_GetProcessType()
 
@@ -230,18 +230,18 @@ Telephony::DialInternal(uint32_t aServic
   }
 
   // We only support one outgoing call at a time.
   if (HasDialingCall()) {
     promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
     return promise.forget();
   }
 
-  nsCOMPtr<nsITelephonyCallback> callback =
-    new TelephonyCallback(GetOwner(), this, promise, aServiceId);
+  nsCOMPtr<nsITelephonyDialCallback> callback =
+    new TelephonyDialCallback(GetOwner(), this, promise, aServiceId);
 
   nsresult rv = mService->Dial(aServiceId, aNumber, aEmergency, callback);
   if (NS_FAILED(rv)) {
     promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
     return promise.forget();
   }
 
   return promise.forget();
--- a/dom/telephony/Telephony.h
+++ b/dom/telephony/Telephony.h
@@ -18,17 +18,17 @@
 #include "TelephonyCall.h"
 
 class nsPIDOMWindow;
 
 namespace mozilla {
 namespace dom {
 namespace telephony {
 
-class TelephonyCallback;
+class TelephonyDialCallback;
 
 } // namespace telephony
 
 class OwningTelephonyCallOrTelephonyCallGroup;
 
 class Telephony MOZ_FINAL : public DOMEventTargetHelper,
                             private nsITelephonyListener
 {
@@ -38,17 +38,17 @@ class Telephony MOZ_FINAL : public DOMEv
    * and passes it to nsITelephonyService. The onreceived events are first
    * delivered to mListener and then forwarded to its owner, Telephony. See
    * also bug 775997 comment #51.
    */
   class Listener;
   class EnumerationAck;
 
   friend class EnumerationAck;
-  friend class telephony::TelephonyCallback;
+  friend class telephony::TelephonyDialCallback;
 
   nsCOMPtr<nsITelephonyService> mService;
   nsRefPtr<Listener> mListener;
 
   nsTArray<nsRefPtr<TelephonyCall> > mCalls;
   nsRefPtr<CallsList> mCallsList;
 
   nsRefPtr<TelephonyCallGroup> mGroup;
--- a/dom/telephony/TelephonyCallback.cpp
+++ b/dom/telephony/TelephonyCallback.cpp
@@ -1,139 +1,34 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "TelephonyCallback.h"
 
-#include "mozilla/dom/DOMMMIError.h"
-#include "nsServiceManagerUtils.h"
+#include "mozilla/dom/Promise.h"
+#include "nsJSUtils.h"
 
 using namespace mozilla::dom;
 using namespace mozilla::dom::telephony;
 
 NS_IMPL_ISUPPORTS(TelephonyCallback, nsITelephonyCallback)
 
-TelephonyCallback::TelephonyCallback(nsPIDOMWindow* aWindow,
-                                     Telephony* aTelephony,
-                                     Promise* aPromise,
-                                     uint32_t aServiceId)
-  : mWindow(aWindow), mTelephony(aTelephony), mPromise(aPromise),
-    mServiceId(aServiceId)
-{
-  MOZ_ASSERT(mTelephony);
-}
-
-nsresult
-TelephonyCallback::NotifyDialMMISuccess(const nsAString& aStatusMessage)
+TelephonyCallback::TelephonyCallback(Promise* aPromise)
+  : mPromise(aPromise)
 {
-  AutoJSAPI jsapi;
-  if (!NS_WARN_IF(jsapi.Init(mWindow))) {
-    return NS_ERROR_FAILURE;
-  }
-
-  JSContext* cx = jsapi.cx();
-
-  MozMMIResult result;
-
-  result.mServiceCode.Assign(mServiceCode);
-  result.mStatusMessage.Assign(aStatusMessage);
-
-  return NotifyDialMMISuccess(cx, result);
-}
-
-nsresult
-TelephonyCallback::NotifyDialMMISuccess(JSContext* aCx,
-                                        const nsAString& aStatusMessage,
-                                        JS::Handle<JS::Value> aInfo)
-{
-  RootedDictionary<MozMMIResult> result(aCx);
-
-  result.mServiceCode.Assign(mServiceCode);
-  result.mStatusMessage.Assign(aStatusMessage);
-  result.mAdditionalInformation.Construct().SetAsObject() = &aInfo.toObject();
-
-  return NotifyDialMMISuccess(aCx, result);
-}
-
-nsresult
-TelephonyCallback::NotifyDialMMISuccess(JSContext* aCx,
-                                        const MozMMIResult& aResult)
-{
-  JS::Rooted<JS::Value> jsResult(aCx);
-
-  if (!ToJSValue(aCx, aResult, &jsResult)) {
-    JS_ClearPendingException(aCx);
-    return NS_ERROR_TYPE_ERR;
-  }
-
-  return NotifyDialMMISuccess(jsResult);
 }
 
 // nsITelephonyCallback
 
 NS_IMETHODIMP
-TelephonyCallback::NotifyDialMMI(const nsAString& aServiceCode)
-{
-  mMMIRequest = new DOMRequest(mWindow);
-  mServiceCode.Assign(aServiceCode);
-
-  mPromise->MaybeResolve(mMMIRequest);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-TelephonyCallback::NotifyDialError(const nsAString& aError)
+TelephonyCallback::NotifySuccess()
 {
-  mPromise->MaybeRejectBrokenly(aError);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-TelephonyCallback::NotifyDialCallSuccess(uint32_t aCallIndex,
-                                         const nsAString& aNumber)
-{
-  nsRefPtr<TelephonyCallId> id = mTelephony->CreateCallId(aNumber);
-  nsRefPtr<TelephonyCall> call =
-      mTelephony->CreateCall(id, mServiceId, aCallIndex,
-                             nsITelephonyService::CALL_STATE_DIALING);
-
-  mPromise->MaybeResolve(call);
+  mPromise->MaybeResolve(JS::UndefinedHandleValue);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-TelephonyCallback::NotifyDialMMISuccess(JS::Handle<JS::Value> aResult)
-{
-  nsCOMPtr<nsIDOMRequestService> rs = do_GetService(DOMREQUEST_SERVICE_CONTRACTID);
-  NS_ENSURE_TRUE(rs, NS_ERROR_FAILURE);
-
-  return rs->FireSuccessAsync(mMMIRequest, aResult);
-}
-
-NS_IMETHODIMP
-TelephonyCallback::NotifyDialMMIError(const nsAString& aError)
+TelephonyCallback::NotifyError(const nsAString& aError)
 {
-  Nullable<int16_t> info;
-
-  nsRefPtr<DOMError> error =
-      new DOMMMIError(mWindow, aError, EmptyString(), mServiceCode, info);
-
-  nsCOMPtr<nsIDOMRequestService> rs = do_GetService(DOMREQUEST_SERVICE_CONTRACTID);
-  NS_ENSURE_TRUE(rs, NS_ERROR_FAILURE);
-
-  return rs->FireDetailedError(mMMIRequest, error);
+  mPromise->MaybeRejectBrokenly(aError);
+  return NS_OK;
 }
-
-NS_IMETHODIMP
-TelephonyCallback::NotifyDialMMIErrorWithInfo(const nsAString& aError,
-                                              uint16_t aInfo)
-{
-  Nullable<int16_t> info(aInfo);
-
-  nsRefPtr<DOMError> error =
-      new DOMMMIError(mWindow, aError, EmptyString(), mServiceCode, info);
-
-  nsCOMPtr<nsIDOMRequestService> rs = do_GetService(DOMREQUEST_SERVICE_CONTRACTID);
-  NS_ENSURE_TRUE(rs, NS_ERROR_FAILURE);
-
-  return rs->FireDetailedError(mMMIRequest, error);
-}
--- a/dom/telephony/TelephonyCallback.h
+++ b/dom/telephony/TelephonyCallback.h
@@ -1,81 +1,38 @@
 /* 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/. */
 
 #ifndef mozilla_dom_TelephonyCallback_h
 #define mozilla_dom_TelephonyCallback_h
 
-#include "Telephony.h"
-#include "mozilla/dom/DOMRequest.h"
-#include "mozilla/dom/MozMobileConnectionBinding.h"
-#include "mozilla/dom/Promise.h"
-#include "mozilla/dom/ToJSValue.h"
 #include "nsAutoPtr.h"
 #include "nsCOMPtr.h"
 #include "nsITelephonyService.h"
-#include "nsJSUtils.h"
-#include "nsString.h"
-
-class nsPIDOMWindow;
 
 namespace mozilla {
 namespace dom {
+
+class Promise;
+
 namespace telephony {
 
-class TelephonyCallback MOZ_FINAL : public nsITelephonyCallback
+class TelephonyCallback : public nsITelephonyCallback
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSITELEPHONYCALLBACK
 
-  TelephonyCallback(nsPIDOMWindow* aWindow, Telephony* aTelephony,
-                    Promise* aPromise, uint32_t aServiceId);
-
-  nsresult
-  NotifyDialMMISuccess(const nsAString& aStatusMessage);
-
-  template<typename T>
-  nsresult
-  NotifyDialMMISuccess(const nsAString& aStatusMessage, const T& aInfo)
-  {
-    AutoJSAPI jsapi;
-    if (!NS_WARN_IF(jsapi.Init(mWindow))) {
-      return NS_ERROR_FAILURE;
-    }
-
-    JSContext* cx = jsapi.cx();
-    JS::Rooted<JS::Value> info(cx);
+  TelephonyCallback(Promise* aPromise);
 
-    if (!ToJSValue(cx, aInfo, &info)) {
-      JS_ClearPendingException(cx);
-      return NS_ERROR_TYPE_ERR;
-    }
-
-    return NotifyDialMMISuccess(cx, aStatusMessage, info);
-  }
-
-private:
-  ~TelephonyCallback() {}
+protected:
+  virtual ~TelephonyCallback() {}
 
-  nsresult
-  NotifyDialMMISuccess(JSContext* aCx, const nsAString& aStatusMessage,
-                       JS::Handle<JS::Value> aInfo);
-
-  nsresult
-  NotifyDialMMISuccess(JSContext* aCx, const MozMMIResult& aResult);
-
-
-  nsCOMPtr<nsPIDOMWindow> mWindow;
-  nsRefPtr<Telephony> mTelephony;
+protected:
   nsRefPtr<Promise> mPromise;
-  uint32_t mServiceId;
-
-  nsRefPtr<DOMRequest> mMMIRequest;
-  nsString mServiceCode;
 };
 
 } // namespace telephony
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_TelephonyCallback_h
new file mode 100644
--- /dev/null
+++ b/dom/telephony/TelephonyDialCallback.cpp
@@ -0,0 +1,133 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "TelephonyDialCallback.h"
+
+#include "mozilla/dom/DOMMMIError.h"
+#include "nsServiceManagerUtils.h"
+
+using namespace mozilla::dom;
+using namespace mozilla::dom::telephony;
+
+NS_IMPL_ISUPPORTS_INHERITED(TelephonyDialCallback, TelephonyCallback,
+                            nsITelephonyDialCallback)
+
+TelephonyDialCallback::TelephonyDialCallback(nsPIDOMWindow* aWindow,
+                                             Telephony* aTelephony,
+                                             Promise* aPromise,
+                                             uint32_t aServiceId)
+  : TelephonyCallback(aPromise), mWindow(aWindow), mTelephony(aTelephony),
+    mServiceId(aServiceId)
+{
+  MOZ_ASSERT(mTelephony);
+}
+
+nsresult
+TelephonyDialCallback::NotifyDialMMISuccess(const nsAString& aStatusMessage)
+{
+  AutoJSAPI jsapi;
+  if (!NS_WARN_IF(jsapi.Init(mWindow))) {
+    return NS_ERROR_FAILURE;
+  }
+
+  JSContext* cx = jsapi.cx();
+
+  MozMMIResult result;
+
+  result.mServiceCode.Assign(mServiceCode);
+  result.mStatusMessage.Assign(aStatusMessage);
+
+  return NotifyDialMMISuccess(cx, result);
+}
+
+nsresult
+TelephonyDialCallback::NotifyDialMMISuccess(JSContext* aCx,
+                                            const nsAString& aStatusMessage,
+                                            JS::Handle<JS::Value> aInfo)
+{
+  RootedDictionary<MozMMIResult> result(aCx);
+
+  result.mServiceCode.Assign(mServiceCode);
+  result.mStatusMessage.Assign(aStatusMessage);
+  result.mAdditionalInformation.Construct().SetAsObject() = &aInfo.toObject();
+
+  return NotifyDialMMISuccess(aCx, result);
+}
+
+nsresult
+TelephonyDialCallback::NotifyDialMMISuccess(JSContext* aCx,
+                                            const MozMMIResult& aResult)
+{
+  JS::Rooted<JS::Value> jsResult(aCx);
+
+  if (!ToJSValue(aCx, aResult, &jsResult)) {
+    JS_ClearPendingException(aCx);
+    return NS_ERROR_TYPE_ERR;
+  }
+
+  return NotifyDialMMISuccess(jsResult);
+}
+
+// nsITelephonyDialCallback
+
+NS_IMETHODIMP
+TelephonyDialCallback::NotifyDialMMI(const nsAString& aServiceCode)
+{
+  mMMIRequest = new DOMRequest(mWindow);
+  mServiceCode.Assign(aServiceCode);
+
+  mPromise->MaybeResolve(mMMIRequest);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+TelephonyDialCallback::NotifyDialCallSuccess(uint32_t aCallIndex,
+                                             const nsAString& aNumber)
+{
+  nsRefPtr<TelephonyCallId> id = mTelephony->CreateCallId(aNumber);
+  nsRefPtr<TelephonyCall> call =
+      mTelephony->CreateCall(id, mServiceId, aCallIndex,
+                             nsITelephonyService::CALL_STATE_DIALING);
+
+  mPromise->MaybeResolve(call);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+TelephonyDialCallback::NotifyDialMMISuccess(JS::Handle<JS::Value> aResult)
+{
+  nsCOMPtr<nsIDOMRequestService> rs = do_GetService(DOMREQUEST_SERVICE_CONTRACTID);
+  NS_ENSURE_TRUE(rs, NS_ERROR_FAILURE);
+
+  return rs->FireSuccessAsync(mMMIRequest, aResult);
+}
+
+NS_IMETHODIMP
+TelephonyDialCallback::NotifyDialMMIError(const nsAString& aError)
+{
+  Nullable<int16_t> info;
+
+  nsRefPtr<DOMError> error =
+      new DOMMMIError(mWindow, aError, EmptyString(), mServiceCode, info);
+
+  nsCOMPtr<nsIDOMRequestService> rs = do_GetService(DOMREQUEST_SERVICE_CONTRACTID);
+  NS_ENSURE_TRUE(rs, NS_ERROR_FAILURE);
+
+  return rs->FireDetailedError(mMMIRequest, error);
+}
+
+NS_IMETHODIMP
+TelephonyDialCallback::NotifyDialMMIErrorWithInfo(const nsAString& aError,
+                                                  uint16_t aInfo)
+{
+  Nullable<int16_t> info(aInfo);
+
+  nsRefPtr<DOMError> error =
+      new DOMMMIError(mWindow, aError, EmptyString(), mServiceCode, info);
+
+  nsCOMPtr<nsIDOMRequestService> rs = do_GetService(DOMREQUEST_SERVICE_CONTRACTID);
+  NS_ENSURE_TRUE(rs, NS_ERROR_FAILURE);
+
+  return rs->FireDetailedError(mMMIRequest, error);
+}
new file mode 100644
--- /dev/null
+++ b/dom/telephony/TelephonyDialCallback.h
@@ -0,0 +1,84 @@
+/* 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/. */
+
+#ifndef mozilla_dom_TelephonyDialCallback_h
+#define mozilla_dom_TelephonyDialCallback_h
+
+#include "Telephony.h"
+#include "mozilla/dom/DOMRequest.h"
+#include "mozilla/dom/MozMobileConnectionBinding.h"
+#include "mozilla/dom/Promise.h"
+#include "mozilla/dom/ToJSValue.h"
+#include "mozilla/dom/telephony/TelephonyCallback.h"
+#include "nsAutoPtr.h"
+#include "nsCOMPtr.h"
+#include "nsITelephonyService.h"
+#include "nsJSUtils.h"
+#include "nsString.h"
+
+class nsPIDOMWindow;
+
+namespace mozilla {
+namespace dom {
+namespace telephony {
+
+class TelephonyDialCallback MOZ_FINAL : public TelephonyCallback,
+                                        public nsITelephonyDialCallback
+{
+public:
+  NS_DECL_ISUPPORTS_INHERITED
+  NS_DECL_NSITELEPHONYDIALCALLBACK
+
+  TelephonyDialCallback(nsPIDOMWindow* aWindow, Telephony* aTelephony,
+                        Promise* aPromise, uint32_t aServiceId);
+
+  NS_FORWARD_NSITELEPHONYCALLBACK(TelephonyCallback::)
+
+  nsresult
+  NotifyDialMMISuccess(const nsAString& aStatusMessage);
+
+  template<typename T>
+  nsresult
+  NotifyDialMMISuccess(const nsAString& aStatusMessage, const T& aInfo)
+  {
+    AutoJSAPI jsapi;
+    if (!NS_WARN_IF(jsapi.Init(mWindow))) {
+      return NS_ERROR_FAILURE;
+    }
+
+    JSContext* cx = jsapi.cx();
+    JS::Rooted<JS::Value> info(cx);
+
+    if (!ToJSValue(cx, aInfo, &info)) {
+      JS_ClearPendingException(cx);
+      return NS_ERROR_TYPE_ERR;
+    }
+
+    return NotifyDialMMISuccess(cx, aStatusMessage, info);
+  }
+
+private:
+  ~TelephonyDialCallback() {}
+
+  nsresult
+  NotifyDialMMISuccess(JSContext* aCx, const nsAString& aStatusMessage,
+                       JS::Handle<JS::Value> aInfo);
+
+  nsresult
+  NotifyDialMMISuccess(JSContext* aCx, const MozMMIResult& aResult);
+
+
+  nsCOMPtr<nsPIDOMWindow> mWindow;
+  nsRefPtr<Telephony> mTelephony;
+  uint32_t mServiceId;
+
+  nsRefPtr<DOMRequest> mMMIRequest;
+  nsString mServiceCode;
+};
+
+} // namespace telephony
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_TelephonyDialCallback_h
new file mode 100644
--- /dev/null
+++ b/dom/telephony/USSDSession.cpp
@@ -0,0 +1,97 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/dom/USSDSession.h"
+
+#include "mozilla/dom/USSDSessionBinding.h"
+#include "mozilla/dom/telephony/TelephonyCallback.h"
+#include "nsIGlobalObject.h"
+#include "nsServiceManagerUtils.h"
+
+using namespace mozilla::dom;
+using namespace mozilla::dom::telephony;
+using mozilla::ErrorResult;
+
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(USSDSession, mWindow)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(USSDSession)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(USSDSession)
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(USSDSession)
+  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
+  NS_INTERFACE_MAP_ENTRY(nsISupports)
+NS_INTERFACE_MAP_END
+
+USSDSession::USSDSession(nsPIDOMWindow* aWindow, nsITelephonyService* aService,
+                         uint32_t aServiceId)
+  : mWindow(aWindow), mService(aService), mServiceId(aServiceId)
+{
+}
+
+USSDSession::~USSDSession()
+{
+}
+
+nsPIDOMWindow*
+USSDSession::GetParentObject() const
+{
+  return mWindow;
+}
+
+JSObject*
+USSDSession::WrapObject(JSContext* aCx)
+{
+  return USSDSessionBinding::Wrap(aCx, this);
+}
+
+// WebIDL
+
+already_AddRefed<USSDSession>
+USSDSession::Constructor(const GlobalObject& aGlobal, uint32_t aServiceId,
+                         ErrorResult& aRv)
+{
+  nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aGlobal.GetAsSupports());
+  if (!window) {
+    aRv.Throw(NS_ERROR_UNEXPECTED);
+    return nullptr;
+  }
+
+  nsCOMPtr<nsITelephonyService> ril =
+    do_GetService(TELEPHONY_SERVICE_CONTRACTID);
+  if (!ril) {
+    aRv.Throw(NS_ERROR_UNEXPECTED);
+    return nullptr;
+  }
+
+  nsRefPtr<USSDSession> session = new USSDSession(window, ril, aServiceId);
+  return session.forget();
+}
+
+already_AddRefed<Promise>
+USSDSession::Send(const nsAString& aUssd, ErrorResult& aRv)
+{
+  if (!mService) {
+    aRv.Throw(NS_ERROR_FAILURE);
+    return nullptr;
+  }
+
+  nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(mWindow);
+  if (!global) {
+    return nullptr;
+  }
+
+  nsRefPtr<Promise> promise = Promise::Create(global, aRv);
+  if (aRv.Failed()) {
+    return nullptr;
+  }
+
+  nsCOMPtr<nsITelephonyCallback> callback = new TelephonyCallback(promise);
+
+  nsresult rv = mService->SendUSSD(mServiceId, aUssd, callback);
+  if (NS_FAILED(rv)) {
+    promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
+  }
+
+  return promise.forget();
+}
new file mode 100644
--- /dev/null
+++ b/dom/telephony/USSDSession.h
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* 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/. */
+
+#ifndef mozilla_dom_USSDSession_h
+#define mozilla_dom_USSDSession_h
+
+#include "mozilla/Attributes.h"
+#include "mozilla/ErrorResult.h"
+#include "mozilla/dom/BindingDeclarations.h"
+#include "mozilla/dom/Promise.h"
+#include "nsAutoPtr.h"
+#include "nsCOMPtr.h"
+#include "nsCycleCollectionParticipant.h"
+#include "nsITelephonyService.h"
+#include "nsPIDOMWindow.h"
+#include "nsWrapperCache.h"
+
+struct JSContext;
+
+namespace mozilla {
+namespace dom {
+
+class USSDSession MOZ_FINAL : public nsISupports,
+                              public nsWrapperCache
+{
+public:
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(USSDSession)
+
+  USSDSession(nsPIDOMWindow* aWindow, nsITelephonyService* aService,
+              uint32_t aServiceId);
+
+  nsPIDOMWindow*
+  GetParentObject() const;
+
+  virtual JSObject*
+  WrapObject(JSContext* aCx) MOZ_OVERRIDE;
+
+  // WebIDL
+  static already_AddRefed<USSDSession>
+  Constructor(const GlobalObject& aGlobal, uint32_t aServiceId,
+              ErrorResult& aRv);
+
+  already_AddRefed<Promise>
+  Send(const nsAString& aUssd, ErrorResult& aRv);
+
+private:
+  ~USSDSession();
+
+  nsCOMPtr<nsPIDOMWindow> mWindow;
+  nsCOMPtr<nsITelephonyService> mService;
+  uint32_t mServiceId;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_USSDSession_h
--- a/dom/telephony/gonk/TelephonyService.js
+++ b/dom/telephony/gonk/TelephonyService.js
@@ -559,75 +559,75 @@ TelephonyService.prototype = {
     if (!aIsDialEmergency) {
       aNumber = gPhoneNumberUtils.normalize(aNumber);
     }
 
     // Validate the number.
     // Note: isPlainPhoneNumber also accepts USSD and SS numbers
     if (!gPhoneNumberUtils.isPlainPhoneNumber(aNumber)) {
       if (DEBUG) debug("Error: Number '" + aNumber + "' is not viable. Drop.");
-      aCallback.notifyDialError(DIAL_ERROR_BAD_NUMBER);
+      aCallback.notifyError(DIAL_ERROR_BAD_NUMBER);
       return;
     }
 
     let mmi = this._parseMMI(aNumber, this._hasCalls(aClientId));
     if (!mmi) {
       this._dialCall(aClientId,
                      { number: aNumber,
                        isDialEmergency: aIsDialEmergency }, aCallback);
     } else if (this._isTemporaryCLIR(mmi)) {
       this._dialCall(aClientId,
                      { number: mmi.dialNumber,
                        clirMode: this._getTemporaryCLIRMode(mmi.procedure),
                        isDialEmergency: aIsDialEmergency }, aCallback);
     } else {
       // Reject MMI code from dialEmergency api.
       if (aIsDialEmergency) {
-        aCallback.notifyDialError(DIAL_ERROR_BAD_NUMBER);
+        aCallback.notifyError(DIAL_ERROR_BAD_NUMBER);
         return;
       }
 
-      this._dialMMI(aClientId, mmi, aCallback);
+      this._dialMMI(aClientId, mmi, aCallback, true);
     }
   },
 
   /**
    * @param aOptions.number
    * @param aOptions.clirMode (optional)
    * @param aOptions.isDialEmergency
    */
   _dialCall: function(aClientId, aOptions, aCallback) {
     if (this._isDialing) {
       if (DEBUG) debug("Error: Already has a dialing call.");
-      aCallback.notifyDialError(DIAL_ERROR_INVALID_STATE_ERROR);
+      aCallback.notifyError(DIAL_ERROR_INVALID_STATE_ERROR);
       return;
     }
 
     // We can only have at most two calls on the same line (client).
     if (this._numCallsOnLine(aClientId) >= 2) {
       if (DEBUG) debug("Error: Already has more than 2 calls on line.");
-      aCallback.notifyDialError(DIAL_ERROR_INVALID_STATE_ERROR);
+      aCallback.notifyError(DIAL_ERROR_INVALID_STATE_ERROR);
       return;
     }
 
     // For DSDS, if there is aleady a call on SIM 'aClientId', we cannot place
     // any new call on other SIM.
     if (this._hasCallsOnOtherClient(aClientId)) {
       if (DEBUG) debug("Error: Already has a call on other sim.");
-      aCallback.notifyDialError(DIAL_ERROR_OTHER_CONNECTION_IN_USE);
+      aCallback.notifyError(DIAL_ERROR_OTHER_CONNECTION_IN_USE);
       return;
     }
 
     aOptions.isEmergency = this._isEmergencyNumber(aOptions.number);
     if (aOptions.isEmergency) {
       // Automatically select a proper clientId for emergency call.
       aClientId = gRadioInterfaceLayer.getClientIdForEmergencyCall() ;
       if (aClientId === -1) {
         if (DEBUG) debug("Error: No client is avaialble for emergency call.");
-        aCallback.notifyDialError(DIAL_ERROR_INVALID_STATE_ERROR);
+        aCallback.notifyError(DIAL_ERROR_INVALID_STATE_ERROR);
         return;
       }
     }
 
     // Before we dial, we have to hold the active call first.
     let activeCall = this._getOneActiveCall(aClientId);
     if (!activeCall) {
       this._sendDialCallRequest(aClientId, aOptions, aCallback);
@@ -650,17 +650,17 @@ TelephonyService.prototype = {
 
   _sendDialCallRequest: function(aClientId, aOptions, aCallback) {
     this._isDialing = true;
 
     this._sendToRilWorker(aClientId, "dial", aOptions, response => {
       this._isDialing = false;
 
       if (!response.success) {
-        aCallback.notifyDialError(response.errorMsg);
+        aCallback.notifyError(response.errorMsg);
         return;
       }
 
       let currentCdmaCallIndex = !response.isCdma ? null :
         Object.keys(this._currentCalls[aClientId])[0];
 
       if (currentCdmaCallIndex == null) {
         aCallback.notifyDialCallSuccess(response.callIndex, response.number);
@@ -668,26 +668,34 @@ TelephonyService.prototype = {
         // RIL doesn't hold the 2nd call. We create one by ourselves.
         aCallback.notifyDialCallSuccess(CDMA_SECOND_CALL_INDEX, response.number);
         this._addCdmaChildCall(aClientId, response.number, currentCdmaCallIndex);
       }
     });
   },
 
   /**
+   * @param aClientId
+   *        Client id.
    * @param aMmi
    *        Parsed MMI structure.
+   * @param aCallback
+   *        A nsITelephonyDialCallback object.
+   * @param aStartNewSession
+   *        True to start a new session for ussd request.
    */
-  _dialMMI: function(aClientId, aMmi, aCallback) {
+  _dialMMI: function(aClientId, aMmi, aCallback, aStartNewSession) {
     let mmiServiceCode = aMmi ?
       this._serviceCodeToKeyString(aMmi.serviceCode) : RIL.MMI_KS_SC_USSD;
 
     aCallback.notifyDialMMI(mmiServiceCode);
 
-    this._sendToRilWorker(aClientId, "sendMMI", { mmi: aMmi }, response => {
+    this._sendToRilWorker(aClientId, "sendMMI",
+                          { mmi: aMmi,
+                            startNewSession: aStartNewSession }, response => {
       if (DEBUG) debug("MMI response: " + JSON.stringify(response));
 
       if (!response.success) {
         if (response.additionalInformation != null) {
           aCallback.notifyDialMMIErrorWithInfo(response.errorMsg,
                                                response.additionalInformation);
         } else {
           aCallback.notifyDialMMIError(response.errorMsg);
@@ -1043,16 +1051,28 @@ TelephonyService.prototype = {
   holdConference: function(aClientId) {
     this._sendToRilWorker(aClientId, "holdConference");
   },
 
   resumeConference: function(aClientId) {
     this._sendToRilWorker(aClientId, "resumeConference");
   },
 
+  sendUSSD: function(aClientId, aUssd, aCallback) {
+    this._sendToRilWorker(aClientId, "sendUSSD",
+                          { ussd: aUssd, checkSession: true },
+                          response => {
+      if (!response.success) {
+        aCallback.notifyError(response.errorMsg);
+      } else {
+        aCallback.notifySuccess();
+      }
+    });
+  },
+
   get microphoneMuted() {
     return gAudioManager.microphoneMuted;
   },
 
   set microphoneMuted(aMuted) {
     if (aMuted == this.microphoneMuted) {
       return;
     }
@@ -1261,19 +1281,37 @@ TelephonyService.prototype = {
   },
 
   notifyConferenceCallStateChanged: function(aState) {
     if (DEBUG) debug("handleConferenceCallStateChanged: " + aState);
     aState = this._convertRILCallState(aState);
     this._notifyAllListeners("conferenceCallStateChanged", [aState]);
   },
 
+  notifyUssdReceived: function(aClientId, aMessage, aSessionEnded) {
+    if (DEBUG) {
+      debug("notifyUssdReceived for " + aClientId + ": " +
+            aMessage + " (sessionEnded : " + aSessionEnded + ")");
+    }
+
+    let info = {
+      serviceId: aClientId,
+      message: aMessage,
+      sessionEnded: aSessionEnded
+    };
+
+    gSystemMessenger.broadcastMessage("ussd-received", info);
+
+    gGonkMobileConnectionService.notifyUssdReceived(aClientId, aMessage,
+                                                    aSessionEnded);
+  },
+
   dialMMI: function(aClientId, aMmiString, aCallback) {
     let mmi = this._parseMMI(aMmiString, this._hasCalls(aClientId));
-    this._dialMMI(aClientId, mmi, aCallback);
+    this._dialMMI(aClientId, mmi, aCallback, false);
   },
 
   /**
    * nsIObserver interface.
    */
 
   observe: function(aSubject, aTopic, aData) {
     switch (aTopic) {
@@ -1290,9 +1328,43 @@ TelephonyService.prototype = {
         this._releaseCallRingWakeLock();
 
         Services.obs.removeObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
         break;
     }
   }
 };
 
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([TelephonyService]);
+/**
+ * This implements nsISystemMessagesWrapper.wrapMessage(), which provides a
+ * plugable way to wrap a "ussd-received" type system message.
+ *
+ * Please see SystemMessageManager.js to know how it customizes the wrapper.
+ */
+function USSDReceivedWrapper() {
+  if (DEBUG) debug("USSDReceivedWrapper()");
+}
+USSDReceivedWrapper.prototype = {
+  // nsISystemMessagesWrapper implementation.
+  wrapMessage: function(aMessage, aWindow) {
+    if (DEBUG) debug("wrapMessage: " + JSON.stringify(aMessage));
+
+    let session = aMessage.sessionEnded ? null :
+      new aWindow.USSDSession(aMessage.serviceId);
+
+    let event = new aWindow.USSDReceivedEvent("ussdreceived", {
+      serviceId: aMessage.serviceId,
+      message: aMessage.message,
+      sessionEnded: aMessage.sessionEnded,
+      session: session
+    });
+
+    return event;
+  },
+
+  classDescription: "USSDReceivedWrapper",
+  classID: Components.ID("{d03684ed-ede4-4210-8206-f4f32772d9f5}"),
+  contractID: "@mozilla.org/dom/system-messages/wrapper/ussd-received;1",
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsISystemMessagesWrapper])
+};
+
+this.NSGetFactory = XPCOMUtils.generateNSGetFactory([TelephonyService,
+                                                    USSDReceivedWrapper]);
--- a/dom/telephony/gonk/TelephonyService.manifest
+++ b/dom/telephony/gonk/TelephonyService.manifest
@@ -1,2 +1,5 @@
 component {67d26434-d063-4d28-9f48-5b3189788155} TelephonyService.js
 contract @mozilla.org/telephony/gonktelephonyservice;1 {67d26434-d063-4d28-9f48-5b3189788155}
+
+component {d03684ed-ede4-4210-8206-f4f32772d9f5} TelephonyService.js
+contract @mozilla.org/dom/system-messages/wrapper/ussd-received;1 {d03684ed-ede4-4210-8206-f4f32772d9f5}
--- a/dom/telephony/ipc/PTelephony.ipdl
+++ b/dom/telephony/ipc/PTelephony.ipdl
@@ -19,20 +19,27 @@ struct EnumerateCallsRequest
 
 struct DialRequest
 {
   uint32_t clientId;
   nsString number;
   bool isEmergency;
 };
 
+struct USSDRequest
+{
+  uint32_t clientId;
+  nsString ussd;
+};
+
 union IPCTelephonyRequest
 {
   EnumerateCallsRequest;
   DialRequest;
+  USSDRequest;
 };
 
 sync protocol PTelephony {
   manager PContent;
   manages PTelephonyRequest;
 
 child:
   NotifyCallError(uint32_t aClientId, int32_t aCallIndex, nsString aError);
--- a/dom/telephony/ipc/PTelephonyRequest.ipdl
+++ b/dom/telephony/ipc/PTelephonyRequest.ipdl
@@ -11,17 +11,22 @@ namespace mozilla {
 namespace dom {
 namespace telephony {
 
 struct EnumerateCallsResponse
 {
   // empty.
 };
 
-struct DialResponseError
+struct SuccessResponse
+{
+  // empty.
+};
+
+struct ErrorResponse
 {
   nsString name;
 };
 
 struct DialResponseCallSuccess
 {
   uint32_t callIndex;
   nsString number;
@@ -37,18 +42,22 @@ struct DialResponseMMIError
 {
   nsString name;
   AdditionalInformation additionalInformation;
 };
 
 union IPCTelephonyResponse
 {
   EnumerateCallsResponse;
+
+  // General.
+  SuccessResponse;
+  ErrorResponse;
+
   // dial
-  DialResponseError;
   DialResponseCallSuccess;
   DialResponseMMISuccess;
   DialResponseMMIError;
 };
 
 protocol PTelephonyRequest
 {
   manager PTelephony;
--- a/dom/telephony/ipc/TelephonyChild.cpp
+++ b/dom/telephony/ipc/TelephonyChild.cpp
@@ -1,16 +1,16 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "TelephonyChild.h"
 
-#include "mozilla/dom/telephony/TelephonyCallback.h"
+#include "mozilla/dom/telephony/TelephonyDialCallback.h"
 #include "TelephonyIPCService.h"
 
 USING_TELEPHONY_NAMESPACE
 
 /*******************************************************************************
  * TelephonyChild
  ******************************************************************************/
 
@@ -142,18 +142,20 @@ TelephonyRequestChild::ActorDestroy(Acto
 
 bool
 TelephonyRequestChild::Recv__delete__(const IPCTelephonyResponse& aResponse)
 {
   switch (aResponse.type()) {
     case IPCTelephonyResponse::TEnumerateCallsResponse:
       mListener->EnumerateCallStateComplete();
       break;
-    case IPCTelephonyResponse::TDialResponseError:
-      return DoResponse(aResponse.get_DialResponseError());
+    case IPCTelephonyResponse::TSuccessResponse:
+      return DoResponse(aResponse.get_SuccessResponse());
+    case IPCTelephonyResponse::TErrorResponse:
+      return DoResponse(aResponse.get_ErrorResponse());
     case IPCTelephonyResponse::TDialResponseCallSuccess:
       return DoResponse(aResponse.get_DialResponseCallSuccess());
     case IPCTelephonyResponse::TDialResponseMMISuccess:
       return DoResponse(aResponse.get_DialResponseMMISuccess());
     case IPCTelephonyResponse::TDialResponseMMIError:
       return DoResponse(aResponse.get_DialResponseMMIError());
     default:
       MOZ_CRASH("Unknown type!");
@@ -182,45 +184,55 @@ TelephonyRequestChild::RecvNotifyEnumera
                                 aData.isMergeable());
   return true;
 }
 
 bool
 TelephonyRequestChild::RecvNotifyDialMMI(const nsString& aServiceCode)
 {
   MOZ_ASSERT(mCallback);
-
-  mCallback->NotifyDialMMI(aServiceCode);
+  nsCOMPtr<nsITelephonyDialCallback> callback = do_QueryInterface(mCallback);
+  callback->NotifyDialMMI(aServiceCode);
   return true;
 }
 
 bool
-TelephonyRequestChild::DoResponse(const DialResponseError& aResponse)
+TelephonyRequestChild::DoResponse(const SuccessResponse& aResponse)
 {
   MOZ_ASSERT(mCallback);
-  mCallback->NotifyDialError(aResponse.name());
+  mCallback->NotifySuccess();
+  return true;
+}
+
+bool
+TelephonyRequestChild::DoResponse(const ErrorResponse& aResponse)
+{
+  MOZ_ASSERT(mCallback);
+  mCallback->NotifyError(aResponse.name());
   return true;
 }
 
 bool
 TelephonyRequestChild::DoResponse(const DialResponseCallSuccess& aResponse)
 {
   MOZ_ASSERT(mCallback);
-  mCallback->NotifyDialCallSuccess(aResponse.callIndex(), aResponse.number());
+  nsCOMPtr<nsITelephonyDialCallback> callback = do_QueryInterface(mCallback);
+  callback->NotifyDialCallSuccess(aResponse.callIndex(), aResponse.number());
   return true;
 }
 
 bool
 TelephonyRequestChild::DoResponse(const DialResponseMMISuccess& aResponse)
 {
   MOZ_ASSERT(mCallback);
 
   // FIXME: Need to overload NotifyDialMMISuccess in the IDL. mCallback is not
   // necessarily an instance of TelephonyCallback.
-  nsRefPtr<TelephonyCallback> callback = static_cast<TelephonyCallback*>(mCallback.get());
+  nsCOMPtr<nsITelephonyDialCallback> dialCallback = do_QueryInterface(mCallback);
+  nsRefPtr<TelephonyDialCallback> callback = static_cast<TelephonyDialCallback*>(dialCallback.get());
 
   nsAutoString statusMessage(aResponse.statusMessage());
   AdditionalInformation info(aResponse.additionalInformation());
 
   switch (info.type()) {
     case AdditionalInformation::Tvoid_t:
       callback->NotifyDialMMISuccess(statusMessage);
       break;
@@ -237,26 +249,27 @@ TelephonyRequestChild::DoResponse(const 
 
   return true;
 }
 
 bool
 TelephonyRequestChild::DoResponse(const DialResponseMMIError& aResponse)
 {
   MOZ_ASSERT(mCallback);
+  nsCOMPtr<nsITelephonyDialCallback> callback = do_QueryInterface(mCallback);
 
   nsAutoString name(aResponse.name());
   AdditionalInformation info(aResponse.additionalInformation());
 
   switch (info.type()) {
     case AdditionalInformation::Tvoid_t:
-      mCallback->NotifyDialMMIError(name);
+      callback->NotifyDialMMIError(name);
       break;
     case AdditionalInformation::Tuint16_t:
-      mCallback->NotifyDialMMIErrorWithInfo(name, info.get_uint16_t());
+      callback->NotifyDialMMIErrorWithInfo(name, info.get_uint16_t());
       break;
     default:
       MOZ_CRASH("Received invalid type!");
       break;
   }
 
   return true;
 }
--- a/dom/telephony/ipc/TelephonyChild.h
+++ b/dom/telephony/ipc/TelephonyChild.h
@@ -79,17 +79,20 @@ protected:
   RecvNotifyEnumerateCallState(const uint32_t& aClientId,
                                const IPCCallStateData& aData) MOZ_OVERRIDE;
 
   virtual bool
   RecvNotifyDialMMI(const nsString& aServiceCode) MOZ_OVERRIDE;
 
 private:
   bool
-  DoResponse(const DialResponseError& aResponse);
+  DoResponse(const SuccessResponse& aResponse);
+
+  bool
+  DoResponse(const ErrorResponse& aResponse);
 
   bool
   DoResponse(const DialResponseCallSuccess& aResponse);
 
   bool
   DoResponse(const DialResponseMMISuccess& aResponse);
 
   bool
--- a/dom/telephony/ipc/TelephonyIPCService.cpp
+++ b/dom/telephony/ipc/TelephonyIPCService.cpp
@@ -157,17 +157,18 @@ TelephonyIPCService::SendRequest(nsITele
 NS_IMETHODIMP
 TelephonyIPCService::EnumerateCalls(nsITelephonyListener *aListener)
 {
   return SendRequest(aListener, nullptr, EnumerateCallsRequest());
 }
 
 NS_IMETHODIMP
 TelephonyIPCService::Dial(uint32_t aClientId, const nsAString& aNumber,
-                           bool aIsEmergency, nsITelephonyCallback *aCallback)
+                           bool aIsEmergency,
+                           nsITelephonyDialCallback *aCallback)
 {
   return SendRequest(nullptr, aCallback,
                      DialRequest(aClientId, nsString(aNumber), aIsEmergency));
 }
 
 NS_IMETHODIMP
 TelephonyIPCService::HangUp(uint32_t aClientId, uint32_t aCallIndex)
 {
@@ -296,16 +297,24 @@ TelephonyIPCService::StopTone(uint32_t a
     return NS_ERROR_FAILURE;
   }
 
   mPTelephonyChild->SendStopTone(aClientId);
   return NS_OK;
 }
 
 NS_IMETHODIMP
+TelephonyIPCService::SendUSSD(uint32_t aClientId, const nsAString& aUssd,
+                              nsITelephonyCallback *aCallback)
+{
+  return SendRequest(nullptr, aCallback,
+                     USSDRequest(aClientId, nsString(aUssd)));
+}
+
+NS_IMETHODIMP
 TelephonyIPCService::GetMicrophoneMuted(bool* aMuted)
 {
   if (!mPTelephonyChild) {
     NS_WARNING("TelephonyService used after shutdown has begun!");
     return NS_ERROR_FAILURE;
   }
 
   mPTelephonyChild->SendGetMicrophoneMuted(aMuted);
--- a/dom/telephony/ipc/TelephonyParent.cpp
+++ b/dom/telephony/ipc/TelephonyParent.cpp
@@ -38,16 +38,18 @@ TelephonyParent::RecvPTelephonyRequestCo
 {
   TelephonyRequestParent* actor = static_cast<TelephonyRequestParent*>(aActor);
 
   switch (aRequest.type()) {
     case IPCTelephonyRequest::TEnumerateCallsRequest:
       return actor->DoRequest(aRequest.get_EnumerateCallsRequest());
     case IPCTelephonyRequest::TDialRequest:
       return actor->DoRequest(aRequest.get_DialRequest());
+    case IPCTelephonyRequest::TUSSDRequest:
+      return actor->DoRequest(aRequest.get_USSDRequest());
     default:
       MOZ_CRASH("Unknown type!");
   }
 
   return false;
 }
 
 PTelephonyRequestParent*
@@ -380,17 +382,18 @@ TelephonyParent::SupplementaryServiceNot
 }
 
 /*******************************************************************************
  * TelephonyRequestParent
  ******************************************************************************/
 
 NS_IMPL_ISUPPORTS(TelephonyRequestParent,
                   nsITelephonyListener,
-                  nsITelephonyCallback)
+                  nsITelephonyCallback,
+                  nsITelephonyDialCallback)
 
 TelephonyRequestParent::TelephonyRequestParent()
   : mActorDestroyed(false)
 {
 }
 
 void
 TelephonyRequestParent::ActorDestroy(ActorDestroyReason why)
@@ -421,19 +424,33 @@ TelephonyRequestParent::DoRequest(const 
 
 bool
 TelephonyRequestParent::DoRequest(const DialRequest& aRequest)
 {
   nsCOMPtr<nsITelephonyService> service =
     do_GetService(TELEPHONY_SERVICE_CONTRACTID);
   if (service) {
     service->Dial(aRequest.clientId(), aRequest.number(),
-                   aRequest.isEmergency(), this);
+                  aRequest.isEmergency(), this);
   } else {
-    return NS_SUCCEEDED(NotifyDialError(NS_LITERAL_STRING("InvalidStateError")));
+    return NS_SUCCEEDED(NotifyError(NS_LITERAL_STRING("InvalidStateError")));
+  }
+
+  return true;
+}
+
+bool
+TelephonyRequestParent::DoRequest(const USSDRequest& aRequest)
+{
+  nsCOMPtr<nsITelephonyService> service =
+    do_GetService(TELEPHONY_SERVICE_CONTRACTID);
+  if (service) {
+    service->SendUSSD(aRequest.clientId(), aRequest.ussd(), this);
+  } else {
+    return NS_SUCCEEDED(NotifyError(NS_LITERAL_STRING("InvalidStateError")));
   }
 
   return true;
 }
 
 nsresult
 TelephonyRequestParent::SendResponse(const IPCTelephonyResponse& aResponse)
 {
@@ -527,30 +544,36 @@ TelephonyRequestParent::NotifyError(uint
 NS_IMETHODIMP
 TelephonyRequestParent::SupplementaryServiceNotification(uint32_t aClientId,
                                                          int32_t aCallIndex,
                                                          uint16_t aNotification)
 {
   MOZ_CRASH("Not a TelephonyParent!");
 }
 
-// nsITelephonyCallback
+// nsITelephonyDialCallback
 
 NS_IMETHODIMP
 TelephonyRequestParent::NotifyDialMMI(const nsAString& aServiceCode)
 {
   NS_ENSURE_TRUE(!mActorDestroyed, NS_ERROR_FAILURE);
 
   return SendNotifyDialMMI(nsAutoString(aServiceCode)) ? NS_OK : NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
-TelephonyRequestParent::NotifyDialError(const nsAString& aError)
+TelephonyRequestParent::NotifySuccess()
 {
-  return SendResponse(DialResponseError(nsAutoString(aError)));
+  return SendResponse(SuccessResponse());
+}
+
+NS_IMETHODIMP
+TelephonyRequestParent::NotifyError(const nsAString& aError)
+{
+  return SendResponse(ErrorResponse(nsAutoString(aError)));
 }
 
 NS_IMETHODIMP
 TelephonyRequestParent::NotifyDialCallSuccess(uint32_t aCallIndex,
                                               const nsAString& aNumber)
 {
   return SendResponse(DialResponseCallSuccess(aCallIndex, nsAutoString(aNumber)));
 }
--- a/dom/telephony/ipc/TelephonyParent.h
+++ b/dom/telephony/ipc/TelephonyParent.h
@@ -93,24 +93,25 @@ protected:
 
 private:
   bool mActorDestroyed;
   bool mRegistered;
 };
 
 class TelephonyRequestParent : public PTelephonyRequestParent
                              , public nsITelephonyListener
-                             , public nsITelephonyCallback
+                             , public nsITelephonyDialCallback
 {
   friend class TelephonyParent;
 
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSITELEPHONYLISTENER
   NS_DECL_NSITELEPHONYCALLBACK
+  NS_DECL_NSITELEPHONYDIALCALLBACK
 
 protected:
   TelephonyRequestParent();
   virtual ~TelephonyRequestParent() {}
 
   virtual void
   ActorDestroy(ActorDestroyReason why);
 
@@ -120,13 +121,16 @@ protected:
 private:
   bool mActorDestroyed;
 
   bool
   DoRequest(const EnumerateCallsRequest& aRequest);
 
   bool
   DoRequest(const DialRequest& aRequest);
+
+  bool
+  DoRequest(const USSDRequest& aRequest);
 };
 
 END_TELEPHONY_NAMESPACE
 
 #endif /* mozilla_dom_telephony_TelephonyParent_h */
--- a/dom/telephony/moz.build
+++ b/dom/telephony/moz.build
@@ -11,35 +11,39 @@ XPIDL_SOURCES += [
 XPIDL_MODULE = 'dom_telephony'
 
 EXPORTS.mozilla.dom += [
     'CallsList.h',
     'Telephony.h',
     'TelephonyCall.h',
     'TelephonyCallGroup.h',
     'TelephonyCallId.h',
+    'USSDSession.h'
 ]
 
 EXPORTS.mozilla.dom.telephony += [
     'ipc/TelephonyChild.h',
     'ipc/TelephonyParent.h',
     'TelephonyCallback.h',
     'TelephonyCommon.h',
+    'TelephonyDialCallback.h',
 ]
 
 UNIFIED_SOURCES += [
     'CallsList.cpp',
     'ipc/TelephonyChild.cpp',
     'ipc/TelephonyIPCService.cpp',
     'ipc/TelephonyParent.cpp',
     'Telephony.cpp',
     'TelephonyCall.cpp',
     'TelephonyCallback.cpp',
     'TelephonyCallGroup.cpp',
     'TelephonyCallId.cpp',
+    'TelephonyDialCallback.cpp',
+    'USSDSession.cpp',
 ]
 
 IPDL_SOURCES += [
     'ipc/PTelephony.ipdl',
     'ipc/PTelephonyRequest.ipdl',
     'ipc/TelephonyTypes.ipdlh'
 ]
 
--- a/dom/telephony/nsIGonkTelephonyService.idl
+++ b/dom/telephony/nsIGonkTelephonyService.idl
@@ -5,28 +5,31 @@
 
 #include "nsITelephonyService.idl"
 
 %{C++
 #define GONK_TELEPHONY_SERVICE_CONTRACTID \
         "@mozilla.org/telephony/gonktelephonyservice;1"
 %}
 
-[scriptable, uuid(8790e2cc-2c68-4ce9-90dc-f68e1b6e4886)]
+[scriptable, uuid(79eec3c3-2dfc-4bbf-b106-af5457651ae0)]
 interface nsIGonkTelephonyService : nsITelephonyService
 {
   void notifyCallDisconnected(in unsigned long clientId, in jsval call);
 
   void notifyCallRing();
 
   void notifyCallStateChanged(in unsigned long clientId, in jsval call,
                               [optional] in boolean skipStateConversion);
 
   void notifyCdmaCallWaiting(in unsigned long clientId, in jsval waitingCall);
 
   void notifySupplementaryService(in unsigned long clientId, in long callIndex,
                                   in AString notification);
 
   void notifyConferenceCallStateChanged(in short state);
 
+  void notifyUssdReceived(in unsigned long clientId, in DOMString message,
+                          in boolean sessionEnded);
+
   void dialMMI(in unsigned long clientId, in AString mmiString,
-               in nsITelephonyCallback callback);
+               in nsITelephonyDialCallback callback);
 };
--- a/dom/telephony/nsITelephonyService.idl
+++ b/dom/telephony/nsITelephonyService.idl
@@ -172,39 +172,41 @@ interface nsITelephonyListener : nsISupp
    * @param message
    *        Detailed error message from RIL.
    */
   void notifyConferenceError(in AString name,
                              in AString message);
 };
 
 /**
- * A callback interface for handling asynchronous response of Telephony.dial().
+ * A callback interface for handling asynchronous response.
  */
-[scriptable, uuid(67533db3-cd38-475c-a774-8d0bbf9169fb)]
+[scriptable, uuid(cffc3f9d-2c88-4a14-8ebc-f216caf0cc1d)]
 interface nsITelephonyCallback : nsISupports
 {
+  void notifySuccess();
+  void notifyError(in AString error);
+};
+
+/**
+ * A callback interface for handling asynchronous response for telephony.dial.
+ */
+[scriptable, uuid(4481212f-72e9-4aef-97e1-5397af782113)]
+interface nsITelephonyDialCallback : nsITelephonyCallback
+{
   /**
    * Called when a dial request is treated as an MMI code and it is about to
    * process the request.
    *
    * @param serviceCode
    *        MMI service code key string that defined in MMI_KS_SC_*
    */
   void notifyDialMMI(in AString serviceCode);
 
   /**
-   * Called when a dial request fails.
-   *
-   * @param error
-   *        Error from RIL.
-   */
-  void notifyDialError(in AString error);
-
-  /**
    * Called when a dial request is treated as a call setup and the result
    * succeeds.
    *
    * @param callIndex
    *        Call index from RIL.
    * @param number
    *        Dialed out phone number (ex: Temporary CLIR prefix will be removed)
    */
@@ -233,17 +235,17 @@ interface nsITelephonyCallback : nsISupp
 #define TELEPHONY_SERVICE_CONTRACTID \
   "@mozilla.org/telephony/telephonyservice;1"
 %}
 
 /**
  * XPCOM component (in the content process) that provides the telephony
  * information.
  */
-[scriptable, uuid(4ff3ecb7-b024-4752-9dd6-c3623c6e6b8a)]
+[scriptable, uuid(79188caa-046a-48e1-b9c5-2e891504dc7a)]
 interface nsITelephonyService : nsISupports
 {
   const unsigned short CALL_STATE_UNKNOWN = 0;
   const unsigned short CALL_STATE_DIALING = 1;
   const unsigned short CALL_STATE_ALERTING = 2;
   const unsigned short CALL_STATE_CONNECTING = 3;
   const unsigned short CALL_STATE_CONNECTED = 4;
   const unsigned short CALL_STATE_HOLDING = 5;
@@ -276,32 +278,42 @@ interface nsITelephonyService : nsISuppo
    * returns false.
    */
   void enumerateCalls(in nsITelephonyListener listener);
 
   /**
    * Functionality for making and managing phone calls.
    */
   void dial(in unsigned long clientId, in DOMString number,
-            in boolean isEmergency, in nsITelephonyCallback callback);
+            in boolean isEmergency, in nsITelephonyDialCallback callback);
   void hangUp(in unsigned long clientId, in unsigned long callIndex);
 
   void startTone(in unsigned long clientId, in DOMString dtmfChar);
   void stopTone(in unsigned long clientId);
 
   void answerCall(in unsigned long clientId, in unsigned long callIndex);
   void rejectCall(in unsigned long clientId, in unsigned long callIndex);
   void holdCall(in unsigned long clientId, in unsigned long callIndex);
   void resumeCall(in unsigned long clientId, in unsigned long callIndex);
 
   void conferenceCall(in unsigned long clientId);
   void separateCall(in unsigned long clientId, in unsigned long callIndex);
   void holdConference(in unsigned long clientId);
   void resumeConference(in unsigned long clientId);
 
+  /**
+   * Send an USSD on existing session. It results in error if the session is
+   * not existed.
+   *
+   * If successful, callback.notifySuccess() will be called.
+   * Otherwise, callback.notifyError() will be called.
+   */
+  void sendUSSD(in unsigned long clientId, in DOMString ussd,
+                in nsITelephonyCallback callback);
+
   attribute bool microphoneMuted;
   attribute bool speakerEnabled;
 };
 
 %{C++
 template<typename T> struct already_AddRefed;
 
 already_AddRefed<nsITelephonyService>
--- a/dom/tests/mochitest/general/test_interfaces.html
+++ b/dom/tests/mochitest/general/test_interfaces.html
@@ -1240,18 +1240,16 @@ var interfaceNamesInGlobalScope =
     "UndoManager",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "URL",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "URLSearchParams",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "UserProximityEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "USSDReceivedEvent", b2g: true, pref: "dom.mobileconnection.enabled"},
-// IMPORTANT: Do not change this list without review from a DOM peer!
     "ValidityState",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "VideoPlaybackQuality", pref: "media.mediasource.enabled"},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "VideoStreamTrack",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "VTTCue",
 // IMPORTANT: Do not change this list without review from a DOM peer!
--- a/dom/webidl/MozNFCTag.webidl
+++ b/dom/webidl/MozNFCTag.webidl
@@ -5,18 +5,16 @@
  * Part of this idl is from:
  * http://w3c.github.io/nfc/proposals/common/nfc.html#nfctag-interface
  *
  * Copyright © 2013 Deutsche Telekom, Inc.
  */
 
 enum NFCTechType {
   "NDEF",
-  "NDEF_WRITABLE",
-  "NDEF_FORMATABLE",
   "P2P",
   "NFC_A",
   "NFC_B",
   "NFC_F",
   "NFC_V",
   "NFC_ISO_DEP",
   "MIFARE_CLASSIC",
   "MIFARE_ULTRALIGHT",
--- a/dom/webidl/NfcOptions.webidl
+++ b/dom/webidl/NfcOptions.webidl
@@ -8,16 +8,17 @@ dictionary NfcCommandOptions
 
   long sessionId;
   DOMString requestId = "";
 
   long powerLevel;
 
   long techType;
 
+  boolean isP2P;
   sequence<MozNDEFRecordOptions> records;
 };
 
 dictionary NfcEventOptions
 {
   DOMString type = "";
 
   long status;
--- a/dom/webidl/USSDReceivedEvent.webidl
+++ b/dom/webidl/USSDReceivedEvent.webidl
@@ -1,19 +1,25 @@
 /* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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/.
  */
 
-[Pref="dom.mobileconnection.enabled",
+[Pref="dom.telephony.enabled",
+ CheckPermissions="telephony mobileconnection",
+ AvailableIn="CertifiedApps",
  Constructor(DOMString type, optional USSDReceivedEventInit eventInitDict)]
 interface USSDReceivedEvent : Event
 {
+  readonly attribute unsigned long serviceId;
   readonly attribute DOMString? message;
-  readonly attribute boolean sessionEnded;
+  readonly attribute USSDSession? session;  // null if session is ended.
+  readonly attribute boolean sessionEnded;  // deprecated. Bug 1070831
 };
 
 dictionary USSDReceivedEventInit : EventInit
 {
+  unsigned long serviceId = 0;
   DOMString? message = null;
+  USSDSession? session = null;
   boolean sessionEnded = false;
 };
new file mode 100644
--- /dev/null
+++ b/dom/webidl/USSDSession.webidl
@@ -0,0 +1,14 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/.
+ */
+
+[Pref="dom.telephony.enabled",
+ CheckPermissions="telephony",
+ AvailableIn="CertifiedApps",
+ Constructor(unsigned long serviceId)]
+interface USSDSession {
+  [Throws]
+  Promise<void> send(DOMString ussd);
+};
--- a/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -503,16 +503,17 @@ WEBIDL_FILES = [
     'UDPMessageEvent.webidl',
     'UDPSocket.webidl',
     'UIEvent.webidl',
     'UndoManager.webidl',
     'URL.webidl',
     'URLSearchParams.webidl',
     'URLUtils.webidl',
     'URLUtilsReadOnly.webidl',
+    'USSDSession.webidl',
     'ValidityState.webidl',
     'VideoPlaybackQuality.webidl',
     'VideoStreamTrack.webidl',
     'VideoTrack.webidl',
     'VideoTrackList.webidl',
     'VTTCue.webidl',
     'VTTRegion.webidl',
     'WaveShaperNode.webidl',